Rebase qemu-android over upstream QEMU v2.7.0

This patch rebases the qemu-android source base
on top of a much more recent version of upstream
QEMU (previous version was 2.2.0).

It was created by doing the following:

- Look at the history of all changes in qemu-android
  over v2.2.0, and "clean it up" into a list of
  small opiniated patches to do one of the following:

    - port back fixes from upstream that happened
      after v2.2.0

    - provide bug-fixes / improvements required
      by the Android emulator (but not directly
      related for Android emulation).

    - add Android-specific features.

- Rebase the "clean patches stack" on top of
  QEMU v2.7.0 (i.e. 1dc33ed90bf). The end process
  ended up being one of this patch's parents,
  i.e. 41b9dc407

- Merge the latter with the 'theirs' strategy
  (favoring the new sources over the current ones).

- Manually adjust any required changes by
  comparing the state of both trees. Fix any
  remaining conflicts.

NOTE: This updates the git submodule for the dtc/
      sub-directory, you may need to run the
      following command in your work directory
      after pulling this change:

         git submodule update dtc

Change-Id: I783ab762a696c8345c37e5ce2c966349f3710073
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 0000000..3ac0cfc
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,2 @@
+((c-mode . ((c-file-style . "stroustrup")
+	    (indent-tabs-mode . nil))))
diff --git a/.gitignore b/.gitignore
index e32a584..88ec249 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 /config-target.*
 /config.status
 /config-temp
+/trace-events-all
 /trace/generated-tracers.h
 /trace/generated-tracers.c
 /trace/generated-tracers-dtrace.h
@@ -17,12 +18,15 @@
 /trace/generated-tcg-tracers.h
 /trace/generated-ust-provider.h
 /trace/generated-ust.c
-/libcacard/trace/generated-tracers.c
+/ui/shader/texture-blit-frag.h
+/ui/shader/texture-blit-vert.h
 *-timestamp
 /*-softmmu
 /*-darwin-user
 /*-linux-user
 /*-bsd-user
+/ivshmem-client
+/ivshmem-server
 /libdis*
 /libuser
 /linux-headers/asm
@@ -32,19 +36,14 @@
 /qapi-visit.[ch]
 /qapi-event.[ch]
 /qmp-commands.h
+/qmp-introspect.[ch]
 /qmp-marshal.c
 /qemu-doc.html
 /qemu-tech.html
 /qemu-doc.info
 /qemu-tech.info
-/qemu.1
-/qemu.pod
-/qemu-img.1
-/qemu-img.pod
 /qemu-img
 /qemu-nbd
-/qemu-nbd.8
-/qemu-nbd.pod
 /qemu-options.def
 /qemu-options.texi
 /qemu-img-cmds.texi
@@ -53,16 +52,17 @@
 /qemu-ga
 /qemu-bridge-helper
 /qemu-monitor.texi
+/qemu-monitor-info.texi
 /qmp-commands.txt
 /vscclient
 /fsdev/virtfs-proxy-helper
-/fsdev/virtfs-proxy-helper.1
-/fsdev/virtfs-proxy-helper.pod
+*.[1-9]
 *.a
 *.aux
 *.cp
 *.dvi
 *.exe
+*.msi
 *.dll
 *.so
 *.mo
@@ -70,6 +70,7 @@
 *.ky
 *.log
 *.pdf
+*.pod
 *.cps
 *.fns
 *.kys
@@ -94,6 +95,10 @@
 /pc-bios/optionrom/linuxboot.bin
 /pc-bios/optionrom/linuxboot.raw
 /pc-bios/optionrom/linuxboot.img
+/pc-bios/optionrom/linuxboot_dma.asm
+/pc-bios/optionrom/linuxboot_dma.bin
+/pc-bios/optionrom/linuxboot_dma.raw
+/pc-bios/optionrom/linuxboot_dma.img
 /pc-bios/optionrom/multiboot.asm
 /pc-bios/optionrom/multiboot.bin
 /pc-bios/optionrom/multiboot.raw
@@ -108,4 +113,5 @@
 cscope.*
 tags
 TAGS
+docker-src.*
 *~
diff --git a/.travis.yml b/.travis.yml
index ad66e5b..f30b10e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,100 +1,101 @@
+sudo: false
 language: c
 python:
   - "2.4"
 compiler:
   - gcc
   - clang
+cache: ccache
+addons:
+  apt:
+    packages:
+      - libaio-dev
+      - libattr1-dev
+      - libbrlapi-dev
+      - libcap-ng-dev
+      - libgnutls-dev
+      - libgtk-3-dev
+      - libiscsi-dev
+      - liblttng-ust-dev
+      - libnfs-dev
+      - libncurses5-dev
+      - libnss3-dev
+      - libpixman-1-dev
+      - libpng12-dev
+      - librados-dev
+      - libsdl1.2-dev
+      - libseccomp-dev
+      - libspice-protocol-dev
+      - libspice-server-dev
+      - libssh2-1-dev
+      - liburcu-dev
+      - libusb-1.0-0-dev
+      - libvte-2.90-dev
+      - sparse
+      - uuid-dev
+
+# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
+# to prevent IRC notifications from forks. This was created using:
+# $ travis encrypt -r "qemu/qemu" "irc.oftc.net#qemu"
 notifications:
   irc:
     channels:
-      - "irc.oftc.net#qemu"
+      - secure: "F7GDRgjuOo5IUyRLqSkmDL7kvdU4UcH3Lm/W2db2JnDHTGCqgEdaYEYKciyCLZ57vOTsTsOgesN8iUT7hNHBd1KWKjZe9KDTZWppWRYVwAwQMzVeSOsbbU4tRoJ6Pp+3qhH1Z0eGYR9ZgKYAoTumDFgSAYRp4IscKS8jkoedOqM="
     on_success: change
     on_failure: always
 env:
   global:
-    - TEST_CMD=""
-    - 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=""
+    - TEST_CMD="make check"
   matrix:
-    # Group major targets together with their linux-user counterparts
-    - TARGETS=alpha-softmmu,alpha-linux-user
-    - TARGETS=arm-softmmu,arm-linux-user,armeb-linux-user,aarch64-softmmu,aarch64-linux-user
-    - TARGETS=cris-softmmu,cris-linux-user
-    - TARGETS=i386-softmmu,i386-linux-user,x86_64-softmmu,x86_64-linux-user
-    - TARGETS=m68k-softmmu,m68k-linux-user
-    - TARGETS=microblaze-softmmu,microblazeel-softmmu,microblaze-linux-user,microblazeel-linux-user
-    - TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
-    - TARGETS=mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,mipsn32-linux-user,mipsn32el-linux-user
-    - TARGETS=or32-softmmu,or32-linux-user
-    - TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu,ppc-linux-user,ppc64-linux-user,ppc64abi32-linux-user,ppc64le-linux-user
-    - TARGETS=s390x-softmmu,s390x-linux-user
-    - TARGETS=sh4-softmmu,sh4eb-softmmu,sh4-linux-user sh4eb-linux-user
-    - TARGETS=sparc-softmmu,sparc64-softmmu,sparc-linux-user,sparc32plus-linux-user,sparc64-linux-user
-    - TARGETS=unicore32-softmmu,unicore32-linux-user
-    # Group remaining softmmu only targets into one build
-    - TARGETS=lm32-softmmu,moxie-softmmu,tricore-softmmu,xtensa-softmmu,xtensaeb-softmmu
+    - CONFIG=""
+    - CONFIG="--enable-debug --enable-debug-tcg --enable-trace-backends=log"
+    - CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-uuid --disable-libusb"
+    - CONFIG="--enable-modules"
+    - CONFIG="--with-coroutine=ucontext"
+    - CONFIG="--with-coroutine=sigaltstack"
 git:
   # we want to do this ourselves
   submodules: false
 before_install:
+  - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update ; fi
+  - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install libffi gettext glib pixman ; fi
   - wget -O - http://people.linaro.org/~alex.bennee/qemu-submodule-git-seed.tar.xz | tar -xvJ
   - git submodule update --init --recursive
-  - sudo apt-get update -qq
-  - sudo apt-get install -qq ${CORE_PKGS} ${NET_PKGS} ${GUI_PKGS} ${EXTRA_PKGS}
 before_script:
-  - ./configure --target-list=${TARGETS} --enable-debug-tcg ${EXTRA_CONFIG}
+  - ./configure ${CONFIG}
 script:
-  - make -j2 && ${TEST_CMD}
+  - make -j3 && ${TEST_CMD}
 matrix:
-  # We manually include a number of additional build for non-standard bits
   include:
-    # Make check target (we only do this once)
-    - env:
-        - TARGETS=alpha-softmmu,arm-softmmu,aarch64-softmmu,cris-softmmu,
-                  i386-softmmu,x86_64-softmmu,m68k-softmmu,microblaze-softmmu,
-                  microblazeel-softmmu,mips-softmmu,mips64-softmmu,
-                  mips64el-softmmu,mipsel-softmmu,or32-softmmu,ppc-softmmu,
-                  ppc64-softmmu,ppcemb-softmmu,s390x-softmmu,sh4-softmmu,
-                  sh4eb-softmmu,sparc-softmmu,sparc64-softmmu,
-                  unicore32-softmmu,unicore32-linux-user,
-                  lm32-softmmu,moxie-softmmu,tricore-softmmu,xtensa-softmmu,
-                  xtensaeb-softmmu
-          TEST_CMD="make check"
+    # gprof/gcov are GCC features
+    - env: CONFIG="--enable-gprof --enable-gcov --disable-pie"
       compiler: gcc
-    # Debug related options
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_CONFIG="--enable-debug"
+    # We manually include builds which we disable "make check" for
+    - env: CONFIG="--enable-debug --enable-tcg-interpreter"
+           TEST_CMD=""
       compiler: gcc
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
+    - env: CONFIG="--enable-trace-backends=simple"
+           TEST_CMD=""
       compiler: gcc
-    # All the extra -dev packages
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_PKGS="libaio-dev libcap-ng-dev libattr1-dev libbrlapi-dev uuid-dev libusb-1.0.0-dev"
+    - env: CONFIG="--enable-trace-backends=ftrace"
+           TEST_CMD=""
       compiler: gcc
-    # Currently configure doesn't force --disable-pie
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
+    - env: CONFIG="--enable-trace-backends=ust"
+           TEST_CMD=""
       compiler: gcc
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_PKGS="sparse"
-           EXTRA_CONFIG="--enable-sparse"
+    - env: CONFIG="--with-coroutine=gthread"
+           TEST_CMD=""
       compiler: gcc
-    # All the trace backends (apart from dtrace)
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_CONFIG="--enable-trace-backends=stderr"
+    - env: CONFIG=""
+      os: osx
+      compiler: clang
+    - env: CONFIG=""
+      sudo: required
+      addons:
+      dist: trusty
       compiler: gcc
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_CONFIG="--enable-trace-backends=simple"
-      compiler: gcc
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-           EXTRA_CONFIG="--enable-trace-backends=ftrace"
-      compiler: gcc
-    - env: TARGETS=i386-softmmu,x86_64-softmmu
-          EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
-          EXTRA_CONFIG="--enable-trace-backends=ust"
-      compiler: gcc
+      before_install:
+        - sudo apt-get update -qq
+        - sudo apt-get build-dep -qq qemu
+        - wget -O - http://people.linaro.org/~alex.bennee/qemu-submodule-git-seed.tar.xz | tar -xvJ
+        - git submodule update --init --recursive
diff --git a/CODING_STYLE b/CODING_STYLE
index d46cfa5..e7fde15 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -31,7 +31,11 @@
 
 2. Line width
 
-Lines are 80 characters; not longer.
+Lines should be 80 characters; try not to make them longer.
+
+Sometimes it is hard to do, especially when dealing with QEMU subsystems
+that use long function or symbol names.  Even in that case, do not make
+lines much longer than 80 characters.
 
 Rationale:
  - Some people like to tile their 24" screens with a 6x4 matrix of 80x24
@@ -39,6 +43,8 @@
    let them keep doing it.
  - Code and especially patches is much more readable if limited to a sane
    line length.  Eighty is traditional.
+ - The four-space indentation makes the most common excuse ("But look
+   at all that white space on the left!") moot.
  - It is the QEMU coding style.
 
 3. Naming
@@ -87,10 +93,15 @@
 
 5. Declarations
 
-Mixed declarations (interleaving statements and declarations within blocks)
-are not allowed; declarations should be at the beginning of blocks.  In other
-words, the code should not generate warnings if using GCC's
--Wdeclaration-after-statement option.
+Mixed declarations (interleaving statements and declarations within
+blocks) are generally not allowed; declarations should be at the beginning
+of blocks.
+
+Every now and then, an exception is made for declarations inside a
+#ifdef or #ifndef block: if the code looks nicer, such declarations can
+be placed at the top of the block even if there are statements above.
+On the other hand, however, it's often best to move that #ifdef/#ifndef
+block to a separate function altogether.
 
 6. Conditional statements
 
diff --git a/HACKING b/HACKING
index 12fbc8a..20a9101 100644
--- a/HACKING
+++ b/HACKING
@@ -157,3 +157,62 @@
  * you may assume that integers are 2s complement representation
  * you may assume that right shift of a signed integer duplicates
    the sign bit (ie it is an arithmetic shift, not a logical shift)
+
+In addition, QEMU assumes that the compiler does not use the latitude
+given in C99 and C11 to treat aspects of signed '<<' as undefined, as
+documented in the GNU Compiler Collection manual starting at version 4.0.
+
+7. Error handling and reporting
+
+7.1 Reporting errors to the human user
+
+Do not use printf(), fprintf() or monitor_printf().  Instead, use
+error_report() or error_vreport() from error-report.h.  This ensures the
+error is reported in the right place (current monitor or stderr), and in
+a uniform format.
+
+Use error_printf() & friends to print additional information.
+
+error_report() prints the current location.  In certain common cases
+like command line parsing, the current location is tracked
+automatically.  To manipulate it manually, use the loc_*() from
+error-report.h.
+
+7.2 Propagating errors
+
+An error can't always be reported to the user right where it's detected,
+but often needs to be propagated up the call chain to a place that can
+handle it.  This can be done in various ways.
+
+The most flexible one is Error objects.  See error.h for usage
+information.
+
+Use the simplest suitable method to communicate success / failure to
+callers.  Stick to common methods: non-negative on success / -1 on
+error, non-negative / -errno, non-null / null, or Error objects.
+
+Example: when a function returns a non-null pointer on success, and it
+can fail only in one way (as far as the caller is concerned), returning
+null on failure is just fine, and certainly simpler and a lot easier on
+the eyes than propagating an Error object through an Error ** parameter.
+
+Example: when a function's callers need to report details on failure
+only the function really knows, use Error **, and set suitable errors.
+
+Do not report an error to the user when you're also returning an error
+for somebody else to handle.  Leave the reporting to the place that
+consumes the error returned.
+
+7.3 Handling errors
+
+Calling exit() is fine when handling configuration errors during
+startup.  It's problematic during normal operation.  In particular,
+monitor commands should never exit().
+
+Do not call exit() or abort() to handle an error that can be triggered
+by the guest (e.g., some unimplemented corner case in guest code
+translation or device emulation).  Guests should not be able to
+terminate QEMU.
+
+Note that &error_fatal is just another way to exit(1), and &error_abort
+is just another way to abort().
diff --git a/LICENSE b/LICENSE
index da70e94..0e0b4b9 100644
--- a/LICENSE
+++ b/LICENSE
@@ -11,7 +11,7 @@
 
 As of July 2013, contributions under version 2 of the GNU General Public
 License (and no later version) are only accepted for the following files
-or directories: bsd-user/, linux-user/, hw/misc/vfio.c, hw/xen/xen_pt*.
+or directories: bsd-user/, linux-user/, hw/vfio/, hw/xen/xen_pt*.
 
 3) The Tiny Code Generator (TCG) is released under the BSD license
    (see license headers in files).
diff --git a/MAINTAINERS b/MAINTAINERS
index bcb69e8..b6fb84e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -50,28 +50,46 @@
 
 General Project Administration
 ------------------------------
-M: Anthony Liguori <aliguori@amazon.com>
 M: Peter Maydell <peter.maydell@linaro.org>
 
+All patches CC here
+L: qemu-devel@nongnu.org
+F: *
+F: */
+
 Responsible Disclosure, Reporting Security Issues
 ------------------------------
 W: http://wiki.qemu.org/SecurityProcess
 M: Michael S. Tsirkin <mst@redhat.com>
-M: Anthony Liguori <aliguori@amazon.com>
 L: secalert@redhat.com
 
 Guest CPU cores (TCG):
 ----------------------
 Overall
 L: qemu-devel@nongnu.org
-S: Odd fixes
+M: Paolo Bonzini <pbonzini@redhat.com>
+M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
+M: Richard Henderson <rth@twiddle.net>
+S: Maintained
 F: cpu-exec.c
+F: cpu-exec-common.c
+F: cpus.c
 F: cputlb.c
+F: exec.c
 F: softmmu_template.h
-F: translate-all.c
-F: include/exec/cpu_ldst.h
-F: include/exec/cpu_ldst_template.h
+F: translate-all.*
+F: translate-common.c
+F: include/exec/cpu*.h
+F: include/exec/exec-all.h
 F: include/exec/helper*.h
+F: include/exec/tb-hash.h
+
+FPU emulation
+M: Aurelien Jarno <aurelien@aurel32.net>
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Odd Fixes
+F: fpu/
+F: include/fpu/
 
 Alpha
 M: Richard Henderson <rth@twiddle.net>
@@ -79,13 +97,18 @@
 F: target-alpha/
 F: hw/alpha/
 F: tests/tcg/alpha/
+F: disas/alpha.c
 
 ARM
 M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: target-arm/
 F: hw/arm/
 F: hw/cpu/a*mpcore.c
+F: disas/arm.c
+F: disas/arm-a64.cc
+F: disas/libvixl/
 
 CRIS
 M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
@@ -93,13 +116,18 @@
 F: target-cris/
 F: hw/cris/
 F: tests/tcg/cris/
+F: disas/cris.c
 
 LM32
 M: Michael Walle <michael@walle.cc>
 S: Maintained
 F: target-lm32/
+F: disas/lm32.c
 F: hw/lm32/
-F: hw/char/lm32_*
+F: hw/*/lm32_*
+F: hw/*/milkymist-*
+F: include/hw/char/lm32_juart.h
+F: include/hw/lm32/
 F: tests/tcg/lm32/
 
 M68K
@@ -112,6 +140,7 @@
 S: Maintained
 F: target-microblaze/
 F: hw/microblaze/
+F: disas/microblaze.c
 
 MIPS
 M: Aurelien Jarno <aurelien@aurel32.net>
@@ -120,11 +149,13 @@
 F: target-mips/
 F: hw/mips/
 F: tests/tcg/mips/
+F: disas/mips.c
 
 Moxie
 M: Anthony Green <green@moxielogic.com>
 S: Maintained
 F: target-moxie/
+F: disas/moxie.c
 
 OpenRISC
 M: Jia Liu <proljc@gmail.com>
@@ -134,11 +165,13 @@
 F: tests/tcg/openrisc/
 
 PowerPC
+M: David Gibson <david@gibson.dropbear.id.au>
 M: Alexander Graf <agraf@suse.de>
 L: qemu-ppc@nongnu.org
 S: Maintained
 F: target-ppc/
 F: hw/ppc/
+F: disas/ppc.c
 
 S390
 M: Richard Henderson <rth@twiddle.net>
@@ -146,19 +179,23 @@
 S: Maintained
 F: target-s390x/
 F: hw/s390x/
+F: disas/s390.c
 
 SH4
 M: Aurelien Jarno <aurelien@aurel32.net>
 S: Odd Fixes
 F: target-sh4/
 F: hw/sh4/
+F: disas/sh4.c
 
 SPARC
-M: Blue Swirl <blauwirbel@gmail.com>
+M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+M: Artyom Tarasenko <atar4qemu@gmail.com>
 S: Maintained
 F: target-sparc/
 F: hw/sparc/
 F: hw/sparc64/
+F: disas/sparc.c
 
 UniCore32
 M: Guan Xuetao <gxt@mprc.pku.edu.cn>
@@ -169,9 +206,11 @@
 X86
 M: Paolo Bonzini <pbonzini@redhat.com>
 M: Richard Henderson <rth@twiddle.net>
-S: Odd Fixes
+M: Eduardo Habkost <ehabkost@redhat.com>
+S: Maintained
 F: target-i386/
 F: hw/i386/
+F: disas/i386.c
 
 Xtensa
 M: Max Filippov <jcmvbkbc@gmail.com>
@@ -196,9 +235,11 @@
 S: Supported
 F: kvm-*
 F: */kvm.*
+F: include/sysemu/kvm*.h
 
 ARM
 M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: target-arm/kvm.c
 
@@ -218,9 +259,14 @@
 M: Alexander Graf <agraf@suse.de>
 S: Maintained
 F: target-s390x/kvm.c
+F: target-s390x/ioinst.[ch]
+F: target-s390x/machine.c
 F: hw/intc/s390_flic.c
 F: hw/intc/s390_flic_kvm.c
 F: include/hw/s390x/s390_flic.h
+F: gdb-xml/s390*.xml
+T: git git://github.com/cohuck/qemu.git s390-next
+T: git git://github.com/borntraeger/qemu.git s390-next
 
 X86
 M: Paolo Bonzini <pbonzini@redhat.com>
@@ -233,11 +279,21 @@
 ----------------------
 
 X86
-M: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+M: Stefano Stabellini <sstabellini@kernel.org>
+M: Anthony Perard <anthony.perard@citrix.com>
 L: xen-devel@lists.xensource.com
 S: Supported
 F: xen-*
 F: */xen*
+F: hw/char/xen_console.c
+F: hw/display/xenfb.c
+F: hw/net/xen_nic.c
+F: hw/block/xen_*
+F: hw/xen/
+F: hw/xenpv/
+F: hw/i386/xen/
+F: include/hw/xen/
+F: include/sysemu/xen-mapcache.h
 
 Hosts:
 ------
@@ -258,99 +314,166 @@
 M: Stefan Weil <sw@weilnetz.de>
 S: Maintained
 F: *win32*
+F: qemu.nsi
 
 ARM Machines
 ------------
 Allwinner-a10
-M: Li Guang <lig.fnst@cn.fujitsu.com>
+M: Beniamino Galvani <b.galvani@gmail.com>
+L: qemu-arm@nongnu.org
 S: Maintained
-F: hw/*/allwinner-a10*
-F: include/hw/*/allwinner-a10*
+F: hw/*/allwinner*
+F: include/hw/*/allwinner*
 F: hw/arm/cubieboard.c
 
+ARM PrimeCell
+M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/char/pl011.c
+F: hw/display/pl110*
+F: hw/dma/pl080.c
+F: hw/dma/pl330.c
+F: hw/gpio/pl061.c
+F: hw/input/pl050.c
+F: hw/intc/pl190.c
+F: hw/sd/pl181.c
+F: hw/timer/pl031.c
+F: include/hw/arm/primecell.h
+
+ARM cores
+M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/intc/arm*
+F: hw/intc/gic_internal.h
+F: hw/misc/a9scu.c
+F: hw/misc/arm11scu.c
+F: hw/timer/a9gtimer*
+F: hw/timer/arm_*
+F: include/hw/arm/arm.h
+F: include/hw/intc/arm*
+F: include/hw/misc/a9scu.h
+F: include/hw/misc/arm11scu.h
+F: include/hw/timer/a9gtimer.h
+F: include/hw/timer/arm_mptimer.h
+
 Exynos
-M: Evgeny Voevodin <e.voevodin@samsung.com>
-M: Maksim Kozlov <m.kozlov@samsung.com>
 M: Igor Mitsyanko <i.mitsyanko@gmail.com>
-M: Dmitry Solodkiy <d.solodkiy@samsung.com>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/*/exynos*
+F: include/hw/arm/exynos4210.h
 
 Calxeda Highbank
 M: Rob Herring <robh@kernel.org>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/highbank.c
 F: hw/net/xgmac.c
 
 Canon DIGIC
 M: Antony Pavlov <antonynpavlov@gmail.com>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: include/hw/arm/digic.h
 F: hw/*/digic*
 
 Gumstix
 L: qemu-devel@nongnu.org
+L: qemu-arm@nongnu.org
 S: Orphan
 F: hw/arm/gumstix.c
 
 i.MX31
 M: Peter Chubb <peter.chubb@nicta.com.au>
+L: qemu-arm@nongnu.org
 S: Odd fixes
 F: hw/*/imx*
 F: hw/arm/kzm.c
+F: include/hw/arm/fsl-imx31.h
 
 Integrator CP
 M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/integratorcp.c
 
-Mainstone
-L: qemu-devel@nongnu.org
-S: Orphan
-F: hw/arm/mainstone.c
-
 Musicpal
 M: Jan Kiszka <jan.kiszka@web.de>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/musicpal.c
 
 nSeries
 M: Andrzej Zaborowski <balrogg@gmail.com>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/nseries.c
 
 Palm
 M: Andrzej Zaborowski <balrogg@gmail.com>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/palm.c
 
 Real View
 M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/arm/realview*
+F: hw/intc/realview_gic.c
+F: include/hw/intc/realview_gic.h
 
-Spitz
+PXA2XX
 M: Andrzej Zaborowski <balrogg@gmail.com>
+L: qemu-arm@nongnu.org
 S: Maintained
+F: hw/arm/mainstone.c
 F: hw/arm/spitz.c
+F: hw/arm/tosa.c
+F: hw/arm/z2.c
+F: hw/*/pxa2xx*
+F: include/hw/arm/pxa.h
 
 Stellaris
 M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/*/stellaris*
 
 Versatile PB
 M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
 S: Maintained
 F: hw/*/versatile*
 
 Xilinx Zynq
-M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+M: Alistair Francis <alistair.francis@xilinx.com>
+L: qemu-arm@nongnu.org
 S: Maintained
-F: hw/arm/xilinx_zynq.c
-F: hw/misc/zynq_slcr.c
+F: hw/*/xilinx_*
 F: hw/*/cadence_*
-F: hw/ssi/xilinx_spips.c
+F: hw/misc/zynq_slcr.c
+F: include/hw/xilinx.h
+X: hw/ssi/xilinx_*
+
+Xilinx ZynqMP
+M: Alistair Francis <alistair.francis@xilinx.com>
+M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/*/xlnx*.c
+F: include/hw/*/xlnx*.c
+
+ARM ACPI Subsystem
+M: Shannon Zhao <zhaoshenglong@huawei.com>
+M: Shannon Zhao <shannon.zhao@linaro.org>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/arm/virt-acpi-build.c
+F: include/hw/arm/virt-acpi-build.h
 
 CRIS Machines
 -------------
@@ -394,7 +517,7 @@
 F: hw/microblaze/petalogix_s3adsp1800_mmu.c
 
 petalogix_ml605
-M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
 S: Maintained
 F: hw/microblaze/petalogix_ml605_mmu.c
 
@@ -475,7 +598,7 @@
 F: hw/misc/macio/
 
 PReP
-M: Andreas Färber <andreas.faerber@web.de>
+L: qemu-devel@nongnu.org
 L: qemu-ppc@nongnu.org
 S: Odd Fixes
 F: hw/ppc/prep.c
@@ -483,6 +606,7 @@
 F: hw/isa/pc87312.[hc]
 
 sPAPR
+M: David Gibson <david@gibson.dropbear.id.au>
 M: Alexander Graf <agraf@suse.de>
 L: qemu-ppc@nongnu.org
 S: Supported
@@ -514,11 +638,13 @@
 --------------
 Sun4m
 M: Blue Swirl <blauwirbel@gmail.com>
+M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
 S: Maintained
 F: hw/sparc/sun4m.c
 
 Sun4u
 M: Blue Swirl <blauwirbel@gmail.com>
+M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
 S: Maintained
 F: hw/sparc64/sun4u.c
 
@@ -530,23 +656,18 @@
 
 S390 Machines
 -------------
-S390 Virtio
-M: Alexander Graf <agraf@suse.de>
-S: Maintained
-F: hw/s390x/s390-*.c
-
 S390 Virtio-ccw
 M: Cornelia Huck <cornelia.huck@de.ibm.com>
 M: Christian Borntraeger <borntraeger@de.ibm.com>
 M: Alexander Graf <agraf@suse.de>
 S: Supported
-F: hw/s390x/s390-virtio-ccw.c
-F: hw/s390x/css.[hc]
-F: hw/s390x/sclp*.[hc]
-F: hw/s390x/ipl*.[hc]
+F: hw/char/sclp*.[hc]
+F: hw/s390x/
 F: include/hw/s390x/
 F: pc-bios/s390-ccw/
-T: git git://github.com/cohuck/qemu virtio-ccw-upstr
+F: hw/watchdog/wdt_diag288.c
+T: git git://github.com/cohuck/qemu.git s390-next
+T: git git://github.com/borntraeger/qemu.git s390-next
 
 UniCore32 Machines
 -------------
@@ -559,7 +680,6 @@
 X86 Machines
 ------------
 PC
-M: Anthony Liguori <aliguori@amazon.com>
 M: Michael S. Tsirkin <mst@redhat.com>
 S: Supported
 F: include/hw/i386/
@@ -576,7 +696,32 @@
 F: hw/acpi/ich9.c
 F: include/hw/acpi/ich9.h
 F: include/hw/acpi/piix.h
+F: hw/misc/sga.c
 
+PC Chipset
+M: Michael S. Tsirkin <mst@redhat.com>
+M: Paolo Bonzini <pbonzini@redhat.com>
+S: Support
+F: hw/char/debugcon.c
+F: hw/char/parallel.c
+F: hw/char/serial*
+F: hw/dma/i8257*
+F: hw/i2c/pm_smbus.c
+F: hw/intc/apic*
+F: hw/intc/ioapic*
+F: hw/intc/i8259*
+F: hw/misc/debugexit.c
+F: hw/misc/pc-testdev.c
+F: hw/timer/hpet*
+F: hw/timer/i8254*
+F: hw/timer/mc146818rtc*
+
+Machine core
+M: Eduardo Habkost <ehabkost@redhat.com>
+M: Marcel Apfelbaum <marcel@redhat.com>
+S: Supported
+F: hw/core/machine.c
+F: include/hw/boards.h
 
 Xtensa Machines
 ---------------
@@ -593,24 +738,69 @@
 
 Devices
 -------
+EDU
+M: Jiri Slaby <jslaby@suse.cz>
+S: Maintained
+F: hw/misc/edu.c
+
 IDE
-M: Kevin Wolf <kwolf@redhat.com>
-M: Stefan Hajnoczi <stefanha@redhat.com>
-S: Odd Fixes
+M: John Snow <jsnow@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
 F: include/hw/ide.h
 F: hw/ide/
+F: hw/block/block.c
+F: hw/block/cdrom.c
+F: hw/block/hd-geometry.c
+F: tests/ide-test.c
+F: tests/ahci-test.c
+F: tests/libqos/ahci*
+T: git git://github.com/jnsnow/qemu.git ide
+
+Floppy
+M: John Snow <jsnow@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: hw/block/fdc.c
+F: include/hw/block/fdc.h
+F: tests/fdc-test.c
+T: git git://github.com/jnsnow/qemu.git ide
 
 OMAP
 M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: hw/*/omap*
+F: include/hw/arm/omap.h
+
+IPack
+M: Alberto Garcia <berto@igalia.com>
+S: Odd Fixes
+F: hw/char/ipoctal232.c
+F: hw/ipack/
 
 PCI
 M: Michael S. Tsirkin <mst@redhat.com>
+M: Marcel Apfelbaum <marcel@redhat.com>
 S: Supported
 F: include/hw/pci/*
+F: hw/misc/pci-testdev.c
 F: hw/pci/*
+F: hw/pci-bridge/*
+
+ACPI/SMBIOS
+M: Michael S. Tsirkin <mst@redhat.com>
+M: Igor Mammedov <imammedo@redhat.com>
+S: Supported
+F: include/hw/acpi/*
+F: include/hw/smbios/*
+F: hw/mem/*
 F: hw/acpi/*
+F: hw/smbios/*
+F: hw/i386/acpi-build.[hc]
+F: hw/i386/*dsl
+F: hw/arm/virt-acpi-build.c
+F: include/hw/arm/virt-acpi-build.h
+F: scripts/acpi*py
 
 ppc4xx
 M: Alexander Graf <agraf@suse.de>
@@ -624,6 +814,19 @@
 L: qemu-ppc@nongnu.org
 S: Supported
 F: hw/ppc/e500*
+F: hw/pci-host/ppce500.c
+F: hw/net/fsl_etsec/
+
+Character devices
+M: Paolo Bonzini <pbonzini@redhat.com>
+S: Odd Fixes
+F: hw/char/
+
+Network devices
+M: Jason Wang <jasowang@redhat.com>
+S: Odd Fixes
+F: hw/net/
+T: git git://github.com/jasowang/qemu.git net
 
 SCSI
 M: Paolo Bonzini <pbonzini@redhat.com>
@@ -637,16 +840,27 @@
 F: hw/scsi/lsi53c895a.c
 
 SSI
-M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
 S: Maintained
 F: hw/ssi/*
 F: hw/block/m25p80.c
+X: hw/ssi/xilinx_*
+
+Xilinx SPI
+M: Alistair Francis <alistair.francis@xilinx.com>
+M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
+S: Maintained
+F: hw/ssi/xilinx_*
 
 USB
 M: Gerd Hoffmann <kraxel@redhat.com>
 S: Maintained
 F: hw/usb/*
 F: tests/usb-*-test.c
+F: docs/usb2.txt
+F: docs/usb-storage.txt
+F: include/hw/usb.h
+F: include/hw/usb/
 
 USB (serial adapter)
 M: Gerd Hoffmann <kraxel@redhat.com>
@@ -657,7 +871,8 @@
 VFIO
 M: Alex Williamson <alex.williamson@redhat.com>
 S: Supported
-F: hw/misc/vfio.c
+F: hw/vfio/*
+F: include/hw/vfio/
 
 vhost
 M: Michael S. Tsirkin <mst@redhat.com>
@@ -665,56 +880,81 @@
 F: hw/*/*vhost*
 
 virtio
-M: Anthony Liguori <aliguori@amazon.com>
 M: Michael S. Tsirkin <mst@redhat.com>
 S: Supported
 F: hw/*/virtio*
+F: net/vhost-user.c
+F: include/hw/virtio/
 
 virtio-9p
 M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+M: Greg Kurz <groug@kaod.org>
 S: Supported
 F: hw/9pfs/
 F: fsdev/
 F: tests/virtio-9p-test.c
 T: git git://github.com/kvaneesh/QEMU.git
+T: git git://github.com/gkurz/qemu.git 9p-next
 
 virtio-blk
-M: Kevin Wolf <kwolf@redhat.com>
 M: Stefan Hajnoczi <stefanha@redhat.com>
+L: qemu-block@nongnu.org
 S: Supported
 F: hw/block/virtio-blk.c
+F: hw/block/dataplane/*
+F: hw/virtio/dataplane/*
+T: git git://github.com/stefanha/qemu.git block
 
 virtio-ccw
 M: Cornelia Huck <cornelia.huck@de.ibm.com>
 M: Christian Borntraeger <borntraeger@de.ibm.com>
 S: Supported
 F: hw/s390x/virtio-ccw.[hc]
-T: git git://github.com/cohuck/qemu virtio-ccw-upstr
+T: git git://github.com/cohuck/qemu.git s390-next
+T: git git://github.com/borntraeger/qemu.git s390-next
+
+virtio-input
+M: Gerd Hoffmann <kraxel@redhat.com>
+S: Maintained
+F: hw/input/virtio-input*.c
+F: include/hw/virtio/virtio-input.h
 
 virtio-serial
 M: Amit Shah <amit.shah@redhat.com>
 S: Supported
 F: hw/char/virtio-serial-bus.c
 F: hw/char/virtio-console.c
+F: include/hw/virtio/virtio-serial.h
+
+virtio-rng
+M: Amit Shah <amit.shah@redhat.com>
+S: Supported
+F: hw/virtio/virtio-rng.c
+F: include/hw/virtio/virtio-rng.h
+F: include/sysemu/rng*.h
+F: backends/rng*.c
 
 nvme
 M: Keith Busch <keith.busch@intel.com>
+L: qemu-block@nongnu.org
 S: Supported
 F: hw/block/nvme*
 F: tests/nvme-test.c
 
 megasas
 M: Hannes Reinecke <hare@suse.de>
+L: qemu-block@nongnu.org
 S: Supported
 F: hw/scsi/megasas.c
 F: hw/scsi/mfi.h
 
-Xilinx EDK
-M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
-M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+Network packet abstractions
+M: Dmitry Fleytman <dmitry@daynix.com>
 S: Maintained
-F: hw/*/xilinx_*
-F: include/hw/xilinx.h
+F: include/net/eth.h
+F: net/eth.c
+F: hw/net/net_rx_pkt*
+F: hw/net/net_tx_pkt*
 
 Vmware
 M: Dmitry Fleytman <dmitry@daynix.com>
@@ -722,10 +962,31 @@
 F: hw/net/vmxnet*
 F: hw/scsi/vmw_pvscsi*
 
+Rocker
+M: Jiri Pirko <jiri@resnulli.us>
+S: Maintained
+F: hw/net/rocker/
+
+NVDIMM
+M: Xiao Guangrong <guangrong.xiao@linux.intel.com>
+S: Maintained
+F: hw/acpi/nvdimm.c
+F: hw/mem/nvdimm.c
+F: include/hw/mem/nvdimm.h
+
+e1000x
+M: Dmitry Fleytman <dmitry@daynix.com>
+S: Maintained
+F: hw/net/e1000x*
+
+e1000e
+M: Dmitry Fleytman <dmitry@daynix.com>
+S: Maintained
+F: hw/net/e1000e*
+
 Subsystems
 ----------
 Audio
-M: Vassili Karpov (malc) <av1474@comtv.ru>
 M: Gerd Hoffmann <kraxel@redhat.com>
 S: Maintained
 F: audio/
@@ -734,24 +995,53 @@
 F: tests/es1370-test.c
 F: tests/intel-hda-test.c
 
-Block
+Block layer core
 M: Kevin Wolf <kwolf@redhat.com>
-M: Stefan Hajnoczi <stefanha@redhat.com>
+M: Max Reitz <mreitz@redhat.com>
+L: qemu-block@nongnu.org
 S: Supported
-F: async.c
-F: aio-*.c
 F: block*
 F: block/
 F: hw/block/
+F: include/block/
 F: qemu-img*
 F: qemu-io*
-F: tests/image-fuzzer/
 F: tests/qemu-iotests/
 T: git git://repo.or.cz/qemu/kevin.git block
+
+Block I/O path
+M: Stefan Hajnoczi <stefanha@redhat.com>
+M: Fam Zheng <famz@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: async.c
+F: aio-*.c
+F: block/io.c
+F: migration/block*
+F: include/block/aio.h
 T: git git://github.com/stefanha/qemu.git block
 
-Character Devices
-M: Anthony Liguori <aliguori@amazon.com>
+Block Jobs
+M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: blockjob.c
+F: include/block/blockjob.h
+F: block/backup.c
+F: block/commit.c
+F: block/stream.c
+F: block/mirror.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+
+Block QAPI, monitor, command line
+M: Markus Armbruster <armbru@redhat.com>
+S: Supported
+F: blockdev.c
+F: block/qapi.c
+F: qapi/block*.json
+T: git git://repo.or.cz/qemu/armbru.git block-next
+
+Character device backends
 M: Paolo Bonzini <pbonzini@redhat.com>
 S: Maintained
 F: qemu-char.c
@@ -763,12 +1053,16 @@
 S: Maintained
 F: backends/baum.c
 
+Coverity model
+M: Markus Armbruster <armbru@redhat.com>
+S: Supported
+F: scripts/coverity-model.c
+
 CPU
-M: Andreas Färber <afaerber@suse.de>
+L: qemu-devel@nongnu.org
 S: Supported
 F: qom/cpu.c
 F: include/qom/cpu.h
-F: target-i386/cpu.c
 
 ICC Bus
 M: Igor Mammedov <imammedo@redhat.com>
@@ -777,10 +1071,19 @@
 F: hw/cpu/icc_bus.c
 
 Device Tree
-M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
 M: Alexander Graf <agraf@suse.de>
 S: Maintained
-F: device_tree.[ch]
+F: device_tree.c
+F: include/sysemu/device_tree.h
+
+Error reporting
+M: Markus Armbruster <armbru@redhat.com>
+S: Supported
+F: include/qapi/error.h
+F: include/qemu/error-report.h
+F: util/error.c
+F: util/qemu-error.c
 
 GDB stub
 L: qemu-devel@nongnu.org
@@ -794,6 +1097,7 @@
 F: include/exec/ioport.h
 F: ioport.c
 F: include/exec/memory.h
+F: include/exec/ram_addr.h
 F: memory.c
 F: include/exec/memory-internal.h
 F: exec.c
@@ -802,24 +1106,23 @@
 M: Gerd Hoffmann <kraxel@redhat.com>
 S: Supported
 F: include/ui/qemu-spice.h
+F: include/ui/spice-display.h
 F: ui/spice-*.c
 F: audio/spiceaudio.c
 F: hw/display/qxl*
 
 Graphics
-M: Anthony Liguori <aliguori@amazon.com>
 M: Gerd Hoffmann <kraxel@redhat.com>
 S: Odd Fixes
 F: ui/
+F: include/ui/
 
 Cocoa graphics
-M: Andreas Färber <andreas.faerber@web.de>
 M: Peter Maydell <peter.maydell@linaro.org>
 S: Odd Fixes
 F: ui/cocoa.m
 
 Main loop
-M: Anthony Liguori <aliguori@amazon.com>
 M: Paolo Bonzini <pbonzini@redhat.com>
 S: Maintained
 F: cpus.c
@@ -835,12 +1138,12 @@
 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>
-M: Stefan Hajnoczi <stefanha@redhat.com>
+Network device backends
+M: Jason Wang <jasowang@redhat.com>
 S: Maintained
 F: net/
-T: git git://github.com/stefanha/qemu.git net
+F: include/net/
+T: git git://github.com/jasowang/qemu.git net
 
 Netmap network backend
 M: Luigi Rizzo <rizzo@iet.unipi.it>
@@ -853,31 +1156,62 @@
 Network Block Device (NBD)
 M: Paolo Bonzini <pbonzini@redhat.com>
 S: Odd Fixes
-F: block/nbd.c
-F: nbd.*
+F: block/nbd*
+F: nbd/
+F: include/block/nbd*
 F: qemu-nbd.c
 T: git git://github.com/bonzini/qemu.git nbd-next
 
-QAPI
-M: Luiz Capitulino <lcapitulino@redhat.com>
-M: Michael Roth <mdroth@linux.vnet.ibm.com>
+NUMA
+M: Eduardo Habkost <ehabkost@redhat.com>
 S: Maintained
+F: numa.c
+F: include/sysemu/numa.h
+T: git git://github.com/ehabkost/qemu.git numa
+
+Host Memory Backends
+M: Eduardo Habkost <ehabkost@redhat.com>
+M: Igor Mammedov <imammedo@redhat.com>
+S: Maintained
+F: backends/hostmem*.c
+F: include/sysemu/hostmem.h
+
+QAPI
+M: Markus Armbruster <armbru@redhat.com>
+M: Michael Roth <mdroth@linux.vnet.ibm.com>
+S: Supported
 F: qapi/
+X: qapi/*.json
+F: include/qapi/
+X: include/qapi/qmp/
+F: include/qapi/qmp/dispatch.h
 F: tests/qapi-schema/
-T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
+F: tests/test-*-visitor.c
+F: tests/test-qmp-*.c
+F: scripts/qapi*
+F: docs/qapi*
+T: git git://repo.or.cz/qemu/armbru.git qapi-next
 
 QAPI Schema
 M: Eric Blake <eblake@redhat.com>
-M: Luiz Capitulino <lcapitulino@redhat.com>
 M: Markus Armbruster <armbru@redhat.com>
 S: Supported
 F: qapi-schema.json
-T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
+F: qapi/*.json
+T: git git://repo.or.cz/qemu/armbru.git qapi-next
 
 QObject
 M: Luiz Capitulino <lcapitulino@redhat.com>
 S: Maintained
 F: qobject/
+F: include/qapi/qmp/
+X: include/qapi/qmp/dispatch.h
+F: tests/check-qdict.c
+F: tests/check-qfloat.c
+F: tests/check-qint.c
+F: tests/check-qjson.c
+F: tests/check-qlist.c
+F: tests/check-qstring.c
 T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
 
 QEMU Guest Agent
@@ -887,7 +1221,6 @@
 T: git git://github.com/mdroth/qemu.git qga
 
 QOM
-M: Anthony Liguori <aliguori@amazon.com>
 M: Andreas Färber <afaerber@suse.de>
 S: Supported
 T: git git://github.com/afaerber/qemu-cpu.git qom-next
@@ -895,21 +1228,33 @@
 X: include/qom/cpu.h
 F: qom/
 X: qom/cpu.c
+F: tests/check-qom-interface.c
+F: tests/check-qom-proplist.c
 F: tests/qom-test.c
 
 QMP
-M: Luiz Capitulino <lcapitulino@redhat.com>
-S: Maintained
+M: Markus Armbruster <armbru@redhat.com>
+S: Supported
 F: qmp.c
 F: monitor.c
 F: qmp-commands.hx
-F: QMP/
-T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
+F: docs/*qmp-*
+F: scripts/qmp/
+T: git git://repo.or.cz/qemu/armbru.git qapi-next
+
+Register API
+M: Alistair Francis <alistair.francis@xilinx.com>
+S: Maintained
+F: hw/core/register.c
+F: include/hw/register.h
 
 SLIRP
+M: Samuel Thibault <samuel.thibault@ens-lyon.org>
 M: Jan Kiszka <jan.kiszka@siemens.com>
 S: Maintained
 F: slirp/
+F: net/slirp.c
+F: include/net/slirp.h
 T: git git://git.kiszka.org/qemu.git queues/slirp
 
 Tracing
@@ -922,18 +1267,18 @@
 T: git git://github.com/stefanha/qemu.git tracing
 
 Checkpatch
-M: Blue Swirl <blauwirbel@gmail.com>
 S: Odd Fixes
 F: scripts/checkpatch.pl
 
 Migration
 M: Juan Quintela <quintela@redhat.com>
+M: Amit Shah <amit.shah@redhat.com>
 S: Maintained
 F: include/migration/
-F: migration*
-F: savevm.c
-F: arch_init.c
-F: vmstate.c
+F: migration/
+F: scripts/vmstate-static-checker.py
+F: tests/vmstate-static-checker-data/
+F: docs/migration.txt
 
 Seccomp
 M: Eduardo Otubo <eduardo.otubo@profitbricks.com>
@@ -941,6 +1286,50 @@
 F: qemu-seccomp.c
 F: include/sysemu/seccomp.h
 
+Cryptography
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Maintained
+F: crypto/
+F: include/crypto/
+F: tests/test-crypto-*
+
+Coroutines
+M: Stefan Hajnoczi <stefanha@redhat.com>
+M: Kevin Wolf <kwolf@redhat.com>
+F: util/*coroutine*
+F: include/qemu/coroutine*
+F: tests/test-coroutine.c
+
+Buffers
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Odd fixes
+F: util/buffer.c
+F: include/qemu/buffer.h
+
+I/O Channels
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Maintained
+F: io/
+F: include/io/
+F: tests/test-io-*
+
+Sockets
+M: Daniel P. Berrange <berrange@redhat.com>
+M: Gerd Hoffmann <kraxel@redhat.com>
+M: Paolo Bonzini <pbonzini@redhat.com>
+S: Maintained
+F: include/qemu/sockets.h
+F: util/qemu-sockets.c
+
+Throttling infrastructure
+M: Alberto Garcia <berto@igalia.com>
+S: Supported
+F: block/throttle-groups.c
+F: include/block/throttle-groups.h
+F: include/qemu/throttle.h
+F: util/throttle.c
+L: qemu-block@nongnu.org
+
 Usermode Emulation
 ------------------
 Overall
@@ -950,8 +1339,7 @@
 F: user-exec.c
 
 BSD user
-M: Blue Swirl <blauwirbel@gmail.com>
-S: Maintained
+S: Orphan
 F: bsd-user/
 
 Linux user
@@ -970,54 +1358,60 @@
 M: Claudio Fontana <claudio.fontana@huawei.com>
 M: Claudio Fontana <claudio.fontana@gmail.com>
 S: Maintained
+L: qemu-arm@nongnu.org
 F: tcg/aarch64/
+F: disas/arm-a64.cc
+F: disas/libvixl/
 
 ARM target
 M: Andrzej Zaborowski <balrogg@gmail.com>
 S: Maintained
+L: qemu-arm@nongnu.org
 F: tcg/arm/
+F: disas/arm.c
 
 i386 target
 L: qemu-devel@nongnu.org
 S: Maintained
 F: tcg/i386/
+F: disas/i386.c
 
 IA64 target
 M: Aurelien Jarno <aurelien@aurel32.net>
 S: Maintained
 F: tcg/ia64/
+F: disas/ia64.c
 
 MIPS target
 M: Aurelien Jarno <aurelien@aurel32.net>
 S: Maintained
 F: tcg/mips/
+F: disas/mips.c
 
 PPC
 M: Vassili Karpov (malc) <av1474@comtv.ru>
 S: Maintained
 F: tcg/ppc/
-
-PPC64 target
-M: Vassili Karpov (malc) <av1474@comtv.ru>
-S: Maintained
-F: tcg/ppc64/
+F: disas/ppc.c
 
 S390 target
 M: Alexander Graf <agraf@suse.de>
 M: Richard Henderson <rth@twiddle.net>
 S: Maintained
 F: tcg/s390/
+F: disas/s390.c
 
 SPARC target
-M: Blue Swirl <blauwirbel@gmail.com>
-S: Maintained
+S: Odd Fixes
 F: tcg/sparc/
+F: disas/sparc.c
 
 TCI target
 M: Stefan Weil <sw@weilnetz.de>
 S: Maintained
 F: tcg/tci/
 F: tci.c
+F: disas/tci.c
 
 Stable branches
 ---------------
@@ -1028,9 +1422,8 @@
 
 Stable 0.15
 L: qemu-stable@nongnu.org
-M: Andreas Färber <afaerber@suse.de>
 T: git git://git.qemu-project.org/qemu-stable-0.15.git
-S: Supported
+S: Orphan
 
 Stable 0.14
 L: qemu-stable@nongnu.org
@@ -1046,28 +1439,38 @@
 -------------
 VMDK
 M: Fam Zheng <famz@redhat.com>
+L: qemu-block@nongnu.org
 S: Supported
 F: block/vmdk.c
 
 RBD
-M: Josh Durgin <josh.durgin@inktank.com>
+M: Josh Durgin <jdurgin@redhat.com>
+M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
 S: Supported
 F: block/rbd.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
 
 Sheepdog
 M: Hitoshi Mitake <mitake.hitoshi@lab.ntt.co.jp>
 M: Liu Yuan <namei.unix@gmail.com>
+M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
 L: sheepdog@lists.wpkg.org
 S: Supported
 F: block/sheepdog.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
 
 VHDX
 M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
 S: Supported
 F: block/vhdx*
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
 
 VDI
 M: Stefan Weil <sw@weilnetz.de>
+L: qemu-block@nongnu.org
 S: Maintained
 F: block/vdi.c
 
@@ -1075,26 +1478,169 @@
 M: Ronnie Sahlberg <ronniesahlberg@gmail.com>
 M: Paolo Bonzini <pbonzini@redhat.com>
 M: Peter Lieven <pl@kamp.de>
+L: qemu-block@nongnu.org
 S: Supported
 F: block/iscsi.c
 
 NFS
+M: Jeff Cody <jcody@redhat.com>
 M: Peter Lieven <pl@kamp.de>
+L: qemu-block@nongnu.org
 S: Maintained
 F: block/nfs.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
 
 SSH
 M: Richard W.M. Jones <rjones@redhat.com>
+M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
 S: Supported
 F: block/ssh.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
 
 ARCHIPELAGO
-M: Chrysostomos Nanakos <cnanakos@grnet.gr>
 M: Chrysostomos Nanakos <chris@include.gr>
+M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
 S: Maintained
 F: block/archipelago.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+
+CURL
+M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/curl.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+
+GLUSTER
+M: Jeff Cody <jcody@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/gluster.c
+T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+
+Null Block Driver
+M: Fam Zheng <famz@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/null.c
 
 Bootdevice
 M: Gonglei <arei.gonglei@huawei.com>
 S: Maintained
 F: bootdevice.c
+
+Quorum
+M: Alberto Garcia <berto@igalia.com>
+S: Supported
+F: block/quorum.c
+L: qemu-block@nongnu.org
+
+blkverify
+M: Stefan Hajnoczi <stefanha@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/blkverify.c
+
+bochs
+M: Stefan Hajnoczi <stefanha@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/bochs.c
+
+cloop
+M: Stefan Hajnoczi <stefanha@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/cloop.c
+
+dmg
+M: Stefan Hajnoczi <stefanha@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/dmg.c
+
+parallels
+M: Stefan Hajnoczi <stefanha@redhat.com>
+M: Denis V. Lunev <den@openvz.org>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/parallels.c
+F: docs/specs/parallels.txt
+
+qed
+M: Stefan Hajnoczi <stefanha@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/qed.c
+
+raw
+M: Kevin Wolf <kwolf@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/linux-aio.c
+F: block/raw-aio.h
+F: block/raw-posix.c
+F: block/raw-win32.c
+F: block/raw_bsd.c
+F: block/win32-aio.c
+
+qcow2
+M: Kevin Wolf <kwolf@redhat.com>
+M: Max Reitz <mreitz@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/qcow2*
+
+qcow
+M: Kevin Wolf <kwolf@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/qcow.c
+
+blkdebug
+M: Kevin Wolf <kwolf@redhat.com>
+M: Max Reitz <mreitz@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/blkdebug.c
+
+vpc
+M: Kevin Wolf <kwolf@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/vpc.c
+
+vvfat
+M: Kevin Wolf <kwolf@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: block/vvfat.c
+
+Image format fuzzer
+M: Stefan Hajnoczi <stefanha@redhat.com>
+L: qemu-block@nongnu.org
+S: Supported
+F: tests/image-fuzzer/
+
+Build and test automation
+-------------------------
+M: Alex Bennée <alex.bennee@linaro.org>
+L: qemu-devel@nongnu.org
+S: Supported
+F: .travis.yml
+
+Documentation
+-------------
+Build system architecture
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Odd Fixes
+F: docs/build-system.txt
+
+Docker testing
+--------------
+Docker based testing framework and cases
+M: Fam Zheng <famz@redhat.com>
+S: Maintained
+F: tests/docker/
diff --git a/Makefile b/Makefile
index f505202..50b4b3a 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,11 @@
 # Always point to the root of the build tree (needs GNU make).
 BUILD_DIR=$(CURDIR)
 
+# Before including a proper config-host.mak, assume we are in the source tree
+SRC_PATH=.
+
+UNCHECKED_GOALS := %clean TAGS cscope ctags docker docker-%
+
 # All following code might depend on configuration variables
 ifneq ($(wildcard config-host.mak),)
 # Put the all: rule here so that config-host.mak can contain dependencies.
@@ -25,8 +30,7 @@
 -include config-all-devices.mak
 -include config-all-disas.mak
 
-include $(SRC_PATH)/rules.mak
-config-host.mak: $(SRC_PATH)/configure
+config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios
 	@echo $@ is out-of-date, running configure
 	@# TODO: The next lines include code which supports a smooth
 	@# transition from old configurations without config.status.
@@ -38,15 +42,19 @@
 	fi
 else
 config-host.mak:
-ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
+ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
 	@echo "Please call configure before running make!"
 	@exit 1
 endif
 endif
 
-GENERATED_HEADERS = config-host.h qemu-options.def
+include $(SRC_PATH)/rules.mak
+
+GENERATED_HEADERS = qemu-version.h config-host.h qemu-options.def
 GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
 GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
+GENERATED_HEADERS += qmp-introspect.h
+GENERATED_SOURCES += qmp-introspect.c
 
 GENERATED_HEADERS += trace/generated-events.h
 GENERATED_SOURCES += trace/generated-events.c
@@ -74,7 +82,7 @@
 configure: ;
 
 .PHONY: all clean cscope distclean dvi html info install install-doc \
-	pdf recurse-all speed test dist
+	pdf recurse-all speed test dist msi FORCE
 
 $(call set-vpath, $(SRC_PATH))
 
@@ -83,7 +91,8 @@
 HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
 
 ifdef BUILD_DOCS
-DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qmp-commands.txt
+DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
+DOCS+=qmp-commands.txt
 ifdef CONFIG_VIRTFS
 DOCS+=fsdev/virtfs-proxy-helper.1
 endif
@@ -108,9 +117,10 @@
 
 -include $(SUBDIR_DEVICES_MAK_DEP)
 
-%/config-devices.mak: default-configs/%.mak
-	$(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $@ $<, "  GEN   $@")
-	@if test -f $@; then \
+%/config-devices.mak: default-configs/%.mak $(SRC_PATH)/scripts/make_device_config.sh
+	$(call quiet-command, \
+            $(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp, "  GEN   $@.tmp")
+	$(call quiet-command, if test -f $@; then \
 	  if cmp -s $@.old $@; then \
 	    mv $@.tmp $@; \
 	    cp -p $@ $@.old; \
@@ -126,7 +136,7 @@
 	 else \
 	  mv $@.tmp $@; \
 	  cp -p $@ $@.old; \
-	 fi
+	 fi, "  GEN   $@");
 
 defconfig:
 	rm -f config-all-devices.mak $(SUBDIR_DEVICES_MAK)
@@ -139,30 +149,55 @@
                 stub-obj-y \
                 util-obj-y \
                 qga-obj-y \
+                ivshmem-client-obj-y \
+                ivshmem-server-obj-y \
                 qga-vss-dll-obj-y \
                 block-obj-y \
                 block-obj-m \
+                crypto-obj-y \
+                crypto-aes-obj-y \
+                qom-obj-y \
+                io-obj-y \
                 common-obj-y \
                 common-obj-m)
 
 ifneq ($(wildcard config-host.mak),)
-include $(SRC_PATH)/tests/Makefile
-endif
-ifeq ($(CONFIG_SMARTCARD_NSS),y)
-include $(SRC_PATH)/libcacard/Makefile
+include $(SRC_PATH)/tests/Makefile.include
 endif
 
 all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
 
+qemu-version.h: FORCE
+	$(call quiet-command, \
+		(cd $(SRC_PATH); \
+		printf '#define QEMU_PKGVERSION '; \
+		if test -n "$(PKGVERSION)"; then \
+			printf '"$(PKGVERSION)"\n'; \
+		else \
+			if test -d .git; then \
+				printf '" ('; \
+				git describe --match 'v*' 2>/dev/null | tr -d '\n'; \
+				if ! git diff-index --quiet HEAD &>/dev/null; then \
+					printf -- '-dirty'; \
+				fi; \
+				printf ')"\n'; \
+			else \
+				printf '""\n'; \
+			fi; \
+		fi) > $@.tmp)
+	$(call quiet-command, cmp -s $@ $@.tmp || mv $@.tmp $@)
+
 config-host.h: config-host.h-timestamp
 config-host.h-timestamp: config-host.mak
-qemu-options.def: $(SRC_PATH)/qemu-options.hx
+qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
 SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
 SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
 
 $(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
+$(SOFTMMU_SUBDIR_RULES): $(crypto-obj-y)
+$(SOFTMMU_SUBDIR_RULES): $(io-obj-y)
 $(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
 
 subdir-%:
@@ -187,19 +222,20 @@
 dtc/%:
 	mkdir -p $@
 
-$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y)
+$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
 
 ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
+# Only keep -O and -g cflags
 romsubdir-%:
-	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pc-bios/$* V="$(V)" TARGET_DIR="$*/",)
+	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pc-bios/$* V="$(V)" TARGET_DIR="$*/" CFLAGS="$(filter -O% -g%,$(CFLAGS))",)
 
 ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
 
 recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
 
-$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h | $(BUILD_DIR)/version.lo
+$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc config-host.h | $(BUILD_DIR)/version.lo
 	$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"  RC    version.o")
-$(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h
+$(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc config-host.h
 	$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"  RC    version.lo")
 
 Makefile: $(version-obj-y) $(version-lobj-y)
@@ -217,16 +253,16 @@
 
 qemu-img.o: qemu-img-cmds.h
 
-qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-io$(EXESUF): qemu-io.o $(block-obj-y) libqemuutil.a libqemustub.a
+qemu-img$(EXESUF): qemu-img.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
+qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
+qemu-io$(EXESUF): qemu-io.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
 
-qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
+qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o libqemuutil.a libqemustub.a
 
-fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o libqemuutil.a libqemustub.a
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o libqemuutil.a libqemustub.a
 fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 
-qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
+qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
@@ -239,42 +275,49 @@
 qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
 $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
-		$(gen-out-type) -o qga/qapi-generated -p "qga-" -i $<, \
+		$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
 		"  GEN   $@")
 qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\
 $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
-		$(gen-out-type) -o qga/qapi-generated -p "qga-" -i $<, \
+		$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
 		"  GEN   $@")
 qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
 $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
-		$(gen-out-type) -o qga/qapi-generated -p "qga-" -i $<, \
+		$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
 		"  GEN   $@")
 
 qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
-               $(SRC_PATH)/qapi/event.json
+               $(SRC_PATH)/qapi/event.json $(SRC_PATH)/qapi/introspect.json \
+               $(SRC_PATH)/qapi/crypto.json $(SRC_PATH)/qapi/rocker.json \
+               $(SRC_PATH)/qapi/trace.json
 
 qapi-types.c qapi-types.h :\
 $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
-		$(gen-out-type) -o "." -b -i $<, \
+		$(gen-out-type) -o "." -b $<, \
 		"  GEN   $@")
 qapi-visit.c qapi-visit.h :\
 $(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
-		$(gen-out-type) -o "." -b -i $<, \
+		$(gen-out-type) -o "." -b $<, \
 		"  GEN   $@")
 qapi-event.c qapi-event.h :\
 $(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
-		$(gen-out-type) -o "." -b -i $<, \
+		$(gen-out-type) -o "." $<, \
 		"  GEN   $@")
 qmp-commands.h qmp-marshal.c :\
 $(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
-		$(gen-out-type) -o "." -m -i $<, \
+		$(gen-out-type) -o "." -m $<, \
+		"  GEN   $@")
+qmp-introspect.h qmp-introspect.c :\
+$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
+		$(gen-out-type) -o "." $<, \
 		"  GEN   $@")
 
 QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
@@ -283,15 +326,44 @@
 qemu-ga$(EXESUF): $(qga-obj-y) libqemuutil.a libqemustub.a
 	$(call LINK, $^)
 
+ifdef QEMU_GA_MSI_ENABLED
+QEMU_GA_MSI=qemu-ga-$(ARCH).msi
+
+msi: $(QEMU_GA_MSI)
+
+$(QEMU_GA_MSI): qemu-ga.exe $(QGA_VSS_PROVIDER)
+
+$(QEMU_GA_MSI): config-host.mak
+
+$(QEMU_GA_MSI):  $(SRC_PATH)/qga/installer/qemu-ga.wxs
+	$(call quiet-command,QEMU_GA_VERSION="$(QEMU_GA_VERSION)" QEMU_GA_MANUFACTURER="$(QEMU_GA_MANUFACTURER)" QEMU_GA_DISTRO="$(QEMU_GA_DISTRO)" BUILD_DIR="$(BUILD_DIR)" \
+	wixl -o $@ $(QEMU_GA_MSI_ARCH) $(QEMU_GA_MSI_WITH_VSS) $(QEMU_GA_MSI_MINGW_DLL_PATH) $<, "  WIXL  $@")
+else
+msi:
+	@echo "MSI build not configured or dependency resolution failed (reconfigure with --enable-guest-agent-msi option)"
+endif
+
+ifneq ($(EXESUF),)
+.PHONY: qemu-ga
+qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
+endif
+
+ivshmem-client$(EXESUF): $(ivshmem-client-obj-y) libqemuutil.a libqemustub.a
+	$(call LINK, $^)
+ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) libqemuutil.a libqemustub.a
+	$(call LINK, $^)
+
 clean:
 # avoid old build problems by removing potentially incorrect old files
 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
 	rm -f qemu-options.def
+	rm -f *.msi
 	find . \( -name '*.l[oa]' -o -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
 	rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
 	rm -f fsdev/*.pod
 	rm -rf .libs */.libs
 	rm -f qemu-img-cmds.h
+	rm -f ui/shader/*-vert.h ui/shader/*-frag.h
 	@# May not be present in GENERATED_HEADERS
 	rm -f trace/generated-tracers-dtrace.dtrace*
 	rm -f trace/generated-tracers-dtrace.h*
@@ -303,6 +375,7 @@
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
 	rm -f $$d/qemu-options.def; \
         done
+	rm -f $(SUBDIR_DEVICES_MAK) config-all-devices.mak
 
 VERSION ?= $(shell cat VERSION)
 
@@ -312,9 +385,9 @@
 	$(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)"
 
 distclean: clean
-	rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi
-	rm -f config-all-devices.mak config-all-disas.mak
-	rm -f po/*.mo
+	rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi qemu-monitor-info.texi
+	rm -f config-all-devices.mak config-all-disas.mak config.status
+	rm -f po/*.mo tests/qemu-iotests/common.env
 	rm -f roms/seabios/config.mak roms/vgabios/config.mak
 	rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.cps qemu-doc.dvi
 	rm -f qemu-doc.fn qemu-doc.fns qemu-doc.info qemu-doc.ky qemu-doc.kys
@@ -327,8 +400,8 @@
 	rm -rf $$d || exit 1 ; \
         done
 	rm -Rf .sdk
-	if test -f pixman/config.log; then make -C pixman distclean; fi
-	if test -f dtc/version_gen.h; then make $(DTC_MAKE_ARGS) clean; fi
+	if test -f pixman/config.log; then $(MAKE) -C pixman distclean; fi
+	if test -f dtc/version_gen.h; then $(MAKE) $(DTC_MAKE_ARGS) clean; fi
 
 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 \
@@ -337,17 +410,17 @@
 
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
-vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
-acpi-dsdt.aml q35-acpi-dsdt.aml \
+vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin \
+acpi-dsdt.aml \
 ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \
 pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
 pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
 efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
 efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \
+efi-e1000e.rom efi-vmxnet3.rom \
 qemu-icon.bmp qemu_logo_no_text.svg \
 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
-multiboot.bin linuxboot.bin kvmvapic.bin \
-s390-zipl.rom \
+multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \
 s390-ccw.img \
 spapr-rtas.bin slof.bin \
 palcode-clipper \
@@ -368,6 +441,9 @@
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
 	$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
 endif
+ifneq (,$(findstring qemu-ga,$(TOOLS)))
+	$(INSTALL_DATA) qemu-ga.8 "$(DESTDIR)$(mandir)/man8"
+endif
 endif
 ifdef CONFIG_VIRTFS
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
@@ -384,16 +460,11 @@
 endif
 endif
 
-install-confdir:
-	$(INSTALL_DIR) "$(DESTDIR)$(qemu_confdir)"
 
-install-sysconfig: install-datadir install-confdir
-	$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)"
-
-install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig \
+install: all $(if $(BUILD_DOCS),install-doc) \
 install-datadir install-localstatedir
 ifneq ($(TOOLS),)
-	$(call install-prog,$(TOOLS),$(DESTDIR)$(bindir))
+	$(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir))
 endif
 ifneq ($(CONFIG_MODULES),)
 	$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
@@ -418,7 +489,7 @@
 	set -e; for x in $(KEYMAPS); do \
 		$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
 	done
-	$(INSTALL_DATA) $(SRC_PATH)/trace-events "$(DESTDIR)$(qemu_datadir)/trace-events"
+	$(INSTALL_DATA) $(BUILD_DIR)/trace-events-all "$(DESTDIR)$(qemu_datadir)/trace-events-all"
 	for d in $(TARGET_DIRS); do \
 	$(MAKE) $(SUBDIR_MAKEFLAGS) TARGET_DIR=$$d/ -C $$d $@ || exit 1 ; \
         done
@@ -427,15 +498,36 @@
 test speed: all
 	$(MAKE) -C tests/tcg $@
 
+.PHONY: ctags
+ctags:
+	rm -f tags
+	find "$(SRC_PATH)" -name '*.[hc]' -exec ctags --append {} +
+
 .PHONY: TAGS
 TAGS:
-	rm -f $@
+	rm -f TAGS
 	find "$(SRC_PATH)" -name '*.[hc]' -exec etags --append {} +
 
 cscope:
-	rm -f ./cscope.*
-	find "$(SRC_PATH)" -name "*.[chsS]" -print | sed 's,^\./,,' > ./cscope.files
-	cscope -b
+	rm -f "$(SRC_PATH)"/cscope.*
+	find "$(SRC_PATH)/" -name "*.[chsS]" -print | sed 's,^\./,,' > "$(SRC_PATH)/cscope.files"
+	cscope -b -i"$(SRC_PATH)/cscope.files"
+
+# opengl shader programs
+ui/shader/%-vert.h: $(SRC_PATH)/ui/shader/%.vert $(SRC_PATH)/scripts/shaderinclude.pl
+	@mkdir -p $(dir $@)
+	$(call quiet-command,\
+		perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\
+		"  VERT  $@")
+
+ui/shader/%-frag.h: $(SRC_PATH)/ui/shader/%.frag $(SRC_PATH)/scripts/shaderinclude.pl
+	@mkdir -p $(dir $@)
+	$(call quiet-command,\
+		perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\
+		"  FRAG  $@")
+
+ui/console-gl.o: $(SRC_PATH)/ui/console-gl.c \
+	ui/shader/texture-blit-vert.h ui/shader/texture-blit-frag.h
 
 # documentation
 MAKEINFO=makeinfo
@@ -454,25 +546,29 @@
 %.pdf: %.texi
 	$(call quiet-command,texi2pdf $(TEXIFLAG) -I . $<,"  GEN   $@")
 
-qemu-options.texi: $(SRC_PATH)/qemu-options.hx
+qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
-qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx
+qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
-qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
+qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
+	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
+
+qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@,"  GEN   $@")
 
-qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
+qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
-qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi
+qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu.pod && \
 	  $(POD2MAN) --section=1 --center=" " --release=" " qemu.pod > $@, \
 	  "  GEN   $@")
+qemu.1: qemu-option-trace.texi
 
-qemu-img.1: qemu-img.texi qemu-img-cmds.texi
+qemu-img.1: qemu-img.texi qemu-option-trace.texi qemu-img-cmds.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-img.pod && \
 	  $(POD2MAN) --section=1 --center=" " --release=" " qemu-img.pod > $@, \
@@ -484,20 +580,27 @@
 	  $(POD2MAN) --section=1 --center=" " --release=" " fsdev/virtfs-proxy-helper.pod > $@, \
 	  "  GEN   $@")
 
-qemu-nbd.8: qemu-nbd.texi
+qemu-nbd.8: qemu-nbd.texi qemu-option-trace.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
 	  $(POD2MAN) --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
 	  "  GEN   $@")
 
+qemu-ga.8: qemu-ga.texi
+	$(call quiet-command, \
+	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-ga.pod && \
+	  $(POD2MAN) --section=8 --center=" " --release=" " qemu-ga.pod > $@, \
+	  "  GEN   $@")
+
 dvi: qemu-doc.dvi qemu-tech.dvi
 html: qemu-doc.html qemu-tech.html
 info: qemu-doc.info qemu-tech.info
 pdf: qemu-doc.pdf qemu-tech.pdf
 
 qemu-doc.dvi qemu-doc.html qemu-doc.info qemu-doc.pdf: \
-	qemu-img.texi qemu-nbd.texi qemu-options.texi \
-	qemu-monitor.texi qemu-img-cmds.texi
+	qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-option-trace.texi \
+	qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
+	qemu-monitor-info.texi
 
 ifdef CONFIG_WIN32
 
@@ -522,7 +625,7 @@
 INSTDIR=/tmp/qemu-nsis
 
 $(INSTALLER): $(SRC_PATH)/qemu.nsi
-	make install prefix=${INSTDIR}
+	$(MAKE) install prefix=${INSTDIR}
 ifdef SIGNCODE
 	(cd ${INSTDIR}; \
          for i in *.exe; do \
@@ -547,6 +650,7 @@
                 $(if $(DLL_PATH),-DDLLDIR="$(DLL_PATH)") \
                 -DSRCDIR="$(SRC_PATH)" \
                 -DOUTFILE="$(INSTALLER)" \
+                -DDISPLAYVERSION="$(VERSION)" \
                 $(SRC_PATH)/qemu.nsi
 	rm -r ${INSTDIR}
 ifdef SIGNCODE
@@ -556,10 +660,12 @@
 
 # Add a dependency on the generated files, so that they are always
 # rebuilt before other object files
-ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
+ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
 Makefile: $(GENERATED_HEADERS)
 endif
 
 # Include automatically generated dependency files
 # Dependencies in Makefile.objs files come from our recursive subdir rules
 -include $(wildcard *.d tests/*.d)
+
+include $(SRC_PATH)/tests/docker/Makefile.include
diff --git a/Makefile.objs b/Makefile.objs
index 18fd35c..297600a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -1,37 +1,38 @@
 #######################################################################
 # Common libraries for tools and emulators
-stub-obj-y = stubs/
-util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o qapi-event.o
+stub-obj-y = stubs/ crypto/
+util-obj-y = util/ qobject/ qapi/
+util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
 
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
 block-obj-y = async.o thread-pool.o
-block-obj-y += nbd.o block.o blockjob.o
+block-obj-y += nbd/
+block-obj-y += block.o blockjob.o
 block-obj-y += main-loop.o iohandler.o qemu-timer.o
 block-obj-$(CONFIG_POSIX) += aio-posix.o
 block-obj-$(CONFIG_WIN32) += aio-win32.o
 block-obj-y += block/
 block-obj-y += qemu-io-cmds.o
 
-block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
-block-obj-y += qemu-coroutine-sleep.o
-block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
-
 block-obj-m = block/
 
+#######################################################################
+# crypto-obj-y is code used by both qemu system emulation and qemu-img
 
-######################################################################
-# smartcard
+crypto-obj-y = crypto/
+crypto-aes-obj-y = crypto/
 
-libcacard-y += libcacard/cac.o libcacard/event.o
-libcacard-y += libcacard/vcard.o libcacard/vreader.o
-libcacard-y += libcacard/vcard_emul_nss.o
-libcacard-y += libcacard/vcard_emul_type.o
-libcacard-y += libcacard/card_7816.o
-libcacard-y += libcacard/vcardt.o
-libcacard/vcard_emul_nss.o-cflags := $(NSS_CFLAGS)
-libcacard/vcard_emul_nss.o-libs := $(NSS_LIBS)
+#######################################################################
+# qom-obj-y is code used by both qemu system emulation and qemu-img
+
+qom-obj-y = qom/
+
+#######################################################################
+# io-obj-y is code used by both qemu system emulation and qemu-img
+
+io-obj-y = io/
 
 ######################################################################
 # Target independent part of system emulation. The long term path is to
@@ -48,15 +49,9 @@
 
 common-obj-$(CONFIG_LINUX) += fsdev/
 
-common-obj-y += migration.o migration-tcp.o
-common-obj-y += vmstate.o
-common-obj-y += qemu-file.o qemu-file-unix.o qemu-file-stdio.o
-common-obj-$(CONFIG_RDMA) += migration-rdma.o
+common-obj-y += migration/
 common-obj-y += qemu-char.o #aio.o
-common-obj-y += block-migration.o
-common-obj-y += page_cache.o xbzrle.o
-
-common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
+common-obj-y += page_cache.o
 
 common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
 
@@ -64,6 +59,8 @@
 common-obj-y += hw/
 common-obj-y += accel.o
 
+common-obj-y += replay/
+
 common-obj-y += ui/
 common-obj-y += bt-host.o bt-vhci.o
 bt-host.o-cflags := $(BLUEZ_CFLAGS)
@@ -71,6 +68,7 @@
 common-obj-y += dma-helpers.o
 common-obj-y += vl.o
 vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
+vl.o-cflags += -DALLOW_CONFIG_ANDROID
 common-obj-y += tpm.o
 
 common-obj-$(CONFIG_SLIRP) += slirp/
@@ -79,18 +77,18 @@
 
 common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
 
-common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
+common-obj-$(CONFIG_FDT) += device_tree.o
 
 ######################################################################
 # qapi
 
 common-obj-y += qmp-marshal.o
+common-obj-y += qmp-introspect.o
 common-obj-y += qmp.o hmp.o
 endif
 
 #######################################################################
 # Target-independent parts used in system and user emulation
-common-obj-y += qemu-log.o
 common-obj-y += tcg-runtime.o
 common-obj-y += hw/
 common-obj-y += qom/
@@ -113,3 +111,52 @@
 # by libqemuutil.a.  These should be moved to a separate .json schema.
 qga-obj-y = qga/
 qga-vss-dll-obj-y = qga/
+
+######################################################################
+# contrib
+ivshmem-client-obj-y = contrib/ivshmem-client/
+ivshmem-server-obj-y = contrib/ivshmem-server/
+
+
+######################################################################
+trace-events-y = trace-events
+trace-events-y += util/trace-events
+trace-events-y += crypto/trace-events
+trace-events-y += io/trace-events
+trace-events-y += migration/trace-events
+trace-events-y += block/trace-events
+trace-events-y += hw/block/trace-events
+trace-events-y += hw/char/trace-events
+trace-events-y += hw/intc/trace-events
+trace-events-y += hw/net/trace-events
+trace-events-y += hw/virtio/trace-events
+trace-events-y += hw/audio/trace-events
+trace-events-y += hw/misc/trace-events
+trace-events-y += hw/usb/trace-events
+trace-events-y += hw/scsi/trace-events
+trace-events-y += hw/nvram/trace-events
+trace-events-y += hw/display/trace-events
+trace-events-y += hw/input/trace-events
+trace-events-y += hw/timer/trace-events
+trace-events-y += hw/dma/trace-events
+trace-events-y += hw/sparc/trace-events
+trace-events-y += hw/sd/trace-events
+trace-events-y += hw/isa/trace-events
+trace-events-y += hw/i386/trace-events
+trace-events-y += hw/9pfs/trace-events
+trace-events-y += hw/ppc/trace-events
+trace-events-y += hw/pci/trace-events
+trace-events-y += hw/s390x/trace-events
+trace-events-y += hw/vfio/trace-events
+trace-events-y += hw/acpi/trace-events
+trace-events-y += hw/arm/trace-events
+trace-events-y += hw/alpha/trace-events
+trace-events-y += ui/trace-events
+trace-events-y += audio/trace-events
+trace-events-y += net/trace-events
+trace-events-y += target-i386/trace-events
+trace-events-y += target-sparc/trace-events
+trace-events-y += target-s390x/trace-events
+trace-events-y += target-ppc/trace-events
+trace-events-y += qom/trace-events
+trace-events-y += linux-user/trace-events
diff --git a/Makefile.target b/Makefile.target
index 523602b..9bd4c2e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,11 +1,13 @@
 # -*- Mode: makefile -*-
 
+BUILD_DIR?=$(CURDIR)/..
+
 include ../config-host.mak
 include config-target.mak
 include config-devices.mak
 include $(SRC_PATH)/rules.mak
 
-$(call set-vpath, $(SRC_PATH))
+$(call set-vpath, $(SRC_PATH):$(BUILD_DIR))
 ifdef CONFIG_LINUX
 QEMU_CFLAGS += -I../linux-headers
 endif
@@ -46,7 +48,7 @@
 TARGET_TYPE=system
 endif
 
-$(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
+$(QEMU_PROG).stp-installed: $(BUILD_DIR)/trace-events-all
 	$(call quiet-command,$(TRACETOOL) \
 		--format=stap \
 		--backends=$(TRACE_BACKENDS) \
@@ -55,7 +57,7 @@
 		--target-type=$(TARGET_TYPE) \
 		< $< > $@,"  GEN   $(TARGET_DIR)$(QEMU_PROG).stp-installed")
 
-$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
+$(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all
 	$(call quiet-command,$(TRACETOOL) \
 		--format=stap \
 		--backends=$(TRACE_BACKENDS) \
@@ -64,7 +66,7 @@
 		--target-type=$(TARGET_TYPE) \
 		< $< > $@,"  GEN   $(TARGET_DIR)$(QEMU_PROG).stp")
 
-$(QEMU_PROG)-simpletrace.stp: $(SRC_PATH)/trace-events
+$(QEMU_PROG)-simpletrace.stp: $(BUILD_DIR)/trace-events-all
 	$(call quiet-command,$(TRACETOOL) \
 		--format=simpletrace-stap \
 		--backends=$(TRACE_BACKENDS) \
@@ -83,8 +85,11 @@
 #########################################################
 # cpu emulator library
 obj-y = exec.o translate-all.o cpu-exec.o
+obj-y += translate-common.o
+obj-y += cpu-exec-common.o
 obj-y += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
 obj-$(CONFIG_TCG_INTERPRETER) += tci.o
+obj-y += tcg/tcg-common.o
 obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
 obj-y += fpu/softfloat.o
 obj-y += target-$(TARGET_BASE_ARCH)/
@@ -103,7 +108,9 @@
 
 ifdef CONFIG_LINUX_USER
 
-QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
+QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \
+             -I$(SRC_PATH)/linux-user/host/$(ARCH) \
+             -I$(SRC_PATH)/linux-user
 
 obj-y += linux-user/
 obj-y += gdbstub.o thunk.o user-exec.o
@@ -129,12 +136,12 @@
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
 obj-y += qtest.o bootdevice.o
 obj-y += hw/
-obj-$(CONFIG_FDT) += device_tree.o
 obj-$(CONFIG_KVM) += kvm-all.o
-obj-y += memory.o savevm.o cputlb.o
+obj-y += memory.o cputlb.o
 obj-y += memory_mapping.o
 obj-y += dump.o
-LIBS+=$(libs_softmmu)
+obj-y += migration/ram.o migration/savevm.o
+LIBS := $(libs_softmmu) $(LIBS)
 
 # xen support
 obj-$(CONFIG_XEN) += xen-common.o
@@ -142,14 +149,16 @@
 obj-$(call lnot,$(CONFIG_XEN)) += xen-common-stub.o
 obj-$(call lnot,$(CONFIG_XEN_I386)) += xen-hvm-stub.o
 
-# HAX support
-ifdef CONFIG_WIN32
-obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-slot.o target-i386/hax-windows.o
+# HAX support, only when targetting i386 or x86_64
+ifeq (y,$(CONFIG_HAX))
+ifneq (,$(filter i386 x86_64,$(TARGET_NAME))
+obj-y += target-i386/hax-all.o target-i386/hax-slot.o
+obj-$(CONFIG_WIN32) += target-i386/hax-windows.o
+obj-$(CONFIG_DARWIN) += target-i386/hax-darwin.o
+else
+obj-y += hax-stub.o
 endif
-ifdef CONFIG_DARWIN
-obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-slot.o target-i386/hax-darwin.o
-endif
-obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
+endif # CONFIG_HAX
 
 # Hardware support
 ifeq ($(TARGET_NAME), sparc64)
@@ -158,7 +167,7 @@
 obj-y += hw/$(TARGET_BASE_ARCH)/
 endif
 
-GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
+GENERATED_HEADERS += hmp-commands.h hmp-commands-info.h qmp-commands-old.h
 
 endif # CONFIG_SOFTMMU
 
@@ -177,24 +186,41 @@
 dummy := $(call unnest-vars,.., \
                block-obj-y \
                block-obj-m \
+               crypto-obj-y \
+               crypto-aes-obj-y \
+               qom-obj-y \
+               io-obj-y \
                common-obj-y \
                common-obj-m)
 target-obj-y := $(target-obj-y-save)
 all-obj-y += $(common-obj-y)
 all-obj-y += $(target-obj-y)
+all-obj-y += $(qom-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
+all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
+all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
+all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
+
+$(QEMU_PROG_BUILD): config-devices.mak
 
 # build either PROG or PROGW
 $(QEMU_PROG_BUILD): $(all-obj-y) ../libqemuutil.a ../libqemustub.a
-	$(call LINK,$^)
+	$(call LINK, $(filter-out %.mak, $^))
+ifdef CONFIG_DARWIN
+	$(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o $@,"  REZ   $(TARGET_DIR)$@")
+	$(call quiet-command,SetFile -a C $@,"  SETFILE $(TARGET_DIR)$@")
+endif
 
 gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
 	$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"  GEN   $(TARGET_DIR)$@")
 
-hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
+hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
-qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx
+hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
+	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
+
+qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
 clean:
diff --git a/README b/README
index c7c990d..f38193f 100644
--- a/README
+++ b/README
@@ -1,3 +1,107 @@
-Read the documentation in qemu-doc.html or on http://wiki.qemu-project.org
+         QEMU README
+         ===========
 
-- QEMU team
+QEMU is a generic and open source machine & userspace emulator and
+virtualizer.
+
+QEMU is capable of emulating a complete machine in software without any
+need for hardware virtualization support. By using dynamic translation,
+it achieves very good performance. QEMU can also integrate with the Xen
+and KVM hypervisors to provide emulated hardware while allowing the
+hypervisor to manage the CPU. With hypervisor support, QEMU can achieve
+near native performance for CPUs. When QEMU emulates CPUs directly it is
+capable of running operating systems made for one machine (e.g. an ARMv7
+board) on a different machine (e.g. an x86_64 PC board).
+
+QEMU is also capable of providing userspace API virtualization for Linux
+and BSD kernel interfaces. This allows binaries compiled against one
+architecture ABI (e.g. the Linux PPC64 ABI) to be run on a host using a
+different architecture ABI (e.g. the Linux x86_64 ABI). This does not
+involve any hardware emulation, simply CPU and syscall emulation.
+
+QEMU aims to fit into a variety of use cases. It can be invoked directly
+by users wishing to have full control over its behaviour and settings.
+It also aims to facilitate integration into higher level management
+layers, by providing a stable command line interface and monitor API.
+It is commonly invoked indirectly via the libvirt library when using
+open source applications such as oVirt, OpenStack and virt-manager.
+
+QEMU as a whole is released under the GNU General Public License,
+version 2. For full licensing details, consult the LICENSE file.
+
+
+Building
+========
+
+QEMU is multi-platform software intended to be buildable on all modern
+Linux platforms, OS-X, Win32 (via the Mingw64 toolchain) and a variety
+of other UNIX targets. The simple steps to build QEMU are:
+
+  mkdir build
+  cd build
+  ../configure
+  make
+
+Complete details of the process for building and configuring QEMU for
+all supported host platforms can be found in the qemu-tech.html file.
+Additional information can also be found online via the QEMU website:
+
+  http://qemu-project.org/Hosts/Linux
+  http://qemu-project.org/Hosts/W32
+
+
+Submitting patches
+==================
+
+The QEMU source code is maintained under the GIT version control system.
+
+   git clone git://git.qemu-project.org/qemu.git
+
+When submitting patches, the preferred approach is to use 'git
+format-patch' and/or 'git send-email' to format & send the mail to the
+qemu-devel@nongnu.org mailing list. All patches submitted must contain
+a 'Signed-off-by' line from the author. Patches should follow the
+guidelines set out in the HACKING and CODING_STYLE files.
+
+Additional information on submitting patches can be found online via
+the QEMU website
+
+  http://qemu-project.org/Contribute/SubmitAPatch
+  http://qemu-project.org/Contribute/TrivialPatches
+
+
+Bug reporting
+=============
+
+The QEMU project uses Launchpad as its primary upstream bug tracker. Bugs
+found when running code built from QEMU git or upstream released sources
+should be reported via:
+
+  https://bugs.launchpad.net/qemu/
+
+If using QEMU via an operating system vendor pre-built binary package, it
+is preferable to report bugs to the vendor's own bug tracker first. If
+the bug is also known to affect latest upstream code, it can also be
+reported via launchpad.
+
+For additional information on bug reporting consult:
+
+  http://qemu-project.org/Contribute/ReportABug
+
+
+Contact
+=======
+
+The QEMU community can be contacted in a number of ways, with the two
+main methods being email and IRC
+
+ - qemu-devel@nongnu.org
+   http://lists.nongnu.org/mailman/listinfo/qemu-devel
+ - #qemu on irc.oftc.net
+
+Information on additional methods of contacting the community can be
+found online via the QEMU website:
+
+  http://qemu-project.org/Contribute/StartHere
+
+-- End
diff --git a/VERSION b/VERSION
index ccbccc3..24ba9a3 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.0
+2.7.0
diff --git a/accel.c b/accel.c
index 8dc588f..6745813 100644
--- a/accel.c
+++ b/accel.c
@@ -23,6 +23,7 @@
  * THE SOFTWARE.
  */
 
+#include "qemu/osdep.h"
 #include "sysemu/accel.h"
 #include "hw/boards.h"
 #include "qemu-common.h"
@@ -121,14 +122,13 @@
         if (!init_failed) {
             fprintf(stderr, "No accelerator found!\n");
         }
-        return 1;
+        return -1;
     }
 
     if (init_failed) {
         fprintf(stderr, "Back to %s accelerator.\n", acc->name);
     }
-
-    return !accel_initialised;
+    return 0;
 }
 
 
diff --git a/aio-posix.c b/aio-posix.c
index d3ac06e..43162a9 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -13,10 +13,14 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "block/block.h"
 #include "qemu/queue.h"
 #include "qemu/sockets.h"
+#ifdef CONFIG_EPOLL_CREATE1
+#include <sys/epoll.h>
+#endif
 
 struct AioHandler
 {
@@ -24,11 +28,167 @@
     IOHandler *io_read;
     IOHandler *io_write;
     int deleted;
-    int pollfds_idx;
     void *opaque;
+    bool is_external;
     QLIST_ENTRY(AioHandler) node;
 };
 
+#ifdef CONFIG_EPOLL_CREATE1
+
+/* The fd number threashold to switch to epoll */
+#define EPOLL_ENABLE_THRESHOLD 64
+
+static void aio_epoll_disable(AioContext *ctx)
+{
+    ctx->epoll_available = false;
+    if (!ctx->epoll_enabled) {
+        return;
+    }
+    ctx->epoll_enabled = false;
+    close(ctx->epollfd);
+}
+
+static inline int epoll_events_from_pfd(int pfd_events)
+{
+    return (pfd_events & G_IO_IN ? EPOLLIN : 0) |
+           (pfd_events & G_IO_OUT ? EPOLLOUT : 0) |
+           (pfd_events & G_IO_HUP ? EPOLLHUP : 0) |
+           (pfd_events & G_IO_ERR ? EPOLLERR : 0);
+}
+
+static bool aio_epoll_try_enable(AioContext *ctx)
+{
+    AioHandler *node;
+    struct epoll_event event;
+
+    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
+        int r;
+        if (node->deleted || !node->pfd.events) {
+            continue;
+        }
+        event.events = epoll_events_from_pfd(node->pfd.events);
+        event.data.ptr = node;
+        r = epoll_ctl(ctx->epollfd, EPOLL_CTL_ADD, node->pfd.fd, &event);
+        if (r) {
+            return false;
+        }
+    }
+    ctx->epoll_enabled = true;
+    return true;
+}
+
+static void aio_epoll_update(AioContext *ctx, AioHandler *node, bool is_new)
+{
+    struct epoll_event event;
+    int r;
+
+    if (!ctx->epoll_enabled) {
+        return;
+    }
+    if (!node->pfd.events) {
+        r = epoll_ctl(ctx->epollfd, EPOLL_CTL_DEL, node->pfd.fd, &event);
+        if (r) {
+            aio_epoll_disable(ctx);
+        }
+    } else {
+        event.data.ptr = node;
+        event.events = epoll_events_from_pfd(node->pfd.events);
+        if (is_new) {
+            r = epoll_ctl(ctx->epollfd, EPOLL_CTL_ADD, node->pfd.fd, &event);
+            if (r) {
+                aio_epoll_disable(ctx);
+            }
+        } else {
+            r = epoll_ctl(ctx->epollfd, EPOLL_CTL_MOD, node->pfd.fd, &event);
+            if (r) {
+                aio_epoll_disable(ctx);
+            }
+        }
+    }
+}
+
+static int aio_epoll(AioContext *ctx, GPollFD *pfds,
+                     unsigned npfd, int64_t timeout)
+{
+    AioHandler *node;
+    int i, ret = 0;
+    struct epoll_event events[128];
+
+    assert(npfd == 1);
+    assert(pfds[0].fd == ctx->epollfd);
+    if (timeout > 0) {
+        ret = qemu_poll_ns(pfds, npfd, timeout);
+    }
+    if (timeout <= 0 || ret > 0) {
+        ret = epoll_wait(ctx->epollfd, events,
+                         sizeof(events) / sizeof(events[0]),
+                         timeout);
+        if (ret <= 0) {
+            goto out;
+        }
+        for (i = 0; i < ret; i++) {
+            int ev = events[i].events;
+            node = events[i].data.ptr;
+            node->pfd.revents = (ev & EPOLLIN ? G_IO_IN : 0) |
+                (ev & EPOLLOUT ? G_IO_OUT : 0) |
+                (ev & EPOLLHUP ? G_IO_HUP : 0) |
+                (ev & EPOLLERR ? G_IO_ERR : 0);
+        }
+    }
+out:
+    return ret;
+}
+
+static bool aio_epoll_enabled(AioContext *ctx)
+{
+    /* Fall back to ppoll when external clients are disabled. */
+    return !aio_external_disabled(ctx) && ctx->epoll_enabled;
+}
+
+static bool aio_epoll_check_poll(AioContext *ctx, GPollFD *pfds,
+                                 unsigned npfd, int64_t timeout)
+{
+    if (!ctx->epoll_available) {
+        return false;
+    }
+    if (aio_epoll_enabled(ctx)) {
+        return true;
+    }
+    if (npfd >= EPOLL_ENABLE_THRESHOLD) {
+        if (aio_epoll_try_enable(ctx)) {
+            return true;
+        } else {
+            aio_epoll_disable(ctx);
+        }
+    }
+    return false;
+}
+
+#else
+
+static void aio_epoll_update(AioContext *ctx, AioHandler *node, bool is_new)
+{
+}
+
+static int aio_epoll(AioContext *ctx, GPollFD *pfds,
+                     unsigned npfd, int64_t timeout)
+{
+    assert(false);
+}
+
+static bool aio_epoll_enabled(AioContext *ctx)
+{
+    return false;
+}
+
+static bool aio_epoll_check_poll(AioContext *ctx, GPollFD *pfds,
+                          unsigned npfd, int64_t timeout)
+{
+    return false;
+}
+
+#endif
+
 static AioHandler *find_aio_handler(AioContext *ctx, int fd)
 {
     AioHandler *node;
@@ -44,11 +204,14 @@
 
 void aio_set_fd_handler(AioContext *ctx,
                         int fd,
+                        bool is_external,
                         IOHandler *io_read,
                         IOHandler *io_write,
                         void *opaque)
 {
     AioHandler *node;
+    bool is_new = false;
+    bool deleted = false;
 
     node = find_aio_handler(ctx, fd);
 
@@ -67,37 +230,43 @@
                  * releasing the walking_handlers lock.
                  */
                 QLIST_REMOVE(node, node);
-                g_free(node);
+                deleted = true;
             }
         }
     } else {
         if (node == NULL) {
             /* Alloc and insert if it's not already there */
-            node = g_malloc0(sizeof(AioHandler));
+            node = g_new0(AioHandler, 1);
             node->pfd.fd = fd;
             QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
 
             g_source_add_poll(&ctx->source, &node->pfd);
+            is_new = true;
         }
         /* Update handler with latest information */
         node->io_read = io_read;
         node->io_write = io_write;
         node->opaque = opaque;
-        node->pollfds_idx = -1;
+        node->is_external = is_external;
 
         node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0);
         node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0);
     }
 
+    aio_epoll_update(ctx, node, is_new);
     aio_notify(ctx);
+    if (deleted) {
+        g_free(node);
+    }
 }
 
 void aio_set_event_notifier(AioContext *ctx,
                             EventNotifier *notifier,
+                            bool is_external,
                             EventNotifierHandler *io_read)
 {
     aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
-                       (IOHandler *)io_read, NULL, notifier);
+                       is_external, (IOHandler *)io_read, NULL, notifier);
 }
 
 bool aio_prepare(AioContext *ctx)
@@ -113,10 +282,12 @@
         int revents;
 
         revents = node->pfd.revents & node->pfd.events;
-        if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
+        if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read &&
+            aio_node_check(ctx, node->is_external)) {
             return true;
         }
-        if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
+        if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write &&
+            aio_node_check(ctx, node->is_external)) {
             return true;
         }
     }
@@ -154,6 +325,7 @@
 
         if (!node->deleted &&
             (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
+            aio_node_check(ctx, node->is_external) &&
             node->io_read) {
             node->io_read(node->opaque);
 
@@ -164,6 +336,7 @@
         }
         if (!node->deleted &&
             (revents & (G_IO_OUT | G_IO_ERR)) &&
+            aio_node_check(ctx, node->is_external) &&
             node->io_write) {
             node->io_write(node->opaque);
             progress = true;
@@ -186,69 +359,142 @@
     return progress;
 }
 
+/* These thread-local variables are used only in a small part of aio_poll
+ * around the call to the poll() system call.  In particular they are not
+ * used while aio_poll is performing callbacks, which makes it much easier
+ * to think about reentrancy!
+ *
+ * Stack-allocated arrays would be perfect but they have size limitations;
+ * heap allocation is expensive enough that we want to reuse arrays across
+ * calls to aio_poll().  And because poll() has to be called without holding
+ * any lock, the arrays cannot be stored in AioContext.  Thread-local data
+ * has none of the disadvantages of these three options.
+ */
+static __thread GPollFD *pollfds;
+static __thread AioHandler **nodes;
+static __thread unsigned npfd, nalloc;
+static __thread Notifier pollfds_cleanup_notifier;
+
+static void pollfds_cleanup(Notifier *n, void *unused)
+{
+    g_assert(npfd == 0);
+    g_free(pollfds);
+    g_free(nodes);
+    nalloc = 0;
+}
+
+static void add_pollfd(AioHandler *node)
+{
+    if (npfd == nalloc) {
+        if (nalloc == 0) {
+            pollfds_cleanup_notifier.notify = pollfds_cleanup;
+            qemu_thread_atexit_add(&pollfds_cleanup_notifier);
+            nalloc = 8;
+        } else {
+            g_assert(nalloc <= INT_MAX);
+            nalloc *= 2;
+        }
+        pollfds = g_renew(GPollFD, pollfds, nalloc);
+        nodes = g_renew(AioHandler *, nodes, nalloc);
+    }
+    nodes[npfd] = node;
+    pollfds[npfd] = (GPollFD) {
+        .fd = node->pfd.fd,
+        .events = node->pfd.events,
+    };
+    npfd++;
+}
+
 bool aio_poll(AioContext *ctx, bool blocking)
 {
     AioHandler *node;
-    bool was_dispatching;
-    int ret;
+    int i, ret;
     bool progress;
+    int64_t timeout;
 
-    was_dispatching = ctx->dispatching;
+    aio_context_acquire(ctx);
     progress = false;
 
     /* aio_notify can avoid the expensive event_notifier_set if
      * everything (file descriptors, bottom halves, timers) will
      * be re-evaluated before the next blocking poll().  This is
      * already true when aio_poll is called with blocking == false;
-     * if blocking == true, it is only true after poll() returns.
-     *
-     * If we're in a nested event loop, ctx->dispatching might be true.
-     * In that case we can restore it just before returning, but we
-     * have to clear it now.
+     * if blocking == true, it is only true after poll() returns,
+     * so disable the optimization now.
      */
-    aio_set_dispatching(ctx, !blocking);
+    if (blocking) {
+        atomic_add(&ctx->notify_me, 2);
+    }
 
     ctx->walking_handlers++;
 
-    g_array_set_size(ctx->pollfds, 0);
+    assert(npfd == 0);
 
     /* fill pollfds */
     QLIST_FOREACH(node, &ctx->aio_handlers, node) {
-        node->pollfds_idx = -1;
-        if (!node->deleted && node->pfd.events) {
-            GPollFD pfd = {
-                .fd = node->pfd.fd,
-                .events = node->pfd.events,
-            };
-            node->pollfds_idx = ctx->pollfds->len;
-            g_array_append_val(ctx->pollfds, pfd);
+        if (!node->deleted && node->pfd.events
+            && !aio_epoll_enabled(ctx)
+            && aio_node_check(ctx, node->is_external)) {
+            add_pollfd(node);
         }
     }
 
-    ctx->walking_handlers--;
+    timeout = blocking ? aio_compute_timeout(ctx) : 0;
 
     /* wait until next event */
-    ret = qemu_poll_ns((GPollFD *)ctx->pollfds->data,
-                         ctx->pollfds->len,
-                         blocking ? aio_compute_timeout(ctx) : 0);
+    if (timeout) {
+        aio_context_release(ctx);
+    }
+    if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
+        AioHandler epoll_handler;
+
+        epoll_handler.pfd.fd = ctx->epollfd;
+        epoll_handler.pfd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
+        npfd = 0;
+        add_pollfd(&epoll_handler);
+        ret = aio_epoll(ctx, pollfds, npfd, timeout);
+    } else  {
+        ret = qemu_poll_ns(pollfds, npfd, timeout);
+    }
+    if (blocking) {
+        atomic_sub(&ctx->notify_me, 2);
+    }
+    if (timeout) {
+        aio_context_acquire(ctx);
+    }
+
+    aio_notify_accept(ctx);
 
     /* if we have any readable fds, dispatch event */
     if (ret > 0) {
-        QLIST_FOREACH(node, &ctx->aio_handlers, node) {
-            if (node->pollfds_idx != -1) {
-                GPollFD *pfd = &g_array_index(ctx->pollfds, GPollFD,
-                                              node->pollfds_idx);
-                node->pfd.revents = pfd->revents;
-            }
+        for (i = 0; i < npfd; i++) {
+            nodes[i]->pfd.revents = pollfds[i].revents;
         }
     }
 
+    npfd = 0;
+    ctx->walking_handlers--;
+
     /* Run dispatch even if there were no readable fds to run timers */
-    aio_set_dispatching(ctx, true);
     if (aio_dispatch(ctx)) {
         progress = true;
     }
 
-    aio_set_dispatching(ctx, was_dispatching);
+    aio_context_release(ctx);
+
     return progress;
 }
+
+void aio_context_setup(AioContext *ctx)
+{
+#ifdef CONFIG_EPOLL_CREATE1
+    assert(!ctx->epollfd);
+    ctx->epollfd = epoll_create1(EPOLL_CLOEXEC);
+    if (ctx->epollfd == -1) {
+        fprintf(stderr, "Failed to create epoll instance: %s", strerror(errno));
+        ctx->epoll_available = false;
+    } else {
+        ctx->epoll_available = true;
+    }
+#endif
+}
diff --git a/aio-win32.c b/aio-win32.c
index d81313b..c8c249e 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -15,6 +15,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "block/block.h"
 #include "qemu/queue.h"
@@ -28,11 +29,13 @@
     GPollFD pfd;
     int deleted;
     void *opaque;
+    bool is_external;
     QLIST_ENTRY(AioHandler) node;
 };
 
 void aio_set_fd_handler(AioContext *ctx,
                         int fd,
+                        bool is_external,
                         IOHandler *io_read,
                         IOHandler *io_write,
                         void *opaque)
@@ -67,7 +70,7 @@
 
         if (node == NULL) {
             /* Alloc and insert if it's not already there */
-            node = g_malloc0(sizeof(AioHandler));
+            node = g_new0(AioHandler, 1);
             node->pfd.fd = fd;
             QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
         }
@@ -86,6 +89,7 @@
         node->opaque = opaque;
         node->io_read = io_read;
         node->io_write = io_write;
+        node->is_external = is_external;
 
         event = event_notifier_get_handle(&ctx->notifier);
         WSAEventSelect(node->pfd.fd, event,
@@ -98,6 +102,7 @@
 
 void aio_set_event_notifier(AioContext *ctx,
                             EventNotifier *e,
+                            bool is_external,
                             EventNotifierHandler *io_notify)
 {
     AioHandler *node;
@@ -129,10 +134,11 @@
     } else {
         if (node == NULL) {
             /* Alloc and insert if it's not already there */
-            node = g_malloc0(sizeof(AioHandler));
+            node = g_new0(AioHandler, 1);
             node->e = e;
             node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
             node->pfd.events = G_IO_IN;
+            node->is_external = is_external;
             QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
 
             g_source_add_poll(&ctx->source, &node->pfd);
@@ -279,36 +285,33 @@
 {
     AioHandler *node;
     HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
-    bool was_dispatching, progress, have_select_revents, first;
+    bool progress, have_select_revents, first;
     int count;
     int timeout;
 
-    have_select_revents = aio_prepare(ctx);
-    if (have_select_revents) {
-        blocking = false;
-    }
-
-    was_dispatching = ctx->dispatching;
+    aio_context_acquire(ctx);
     progress = false;
 
     /* aio_notify can avoid the expensive event_notifier_set if
      * everything (file descriptors, bottom halves, timers) will
      * be re-evaluated before the next blocking poll().  This is
      * already true when aio_poll is called with blocking == false;
-     * if blocking == true, it is only true after poll() returns.
-     *
-     * If we're in a nested event loop, ctx->dispatching might be true.
-     * In that case we can restore it just before returning, but we
-     * have to clear it now.
+     * if blocking == true, it is only true after poll() returns,
+     * so disable the optimization now.
      */
-    aio_set_dispatching(ctx, !blocking);
+    if (blocking) {
+        atomic_add(&ctx->notify_me, 2);
+    }
+
+    have_select_revents = aio_prepare(ctx);
 
     ctx->walking_handlers++;
 
     /* fill fd sets */
     count = 0;
     QLIST_FOREACH(node, &ctx->aio_handlers, node) {
-        if (!node->deleted && node->io_notify) {
+        if (!node->deleted && node->io_notify
+            && aio_node_check(ctx, node->is_external)) {
             events[count++] = event_notifier_get_handle(node->e);
         }
     }
@@ -316,20 +319,36 @@
     ctx->walking_handlers--;
     first = true;
 
-    /* wait until next event */
-    while (count > 0) {
+    /* ctx->notifier is always registered.  */
+    assert(count > 0);
+
+    /* Multiple iterations, all of them non-blocking except the first,
+     * may be necessary to process all pending events.  After the first
+     * WaitForMultipleObjects call ctx->notify_me will be decremented.
+     */
+    do {
         HANDLE event;
         int ret;
 
-        timeout = blocking
+        timeout = blocking && !have_select_revents
             ? qemu_timeout_ns_to_ms(aio_compute_timeout(ctx)) : 0;
-        ret = WaitForMultipleObjects(count, events, FALSE, timeout);
-        aio_set_dispatching(ctx, true);
-
-        if (first && aio_bh_poll(ctx)) {
-            progress = true;
+        if (timeout) {
+            aio_context_release(ctx);
         }
-        first = false;
+        ret = WaitForMultipleObjects(count, events, FALSE, timeout);
+        if (blocking) {
+            assert(first);
+            atomic_sub(&ctx->notify_me, 2);
+        }
+        if (timeout) {
+            aio_context_acquire(ctx);
+        }
+
+        if (first) {
+            aio_notify_accept(ctx);
+            progress |= aio_bh_poll(ctx);
+            first = false;
+        }
 
         /* if we have any signaled events, dispatch event */
         event = NULL;
@@ -344,10 +363,14 @@
         blocking = false;
 
         progress |= aio_dispatch_handlers(ctx, event);
-    }
+    } while (count > 0);
 
     progress |= timerlistgroup_run_timers(&ctx->tlg);
 
-    aio_set_dispatching(ctx, was_dispatching);
+    aio_context_release(ctx);
     return progress;
 }
+
+void aio_context_setup(AioContext *ctx)
+{
+}
diff --git a/android-commands.h b/android-commands.h
deleted file mode 100644
index e612bb0..0000000
--- a/android-commands.h
+++ /dev/null
@@ -1,522 +0,0 @@
-
-/* hand-written for now; consider .hx autogen */
-
-static mon_cmd_t android_redir_cmds[] = {
-    {
-        .name = "list",
-        .args_type = "",
-        .params = "",
-        .help = "list current redirections",
-        .mhandler.cmd = android_console_redir_list,
-    },
-    {
-        .name = "add",
-        .args_type = "arg:s",
-        .params = "[tcp|udp]:hostport:guestport",
-        .help = "add new redirection",
-        .mhandler.cmd = android_console_redir_add,
-    },
-    {
-        .name = "del",
-        .args_type = "arg:s",
-        .params = "[tcp|udp]:hostport",
-        .help = "remove existing redirection",
-        .mhandler.cmd = android_console_redir_del,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_power_cmds[] = {
-    {
-        .name = "display",
-        .args_type = "",
-        .params = "",
-        .help = "display battery and charger state",
-        .mhandler.cmd = android_console_power_display,
-    },
-    {
-        .name = "ac",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "set AC charging state",
-        .mhandler.cmd = android_console_power_ac,
-    },
-    {
-        .name = "status",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "set battery status",
-        .mhandler.cmd = android_console_power_status,
-    },
-    {
-        .name = "present",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "set battery present state",
-        .mhandler.cmd = android_console_power_present,
-    },
-    {
-        .name = "health",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "set battery health state",
-        .mhandler.cmd = android_console_power_health,
-    },
-    {
-        .name = "capacity",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "set battery capacity state",
-        .mhandler.cmd = android_console_power_capacity,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_event_cmds[] = {
-    {
-        .name = "types",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "list all <type> aliases",
-        .mhandler.cmd = android_console_event_types,
-    },
-    {
-        .name = "codes",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "list all <code> aliases for a given <type>",
-        .mhandler.cmd = android_console_event_codes,
-    },
-    {
-        .name = "send",
-        .args_type  = "arg:s?",
-        .params = "",
-        .help = "send a series of events to the kernel",
-        .mhandler.cmd = android_console_event_send,
-    },
-    {
-        .name = "text",
-        .args_type  = "arg:S?",
-        .params = "",
-        .help = "simulate keystrokes from a given text",
-        .mhandler.cmd = android_console_event_text,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_avd_snapshot_cmds[] = {
-    {
-        .name = "list",
-        .args_type = "",
-        .params = "",
-        .help = "'avd snapshot list' will show a list of all state snapshots "
-                "that can be loaded",
-        .mhandler.cmd = android_console_avd_snapshot_list,
-    },
-    {
-        .name = "save",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "'avd snapshot save <name>' will save the current (run-time) "
-                "state to a snapshot with the given name",
-        .mhandler.cmd = android_console_avd_snapshot_save,
-    },
-    {
-        .name = "load",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "'avd snapshot load <name>' will load the state snapshot of "
-                "the given name",
-        .mhandler.cmd = android_console_avd_snapshot_load,
-    },
-    {
-        .name = "del",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "'avd snapshot del <name>' will delete the state snapshot with "
-                "the given name",
-        .mhandler.cmd = android_console_avd_snapshot_del,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_avd_cmds[] = {
-    {
-        .name = "stop",
-        .args_type = "",
-        .params = "",
-        .help = "stop the virtual device",
-        .mhandler.cmd = android_console_avd_stop,
-    },
-    {
-        .name = "start",
-        .args_type = "",
-        .params = "",
-        .help = "start/restart the virtual device",
-        .mhandler.cmd = android_console_avd_start,
-    },
-    {
-        .name = "status",
-        .args_type = "",
-        .params = "",
-        .help = "query virtual device status",
-        .mhandler.cmd = android_console_avd_status,
-    },
-    {
-        .name = "name",
-        .args_type = "",
-        .params = "",
-        .help = "query virtual device name",
-        .mhandler.cmd = android_console_avd_name,
-    },
-    {
-        .name = "snapshot",
-        .args_type = "item:s",
-        .params = "",
-        .help = "state snapshot commands",
-        .mhandler.cmd = android_console_avd_snapshot,
-        .sub_cmds.static_table = android_avd_snapshot_cmds,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_finger_cmds[] = {
-    {
-        .name = "touch",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "touch fingerprint sensor with <fingerid>",
-        .mhandler.cmd = android_console_finger_touch,
-    },
-    {
-        .name = "remove",
-        .args_type = "",
-        .params = "",
-        .help = "remove finger from the fingerprint sensor",
-        .mhandler.cmd = android_console_finger_remove,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_geo_cmds[] = {
-    {
-        .name = "nmea",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "send a GPS NMEA sentence\n"
-            "'geo nema <sentence>' sends an NMEA 0183 sentence to the emulated device, as\n"
-            "if it came from an emulated GPS modem. <sentence> must begin with '$GP'. Only\n"
-            "'$GPGGA' and '$GPRCM' sentences are supported at the moment.\n",
-        .mhandler.cmd = android_console_geo_nmea,
-    },
-    {
-        .name = "fix",
-        .args_type = "arg:S?",
-        .params = "",
-        .help = "send a simple GPS fix\n"
-            "'geo fix <longitude> <latitude> [<altitude> [<satellites>]]'\n"
-            " allows you to send a simple GPS fix to the emulated system.\n"
-            " The parameters are:\n\n"
-            "  <longitude>   longitude, in decimal degrees\n"
-            "  <latitude>    latitude, in decimal degrees\n"
-            "  <altitude>    optional altitude in meters\n"
-            "  <satellites>  number of satellites being tracked (1-12)\n"
-            "\n",
-        .mhandler.cmd = android_console_geo_fix,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_sms_cmds[] = {
-    {
-        .name = "send",
-        .args_type = "arg:S?",
-        .params = "",
-        .help = "send inbound SMS text message\n"
-            "'sms send <phonenumber> <message>' allows you to simulate a new inbound sms message\n",
-        .mhandler.cmd = android_console_sms_send,
-    },
-    {
-        .name = "pdu",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "send inbound SMS PDU\n"
-            "'sms pdu <hexstring>' allows you to simulate a new inbound sms PDU\n"
-             "(used internally when one emulator sends SMS messages to another instance).\n"
-             "you probably don't want to play with this at all\n"
-             "\n",
-        .mhandler.cmd = android_console_sms_pdu,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_cdma_cmds[] = {
-    {
-        .name = "ssource",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "set the current CDMA subscription source\n"
-            "'cdma ssource <ssource>' allows you to specify where to read the subscription from\n",
-        .mhandler.cmd = android_console_cdma_ssource,
-    },
-    {
-        .name = "prl_version",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "dump the current PRL version\n"
-        "'cdma prl_version <version>' allows you to dump the current PRL version\n",
-        .mhandler.cmd = android_console_cdma_prl_version,
-    },
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_gsm_cmds[] = {
-    {
-        .name = "list",
-        .args_type = "",
-        .params = "",
-        .help = "list current phone calls\n"
-            "'gsm list' lists all inbound and outbound calls and their state\n",
-        .mhandler.cmd = android_console_gsm_list,
-    },
-    {
-        .name = "call",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "create inbound phone call\n"
-            "'gsm call <phonenumber>' allows you to simulate a new inbound call\n",
-        .mhandler.cmd = android_console_gsm_call,
-    },
-    {
-        .name = "busy",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "close waiting outbound call as busy\n"
-            "'gsm busy <phonenumber>' closes an outbound call, reporting\n"
-    "the remote phone as busy. only possible if the call is 'waiting'.\n",
-        .mhandler.cmd = android_console_gsm_busy,
-    },
-    {
-        .name = "hold",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "change the state of an outbound call to 'held'\n"
-            "'gsm hold <remoteNumber>' change the state of a call to 'held'. this is only possible\n"
-    "if the call in the 'waiting' or 'active' state\n",
-        .mhandler.cmd = android_console_gsm_hold,
-    },
-    {
-        .name = "accept",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "change the state of an outbound call to 'active'\n"
-            "'gsm accept <remoteNumber>' change the state of a call to 'active'. this is only possible\n"
-    "if the call is in the 'waiting' or 'held' state\n",
-        .mhandler.cmd = android_console_gsm_accept,
-    },
-    {
-        .name = "cancel",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "disconnect an inbound or outbound phone call\n"
-            "'gsm cancel <phonenumber>' allows you to simulate the end of an inbound or outbound call\n",
-        .mhandler.cmd = android_console_gsm_cancel,
-    },
-    {
-        .name = "data",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "modify data connection state"
-            "'gsm data <state>' allows you to modify the data connection state\n",
-        .mhandler.cmd = android_console_gsm_data,
-    },
-    {
-        .name = "voice",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "modify voice connection state"
-            "'gsm voice <state>' allows you to modify the voice connection state\n",
-        .mhandler.cmd = android_console_gsm_voice,
-    },
-    {
-        .name = "status",
-        .args_type = "",
-        .params = "",
-        .help = "display GSM status"
-            "'gsm status' displays the current state of the GSM emulation\n",
-        .mhandler.cmd = android_console_gsm_status,
-    },
-    {
-        .name = "signal",
-        .args_type = "arg:S?",
-        .params = "",
-        .help = "sets the rssi and ber"
-                "signal <rssi> [<ber>]' changes the reported strength and error rate on next (15s) update.\n"
-                "rssi range is 0..31 and 99 for unknown\n"
-                "ber range is 0..7 percent and 99 for unknown\n",
-        .mhandler.cmd = android_console_gsm_signal,
-    },
-    {
-        .name = "signal-profile",
-        .args_type = "arg:S?",
-        .params = "",
-        .help = "sets the signal strength profile"
-            "signal-profile <strength>' changes the reported strength on next (15s) update.\n"
-            "strength range is 0..4\n",
-        .mhandler.cmd = android_console_gsm_signal_profile,
-    },
-    { NULL, NULL, },
-};
-
-#ifdef _WIN32
-// NOTE: HELP_COMMAND is defined by winuser.h which conflicts with this.
-#undef HELP_COMMAND
-#endif
-
-#define HELP_COMMAND                                                  \
-    {                                                                 \
-        .name = "help|h|?", .args_type = "helptext:S?", .params = "", \
-        .help = "print a list of commands",                           \
-        .mhandler.cmd = android_console_help,                         \
-    }
-
-#define QUIT_COMMAND                                                          \
-    {                                                                         \
-        .name = "quit|exit", .args_type = "", .params = "",                   \
-        .help = "quit control session", .mhandler.cmd = android_console_quit, \
-    }
-
-#define AVD_HELP "control virtual device execution"
-
-static mon_cmd_t android_cmds[] = {
-    HELP_COMMAND,
-    {
-        .name = "crash",
-        .args_type = "",
-        .params = "",
-        .help = "crash the emulator instance",
-        .mhandler.cmd = android_console_crash,
-    },
-    {
-        .name = "kill",
-        .args_type = "",
-        .params = "",
-        .help = "kill the emulator instance",
-        .mhandler.cmd = android_console_kill,
-    },
-    QUIT_COMMAND,
-    {
-        .name = "redir",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "manage port redirections",
-        .mhandler.cmd = android_console_redir,
-        .sub_cmds.static_table = android_redir_cmds,
-    },
-    {   .name = "power",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "power related commands",
-        .mhandler.cmd = android_console_power,
-        .sub_cmds.static_table = android_power_cmds,
-    },
-    {   .name = "event",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "simulate hardware events",
-        .mhandler.cmd = android_console_event,
-        .sub_cmds.static_table = android_event_cmds,
-    },
-    {   .name = "avd",
-        .args_type = "item:s?",
-        .params = "",
-        .help = AVD_HELP,
-        .mhandler.cmd = android_console_avd,
-        .sub_cmds.static_table = android_avd_cmds,
-    },
-    {   .name = "finger",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "manage emulator fingerprint",
-        .mhandler.cmd = android_console_finger,
-        .sub_cmds.static_table = android_finger_cmds,
-    },
-    {   .name = "geo",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "Geo-location commands",
-        .mhandler.cmd = android_console_geo,
-        .sub_cmds.static_table = android_geo_cmds,
-    },
-    {   .name = "sms",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "SMS related commands",
-        .mhandler.cmd = android_console_sms,
-        .sub_cmds.static_table = android_sms_cmds,
-    },
-    {   .name = "cdma",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "CDMA related commands",
-        .mhandler.cmd = android_console_cdma,
-        .sub_cmds.static_table = android_cdma_cmds,
-    },
-        {   .name = "gsm",
-        .args_type = "item:s?",
-        .params = "",
-        .help = "GSM related commands",
-        .mhandler.cmd = android_console_gsm,
-        .sub_cmds.static_table = android_gsm_cmds,
-    },
-    {
-        .name = "rotate",
-        .args_type = "",
-        .params = "",
-        .help = "rotate the screen by 90 degrees",
-        .mhandler.cmd = android_console_rotate_screen,
-    },
-
-    { NULL, NULL, },
-};
-
-static mon_cmd_t android_preauth_avd_cmds[] = {
-    {
-        .name = "name",
-        .args_type = "",
-        .params = "",
-        .help = "query virtual device name",
-        .mhandler.cmd = android_console_avd_name,
-    },
-    {
-        NULL,
-        NULL,
-    },
-};
-
-/* "preauth" commands are the set of commands that are legal before
-* authentication.  "avd name is special cased here because it is needed by
-* older versions of Android Studio */
-static mon_cmd_t android_preauth_cmds[] = {
-    HELP_COMMAND,
-    {
-        .name = "auth",
-        .args_type = "arg:s?",
-        .params = "",
-        .help = "use 'auth <auth_token>' to get extended functionality",
-        .mhandler.cmd = android_console_auth,
-    },
-    {
-        .name = "avd",
-        .args_type = "item:s?",
-        .params = "",
-        .help = AVD_HELP,
-        .mhandler.cmd = android_console_avd_preauth,
-        .sub_cmds.static_table = android_preauth_avd_cmds,
-    },
-    QUIT_COMMAND,
-    {
-        NULL,
-        NULL,
-    },
-};
diff --git a/android-qemu2-glue/android_qemud.cpp b/android-qemu2-glue/android_qemud.cpp
index 26e4313..c6e32bc 100644
--- a/android-qemu2-glue/android_qemud.cpp
+++ b/android-qemu2-glue/android_qemud.cpp
@@ -16,8 +16,10 @@
 #include "android-qemu2-glue/utils/stream.h"
 
 extern "C" {
-    #include "qemu-common.h"
-    #include "migration/vmstate.h"
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qom/object.h"
+#include "migration/vmstate.h"
 }
 
 /* Version number of snapshots code. Increment whenever the data saved
diff --git a/android-qemu2-glue/base/async/Looper.cpp b/android-qemu2-glue/base/async/Looper.cpp
index 3aa29a6..643047f 100644
--- a/android-qemu2-glue/base/async/Looper.cpp
+++ b/android-qemu2-glue/base/async/Looper.cpp
@@ -19,6 +19,7 @@
 #include "android/utils/stream.h"
 
 extern "C" {
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "sysemu/char.h"
diff --git a/android-qemu2-glue/base/files/QemuFileStream.cpp b/android-qemu2-glue/base/files/QemuFileStream.cpp
index 32ac51e..33cb007 100644
--- a/android-qemu2-glue/base/files/QemuFileStream.cpp
+++ b/android-qemu2-glue/base/files/QemuFileStream.cpp
@@ -14,6 +14,7 @@
 #include "android/base/Log.h"
 
 extern "C" {
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "migration/qemu-file.h"
 }
diff --git a/android-qemu2-glue/build/Makefile.qemu2-glue.mk b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
index 330fb92..649c1a0 100644
--- a/android-qemu2-glue/build/Makefile.qemu2-glue.mk
+++ b/android-qemu2-glue/build/Makefile.qemu2-glue.mk
@@ -1,45 +1,55 @@
 # A static library containing the android-emu glue code
 
-$(call start-emulator-library,libqemu2_glue)
+QEMU2_GLUE_INCLUDES := $(ANDROID_EMU_INCLUDES)
+
+$(call start-emulator-library,libqemu2-glue)
 
 LOCAL_CFLAGS += $(QEMU2_CFLAGS)
 
 LOCAL_C_INCLUDES += \
     $(QEMU2_INCLUDES) \
+    $(QEMU2_GLUE_INCLUDES) \
     $(LOCAL_PATH)/slirp \
-    $(LOCAL_PATH)/tcg \
 
 LOCAL_SRC_FILES := \
     android_qemud.cpp \
-    display.cpp \
-    looper-qemu.cpp \
-    net-android.cpp \
-    qemu-battery-agent-impl.c \
-    qemu-clipboard-agent-impl.cpp \
-    qemu-cellular-agent-impl.c \
-    qemu-display-agent-impl.cpp \
-    qemu-finger-agent-impl.c \
-    qemu-location-agent-impl.c \
-    qemu-net-agent-impl.c \
-    qemu-sensors-agent-impl.c \
-    qemu-setup.cpp \
-    qemu-telephony-agent-impl.c \
-    qemu-user-event-agent-impl.c \
-    qemu-vm-operations-impl.c \
-    qemu-window-agent-impl.c \
-    utils/stream.cpp \
     base/async/Looper.cpp \
     base/files/QemuFileStream.cpp \
+    display.cpp \
     emulation/android_pipe_device.cpp \
     emulation/charpipe.c \
     emulation/CharSerialLine.cpp \
     emulation/goldfish_sync.cpp \
     emulation/serial_line.cpp \
     emulation/VmLock.cpp \
+    looper-qemu.cpp \
+    net-android.cpp \
+    qemu-battery-agent-impl.c \
+    qemu-cellular-agent-impl.c \
+    qemu-clipboard-agent-impl.cpp \
+    qemu-display-agent-impl.cpp \
+    qemu-finger-agent-impl.c \
+    qemu-location-agent-impl.c \
+    qemu-net-agent-impl.c \
+    qemu-sensors-agent-impl.c \
+    qemu-setup.cpp \
+    qemu-setup-dns-servers.cpp \
+    qemu-telephony-agent-impl.c \
+    qemu-user-event-agent-impl.c \
+    qemu-vm-operations-impl.c \
+    qemu-window-agent-impl.c \
     telephony/modem_init.c \
+    utils/stream.cpp \
 
 LOCAL_SRC_FILES := $(LOCAL_SRC_FILES:%=android-qemu2-glue/%)
 
 $(call end-emulator-library)
 
-QEMU2_GLUE_STATIC_LIBRARIES := libqemu2_glue
+QEMU2_GLUE_STATIC_LIBRARIES := \
+    libqemu2-glue \
+    emulator-libui \
+    $(EMULATOR_LIBUI_STATIC_LIBRARIES)
+
+QEMU2_GLUE_LDFLAGS := $(EMULATOR_LIBUI_LDFLAGS)
+
+QEMU2_GLUE_LDLIBS := $(EMULATOR_LIBUI_LDLIBS)
diff --git a/android-qemu2-glue/build/Makefile.qemu2-sources.mk b/android-qemu2-glue/build/Makefile.qemu2-sources.mk
index 09bd237..94060c2 100644
--- a/android-qemu2-glue/build/Makefile.qemu2-sources.mk
+++ b/android-qemu2-glue/build/Makefile.qemu2-sources.mk
@@ -15,17 +15,20 @@
     backends/rng.c \
     backends/testdev.c \
     backends/tpm.c \
-    block-migration.c \
     block.c \
     block/accounting.c \
     block/backup.c \
     block/blkdebug.c \
+    block/blkreplay.c \
     block/blkverify.c \
     block/block-backend.c \
     block/bochs.c \
     block/cloop.c \
     block/commit.c \
+    block/crypto.c \
+    block/dirty-bitmap.c \
     block/dmg.c \
+    block/io.c \
     block/mirror.c \
     block/nbd-client.c \
     block/nbd.c \
@@ -44,23 +47,52 @@
     block/qed-l2-cache.c \
     block/qed-table.c \
     block/qed.c \
+    block/quorum.c \
     block/raw_bsd.c \
     block/sheepdog.c \
     block/snapshot.c \
     block/stream.c \
+    block/throttle-groups.c \
     block/vdi.c \
     block/vmdk.c \
     block/vpc.c \
     block/vvfat.c \
+    block/write-threshold.c \
     blockdev-nbd.c \
     blockdev.c \
     blockjob.c \
     bt-host.c \
     bt-vhci.c \
+    crypto/aes.c \
+    crypto/afsplit.c \
+    crypto/block-luks.c \
+    crypto/block-qcow.c \
+    crypto/block.c \
+    crypto/cipher.c \
+    crypto/desrfb.c \
+    crypto/hash-glib.c \
+    crypto/hash.c \
+    crypto/init.c \
+    crypto/ivgen-essiv.c \
+    crypto/ivgen-plain.c \
+    crypto/ivgen-plain64.c \
+    crypto/ivgen.c \
+    crypto/pbkdf.c \
+    crypto/random-platform.c \
+    crypto/secret.c \
+    crypto/tlscreds.c \
+    crypto/tlscredsanon.c \
+    crypto/tlscredsx509.c \
+    crypto/tlssession.c \
+    crypto/xts.c \
     device-hotplug.c \
+    device_tree.c \
     disas/i386.c \
     dma-helpers.c \
     hmp.c \
+    hw/acpi/acpi_interface.c \
+    hw/acpi/aml-build.c \
+    hw/acpi/bios-linker-loader.c \
     hw/audio/ac97.c \
     hw/audio/es1370.c \
     hw/audio/hda-codec.c \
@@ -81,19 +113,19 @@
     hw/char/serial-pci.c \
     hw/char/serial.c \
     hw/char/virtio-console.c \
-    hw/char/virtio-pingpong.c \
+    hw/core/bus.c \
     hw/core/fw-path-provider.c \
     hw/core/hotplug.c \
     hw/core/irq.c \
     hw/core/loader.c \
     hw/core/machine.c \
-    hw/core/nmi.c \
     hw/core/null-machine.c \
-    hw/core/platform-bus.c \
     hw/core/qdev-properties-system.c \
     hw/core/qdev-properties.c \
     hw/core/qdev.c \
+    hw/core/register.c \
     hw/core/sysbus.c \
+    hw/display/vga-pci.c \
     hw/i2c/core.c \
     hw/i2c/smbus.c \
     hw/i2c/smbus_eeprom.c \
@@ -105,26 +137,33 @@
     hw/ide/qdev.c \
     hw/input/hid.c \
     hw/input/ps2.c \
+    hw/input/virtio-input-hid.c \
+    hw/input/virtio-input.c \
     hw/ipack/ipack.c \
     hw/ipack/tpci200.c \
     hw/isa/isa-bus.c \
     hw/misc/pci-testdev.c \
     hw/net/e1000.c \
+    hw/net/e1000e.c \
+    hw/net/e1000e_core.c \
+    hw/net/e1000x_common.c \
     hw/net/eepro100.c \
     hw/net/ne2000.c \
+    hw/net/net_rx_pkt.c \
+    hw/net/net_tx_pkt.c \
     hw/net/pcnet-pci.c \
     hw/net/pcnet.c \
+    hw/net/rocker/rocker.c \
+    hw/net/rocker/rocker_desc.c \
+    hw/net/rocker/rocker_fp.c \
+    hw/net/rocker/rocker_of_dpa.c \
+    hw/net/rocker/rocker_world.c \
     hw/net/rtl8139.c \
     hw/net/vmxnet3.c \
-    hw/net/vmxnet_rx_pkt.c \
-    hw/net/vmxnet_tx_pkt.c \
     hw/nvram/eeprom93xx.c \
     hw/nvram/fw_cfg.c \
-    hw/pci-bridge/i82801b11.c \
-    hw/pci-bridge/ioh3420.c \
     hw/pci-bridge/pci_bridge_dev.c \
-    hw/pci-bridge/xio3130_downstream.c \
-    hw/pci-bridge/xio3130_upstream.c \
+    hw/pci-bridge/pci_expander_bridge.c \
     hw/pci-host/pam.c \
     hw/pci/msi.c \
     hw/pci/msix.c \
@@ -142,12 +181,17 @@
     hw/scsi/esp.c \
     hw/scsi/lsi53c895a.c \
     hw/scsi/megasas.c \
+    hw/scsi/mptconfig.c \
+    hw/scsi/mptendian.c \
+    hw/scsi/mptsas.c \
     hw/scsi/scsi-bus.c \
     hw/scsi/scsi-disk.c \
     hw/scsi/scsi-generic.c \
     hw/scsi/vmw_pvscsi.c \
+    hw/sd/core.c \
+    hw/sd/sd.c \
+    hw/sd/sdhci.c \
     hw/usb/bus.c \
-    hw/usb/ccid-card-passthru.c \
     hw/usb/combined-packet.c \
     hw/usb/core.c \
     hw/usb/desc-msos.c \
@@ -163,29 +207,52 @@
     hw/usb/dev-uas.c \
     hw/usb/dev-wacom.c \
     hw/usb/hcd-ehci-pci.c \
-    hw/usb/hcd-ehci-sysbus.c \
     hw/usb/hcd-ehci.c \
     hw/usb/hcd-ohci.c \
     hw/usb/hcd-uhci.c \
     hw/usb/hcd-xhci.c \
     hw/usb/host-stub.c \
     hw/usb/libhw.c \
-    hw/virtio/dataplane/vring.c \
     hw/virtio/virtio-bus.c \
     hw/virtio/virtio-mmio.c \
     hw/virtio/virtio-pci.c \
     hw/virtio/virtio-rng.c \
     hw/watchdog/watchdog.c \
     hw/watchdog/wdt_i6300esb.c \
+    io/channel-buffer.c \
+    io/channel-command.c \
+    io/channel-file.c \
+    io/channel-socket.c \
+    io/channel-tls.c \
+    io/channel-util.c \
+    io/channel-watch.c \
+    io/channel-websock.c \
+    io/channel.c \
+    io/task.c \
     iohandler.c \
     iothread.c \
     main-loop.c \
-    migration-tcp.c \
-    migration.c \
-    nbd.c \
+    migration/block.c \
+    migration/exec.c \
+    migration/fd.c \
+    migration/migration.c \
+    migration/postcopy-ram.c \
+    migration/qemu-file-channel.c \
+    migration/qemu-file.c \
+    migration/qjson.c \
+    migration/socket.c \
+    migration/tls.c \
+    migration/vmstate.c \
+    migration/xbzrle.c \
+    nbd/client.c \
+    nbd/common.c \
+    nbd/server.c \
     net/checksum.c \
     net/dump.c \
     net/eth.c \
+    net/filter-buffer.c \
+    net/filter-mirror.c \
+    net/filter.c \
     net/hub.c \
     net/net.c \
     net/queue.c \
@@ -195,15 +262,7 @@
     page_cache.c \
     qdev-monitor.c \
     qemu-char.c \
-    qemu-coroutine-io.c \
-    qemu-coroutine-lock.c \
-    qemu-coroutine-sleep.c \
-    qemu-coroutine.c \
-    qemu-file-stdio.c \
-    qemu-file-unix.c \
-    qemu-file.c \
     qemu-io-cmds.c \
-    qemu-log.c \
     qemu-timer.c \
     qmp.c \
     qom/container.c \
@@ -211,16 +270,27 @@
     qom/object.c \
     qom/object_interfaces.c \
     qom/qom-qobject.c \
+    replay/replay-char.c \
+    replay/replay-events.c \
+    replay/replay-input.c \
+    replay/replay-internal.c \
+    replay/replay-time.c \
+    replay/replay.c \
     slirp/arp_table.c \
     slirp/bootp.c \
     slirp/cksum.c \
+    slirp/dhcpv6.c \
     slirp/dnssearch.c \
     slirp/if.c \
+    slirp/ip6_icmp.c \
+    slirp/ip6_input.c \
+    slirp/ip6_output.c \
     slirp/ip_icmp.c \
     slirp/ip_input.c \
     slirp/ip_output.c \
     slirp/mbuf.c \
     slirp/misc.c \
+    slirp/ndp_table.c \
     slirp/sbuf.c \
     slirp/slirp.c \
     slirp/socket.c \
@@ -230,38 +300,34 @@
     slirp/tcp_timer.c \
     slirp/tftp.c \
     slirp/udp.c \
+    slirp/udp6.c \
     tcg-runtime.c \
     thread-pool.c \
     tpm.c \
     ui/console.c \
     ui/cursor.c \
-    ui/d3des.c \
     ui/input-keymap.c \
     ui/input-legacy.c \
     ui/input.c \
     ui/keymaps.c \
     ui/qemu-pixman.c \
+    ui/vnc-auth-vencrypt.c \
     ui/vnc-enc-hextile.c \
     ui/vnc-enc-tight.c \
     ui/vnc-enc-zlib.c \
     ui/vnc-enc-zrle.c \
     ui/vnc-jobs.c \
     ui/vnc-palette.c \
+    ui/vnc-ws.c \
     ui/vnc.c \
     ui/x_keymap.c \
-    vmstate.c \
-    xbzrle.c \
 
 QEMU2_COMMON_SOURCES_darwin-x86_64 := \
     aio-posix.c \
     audio/coreaudio.c \
     backends/rng-random.c \
     block/raw-posix.c \
-    coroutine-sigaltstack.c \
     hw/usb/dev-mtp.c \
-    migration-exec.c \
-    migration-fd.c \
-    migration-unix.c \
     net/tap-bsd.c \
     net/tap.c \
     net/vhost-user.c \
@@ -274,38 +340,35 @@
     backends/hostmem-file.c \
     backends/rng-random.c \
     block/raw-posix.c \
-    coroutine-ucontext.c \
     fsdev/qemu-fsdev-dummy.c \
     fsdev/qemu-fsdev-opts.c \
+    hw/input/virtio-input-host.c \
     hw/tpm/tpm_passthrough.c \
+    hw/tpm/tpm_util.c \
     hw/usb/dev-mtp.c \
-    migration-exec.c \
-    migration-fd.c \
-    migration-unix.c \
     net/tap-linux.c \
     net/tap.c \
     net/vhost-user.c \
     os-posix.c \
+    ui/input-linux.c \
 
 QEMU2_COMMON_SOURCES_windows-x86 := \
     aio-win32.c \
     audio/audio_win_int.c \
+    audio/dsoundaudio.c \
     audio/winaudio.c \
-    audio/winwaveaudio.c \
     block/raw-win32.c \
     block/win32-aio.c \
-    coroutine-win32.c \
     net/tap-win32.c \
     os-win32.c \
 
 QEMU2_COMMON_SOURCES_windows-x86_64 := \
     aio-win32.c \
     audio/audio_win_int.c \
+    audio/dsoundaudio.c \
     audio/winaudio.c \
-    audio/winwaveaudio.c \
     block/raw-win32.c \
     block/win32-aio.c \
-    coroutine-win32.c \
     net/tap-win32.c \
     os-win32.c \
 
@@ -313,10 +376,10 @@
     arch_init.c \
     balloon.c \
     bootdevice.c \
+    cpu-exec-common.c \
     cpu-exec.c \
     cpus.c \
     cputlb.c \
-    device_tree.c \
     disas.c \
     dump.c \
     exec.c \
@@ -325,7 +388,13 @@
     hw/block/dataplane/virtio-blk.c \
     hw/block/virtio-blk.c \
     hw/char/virtio-serial-bus.c \
+    hw/core/nmi.c \
+    hw/cpu/core.c \
     hw/display/vga.c \
+    hw/display/virtio-gpu-3d.c \
+    hw/display/virtio-gpu-pci.c \
+    hw/display/virtio-gpu.c \
+    hw/misc/edu.c \
     hw/net/vhost_net.c \
     hw/net/virtio-net.c \
     hw/scsi/virtio-scsi-dataplane.c \
@@ -335,23 +404,34 @@
     ioport.c \
     memory.c \
     memory_mapping.c \
+    migration/ram.c \
+    migration/savevm.c \
     monitor.c \
     numa.c \
     qtest.c \
-    savevm.c \
     tcg/optimize.c \
-    tcg/tcg.c \
+    tcg/tcg-common.c \
     tcg/tcg-op.c \
+    tcg/tcg.c \
+    trace/control-target.c \
     translate-all.c \
-    vl.c \
+    translate-common.c \
     xen-common-stub.c \
     xen-hvm-stub.c \
 
 QEMU2_TARGET_aarch64_SOURCES := \
+    disas/arm-a64.cc \
     disas/arm.c \
-    hax-stub.c \
+    disas/libvixl/vixl/a64/decoder-a64.cc \
+    disas/libvixl/vixl/a64/disasm-a64.cc \
+    disas/libvixl/vixl/a64/instructions-a64.cc \
+    disas/libvixl/vixl/compiler-intrinsics.cc \
+    disas/libvixl/vixl/utils.cc \
     hw/arm/allwinner-a10.c \
     hw/arm/armv7m.c \
+    hw/arm/ast2400.c \
+    hw/arm/bcm2835_peripherals.c \
+    hw/arm/bcm2836.c \
     hw/arm/boot.c \
     hw/arm/collie.c \
     hw/arm/cubieboard.c \
@@ -359,29 +439,42 @@
     hw/arm/digic_boards.c \
     hw/arm/exynos4210.c \
     hw/arm/exynos4_boards.c \
+    hw/arm/fsl-imx25.c \
+    hw/arm/fsl-imx31.c \
+    hw/arm/fsl-imx6.c \
     hw/arm/gumstix.c \
     hw/arm/highbank.c \
+    hw/arm/imx25_pdk.c \
     hw/arm/integratorcp.c \
     hw/arm/kzm.c \
     hw/arm/mainstone.c \
     hw/arm/musicpal.c \
+    hw/arm/netduino2.c \
     hw/arm/nseries.c \
     hw/arm/omap1.c \
     hw/arm/omap2.c \
     hw/arm/omap_sx1.c \
     hw/arm/palm.c \
+    hw/arm/palmetto-bmc.c \
     hw/arm/pxa2xx.c \
     hw/arm/pxa2xx_gpio.c \
     hw/arm/pxa2xx_pic.c \
+    hw/arm/raspi.c \
     hw/arm/realview.c \
+    hw/arm/sabrelite.c \
     hw/arm/spitz.c \
     hw/arm/stellaris.c \
+    hw/arm/stm32f205_soc.c \
     hw/arm/strongarm.c \
+    hw/arm/sysbus-fdt.c \
     hw/arm/tosa.c \
     hw/arm/versatilepb.c \
     hw/arm/vexpress.c \
+    hw/arm/virt-acpi-build.c \
     hw/arm/virt.c \
     hw/arm/xilinx_zynq.c \
+    hw/arm/xlnx-ep108.c \
+    hw/arm/xlnx-zynqmp.c \
     hw/arm/z2.c \
     hw/audio/lm4549.c \
     hw/audio/marvell_88w8618.c \
@@ -392,20 +485,26 @@
     hw/block/nand.c \
     hw/block/onenand.c \
     hw/block/pflash_cfi02.c \
+    hw/char/bcm2835_aux.c \
     hw/char/cadence_uart.c \
     hw/char/digic-uart.c \
     hw/char/exynos4210_uart.c \
     hw/char/imx_serial.c \
     hw/char/omap_uart.c \
     hw/char/pl011.c \
+    hw/char/stm32f2xx_usart.c \
+    hw/core/platform-bus.c \
     hw/core/ptimer.c \
     hw/cpu/a15mpcore.c \
     hw/cpu/a9mpcore.c \
     hw/cpu/arm11mpcore.c \
     hw/cpu/realview_mpcore.c \
     hw/display/ads7846.c \
+    hw/display/bcm2835_fb.c \
     hw/display/blizzard.c \
+    hw/display/dpcd.c \
     hw/display/exynos4210_fimd.c \
+    hw/display/framebuffer.c \
     hw/display/omap_dss.c \
     hw/display/omap_lcdc.c \
     hw/display/pl110.c \
@@ -413,17 +512,26 @@
     hw/display/ssd0303.c \
     hw/display/ssd0323.c \
     hw/display/tc6393xb.c \
+    hw/display/xlnx_dp.c \
+    hw/dma/bcm2835_dma.c \
     hw/dma/omap_dma.c \
     hw/dma/pl080.c \
     hw/dma/pl330.c \
     hw/dma/pxa2xx_dma.c \
     hw/dma/soc_dma.c \
+    hw/dma/xlnx-zynq-devcfg.c \
+    hw/dma/xlnx_dpdma.c \
+    hw/gpio/gpio_key.c \
+    hw/gpio/imx_gpio.c \
     hw/gpio/max7310.c \
     hw/gpio/omap_gpio.c \
     hw/gpio/pl061.c \
     hw/gpio/zaurus.c \
+    hw/i2c/aspeed_i2c.c \
     hw/i2c/bitbang_i2c.c \
     hw/i2c/exynos4210_i2c.c \
+    hw/i2c/i2c-ddc.c \
+    hw/i2c/imx_i2c.c \
     hw/i2c/omap_i2c.c \
     hw/i2c/versatile_i2c.c \
     hw/ide/microdrive.c \
@@ -436,7 +544,16 @@
     hw/intc/allwinner-a10-pic.c \
     hw/intc/arm_gic.c \
     hw/intc/arm_gic_common.c \
+    hw/intc/arm_gicv2m.c \
+    hw/intc/arm_gicv3.c \
+    hw/intc/arm_gicv3_common.c \
+    hw/intc/arm_gicv3_cpuif.c \
+    hw/intc/arm_gicv3_dist.c \
+    hw/intc/arm_gicv3_redist.c \
     hw/intc/armv7m_nvic.c \
+    hw/intc/aspeed_vic.c \
+    hw/intc/bcm2835_ic.c \
+    hw/intc/bcm2836_control.c \
     hw/intc/exynos4210_combiner.c \
     hw/intc/exynos4210_gic.c \
     hw/intc/imx_avic.c \
@@ -448,8 +565,16 @@
     hw/misc/arm_integrator_debug.c \
     hw/misc/arm_l2x0.c \
     hw/misc/arm_sysctl.c \
+    hw/misc/aspeed_scu.c \
+    hw/misc/auxbus.c \
+    hw/misc/bcm2835_mbox.c \
+    hw/misc/bcm2835_property.c \
     hw/misc/cbus.c \
     hw/misc/exynos4210_pmu.c \
+    hw/misc/imx25_ccm.c \
+    hw/misc/imx31_ccm.c \
+    hw/misc/imx6_ccm.c \
+    hw/misc/imx6_src.c \
     hw/misc/imx_ccm.c \
     hw/misc/max111x.c \
     hw/misc/mst_fpga.c \
@@ -458,22 +583,31 @@
     hw/misc/omap_l4.c \
     hw/misc/omap_sdrc.c \
     hw/misc/omap_tap.c \
+    hw/misc/stm32f2xx_syscfg.c \
     hw/misc/tmp105.c \
+    hw/misc/zynq-xadc.c \
     hw/misc/zynq_slcr.c \
     hw/net/allwinner_emac.c \
     hw/net/cadence_gem.c \
+    hw/net/imx_fec.c \
     hw/net/lan9118.c \
     hw/net/smc91c111.c \
     hw/net/stellaris_enet.c \
     hw/net/xgmac.c \
+    hw/pci-bridge/i82801b11.c \
+    hw/pci-bridge/ioh3420.c \
+    hw/pci-bridge/xio3130_downstream.c \
+    hw/pci-bridge/xio3130_upstream.c \
+    hw/pci-host/gpex.c \
     hw/pci-host/versatile.c \
     hw/pcmcia/pxa2xx.c \
     hw/sd/omap_mmc.c \
     hw/sd/pl181.c \
     hw/sd/pxa2xx_mmci.c \
-    hw/sd/sd.c \
-    hw/sd/sdhci.c \
     hw/sd/ssi-sd.c \
+    hw/smbios/smbios.c \
+    hw/ssi/aspeed_smc.c \
+    hw/ssi/imx_spi.c \
     hw/ssi/omap_spi.c \
     hw/ssi/pl022.c \
     hw/ssi/ssi.c \
@@ -482,6 +616,7 @@
     hw/timer/allwinner-a10-pit.c \
     hw/timer/arm_mptimer.c \
     hw/timer/arm_timer.c \
+    hw/timer/aspeed_timer.c \
     hw/timer/cadence_ttc.c \
     hw/timer/digic-timer.c \
     hw/timer/ds1338.c \
@@ -494,10 +629,14 @@
     hw/timer/omap_synctimer.c \
     hw/timer/pl031.c \
     hw/timer/pxa2xx_timer.c \
-    hw/timer/tusb6010.c \
+    hw/timer/stm32f2xx_timer.c \
     hw/timer/twl92230.c \
+    hw/usb/hcd-ehci-sysbus.c \
     hw/usb/hcd-musb.c \
+    hw/usb/tusb6010.c \
     kvm-stub.c \
+    target-arm/arch_dump.c \
+    target-arm/arm-powerctl.c \
     target-arm/arm-semi.c \
     target-arm/cpu.c \
     target-arm/cpu64.c \
@@ -509,6 +648,7 @@
     target-arm/iwmmxt_helper.c \
     target-arm/kvm-stub.c \
     target-arm/machine.c \
+    target-arm/monitor.c \
     target-arm/neon_helper.c \
     target-arm/op_helper.c \
     target-arm/psci.c \
@@ -516,10 +656,18 @@
     target-arm/translate.c \
 
 QEMU2_TARGET_arm_SOURCES := \
+    disas/arm-a64.cc \
     disas/arm.c \
-    hax-stub.c \
+    disas/libvixl/vixl/a64/decoder-a64.cc \
+    disas/libvixl/vixl/a64/disasm-a64.cc \
+    disas/libvixl/vixl/a64/instructions-a64.cc \
+    disas/libvixl/vixl/compiler-intrinsics.cc \
+    disas/libvixl/vixl/utils.cc \
     hw/arm/allwinner-a10.c \
     hw/arm/armv7m.c \
+    hw/arm/ast2400.c \
+    hw/arm/bcm2835_peripherals.c \
+    hw/arm/bcm2836.c \
     hw/arm/boot.c \
     hw/arm/collie.c \
     hw/arm/cubieboard.c \
@@ -527,27 +675,38 @@
     hw/arm/digic_boards.c \
     hw/arm/exynos4210.c \
     hw/arm/exynos4_boards.c \
+    hw/arm/fsl-imx25.c \
+    hw/arm/fsl-imx31.c \
+    hw/arm/fsl-imx6.c \
     hw/arm/gumstix.c \
     hw/arm/highbank.c \
+    hw/arm/imx25_pdk.c \
     hw/arm/integratorcp.c \
     hw/arm/kzm.c \
     hw/arm/mainstone.c \
     hw/arm/musicpal.c \
+    hw/arm/netduino2.c \
     hw/arm/nseries.c \
     hw/arm/omap1.c \
     hw/arm/omap2.c \
     hw/arm/omap_sx1.c \
     hw/arm/palm.c \
+    hw/arm/palmetto-bmc.c \
     hw/arm/pxa2xx.c \
     hw/arm/pxa2xx_gpio.c \
     hw/arm/pxa2xx_pic.c \
+    hw/arm/raspi.c \
     hw/arm/realview.c \
+    hw/arm/sabrelite.c \
     hw/arm/spitz.c \
     hw/arm/stellaris.c \
+    hw/arm/stm32f205_soc.c \
     hw/arm/strongarm.c \
+    hw/arm/sysbus-fdt.c \
     hw/arm/tosa.c \
     hw/arm/versatilepb.c \
     hw/arm/vexpress.c \
+    hw/arm/virt-acpi-build.c \
     hw/arm/virt.c \
     hw/arm/xilinx_zynq.c \
     hw/arm/z2.c \
@@ -560,20 +719,25 @@
     hw/block/nand.c \
     hw/block/onenand.c \
     hw/block/pflash_cfi02.c \
+    hw/char/bcm2835_aux.c \
     hw/char/cadence_uart.c \
     hw/char/digic-uart.c \
     hw/char/exynos4210_uart.c \
     hw/char/imx_serial.c \
     hw/char/omap_uart.c \
     hw/char/pl011.c \
+    hw/char/stm32f2xx_usart.c \
+    hw/core/platform-bus.c \
     hw/core/ptimer.c \
     hw/cpu/a15mpcore.c \
     hw/cpu/a9mpcore.c \
     hw/cpu/arm11mpcore.c \
     hw/cpu/realview_mpcore.c \
     hw/display/ads7846.c \
+    hw/display/bcm2835_fb.c \
     hw/display/blizzard.c \
     hw/display/exynos4210_fimd.c \
+    hw/display/framebuffer.c \
     hw/display/omap_dss.c \
     hw/display/omap_lcdc.c \
     hw/display/pl110.c \
@@ -581,17 +745,23 @@
     hw/display/ssd0303.c \
     hw/display/ssd0323.c \
     hw/display/tc6393xb.c \
+    hw/dma/bcm2835_dma.c \
     hw/dma/omap_dma.c \
     hw/dma/pl080.c \
     hw/dma/pl330.c \
     hw/dma/pxa2xx_dma.c \
     hw/dma/soc_dma.c \
+    hw/dma/xlnx-zynq-devcfg.c \
+    hw/gpio/gpio_key.c \
+    hw/gpio/imx_gpio.c \
     hw/gpio/max7310.c \
     hw/gpio/omap_gpio.c \
     hw/gpio/pl061.c \
     hw/gpio/zaurus.c \
+    hw/i2c/aspeed_i2c.c \
     hw/i2c/bitbang_i2c.c \
     hw/i2c/exynos4210_i2c.c \
+    hw/i2c/imx_i2c.c \
     hw/i2c/omap_i2c.c \
     hw/i2c/versatile_i2c.c \
     hw/ide/microdrive.c \
@@ -604,7 +774,16 @@
     hw/intc/allwinner-a10-pic.c \
     hw/intc/arm_gic.c \
     hw/intc/arm_gic_common.c \
+    hw/intc/arm_gicv2m.c \
+    hw/intc/arm_gicv3.c \
+    hw/intc/arm_gicv3_common.c \
+    hw/intc/arm_gicv3_cpuif.c \
+    hw/intc/arm_gicv3_dist.c \
+    hw/intc/arm_gicv3_redist.c \
     hw/intc/armv7m_nvic.c \
+    hw/intc/aspeed_vic.c \
+    hw/intc/bcm2835_ic.c \
+    hw/intc/bcm2836_control.c \
     hw/intc/exynos4210_combiner.c \
     hw/intc/exynos4210_gic.c \
     hw/intc/imx_avic.c \
@@ -616,8 +795,15 @@
     hw/misc/arm_integrator_debug.c \
     hw/misc/arm_l2x0.c \
     hw/misc/arm_sysctl.c \
+    hw/misc/aspeed_scu.c \
+    hw/misc/bcm2835_mbox.c \
+    hw/misc/bcm2835_property.c \
     hw/misc/cbus.c \
     hw/misc/exynos4210_pmu.c \
+    hw/misc/imx25_ccm.c \
+    hw/misc/imx31_ccm.c \
+    hw/misc/imx6_ccm.c \
+    hw/misc/imx6_src.c \
     hw/misc/imx_ccm.c \
     hw/misc/max111x.c \
     hw/misc/mst_fpga.c \
@@ -626,22 +812,31 @@
     hw/misc/omap_l4.c \
     hw/misc/omap_sdrc.c \
     hw/misc/omap_tap.c \
+    hw/misc/stm32f2xx_syscfg.c \
     hw/misc/tmp105.c \
+    hw/misc/zynq-xadc.c \
     hw/misc/zynq_slcr.c \
     hw/net/allwinner_emac.c \
     hw/net/cadence_gem.c \
+    hw/net/imx_fec.c \
     hw/net/lan9118.c \
     hw/net/smc91c111.c \
     hw/net/stellaris_enet.c \
     hw/net/xgmac.c \
+    hw/pci-bridge/i82801b11.c \
+    hw/pci-bridge/ioh3420.c \
+    hw/pci-bridge/xio3130_downstream.c \
+    hw/pci-bridge/xio3130_upstream.c \
+    hw/pci-host/gpex.c \
     hw/pci-host/versatile.c \
     hw/pcmcia/pxa2xx.c \
     hw/sd/omap_mmc.c \
     hw/sd/pl181.c \
     hw/sd/pxa2xx_mmci.c \
-    hw/sd/sd.c \
-    hw/sd/sdhci.c \
     hw/sd/ssi-sd.c \
+    hw/smbios/smbios.c \
+    hw/ssi/aspeed_smc.c \
+    hw/ssi/imx_spi.c \
     hw/ssi/omap_spi.c \
     hw/ssi/pl022.c \
     hw/ssi/ssi.c \
@@ -650,6 +845,7 @@
     hw/timer/allwinner-a10-pit.c \
     hw/timer/arm_mptimer.c \
     hw/timer/arm_timer.c \
+    hw/timer/aspeed_timer.c \
     hw/timer/cadence_ttc.c \
     hw/timer/digic-timer.c \
     hw/timer/ds1338.c \
@@ -662,10 +858,14 @@
     hw/timer/omap_synctimer.c \
     hw/timer/pl031.c \
     hw/timer/pxa2xx_timer.c \
-    hw/timer/tusb6010.c \
+    hw/timer/stm32f2xx_timer.c \
     hw/timer/twl92230.c \
+    hw/usb/hcd-ehci-sysbus.c \
     hw/usb/hcd-musb.c \
+    hw/usb/tusb6010.c \
     kvm-stub.c \
+    target-arm/arch_dump.c \
+    target-arm/arm-powerctl.c \
     target-arm/arm-semi.c \
     target-arm/cpu.c \
     target-arm/crypto_helper.c \
@@ -674,19 +874,24 @@
     target-arm/iwmmxt_helper.c \
     target-arm/kvm-stub.c \
     target-arm/machine.c \
+    target-arm/monitor.c \
     target-arm/neon_helper.c \
     target-arm/op_helper.c \
     target-arm/psci.c \
     target-arm/translate.c \
 
 QEMU2_TARGET_i386_SOURCES := \
-    hw/acpi/acpi_interface.c \
     hw/acpi/core.c \
+    hw/acpi/cpu.c \
     hw/acpi/cpu_hotplug.c \
     hw/acpi/ich9.c \
+    hw/acpi/ipmi.c \
     hw/acpi/memory_hotplug.c \
+    hw/acpi/memory_hotplug_acpi_table.c \
+    hw/acpi/nvdimm.c \
     hw/acpi/pcihp.c \
     hw/acpi/piix4.c \
+    hw/acpi/tco.c \
     hw/audio/adlib.c \
     hw/audio/cs4231a.c \
     hw/audio/fmopl.c \
@@ -698,24 +903,21 @@
     hw/block/fdc.c \
     hw/char/debugcon.c \
     hw/char/parallel.c \
-    hw/cpu/icc_bus.c \
     hw/display/cirrus_vga.c \
     hw/display/vga-isa.c \
-    hw/display/vga-pci.c \
+    hw/display/virtio-vga.c \
     hw/display/vmware_vga.c \
     hw/dma/i8257.c \
     hw/i2c/pm_smbus.c \
     hw/i2c/smbus_ich9.c \
-    hw/i386/acpi-build.c \
-    hw/i386/bios-linker-loader.c \
     hw/i386/intel_iommu.c \
     hw/i386/kvmvapic.c \
     hw/i386/multiboot.c \
     hw/i386/pc.c \
-    hw/i386/pc_piix.c \
     hw/i386/pc_q35.c \
     hw/i386/pc_sysfw.c \
-    hw/i386/smbios.c \
+    hw/i386/pci-assign-load-rom.c \
+    hw/i386/x86-iommu.c \
     hw/ide/isa.c \
     hw/ide/piix.c \
     hw/input/pckbd.c \
@@ -726,8 +928,14 @@
     hw/intc/i8259_common.c \
     hw/intc/ioapic.c \
     hw/intc/ioapic_common.c \
+    hw/ipmi/ipmi.c \
+    hw/ipmi/ipmi_bmc_extern.c \
+    hw/ipmi/ipmi_bmc_sim.c \
+    hw/ipmi/isa_ipmi_bt.c \
+    hw/ipmi/isa_ipmi_kcs.c \
     hw/isa/apm.c \
     hw/isa/lpc_ich9.c \
+    hw/mem/nvdimm.c \
     hw/mem/pc-dimm.c \
     hw/misc/applesmc.c \
     hw/misc/debugexit.c \
@@ -736,9 +944,14 @@
     hw/misc/sga.c \
     hw/misc/vmport.c \
     hw/net/ne2000-isa.c \
+    hw/pci-bridge/i82801b11.c \
+    hw/pci-bridge/ioh3420.c \
+    hw/pci-bridge/xio3130_downstream.c \
+    hw/pci-bridge/xio3130_upstream.c \
     hw/pci-host/piix.c \
     hw/pci-host/q35.c \
-    hw/pci/pci-hotplug-old.c \
+    hw/smbios/smbios.c \
+    hw/smbios/smbios_type_38.c \
     hw/timer/hpet.c \
     hw/timer/i8254.c \
     hw/timer/i8254_common.c \
@@ -747,6 +960,7 @@
     hw/watchdog/wdt_ib700.c \
     target-i386/arch_dump.c \
     target-i386/arch_memory_mapping.c \
+    target-i386/bpt_helper.c \
     target-i386/cc_helper.c \
     target-i386/cpu.c \
     target-i386/excp_helper.c \
@@ -757,6 +971,8 @@
     target-i386/machine.c \
     target-i386/mem_helper.c \
     target-i386/misc_helper.c \
+    target-i386/monitor.c \
+    target-i386/mpx_helper.c \
     target-i386/seg_helper.c \
     target-i386/smm_helper.c \
     target-i386/svm_helper.c \
@@ -764,12 +980,11 @@
 
 QEMU2_TARGET_mips64el_SOURCES := \
     disas/mips.c \
-    hax-stub.c \
-    hw/acpi/acpi_interface.c \
     hw/acpi/core.c \
+    hw/acpi/cpu.c \
     hw/acpi/cpu_hotplug.c \
-    hw/acpi/ich9.c \
     hw/acpi/memory_hotplug.c \
+    hw/acpi/memory_hotplug_acpi_table.c \
     hw/acpi/pcihp.c \
     hw/acpi/piix4.c \
     hw/audio/adlib.c \
@@ -788,7 +1003,6 @@
     hw/display/jazz_led.c \
     hw/display/vga-isa-mm.c \
     hw/display/vga-isa.c \
-    hw/display/vga-pci.c \
     hw/display/vmware_vga.c \
     hw/dma/i8257.c \
     hw/dma/rc4030.c \
@@ -800,10 +1014,12 @@
     hw/input/pckbd.c \
     hw/intc/i8259.c \
     hw/intc/i8259_common.c \
+    hw/intc/mips_gic.c \
     hw/isa/apm.c \
     hw/isa/piix4.c \
     hw/isa/vt82c686.c \
     hw/mips/addr.c \
+    hw/mips/cps.c \
     hw/mips/cputimer.c \
     hw/mips/gt64xxx_pci.c \
     hw/mips/mips_fulong2e.c \
@@ -812,6 +1028,9 @@
     hw/mips/mips_malta.c \
     hw/mips/mips_mipssim.c \
     hw/mips/mips_r4k.c \
+    hw/misc/mips_cmgcr.c \
+    hw/misc/mips_cpc.c \
+    hw/misc/mips_itu.c \
     hw/misc/pc-testdev.c \
     hw/net/dp8393x.c \
     hw/net/mipsnet.c \
@@ -821,6 +1040,7 @@
     hw/timer/i8254.c \
     hw/timer/i8254_common.c \
     hw/timer/mc146818rtc.c \
+    hw/timer/mips_gictimer.c \
     kvm-stub.c \
     target-mips/cpu.c \
     target-mips/dsp_helper.c \
@@ -828,18 +1048,18 @@
     target-mips/helper.c \
     target-mips/lmi_helper.c \
     target-mips/machine.c \
+    target-mips/mips-semi.c \
     target-mips/msa_helper.c \
     target-mips/op_helper.c \
     target-mips/translate.c \
 
 QEMU2_TARGET_mipsel_SOURCES := \
     disas/mips.c \
-    hax-stub.c \
-    hw/acpi/acpi_interface.c \
     hw/acpi/core.c \
+    hw/acpi/cpu.c \
     hw/acpi/cpu_hotplug.c \
-    hw/acpi/ich9.c \
     hw/acpi/memory_hotplug.c \
+    hw/acpi/memory_hotplug_acpi_table.c \
     hw/acpi/pcihp.c \
     hw/acpi/piix4.c \
     hw/audio/adlib.c \
@@ -854,14 +1074,10 @@
     hw/char/parallel.c \
     hw/core/empty_slot.c \
     hw/display/cirrus_vga.c \
-    hw/display/g364fb.c \
-    hw/display/jazz_led.c \
     hw/display/vga-isa-mm.c \
     hw/display/vga-isa.c \
-    hw/display/vga-pci.c \
     hw/display/vmware_vga.c \
     hw/dma/i8257.c \
-    hw/dma/rc4030.c \
     hw/i2c/pm_smbus.c \
     hw/i2c/smbus_ich9.c \
     hw/ide/isa.c \
@@ -869,24 +1085,27 @@
     hw/input/pckbd.c \
     hw/intc/i8259.c \
     hw/intc/i8259_common.c \
+    hw/intc/mips_gic.c \
     hw/isa/apm.c \
     hw/isa/piix4.c \
     hw/mips/addr.c \
+    hw/mips/cps.c \
     hw/mips/cputimer.c \
     hw/mips/gt64xxx_pci.c \
     hw/mips/mips_int.c \
-    hw/mips/mips_jazz.c \
     hw/mips/mips_malta.c \
     hw/mips/mips_mipssim.c \
     hw/mips/mips_r4k.c \
+    hw/misc/mips_cmgcr.c \
+    hw/misc/mips_cpc.c \
+    hw/misc/mips_itu.c \
     hw/misc/pc-testdev.c \
-    hw/net/dp8393x.c \
     hw/net/mipsnet.c \
     hw/net/ne2000-isa.c \
-    hw/nvram/ds1225y.c \
     hw/timer/i8254.c \
     hw/timer/i8254_common.c \
     hw/timer/mc146818rtc.c \
+    hw/timer/mips_gictimer.c \
     kvm-stub.c \
     target-mips/cpu.c \
     target-mips/dsp_helper.c \
@@ -894,18 +1113,23 @@
     target-mips/helper.c \
     target-mips/lmi_helper.c \
     target-mips/machine.c \
+    target-mips/mips-semi.c \
     target-mips/msa_helper.c \
     target-mips/op_helper.c \
     target-mips/translate.c \
 
 QEMU2_TARGET_x86_64_SOURCES := \
-    hw/acpi/acpi_interface.c \
     hw/acpi/core.c \
+    hw/acpi/cpu.c \
     hw/acpi/cpu_hotplug.c \
     hw/acpi/ich9.c \
+    hw/acpi/ipmi.c \
     hw/acpi/memory_hotplug.c \
+    hw/acpi/memory_hotplug_acpi_table.c \
+    hw/acpi/nvdimm.c \
     hw/acpi/pcihp.c \
     hw/acpi/piix4.c \
+    hw/acpi/tco.c \
     hw/audio/adlib.c \
     hw/audio/cs4231a.c \
     hw/audio/fmopl.c \
@@ -917,24 +1141,21 @@
     hw/block/fdc.c \
     hw/char/debugcon.c \
     hw/char/parallel.c \
-    hw/cpu/icc_bus.c \
     hw/display/cirrus_vga.c \
     hw/display/vga-isa.c \
-    hw/display/vga-pci.c \
+    hw/display/virtio-vga.c \
     hw/display/vmware_vga.c \
     hw/dma/i8257.c \
     hw/i2c/pm_smbus.c \
     hw/i2c/smbus_ich9.c \
-    hw/i386/acpi-build.c \
-    hw/i386/bios-linker-loader.c \
     hw/i386/intel_iommu.c \
     hw/i386/kvmvapic.c \
     hw/i386/multiboot.c \
     hw/i386/pc.c \
-    hw/i386/pc_piix.c \
     hw/i386/pc_q35.c \
     hw/i386/pc_sysfw.c \
-    hw/i386/smbios.c \
+    hw/i386/pci-assign-load-rom.c \
+    hw/i386/x86-iommu.c \
     hw/ide/isa.c \
     hw/ide/piix.c \
     hw/input/pckbd.c \
@@ -945,8 +1166,14 @@
     hw/intc/i8259_common.c \
     hw/intc/ioapic.c \
     hw/intc/ioapic_common.c \
+    hw/ipmi/ipmi.c \
+    hw/ipmi/ipmi_bmc_extern.c \
+    hw/ipmi/ipmi_bmc_sim.c \
+    hw/ipmi/isa_ipmi_bt.c \
+    hw/ipmi/isa_ipmi_kcs.c \
     hw/isa/apm.c \
     hw/isa/lpc_ich9.c \
+    hw/mem/nvdimm.c \
     hw/mem/pc-dimm.c \
     hw/misc/applesmc.c \
     hw/misc/debugexit.c \
@@ -955,9 +1182,14 @@
     hw/misc/sga.c \
     hw/misc/vmport.c \
     hw/net/ne2000-isa.c \
+    hw/pci-bridge/i82801b11.c \
+    hw/pci-bridge/ioh3420.c \
+    hw/pci-bridge/xio3130_downstream.c \
+    hw/pci-bridge/xio3130_upstream.c \
     hw/pci-host/piix.c \
     hw/pci-host/q35.c \
-    hw/pci/pci-hotplug-old.c \
+    hw/smbios/smbios.c \
+    hw/smbios/smbios_type_38.c \
     hw/timer/hpet.c \
     hw/timer/i8254.c \
     hw/timer/i8254_common.c \
@@ -966,6 +1198,7 @@
     hw/watchdog/wdt_ib700.c \
     target-i386/arch_dump.c \
     target-i386/arch_memory_mapping.c \
+    target-i386/bpt_helper.c \
     target-i386/cc_helper.c \
     target-i386/cpu.c \
     target-i386/excp_helper.c \
@@ -976,6 +1209,8 @@
     target-i386/machine.c \
     target-i386/mem_helper.c \
     target-i386/misc_helper.c \
+    target-i386/monitor.c \
+    target-i386/mpx_helper.c \
     target-i386/seg_helper.c \
     target-i386/smm_helper.c \
     target-i386/svm_helper.c \
@@ -984,8 +1219,15 @@
 QEMU2_TARGET_aarch64_SOURCES_darwin-x86_64 := \
 
 QEMU2_TARGET_aarch64_SOURCES_linux-x86_64 := \
-    hw/misc/vfio.c \
+    hw/misc/ivshmem.c \
     hw/scsi/vhost-scsi.c \
+    hw/vfio/amd-xgbe.c \
+    hw/vfio/calxeda-xgmac.c \
+    hw/vfio/common.c \
+    hw/vfio/pci-quirks.c \
+    hw/vfio/pci.c \
+    hw/vfio/platform.c \
+    hw/vfio/spapr.c \
     hw/virtio/vhost-backend.c \
     hw/virtio/vhost-user.c \
     hw/virtio/vhost.c \
@@ -997,8 +1239,15 @@
 QEMU2_TARGET_arm_SOURCES_darwin-x86_64 := \
 
 QEMU2_TARGET_arm_SOURCES_linux-x86_64 := \
-    hw/misc/vfio.c \
+    hw/misc/ivshmem.c \
     hw/scsi/vhost-scsi.c \
+    hw/vfio/amd-xgbe.c \
+    hw/vfio/calxeda-xgmac.c \
+    hw/vfio/common.c \
+    hw/vfio/pci-quirks.c \
+    hw/vfio/pci.c \
+    hw/vfio/platform.c \
+    hw/vfio/spapr.c \
     hw/virtio/vhost-backend.c \
     hw/virtio/vhost-user.c \
     hw/virtio/vhost.c \
@@ -1009,47 +1258,52 @@
 
 QEMU2_TARGET_i386_SOURCES_darwin-x86_64 := \
     kvm-stub.c \
-    target-i386/hax-all.c \
-    target-i386/hax-darwin.c \
-    target-i386/hax-slot.c \
     target-i386/kvm-stub.c \
 
 QEMU2_TARGET_i386_SOURCES_linux-x86_64 := \
-    hax-stub.c \
     hw/i386/kvm/apic.c \
     hw/i386/kvm/clock.c \
     hw/i386/kvm/i8254.c \
     hw/i386/kvm/i8259.c \
     hw/i386/kvm/ioapic.c \
     hw/i386/kvm/pci-assign.c \
+    hw/misc/hyperv_testdev.c \
     hw/misc/ivshmem.c \
-    hw/misc/vfio.c \
     hw/scsi/vhost-scsi.c \
+    hw/vfio/amd-xgbe.c \
+    hw/vfio/calxeda-xgmac.c \
+    hw/vfio/common.c \
+    hw/vfio/pci-quirks.c \
+    hw/vfio/pci.c \
+    hw/vfio/platform.c \
+    hw/vfio/spapr.c \
     hw/virtio/vhost-backend.c \
     hw/virtio/vhost-user.c \
     hw/virtio/vhost.c \
     kvm-all.c \
+    target-i386/hyperv.c \
     target-i386/kvm.c \
 
 QEMU2_TARGET_i386_SOURCES_windows-x86 := \
     kvm-stub.c \
-    target-i386/hax-all.c \
-    target-i386/hax-slot.c \
-    target-i386/hax-windows.c \
     target-i386/kvm-stub.c \
 
 QEMU2_TARGET_i386_SOURCES_windows-x86_64 := \
     kvm-stub.c \
-    target-i386/hax-all.c \
-    target-i386/hax-slot.c \
-    target-i386/hax-windows.c \
     target-i386/kvm-stub.c \
 
 QEMU2_TARGET_mips64el_SOURCES_darwin-x86_64 := \
 
 QEMU2_TARGET_mips64el_SOURCES_linux-x86_64 := \
-    hw/misc/vfio.c \
+    hw/misc/ivshmem.c \
     hw/scsi/vhost-scsi.c \
+    hw/vfio/amd-xgbe.c \
+    hw/vfio/calxeda-xgmac.c \
+    hw/vfio/common.c \
+    hw/vfio/pci-quirks.c \
+    hw/vfio/pci.c \
+    hw/vfio/platform.c \
+    hw/vfio/spapr.c \
     hw/virtio/vhost-backend.c \
     hw/virtio/vhost-user.c \
     hw/virtio/vhost.c \
@@ -1061,8 +1315,15 @@
 QEMU2_TARGET_mipsel_SOURCES_darwin-x86_64 := \
 
 QEMU2_TARGET_mipsel_SOURCES_linux-x86_64 := \
-    hw/misc/vfio.c \
+    hw/misc/ivshmem.c \
     hw/scsi/vhost-scsi.c \
+    hw/vfio/amd-xgbe.c \
+    hw/vfio/calxeda-xgmac.c \
+    hw/vfio/common.c \
+    hw/vfio/pci-quirks.c \
+    hw/vfio/pci.c \
+    hw/vfio/platform.c \
+    hw/vfio/spapr.c \
     hw/virtio/vhost-backend.c \
     hw/virtio/vhost-user.c \
     hw/virtio/vhost.c \
@@ -1073,39 +1334,37 @@
 
 QEMU2_TARGET_x86_64_SOURCES_darwin-x86_64 := \
     kvm-stub.c \
-    target-i386/hax-all.c \
-    target-i386/hax-darwin.c \
-    target-i386/hax-slot.c \
     target-i386/kvm-stub.c \
 
 QEMU2_TARGET_x86_64_SOURCES_linux-x86_64 := \
-    hax-stub.c \
     hw/i386/kvm/apic.c \
     hw/i386/kvm/clock.c \
     hw/i386/kvm/i8254.c \
     hw/i386/kvm/i8259.c \
     hw/i386/kvm/ioapic.c \
     hw/i386/kvm/pci-assign.c \
+    hw/misc/hyperv_testdev.c \
     hw/misc/ivshmem.c \
-    hw/misc/vfio.c \
     hw/scsi/vhost-scsi.c \
+    hw/vfio/amd-xgbe.c \
+    hw/vfio/calxeda-xgmac.c \
+    hw/vfio/common.c \
+    hw/vfio/pci-quirks.c \
+    hw/vfio/pci.c \
+    hw/vfio/platform.c \
+    hw/vfio/spapr.c \
     hw/virtio/vhost-backend.c \
     hw/virtio/vhost-user.c \
     hw/virtio/vhost.c \
     kvm-all.c \
+    target-i386/hyperv.c \
     target-i386/kvm.c \
 
 QEMU2_TARGET_x86_64_SOURCES_windows-x86 := \
     kvm-stub.c \
-    target-i386/hax-all.c \
-    target-i386/hax-slot.c \
-    target-i386/hax-windows.c \
     target-i386/kvm-stub.c \
 
 QEMU2_TARGET_x86_64_SOURCES_windows-x86_64 := \
     kvm-stub.c \
-    target-i386/hax-all.c \
-    target-i386/hax-slot.c \
-    target-i386/hax-windows.c \
     target-i386/kvm-stub.c \
 
diff --git a/android-qemu2-glue/build/Makefile.qemu2-target.mk b/android-qemu2-glue/build/Makefile.qemu2-target.mk
index 621c87c..2c45668 100644
--- a/android-qemu2-glue/build/Makefile.qemu2-target.mk
+++ b/android-qemu2-glue/build/Makefile.qemu2-target.mk
@@ -36,13 +36,14 @@
 # If $(QEMU2_TARGET_CPU) is $1, then return $2, or the empty string otherwise.
 qemu2-if-target-arch = $(if $(filter $1,$(QEMU2_TARGET_CPU)),$2)
 
-$(call start-emulator-program,qemu-system-$(QEMU2_TARGET_SYSTEM))
+# A library that contains all QEMU2 target-specific sources, excluding
+# anything implemented by the glue code.
 
-LOCAL_CFLAGS += \
+QEMU2_SYSTEM_CFLAGS := \
     $(QEMU2_CFLAGS) \
-    $(EMULATOR_LIBUI_CFLAGS)
+    -DNEED_CPU_H \
 
-LOCAL_C_INCLUDES += \
+QEMU2_SYSTEM_INCLUDES := \
     $(QEMU2_INCLUDES) \
     $(QEMU2_DEPS_TOP_DIR)/include \
     $(call qemu2-if-linux,$(LOCAL_PATH)/linux-headers) \
@@ -50,15 +51,31 @@
     $(LOCAL_PATH)/target-$(QEMU2_TARGET_TARGET) \
     $(LOCAL_PATH)/tcg \
     $(LOCAL_PATH)/tcg/i386 \
-    $(LOCAL_PATH)/target-$(QEMU2_TARGET_TARGET) \
-    $(ANDROID_EMU_INCLUDES) \
-    $(LIBCURL_INCLUDES) \
-    $(EMULATOR_LIBUI_INCLUDES) \
 
-LOCAL_CFLAGS += -DNEED_CPU_H
+QEMU2_SYSTEM_LDFLAGS := $(QEMU2_DEPS_LDFLAGS)
+
+QEMU2_SYSTEM_LDLIBS := \
+    $(QEMU2_GLIB_LDLIBS) \
+    $(QEMU2_PIXMAN_LDLIBS) \
+    $(CXX_STD_LIB) \
+    -lfdt \
+    $(call qemu2-if-windows, -lvfw32 -ldxguid) \
+    $(call qemu2-if-linux, -lpulse) \
+
+QEMU2_SYSTEM_STATIC_LIBRARIES := \
+    emulator-zlib
+
+$(call start-emulator-library,libqemu2-system-$(QEMU2_TARGET_SYSTEM))
+
+LOCAL_CFLAGS += \
+    $(QEMU2_SYSTEM_CFLAGS) \
+    -DPOISON_CONFIG_ANDROID \
+
+LOCAL_C_INCLUDES += \
+    $(QEMU2_SYSTEM_INCLUDES) \
+    $(call qemu2-if-target,arm arm64,$(LOCAL_PATH)/disas/libvixl) \
 
 LOCAL_SRC_FILES += \
-    android-qemu2-glue/main.cpp \
     $(QEMU2_TARGET_SOURCES) \
     $(QEMU2_TARGET_$(QEMU2_TARGET_CPU)_SOURCES) \
     $(QEMU2_TARGET_$(QEMU2_TARGET_CPU)_SOURCES_$(BUILD_TARGET_TAG))
@@ -66,14 +83,16 @@
 LOCAL_SRC_FILES += \
     hw/audio/goldfish_audio.c \
     hw/char/goldfish_tty.c \
-    hw/display/framebuffer.c \
     hw/display/goldfish_fb.c \
+    $(call qemu2-if-target,arm arm64,, \
+        hw/display/framebuffer.c \
+        ) \
     hw/input/goldfish_events.c \
     hw/intc/goldfish_pic.c \
-    hw/misc/goldfish_pipe.c \
-    hw/misc/goldfish_battery.c \
-    hw/misc/goldfish_sync.c \
     hw/timer/goldfish_timer.c \
+    hw/misc/goldfish_battery.c \
+    hw/misc/goldfish_pipe.c \
+    hw/misc/goldfish_sync.c \
     $(call qemu2-if-target,arm arm64,\
         hw/arm/ranchu.c) \
     $(call qemu2-if-target,mips mips64,\
@@ -88,40 +107,141 @@
 endif
 
 LOCAL_SRC_FILES += \
+    stubs/target-get-monitor-def.c \
     $(call qemu2-if-target,arm arm64 mips mips64,\
-        stubs/dump.c \
-        stubs/pci-drive-hot-add.c \
         stubs/qmp_pc_dimm_device_list.c \
         ) \
+    $(call qemu2-if-target,x86 x86_64,, \
+        stubs/pc_madt_cpu_entry.c \
+        stubs/smbios_type_38.c \
+        stubs/target-monitor-defs.c \
+        ) \
     $(call qemu2-if-target,mips mips64, \
-        stubs/arch-query-cpu-def.c)
+        stubs/dump.c \
+        stubs/arch-query-cpu-def.c \
+        ) \
+    $(call qemu2-if-linux,, \
+        stubs/vhost.c \
+        ) \
+
+# HAX support.
+HAX_COMMON_SOURCES := \
+    target-i386/hax-all.c \
+    target-i386/hax-slot.c \
+
+LOCAL_SRC_FILES += \
+    $(call qemu2-if-target,x86 x86_64, \
+        $(call qemu2-if-windows, \
+            $(HAX_COMMON_SOURCES) \
+            target-i386/hax-windows.c) \
+        $(call qemu2-if-darwin, \
+            $(HAX_COMMON_SOURCES) \
+            target-i386/hax-darwin.c) \
+	$(call qemu2-if-linux, \
+	    hax-stub.c) \
+    , \
+        hax-stub.c \
+    ) \
 
 LOCAL_PREBUILTS_OBJ_FILES += \
     $(call qemu2-if-windows,$(QEMU2_AUTO_GENERATED_DIR)/version.o)
 
+$(call end-emulator-library)
+
+# The upstream version of QEMU2, without any Android-specific hacks.
+# This uses the regular SDL2 UI backend.
+
+$(call start-emulator-program,qemu-upstream-$(QEMU2_TARGET_SYSTEM))
+
 LOCAL_WHOLE_STATIC_LIBRARIES += \
-    libqemu2_common \
-    libqemu2_glue \
-    $(call qemu2-if-target,arm arm64, libqemu2_common_aarch64) \
+    libqemu2-system-$(QEMU2_TARGET_SYSTEM) \
+    libqemu2-common \
 
 LOCAL_STATIC_LIBRARIES += \
-    emulator-libui \
-    $(EMULATOR_LIBUI_STATIC_LIBRARIES) \
+    $(QEMU2_SYSTEM_STATIC_LIBRARIES) \
+
+LOCAL_CFLAGS += \
+    $(QEMU2_SYSTEM_CFLAGS) \
+
+LOCAL_C_INCLUDES += \
+    $(QEMU2_SYSTEM_INCLUDES) \
+    $(QEMU2_SDL2_INCLUDES) \
+
+LOCAL_SRC_FILES += \
+    $(call qemu2-if-target,x86 x86_64, \
+        hw/i386/acpi-build.c \
+        hw/i386/pc_piix.c \
+        ) \
+    $(call qemu2-if-windows, \
+        stubs/win32-stubs.c \
+        ) \
+    ui/sdl2.c \
+    ui/sdl2-input.c \
+    ui/sdl2-2d.c \
+    vl.c \
+
+LOCAL_LDFLAGS += $(QEMU2_SYSTEM_LDFLAGS)
+
+LOCAL_LDLIBS += \
+    $(QEMU2_SYSTEM_LDLIBS) \
+    $(QEMU2_SDL2_LDLIBS) \
+
+LOCAL_INSTALL_DIR := qemu/$(BUILD_TARGET_TAG)
+
+$(call end-emulator-program)
+
+
+# The emulator-specific version of QEMU2, with CONFIG_ANDROID defined at
+# compile-time.
+
+$(call start-emulator-program,qemu-system-$(QEMU2_TARGET_SYSTEM))
+
+LOCAL_WHOLE_STATIC_LIBRARIES += \
+    libqemu2-glue \
+    libqemu2-system-$(QEMU2_TARGET_SYSTEM) \
+    libqemu2-common \
+
+LOCAL_STATIC_LIBRARIES += \
+    $(QEMU2_SYSTEM_STATIC_LIBRARIES) \
+    $(QEMU2_GLUE_STATIC_LIBRARIES) \
     $(ANDROID_EMU_STATIC_LIBRARIES) \
 
+LOCAL_CFLAGS += \
+    $(QEMU2_SYSTEM_CFLAGS) \
+    -DCONFIG_ANDROID \
+
+LOCAL_C_INCLUDES += \
+    $(QEMU2_SYSTEM_INCLUDES) \
+    $(QEMU2_GLUE_INCLUDES) \
+    $(ANDROID_EMU_INCLUDES) \
+
+# For now, use stubs/sdl-null.c as an empty/fake SDL UI backend.
+# TODO: Use the glue code to use the Qt-based UI instead.
+LOCAL_SRC_FILES += \
+    android-qemu2-glue/main.cpp \
+    $(call qemu2-if-target,x86 x86_64, \
+        hw/i386/acpi-build.c \
+        hw/i386/pc_piix.c \
+        ) \
+    $(call qemu2-if-windows, \
+        android-qemu2-glue/stubs/win32-stubs.c \
+        ) \
+    vl.c \
+
+LOCAL_LDFLAGS += $(QEMU2_SYSTEM_LDFLAGS) $(QEMU2_GLUE_LDFLAGS)
+LOCAL_LDLIBS += $(QEMU2_SYSTEM_LDLIBS) $(QEMU2_GLUE_LDLIBS)
+
 LOCAL_LDFLAGS += \
     $(QEMU2_DEPS_LDFLAGS) \
-    $(EMULATOR_LIBUI_LDFLAGS)
 
 LOCAL_LDLIBS += \
     $(QEMU2_GLIB_LDLIBS) \
     $(QEMU2_PIXMAN_LDLIBS) \
     $(CXX_STD_LIB) \
     -lfdt \
-    $(call qemu2-if-windows, -lvfw32) \
+    $(call qemu2-if-windows, -lvfw32 -ldxguid) \
     $(call qemu2-if-linux, -lpulse) \
     $(ANDROID_EMU_LDLIBS) \
-    $(EMULATOR_LIBUI_LDLIBS) \
 
 LOCAL_INSTALL_DIR := qemu/$(BUILD_TARGET_TAG)
 
diff --git a/android-qemu2-glue/build/Makefile.qemu2.mk b/android-qemu2-glue/build/Makefile.qemu2.mk
index 481f665..8934608 100644
--- a/android-qemu2-glue/build/Makefile.qemu2.mk
+++ b/android-qemu2-glue/build/Makefile.qemu2.mk
@@ -56,6 +56,47 @@
 QEMU2_PIXMAN_INCLUDES := $(QEMU2_DEPS_TOP_DIR)/include/pixman-1
 QEMU2_PIXMAN_LDLIBS := -lpixman-1
 
+QEMU2_SDL2_INCLUDES := $(QEMU2_DEPS_TOP_DIR)/include/SDL2
+QEMU2_SDL2_LDLIBS := \
+    $(call qemu2-if-windows, \
+        -lmingw32 \
+    ) \
+    -lSDL2 \
+    $(call qemu2-if-darwin,, \
+        -lSDL2main \
+    ) \
+    $(call qemu2-if-windows, \
+        -limm32 \
+        -ldinput8 \
+        -ldxguid \
+        -ldxerr8 \
+        -luser32 \
+        -lgdi32 \
+        -lwinmm \
+        -lole32 \
+        -loleaut32 \
+        -lshell32 \
+        -lversion \
+        -luuid \
+    , \
+        -ldl \
+    ) \
+
+ifeq (darwin,$(BUILD_TARGET_OS))
+# NOTE: Because the following contain commas, we cannot use qemu2-if-darwin!
+QEMU2_SDL2_LDLIBS += \
+    -Wl,-framework,OpenGL \
+    -Wl,-framework,ForceFeedback \
+    -lobjc \
+    -Wl,-framework,Cocoa \
+    -Wl,-framework,Carbon \
+    -Wl,-framework,IOKit \
+    -Wl,-framework,CoreAudio \
+    -Wl,-framework,AudioToolbox \
+    -Wl,-framework,AudioUnit \
+
+endif
+
 # Ensure config-host.h can be found properly.
 QEMU2_INCLUDES := $(LOCAL_PATH)/android-qemu2-glue/config/$(BUILD_TARGET_TAG)
 
@@ -64,7 +105,6 @@
     $(LOCAL_PATH) \
     $(LOCAL_PATH)/include \
     $(QEMU2_AUTO_GENERATED_DIR) \
-    $(ANDROID_EMU_INCLUDES) \
 
 QEMU2_INCLUDES += $(QEMU2_GLIB_INCLUDES) $(QEMU2_PIXMAN_INCLUDES)
 
@@ -79,23 +119,33 @@
     $(LIBCURL_CFLAGS) \
     -D_GNU_SOURCE \
     -D_FILE_OFFSET_BITS=64 \
-    -DCONFIG_ANDROID \
     $(call qemu2-if-darwin, -Wno-initializer-overrides) \
 
-include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-glue.mk
+QEMU2_CFLAGS += \
+    -Wno-unused-function \
+    $(call qemu2-if-darwin, \
+        -Wno-unused-value \
+        -Wno-parentheses-equality \
+        -Wno-self-assign \
+        , \
+        -Wno-unused-variable \
+        -Wno-unused-but-set-variable \
+        -Wno-maybe-uninitialized \
+        ) \
+    -UNDEBUG \
+
+#include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-glue.mk
 
 #include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-qt.mk
 
 include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-sources.mk
 
-# Custom fixes.
-QEMU2_COMMON_SOURCES += \
-    stubs/kvm.c
-
 # A static library containing target-independent code
-$(call start-emulator-library,libqemu2_common)
+$(call start-emulator-library,libqemu2-common)
 
-LOCAL_CFLAGS += $(QEMU2_CFLAGS)
+LOCAL_CFLAGS += \
+    $(QEMU2_CFLAGS) \
+    -DPOISON_CONFIG_ANDROID \
 
 LOCAL_C_INCLUDES += \
     $(QEMU2_INCLUDES) \
@@ -111,117 +161,112 @@
     $(QEMU2_AUTO_GENERATED_DIR)/qapi-event.c \
     $(QEMU2_AUTO_GENERATED_DIR)/qapi-types.c \
     $(QEMU2_AUTO_GENERATED_DIR)/qapi-visit.c \
+    $(QEMU2_AUTO_GENERATED_DIR)/qmp-introspect.c \
     $(QEMU2_AUTO_GENERATED_DIR)/qmp-marshal.c \
     $(QEMU2_AUTO_GENERATED_DIR)/trace/generated-events.c \
     $(QEMU2_AUTO_GENERATED_DIR)/trace/generated-tracers.c \
 
 # Stuff from libqemuutil, order follows util/Makefile.objs
 LOCAL_SRC_FILES += \
-    qapi/qapi-visit-core.c \
+    crypto/pbkdf-stub.c \
+    qapi/opts-visitor.c \
+    qapi/qapi-clone-visitor.c \
     qapi/qapi-dealloc-visitor.c \
+    qapi/qapi-util.c \
+    qapi/qapi-visit-core.c \
+    qapi/qmp-dispatch.c \
+    qapi/qmp-event.c \
     qapi/qmp-input-visitor.c \
     qapi/qmp-output-visitor.c \
     qapi/qmp-registry.c \
-    qapi/qmp-dispatch.c \
     qapi/string-input-visitor.c \
     qapi/string-output-visitor.c \
-    qapi/opts-visitor.c \
-    qapi/qmp-event.c \
-    qapi/qapi-util.c \
-    qobject/qint.c \
-    qobject/qstring.c \
-    qobject/qdict.c \
-    qobject/qlist.c \
-    qobject/qfloat.c \
-    qobject/qbool.c \
-    qobject/qjson.c \
     qobject/json-lexer.c \
-    qobject/json-streamer.c \
     qobject/json-parser.c \
-    qobject/qerror.c \
+    qobject/json-streamer.c \
+    qobject/qbool.c \
+    qobject/qdict.c \
+    qobject/qfloat.c \
+    qobject/qint.c \
+    qobject/qjson.c \
+    qobject/qlist.c \
+    qobject/qnull.c \
+    qobject/qobject.c \
+    qobject/qstring.c \
     trace/control.c \
     trace/qmp.c \
-    util/osdep.c \
-    util/cutils.c \
-    util/unicode.c \
-    util/qemu-timer-common.c \
-    $(call qemu2-if-windows, \
-        util/oslib-win32.c \
-        util/qemu-thread-win32.c \
-        util/event_notifier-win32.c \
-        ) \
-    $(call qemu2-if-posix, \
-        util/oslib-posix.c \
-        util/qemu-thread-posix.c \
-        util/event_notifier-posix.c \
-        util/qemu-openpty.c \
-        ) \
-    util/envlist.c \
-    util/path.c \
-    util/module.c \
-    $(call qemu2-if-build-target-arch,x86, util/host-utils.c) \
+    util/abort.c \
+    util/acl.c \
+    util/base64.c \
     util/bitmap.c \
     util/bitops.c \
-    util/hbitmap.c \
-    util/fifo8.c \
-    util/acl.c \
+    util/buffer.c \
+    util/crc32c.c \
+    util/cutils.c \
+    util/envlist.c \
     util/error.c \
-    util/qemu-error.c \
-    $(call qemu2-if-posix, \
-        util/compatfd.c \
-        ) \
+    util/fifo8.c \
+    util/getauxval.c \
+    util/hexdump.c \
+    util/hbitmap.c \
     util/id.c \
     util/iov.c \
-    util/aes.c \
-    util/qemu-config.c \
-    util/qemu-sockets.c \
-    util/uri.c \
+    util/log.c \
+    util/module.c \
     util/notify.c \
+    util/osdep.c \
+    util/path.c \
+    util/qdist.c \
+    util/qemu-config.c \
+    util/qemu-coroutine.c \
+    util/qemu-coroutine-io.c \
+    util/qemu-coroutine-lock.c \
+    util/qemu-coroutine-sleep.c \
+    util/qemu-error.c \
     util/qemu-option.c \
     util/qemu-progress.c \
-    util/hexdump.c \
-    util/crc32c.c \
-    util/throttle.c \
-    util/getauxval.c \
+    util/qemu-sockets.c \
+    util/qemu-timer-common.c \
+    util/qht.c \
+    util/range.c \
+    util/rcu.c \
     util/readline.c \
     util/rfifolock.c \
+    util/timed-average.c \
+    util/throttle.c \
+    util/unicode.c \
+    util/uri.c \
     $(call qemu2-if-windows, \
-        util/shared-library-win32.c \
+        util/coroutine-win32.c \
+        util/event_notifier-win32.c \
+        util/oslib-win32.c \
+        util/qemu-thread-win32.c \
+        ) \
+    $(call qemu2-if-linux, \
+        util/coroutine-ucontext.c \
+        util/memfd.c \
+        ) \
+    $(call qemu2-if-darwin, \
+        util/coroutine-sigaltstack.c \
         ) \
     $(call qemu2-if-posix, \
-        util/shared-library-posix.c \
+        util/event_notifier-posix.c \
+        util/mmap-alloc.c \
+        util/oslib-posix.c \
+        util/qemu-openpty.c \
+        util/qemu-thread-posix.c \
+        ) \
+    $(call qemu2-if-build-target-arch,x86, util/host-utils.c) \
+    $(call qemu2-if-posix, \
+        util/compatfd.c \
         ) \
 
 $(call gen-hw-config-defs)
 QEMU2_INCLUDES += $(QEMU_HW_CONFIG_DEFS_INCLUDES)
 
-LOCAL_SRC_FILES += \
-    $(QEMU2_GLUE_SOURCES)
-
 $(call end-emulator-library)
 
-# Special case, the following sources are only used by the arm64
-# target but cannot be part of libqemu2_aarch64 because they need
-# to be compiled without NEED_CPU_H
-$(call start-emulator-library,libqemu2_common_aarch64)
-
-LOCAL_CPP_EXTENSION := .cc
-
-LOCAL_C_INCLUDES += \
-    $(QEMU2_INCLUDES) \
-    $(LOCAL_PATH)/target-arm \
-    $(LOCAL_PATH)/disas/libvixl
-
-LOCAL_CFLAGS += $(QEMU2_CFLAGS)
-
-LOCAL_SRC_FILES += \
-    disas/arm-a64.cc \
-    disas/libvixl/a64/decoder-a64.cc \
-    disas/libvixl/a64/disasm-a64.cc \
-    disas/libvixl/a64/instructions-a64.cc \
-    disas/libvixl/utils.cc \
-
-$(call end-emulator-library)
+include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-glue.mk
 
 QEMU2_TARGET := x86
 include $(LOCAL_PATH)/android-qemu2-glue/build/Makefile.qemu2-target.mk
diff --git a/android-qemu2-glue/build/configure.sh b/android-qemu2-glue/build/configure.sh
index c258d55..1dbe87f 100644
--- a/android-qemu2-glue/build/configure.sh
+++ b/android-qemu2-glue/build/configure.sh
@@ -7,6 +7,10 @@
 
 QEMU2_AUTOGENERATED_DIR=$OUT_DIR/build/qemu2-qapi-auto-generated
 
+replace_with_if_different () {
+    cmp -s "$1" "$2" || mv "$2" "$1"
+}
+
 probe_prebuilts_dir "QEMU2 Dependencies" \
     QEMU2_DEPS_PREBUILTS_DIR \
     qemu-android-deps
@@ -15,23 +19,76 @@
 
 python $QEMU2_TOP_DIR/scripts/qapi-types.py \
     --builtins \
-    -i $QEMU2_TOP_DIR/qapi-schema.json \
-    -o $QEMU2_AUTOGENERATED_DIR
+    -o $QEMU2_AUTOGENERATED_DIR \
+    $QEMU2_TOP_DIR/qapi-schema.json
 
 python $QEMU2_TOP_DIR/scripts/qapi-visit.py \
     --builtins \
-    -i $QEMU2_TOP_DIR/qapi-schema.json \
-    -o $QEMU2_AUTOGENERATED_DIR
+    -o $QEMU2_AUTOGENERATED_DIR \
+    $QEMU2_TOP_DIR/qapi-schema.json
 
 python $QEMU2_TOP_DIR/scripts/qapi-event.py \
-    --builtins \
-    -i $QEMU2_TOP_DIR/qapi-schema.json \
-    -o $QEMU2_AUTOGENERATED_DIR
+    -o $QEMU2_AUTOGENERATED_DIR \
+    $QEMU2_TOP_DIR/qapi-schema.json
+
+python $QEMU2_TOP_DIR/scripts/qapi-introspect.py \
+    -o $QEMU2_AUTOGENERATED_DIR \
+    $QEMU2_TOP_DIR/qapi-schema.json
 
 python $QEMU2_TOP_DIR/scripts/qapi-commands.py \
     --middle \
-    -i $QEMU2_TOP_DIR/qapi-schema.json \
-    -o $QEMU2_AUTOGENERATED_DIR
+    -o $QEMU2_AUTOGENERATED_DIR \
+    $QEMU2_TOP_DIR/qapi-schema.json
+
+TRACE_EVENT_FILES="\
+    trace-events \
+    util/trace-events \
+    crypto/trace-events \
+    io/trace-events \
+    migration/trace-events \
+    block/trace-events \
+    hw/block/trace-events \
+    hw/char/trace-events \
+    hw/intc/trace-events \
+    hw/net/trace-events \
+    hw/virtio/trace-events \
+    hw/audio/trace-events \
+    hw/misc/trace-events \
+    hw/usb/trace-events \
+    hw/scsi/trace-events \
+    hw/nvram/trace-events \
+    hw/display/trace-events \
+    hw/input/trace-events \
+    hw/timer/trace-events \
+    hw/dma/trace-events \
+    hw/sparc/trace-events \
+    hw/sd/trace-events \
+    hw/isa/trace-events \
+    hw/i386/trace-events \
+    hw/9pfs/trace-events \
+    hw/ppc/trace-events \
+    hw/pci/trace-events \
+    hw/s390x/trace-events \
+    hw/vfio/trace-events \
+    hw/acpi/trace-events \
+    hw/arm/trace-events \
+    hw/alpha/trace-events \
+    ui/trace-events \
+    audio/trace-events \
+    net/trace-events \
+    target-i386/trace-events \
+    target-sparc/trace-events \
+    target-s390x/trace-events \
+    target-ppc/trace-events \
+    qom/trace-events \
+    linux-user/trace-events \
+"
+
+TRACE_EVENTS_ALL=$QEMU2_AUTOGENERATED_DIR/trace-events-all
+rm -f "$TRACE_EVENTS_ALL" && touch "$TRACE_EVENTS_ALL"
+for TRACE_EVENT_FILE in $TRACE_EVENT_FILES; do
+    (cat "$QEMU2_TOP_DIR/$TRACE_EVENT_FILE" >> $TRACE_EVENTS_ALL)
+done
 
 mkdir -p "$QEMU2_AUTOGENERATED_DIR"/trace
 
@@ -39,60 +96,69 @@
     --backends=nop \
     --format=h \
     --target-type system \
-    < $QEMU2_TOP_DIR/trace-events \
+    < $TRACE_EVENTS_ALL \
     > $QEMU2_AUTOGENERATED_DIR/trace/generated-tracers.h
 
 python $QEMU2_TOP_DIR/scripts/tracetool.py \
     --backends=nop \
     --format=c \
     --target-type system \
-    < $QEMU2_TOP_DIR/trace-events \
+    < $TRACE_EVENTS_ALL \
     > $QEMU2_AUTOGENERATED_DIR/trace/generated-tracers.c
 
 python $QEMU2_TOP_DIR/scripts/tracetool.py \
     --backends=nop \
     --format=events-h \
     --target-type system \
-    < $QEMU2_TOP_DIR/trace-events \
+    < $TRACE_EVENTS_ALL \
     > $QEMU2_AUTOGENERATED_DIR/trace/generated-events.h
 
 python $QEMU2_TOP_DIR/scripts/tracetool.py \
     --backends=nop \
     --format=events-c \
     --target-type system \
-    < $QEMU2_TOP_DIR/trace-events \
+    < $TRACE_EVENTS_ALL \
     > $QEMU2_AUTOGENERATED_DIR/trace/generated-events.c
 
 python $QEMU2_TOP_DIR/scripts/tracetool.py \
     --backends=nop \
     --format=tcg-helper-h \
     --target-type system \
-    < $QEMU2_TOP_DIR/trace-events \
+    < $TRACE_EVENTS_ALL \
     > $QEMU2_AUTOGENERATED_DIR/trace/generated-helpers.h
 
 python $QEMU2_TOP_DIR/scripts/tracetool.py \
     --backends=nop \
     --format=tcg-helper-wrapper-h \
     --target-type system \
-    < $QEMU2_TOP_DIR/trace-events \
+    < $TRACE_EVENTS_ALL \
     > $QEMU2_AUTOGENERATED_DIR/trace/generated-helpers-wrappers.h
 
 python $QEMU2_TOP_DIR/scripts/tracetool.py \
     --backends=nop \
     --format=tcg-h \
     --target-type system \
-    < $QEMU2_TOP_DIR/trace-events \
+    < $TRACE_EVENTS_ALL \
     > $QEMU2_AUTOGENERATED_DIR/trace/generated-tcg-tracers.h
 
 bash $QEMU2_TOP_DIR/scripts/hxtool -h \
     < $QEMU2_TOP_DIR/qemu-options.hx \
     > $QEMU2_AUTOGENERATED_DIR/qemu-options.def
 
+replace_with_if_different \
+    "$QEMU2_TOP_DIR/qemu-options.def" \
+    $QEMU2_AUTOGENERATED_DIR/qemu-options.def
+
+
 bash $QEMU2_TOP_DIR/scripts/hxtool -h \
     < $QEMU2_TOP_DIR/hmp-commands.hx \
     > $QEMU2_AUTOGENERATED_DIR/hmp-commands.h
 
 bash $QEMU2_TOP_DIR/scripts/hxtool -h \
+    < $QEMU2_TOP_DIR/hmp-commands-info.hx \
+    > $QEMU2_AUTOGENERATED_DIR/hmp-commands-info.h
+
+bash $QEMU2_TOP_DIR/scripts/hxtool -h \
     < $QEMU2_TOP_DIR/qmp-commands.hx \
     > $QEMU2_AUTOGENERATED_DIR/qmp-commands-old.h
 
@@ -100,13 +166,6 @@
     < $QEMU2_TOP_DIR/qemu-img-cmds.hx \
     > $QEMU2_AUTOGENERATED_DIR/qemu-img-cmds.h
 
-HEX_FILES=$(find $QEMU2_TOP_DIR/hw/i386/ -name "*.hex.generated" | \
-    sed -e 's|'$QEMU2_TOP_DIR/'||g')
-mkdir -p $QEMU2_AUTOGENERATED_DIR/hw/i386
-for HEX_FILES in $HEX_FILES; do
-    cp "$QEMU2_TOP_DIR/$HEX_FILES" "$QEMU2_AUTOGENERATED_DIR/${HEX_FILES%.generated}"
-done
-
 rm -f $QEMU2_AUTOGENERATED_DIR/gdbstub-xml-arm64.c
 bash $QEMU2_TOP_DIR/scripts/feature_to_c.sh \
     $QEMU2_AUTOGENERATED_DIR/gdbstub-xml-arm64.c \
@@ -131,6 +190,22 @@
         $QEMU2_TOP_DIR/version.rc
 fi
 
+# Generate qemu-version.h from Git history.
+QEMU_VERSION_H=$QEMU2_AUTOGENERATED_DIR/qemu-version.h
+QEMU_VERSION_H_TMP=$QEMU_VERSION_H.tmp
+rm -f "$QEMU_VERSION_H"
+if [ -d "$QEMU2_TOP_DIR/.git" ]; then
+    QEMU_VERSION=$(cd "$QEMU2_TOP_DIR" && git describe --match 'v*' 2>/dev/null | tr -d '\n')
+else
+    QEMU_VERSION=$(date "+%Y-%m-%d")
+fi
+
+echo "QEMU2    : Version [$QEMU_VERSION]"
+
+printf "#define QEMU_PKGVERSION \"(android-%s)\"\n" "$QEMU_VERSION" > $QEMU_VERSION_H_TMP
+replace_with_if_different "$QEMU_VERSION_H" "$QEMU_VERSION_H_TMP"
+rm -f "$QEMU_VERSION_TMP_H"
+
 # Work-around for a QEMU2 bug:
 # $QEMU2/linux-headers/linux/kvm.h includes <asm/kvm.h>
 # but $QEMU2/linux-headers/asm/ doesn't exist. It is supposed
@@ -139,4 +214,5 @@
 # The end result is that the <asm/kvm.h> from the host system
 # or toolchain sysroot is being included, which ends up in a
 # conflict. Work around it by creating a symlink here
+rm -f $QEMU2_AUTOGENERATED_DIR/asm
 ln -sf $QEMU2_TOP_DIR/linux-headers/asm-x86 $QEMU2_AUTOGENERATED_DIR/asm
diff --git a/android-qemu2-glue/config/darwin-x86_64/config-host.h b/android-qemu2-glue/config/darwin-x86_64/config-host.h
index 72dc9eb..1a7cdee 100644
--- a/android-qemu2-glue/config/darwin-x86_64/config-host.h
+++ b/android-qemu2-glue/config/darwin-x86_64/config-host.h
@@ -1,11 +1,11 @@
 /* Automatically generated by create_config - do not modify */
-#define CONFIG_QEMU_CONFDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/etc/qemu"
-#define CONFIG_QEMU_DATADIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/share/qemu"
-#define CONFIG_QEMU_DOCDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/share/doc/qemu"
-#define CONFIG_QEMU_MODDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/lib/qemu"
-#define CONFIG_QEMU_LOCALSTATEDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/var"
-#define CONFIG_QEMU_HELPERDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/libexec"
-#define CONFIG_QEMU_LOCALEDIR "/Volumes/Android/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/darwin-x86_64/share/locale"
+#define CONFIG_QEMU_CONFDIR "/tmp/qemu-android-build/prebuilts/qemu-android-deps/darwin-x86_64/etc/qemu"
+#define CONFIG_QEMU_DATADIR "/tmp/qemu-android-build/prebuilts/qemu-android-deps/darwin-x86_64/share/qemu"
+#define CONFIG_QEMU_DOCDIR "/tmp/qemu-android-build/prebuilts/qemu-android-deps/darwin-x86_64/share/doc/qemu"
+#define CONFIG_QEMU_MODDIR "/tmp/qemu-android-build/prebuilts/qemu-android-deps/darwin-x86_64/lib/qemu"
+#define CONFIG_QEMU_LOCALSTATEDIR "/tmp/qemu-android-build/prebuilts/qemu-android-deps/darwin-x86_64/var"
+#define CONFIG_QEMU_HELPERDIR "/tmp/qemu-android-build/prebuilts/qemu-android-deps/darwin-x86_64/libexec"
+#define CONFIG_QEMU_LOCALEDIR "/tmp/qemu-android-build/prebuilts/qemu-android-deps/darwin-x86_64/share/locale"
 #define HOST_X86_64 1
 #define CONFIG_POSIX 1
 #define CONFIG_DARWIN 1
@@ -22,23 +22,23 @@
 #define CONFIG_VNC 1
 #define CONFIG_FNMATCH 1
 #define CONFIG_UUID 1
-#define QEMU_VERSION "2.2.0"
-#define QEMU_PKGVERSION ""
+#define QEMU_VERSION "2.7.0"
 #define CONFIG_SDL 1
 #define CONFIG_SDLABI 2.0
+#define CONFIG_HAS_GLIB_SUBPROCESS_TESTS 1
+#define CONFIG_TLS_PRIORITY "NORMAL"
+#define HAVE_IFADDRS_H 1
 #define CONFIG_IOVEC 1
 #define CONFIG_FDT 1
 #define CONFIG_MADVISE 1
 #define CONFIG_POSIX_MADVISE 1
 #define CONFIG_BSD 1
-#define CONFIG_ZERO_MALLOC 1
 #define CONFIG_QOM_CAST_DEBUG 1
 #define CONFIG_COROUTINE_BACKEND sigaltstack
 #define CONFIG_COROUTINE_POOL 1
 #define CONFIG_CPUID_H 1
 #define CONFIG_INT128 1
-#define CONFIG_TPM $(CONFIG_SOFTMMU)
-#define CONFIG_TRACE_NOP 1
+#define CONFIG_TPM 1
+#define CONFIG_TRACE_LOG 1
 #define CONFIG_TRACE_FILE trace
 #define HOST_DSOSUF ".so"
-#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/config/linux-x86_64/config-host.h b/android-qemu2-glue/config/linux-x86_64/config-host.h
index 739c90a..1cbccdf 100644
--- a/android-qemu2-glue/config/linux-x86_64/config-host.h
+++ b/android-qemu2-glue/config/linux-x86_64/config-host.h
@@ -22,8 +22,7 @@
     NULL
 #define CONFIG_VNC 1
 #define CONFIG_FNMATCH 1
-#define QEMU_VERSION "2.2.0"
-#define QEMU_PKGVERSION ""
+#define QEMU_VERSION "2.7.0"
 #define CONFIG_SDL 1
 #define CONFIG_SDLABI 2.0
 #define CONFIG_UTIMENSAT 1
@@ -40,12 +39,14 @@
 #define CONFIG_PRCTL_PR_SET_TIMERSLACK 1
 #define CONFIG_EPOLL 1
 #define CONFIG_EPOLL_CREATE1 1
-#define CONFIG_EPOLL_PWAIT 1
 #define CONFIG_SENDFILE 1
 #define CONFIG_TIMERFD 1
 #define CONFIG_INOTIFY 1
 #define CONFIG_INOTIFY1 1
 #define CONFIG_BYTESWAP_H 1
+#define CONFIG_HAS_GLIB_SUBPROCESS_TESTS 1
+#define CONFIG_TLS_PRIORITY "NORMAL"
+#define HAVE_IFADDRS_H 1
 #define CONFIG_VHOST_SCSI 1
 #define CONFIG_IOVEC 1
 #define CONFIG_PREADV 1
@@ -54,9 +55,6 @@
 #define CONFIG_FDATASYNC 1
 #define CONFIG_MADVISE 1
 #define CONFIG_POSIX_MADVISE 1
-#define CONFIG_SIGEV_THREAD_ID 1
-#define CONFIG_GLX 1
-#define CONFIG_ZERO_MALLOC 1
 #define CONFIG_QOM_CAST_DEBUG 1
 #define CONFIG_COROUTINE_BACKEND ucontext
 #define CONFIG_COROUTINE_POOL 1
@@ -65,9 +63,9 @@
 #define CONFIG_HAS_ENVIRON 1
 #define CONFIG_CPUID_H 1
 #define CONFIG_INT128 1
-#define CONFIG_TPM $(CONFIG_SOFTMMU)
+#define CONFIG_TPM 1
 #define CONFIG_TPM_PASSTHROUGH 1
-#define CONFIG_TRACE_NOP 1
+#define CONFIG_TRACE_LOG 1
 #define CONFIG_TRACE_FILE trace
+#define CONFIG_IASL iasl
 #define HOST_DSOSUF ".so"
-#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/config/target-mips/config-target.h b/android-qemu2-glue/config/target-mips/config-target.h
index f7c37f0..e0a14fb 100644
--- a/android-qemu2-glue/config/target-mips/config-target.h
+++ b/android-qemu2-glue/config/target-mips/config-target.h
@@ -2,6 +2,7 @@
 #define TARGET_ABI_MIPSO32 1
 #define TARGET_MIPS 1
 #define TARGET_NAME "mipsel"
+#define TARGET_MIPS 1
 #define CONFIG_SOFTMMU 1
 #define CONFIG_I386_DIS 1
 #define CONFIG_MIPS_DIS 1
diff --git a/android-qemu2-glue/config/windows-x86/config-host.h b/android-qemu2-glue/config/windows-x86/config-host.h
index 3bc3a6e..476bdb9 100644
--- a/android-qemu2-glue/config/windows-x86/config-host.h
+++ b/android-qemu2-glue/config/windows-x86/config-host.h
@@ -7,35 +7,35 @@
 #define CONFIG_QEMU_LOCALEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86/locale"
 #define HOST_I386 1
 #define CONFIG_WIN32 1
-#define CONFIG_FILEVERSION 2,2,0,0
-#define CONFIG_PRODUCTVERSION 2,2,0,0
+#define CONFIG_FILEVERSION 2,7,0,0
+#define CONFIG_PRODUCTVERSION 2,7,0,0
 #define CONFIG_SLIRP 1
 #define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
 #define CONFIG_AUDIO_DRIVERS \
     &winaudio_audio_driver,\
-    &winwave_audio_driver,\
+    &dsound_audio_driver,\
 
 #define CONFIG_WINAUDIO 1
-#define CONFIG_WINWAVE 1
+#define CONFIG_DSOUND 1
 #define CONFIG_AUDIO_WIN_INT 1
 #define CONFIG_BDRV_RW_WHITELIST\
     NULL
 #define CONFIG_BDRV_RO_WHITELIST\
     NULL
 #define CONFIG_VNC 1
-#define QEMU_VERSION "2.2.0"
-#define QEMU_PKGVERSION ""
+#define QEMU_VERSION "2.7.0"
 #define CONFIG_SDL 1
 #define CONFIG_SDLABI 2.0
+#define CONFIG_HAS_GLIB_SUBPROCESS_TESTS 1
+#define CONFIG_TLS_PRIORITY "NORMAL"
 #define CONFIG_FDT 1
-#define CONFIG_ZERO_MALLOC 1
 #define CONFIG_QOM_CAST_DEBUG 1
 #define CONFIG_COROUTINE_BACKEND win32
 #define CONFIG_COROUTINE_POOL 1
 #define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1
 #define CONFIG_CPUID_H 1
-#define CONFIG_TPM $(CONFIG_SOFTMMU)
-#define CONFIG_TRACE_NOP 1
+#define CONFIG_TPM 1
+#define CONFIG_TRACE_LOG 1
 #define CONFIG_TRACE_FILE trace
+#define CONFIG_IASL iasl
 #define HOST_DSOSUF ".dll"
-#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/config/windows-x86_64/config-host.h b/android-qemu2-glue/config/windows-x86_64/config-host.h
index a3df876..ff2870d 100644
--- a/android-qemu2-glue/config/windows-x86_64/config-host.h
+++ b/android-qemu2-glue/config/windows-x86_64/config-host.h
@@ -7,36 +7,36 @@
 #define CONFIG_QEMU_LOCALEDIR "/opt2/digit/repo/studio-dev/prebuilts/android-emulator-build/qemu-android-deps/windows-x86_64/locale"
 #define HOST_X86_64 1
 #define CONFIG_WIN32 1
-#define CONFIG_FILEVERSION 2,2,0,0
-#define CONFIG_PRODUCTVERSION 2,2,0,0
+#define CONFIG_FILEVERSION 2,7,0,0
+#define CONFIG_PRODUCTVERSION 2,7,0,0
 #define CONFIG_SLIRP 1
 #define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
 #define CONFIG_AUDIO_DRIVERS \
     &winaudio_audio_driver,\
-    &winwave_audio_driver,\
+    &dsound_audio_driver,\
 
 #define CONFIG_WINAUDIO 1
-#define CONFIG_WINWAVE 1
+#define CONFIG_DSOUND 1
 #define CONFIG_AUDIO_WIN_INT 1
 #define CONFIG_BDRV_RW_WHITELIST\
     NULL
 #define CONFIG_BDRV_RO_WHITELIST\
     NULL
 #define CONFIG_VNC 1
-#define QEMU_VERSION "2.2.0"
-#define QEMU_PKGVERSION ""
+#define QEMU_VERSION "2.7.0"
 #define CONFIG_SDL 1
 #define CONFIG_SDLABI 2.0
+#define CONFIG_HAS_GLIB_SUBPROCESS_TESTS 1
+#define CONFIG_TLS_PRIORITY "NORMAL"
 #define CONFIG_FDT 1
-#define CONFIG_ZERO_MALLOC 1
 #define CONFIG_QOM_CAST_DEBUG 1
 #define CONFIG_COROUTINE_BACKEND win32
 #define CONFIG_COROUTINE_POOL 1
 #define CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE 1
 #define CONFIG_CPUID_H 1
 #define CONFIG_INT128 1
-#define CONFIG_TPM $(CONFIG_SOFTMMU)
-#define CONFIG_TRACE_NOP 1
+#define CONFIG_TPM 1
+#define CONFIG_TRACE_LOG 1
 #define CONFIG_TRACE_FILE trace
+#define CONFIG_IASL iasl
 #define HOST_DSOSUF ".dll"
-#define CONFIG_ANDROID 1
diff --git a/android-qemu2-glue/display.cpp b/android-qemu2-glue/display.cpp
index 99a9683..0f2a055 100644
--- a/android-qemu2-glue/display.cpp
+++ b/android-qemu2-glue/display.cpp
@@ -19,7 +19,8 @@
 #include "android/emulator-window.h"
 
 extern "C" {
-    #include "ui/console.h"
+#include "qemu/osdep.h"
+#include "ui/console.h"
 }
 
 namespace {
@@ -149,6 +150,10 @@
     return true;
 }
 
+extern "C" void sdl_display_early_init(int opengl) {
+    (void)opengl;
+}
+
 extern "C" bool sdl_display_init(DisplayState* ds,
                                  int full_screen,
                                  int no_frame) {
diff --git a/android-qemu2-glue/display.h b/android-qemu2-glue/display.h
index 98fc9c7..9eb7148 100644
--- a/android-qemu2-glue/display.h
+++ b/android-qemu2-glue/display.h
@@ -18,8 +18,9 @@
 
 ANDROID_BEGIN_HEADER
 
-#include "ui/console.h"
-#include "../qemu/android/framebuffer.h"
+#include "qemu/osdep.h"
+#include "qemu/typedefs.h"
+#include "android/framebuffer.h"
 
 bool android_display_init(DisplayState* ds, QFrameBuffer* qfbuff);
 
diff --git a/android-qemu2-glue/emulation/CharSerialLine.cpp b/android-qemu2-glue/emulation/CharSerialLine.cpp
index 6a958f6..e3e4063 100644
--- a/android-qemu2-glue/emulation/CharSerialLine.cpp
+++ b/android-qemu2-glue/emulation/CharSerialLine.cpp
@@ -11,7 +11,10 @@
 
 #include "android-qemu2-glue/emulation/CharSerialLine.h"
 
+#include <type_traits>
+
 extern "C" {
+#include "qemu/osdep.h"
 #include "sysemu/char.h"
 }
 
diff --git a/android-qemu2-glue/emulation/VmLock.cpp b/android-qemu2-glue/emulation/VmLock.cpp
index ece6ab3..9bc0ce3 100644
--- a/android-qemu2-glue/emulation/VmLock.cpp
+++ b/android-qemu2-glue/emulation/VmLock.cpp
@@ -14,24 +14,15 @@
 
 #include "android-qemu2-glue/emulation/VmLock.h"
 
-#include "android/base/Log.h"
+#include <type_traits>
 
 extern "C" {
+#include "qemu/osdep.h"
 #include "qemu/main-loop.h"
 }  // extern "C"
 
 namespace qemu2 {
 
-// TECHNICAL NOTE:
-//
-// This implementation needs to protect against recursive lock() calls
-// which can happen because some code in AndroidEmu calls it, without
-// knowing whether it's running in the thread that holds the BQL or not.
-//
-// What we want is to ensure that qemu_mutex_lock_iothread() is always true
-// when we leave ::lock(), and that it will be false when ::unlock() has
-// been called as often as ::lock() was.
-
 void VmLock::lock() {
     qemu_mutex_lock_iothread();
 }
@@ -41,7 +32,7 @@
 }
 
 bool VmLock::isLockedBySelf() const {
-    return qemu_mutex_check_iothread();
+    return qemu_mutex_iothread_locked();
 }
 
 }  // namespace qemu2
diff --git a/android-qemu2-glue/emulation/charpipe.c b/android-qemu2-glue/emulation/charpipe.c
index c03f8ac..1d4b59e 100644
--- a/android-qemu2-glue/emulation/charpipe.c
+++ b/android-qemu2-glue/emulation/charpipe.c
@@ -11,11 +11,12 @@
 */
 #include "android/utils/debug.h"
 #include "android/utils/cbuffer.h"
+#include "qemu/osdep.h"
 #include "sysemu/char.h"
 
-#define  xxDEBUG
+#define DEBUG 0
 
-#ifdef DEBUG
+#if DEBUG
 #  include <stdio.h>
 #  define  D(...)   ( fprintf( stderr, __VA_ARGS__ ), fprintf(stderr, "\n") )
 #else
@@ -441,7 +442,7 @@
 
 
 void
-charpipe_poll( void )
+qemu_charpipe_poll( void )
 {
     CharPipeState*  cp     = _s_charpipes;
     CharPipeState*  cp_end = cp + MAX_CHAR_PIPES;
diff --git a/android-qemu2-glue/emulation/charpipe.h b/android-qemu2-glue/emulation/charpipe.h
index 7a62487..2ab24e9 100644
--- a/android-qemu2-glue/emulation/charpipe.h
+++ b/android-qemu2-glue/emulation/charpipe.h
@@ -11,6 +11,7 @@
 */
 #pragma once
 
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "android/utils/compiler.h"
 
@@ -20,16 +21,17 @@
  * QEMU components. For Android, this is used to connect an emulated serial port
  * with the android modem
  */
-extern int  qemu_chr_open_charpipe( CharDriverState* *pfirst, CharDriverState* *psecond );
+extern int qemu_chr_open_charpipe(CharDriverState* *pfirst,
+                                  CharDriverState* *psecond);
 
 /* create a buffering character driver for a given endpoint. The result will buffer
  * anything that is sent to it but cannot be sent to the endpoint immediately.
  * On the other hand, if the endpoint calls can_read() or read(), these calls
  * are passed immediately to the can_read() or read() handlers of the result.
  */
-extern CharDriverState*  qemu_chr_open_buffer( CharDriverState*  endpoint );
+extern CharDriverState *qemu_chr_open_buffer(CharDriverState*  endpoint);
 
 /* must be called from the main event loop to poll all charpipes */
-extern void charpipe_poll( void );
+extern void qemu_charpipe_poll(void);
 
 ANDROID_END_HEADER
diff --git a/android-qemu2-glue/main.cpp b/android-qemu2-glue/main.cpp
index 3735019..0a18f06 100755
--- a/android-qemu2-glue/main.cpp
+++ b/android-qemu2-glue/main.cpp
@@ -448,6 +448,7 @@
     if (opts->skip_adb_auth) {
         args[n++] = "-skip-adb-auth";
     }
+
     /** SNAPSHOT STORAGE HANDLING */
 
     /* If we have a valid snapshot storage path */
@@ -709,12 +710,6 @@
     args[n++] = "-cpu";
     args[n++] = kTarget.qemuCpu;
 
-    // Set env var to "on" for Intel PMU if the feature is enabled.
-    // cpu.c will then read that.
-    if (android::featurecontrol::isEnabled(android::featurecontrol::IntelPerformanceMonitoringUnit)) {
-        System::get()->envSet("ANDROID_EMU_FEATURE_IntelPerformanceMonitoringUnit", "on");
-    }
-
 #if defined(TARGET_X86_64) || defined(TARGET_I386)
     char* accel_status = NULL;
     CpuAccelMode accel_mode = ACCEL_AUTO;
diff --git a/android-qemu2-glue/net-android.cpp b/android-qemu2-glue/net-android.cpp
index d5fe8b3..913e6b5 100644
--- a/android-qemu2-glue/net-android.cpp
+++ b/android-qemu2-glue/net-android.cpp
@@ -1,4 +1,4 @@
-// Copyright 2015 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
 //
 // This software is licensed under the terms of the GNU General Public
 // License version 2, as published by the Free Software Foundation, and
@@ -9,7 +9,8 @@
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 // GNU General Public License for more details.
 
-#include "net-android.h"
+#include "android-qemu2-glue/net-android.h"
+
 #include "android/android.h"
 #include "android/network/constants.h"
 #include "android/network/globals.h"
@@ -17,48 +18,48 @@
 #include "android/shaper.h"
 
 extern "C" {
-#include "net/net.h"
+#include "qemu/osdep.h"
+#include "net/slirp.h"
 }
 
-#if defined(CONFIG_SLIRP)
-static void* s_slirp_state = nullptr;
-static void* s_net_client_state = nullptr;
-static Slirp* s_slirp = nullptr;
+static void* s_opaque = nullptr;
 
-static void
-android_net_delay_in_cb(void* data, size_t size, void* opaque)
+void android_qemu_init_slirp_shapers(void)
 {
-    slirp_input(s_slirp, static_cast<const uint8_t*>(data), size);
-}
+    android_net_delay_in = netdelay_create(
+            [](void* data, size_t size, void* opaque) {
+                net_slirp_receive_raw(s_opaque,
+                                      static_cast<const uint8_t*>(data),
+                                      static_cast<int>(size));
+            });
 
-static void
-android_net_shaper_in_cb(void* data, size_t size, void* opaque)
-{
-    netdelay_send_aux(android_net_delay_in, data, size, opaque);
-}
+    android_net_shaper_in = netshaper_create(1,
+            [](void* data, size_t size, void* opaque) {
+                netdelay_send_aux(android_net_delay_in, data, size, opaque);
+            });
 
-static void
-android_net_shaper_out_cb(void* data, size_t size, void* opaque)
-{
-    qemu_send_packet(static_cast<NetClientState*>(s_net_client_state),
-                     static_cast<const uint8_t*>(data),
-                     size);
-}
-
-void
-slirp_init_shapers(void* slirp_state, void* net_client_state, Slirp* slirp)
-{
-    s_slirp_state = slirp_state;
-    s_net_client_state = net_client_state;
-    s_slirp = slirp;
-    android_net_delay_in = netdelay_create(android_net_delay_in_cb);
-    android_net_shaper_in = netshaper_create(1, android_net_shaper_in_cb);
-    android_net_shaper_out = netshaper_create(1, android_net_shaper_out_cb);
+    android_net_shaper_out = netshaper_create(1,
+            [](void* data, size_t size, void* opaque) {
+                net_slirp_output_raw(opaque,
+                                     static_cast<const uint8_t*>(data),
+                                     static_cast<int>(size));
+            });
 
     netdelay_set_latency(android_net_delay_in, android_net_min_latency,
                          android_net_max_latency);
+
     netshaper_set_rate(android_net_shaper_out, android_net_download_speed);
     netshaper_set_rate(android_net_shaper_in, android_net_upload_speed);
-}
-#endif  // CONFIG_SLIRP
 
+    s_opaque = net_slirp_set_shapers(
+            android_net_shaper_out,
+            [](void* opaque, const void* data, int len) {
+                netshaper_send_aux(static_cast<NetShaper>(opaque),
+                                   (char*)data, len, s_opaque);
+            },
+            android_net_shaper_in,
+            [](void* opaque, const void* data, int len) {
+                netshaper_send_aux(static_cast<NetShaper>(opaque),
+                                   (void*)data, len, s_opaque);
+            });
+}
diff --git a/android-qemu2-glue/net-android.h b/android-qemu2-glue/net-android.h
index 693d87e..83add05 100644
--- a/android-qemu2-glue/net-android.h
+++ b/android-qemu2-glue/net-android.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Android Open Source Project
+// Copyright 2016 The Android Open Source Project
 //
 // This software is licensed under the terms of the GNU General Public
 // License version 2, as published by the Free Software Foundation, and
@@ -11,17 +11,10 @@
 
 #pragma once
 
-#include "config-host.h"
 #include "android/utils/compiler.h"
 
 ANDROID_BEGIN_HEADER
 
-#if defined(CONFIG_SLIRP)
-#include "libslirp.h"
-
-void slirp_init_shapers(void* slirp_state,
-                        void* net_client_state,
-                        Slirp *slirp);
-#endif  // CONFIG_SLIRP
+void android_qemu_init_slirp_shapers(void);
 
 ANDROID_END_HEADER
diff --git a/android-qemu2-glue/qemu-display-agent-impl.cpp b/android-qemu2-glue/qemu-display-agent-impl.cpp
index 8559da5..8167372 100644
--- a/android-qemu2-glue/qemu-display-agent-impl.cpp
+++ b/android-qemu2-glue/qemu-display-agent-impl.cpp
@@ -15,9 +15,12 @@
 #include "android-qemu2-glue/qemu-control-impl.h"
 
 extern "C" {
-    #include "ui/console.h"
+#include "qemu/osdep.h"
+#include "ui/console.h"
 }
 
+#include <string.h>
+
 static void getFrameBuffer(int* w, int* h, int* lineSize, int* bytesPerPixel,
                            uint8_t** frameBufferData) {
     // find the first graphics console
@@ -56,36 +59,51 @@
 }
 
 namespace {
-    struct dul_data {
-        AndroidDisplayUpdateCallback callback;
-        void* opaque;
-    };
-}
 
-static void on_display_update(DisplayUpdateListener* dul,
-        int x, int y, int w, int h) {
-    dul_data* data = static_cast<dul_data*>(dul->opaque);
-    data->callback(data->opaque, x, y, w, h);
-}
+struct AndroidDisplayChangeListener : public DisplayChangeListener {
+    AndroidDisplayChangeListener(AndroidDisplayUpdateCallback callback,
+                                 void* opaque) {
+        memset(this, 0, sizeof(*this));
+        mCallback = callback;
+        mOpaque = opaque;
+        this->ops = &kOps;
+        register_displaychangelistener(this);
+    }
+
+    ~AndroidDisplayChangeListener() {
+        unregister_displaychangelistener(this);
+    }
+
+    AndroidDisplayUpdateCallback mCallback;
+    void* mOpaque;
+
+    static void onDisplayUpdate(DisplayChangeListener* dcl,
+                                int x, int y, int w, int h) {
+        auto adcl = reinterpret_cast<AndroidDisplayChangeListener*>(dcl);
+        adcl->mCallback(adcl->mOpaque, x, y, w, h);
+    }
+
+    static const DisplayChangeListenerOps kOps;
+};
+
+// static
+const DisplayChangeListenerOps AndroidDisplayChangeListener::kOps = {
+    .dpy_name = "qemu2 display",
+    .dpy_refresh = nullptr,
+    .dpy_gfx_update = &onDisplayUpdate,
+};
+
+}  // namespace
 
 static void registerUpdateListener(AndroidDisplayUpdateCallback callback,
                                    void* opaque) {
-    const auto listener = new DisplayUpdateListener();
-    *listener = DisplayUpdateListener();
-    listener->dpy_gfx_update = &on_display_update;
-
-    auto data = new dul_data();
-    data->callback = callback;
-    data->opaque = opaque;
-    listener->opaque = data;
-
-    register_displayupdatelistener(listener);
+    static AndroidDisplayChangeListener* s_listener =
+            new AndroidDisplayChangeListener(callback, opaque);
 }
 
-
 static const QAndroidDisplayAgent displayAgent = {
-        .getFrameBuffer = &getFrameBuffer,
-        .registerUpdateListener = &registerUpdateListener
+    .getFrameBuffer = &getFrameBuffer,
+    .registerUpdateListener = &registerUpdateListener
 };
 
 const QAndroidDisplayAgent* const gQAndroidDisplayAgent = &displayAgent;
diff --git a/android-qemu2-glue/qemu-net-agent-impl.c b/android-qemu2-glue/qemu-net-agent-impl.c
index 3bb1e72..eac5b77 100644
--- a/android-qemu2-glue/qemu-net-agent-impl.c
+++ b/android-qemu2-glue/qemu-net-agent-impl.c
@@ -15,6 +15,7 @@
 #include "android/emulation/control/net_agent.h"
 
 #include "android/utils/sockets.h"
+#include "qemu/osdep.h"
 #include "qemu/sockets.h"
 #include "net/slirp.h"
 
@@ -22,21 +23,20 @@
 #include "libslirp.h"
 
 static bool isSlirpInited() {
-    return net_slirp_is_inited() != 0;
+    return net_slirp_state() != NULL;
 }
 
 static bool slirpRedir(bool isUdp, int hostPort,
                       uint32_t guestAddr, int guestPort) {
     struct in_addr host = { .s_addr = htonl(SOCK_ADDRESS_INET_LOOPBACK) };
     struct in_addr guest = { .s_addr = 0 };
-    return slirp_add_hostfwd(net_slirp_lookup(NULL, NULL, NULL), isUdp,
-                             host, hostPort, guest, guestPort) == 0;
+    return slirp_add_hostfwd(net_slirp_state(), isUdp, host, hostPort, guest,
+                             guestPort) == 0;
 }
 
 bool slirpUnredir(bool isUdp, int hostPort) {
     struct in_addr host = { .s_addr = htonl(SOCK_ADDRESS_INET_LOOPBACK) };
-    return slirp_remove_hostfwd(net_slirp_lookup(NULL, NULL, NULL), isUdp,
-                                host, hostPort) == 0;
+    return slirp_remove_hostfwd(net_slirp_state(), isUdp, host, hostPort) == 0;
 }
 
 
diff --git a/android-qemu2-glue/qemu-setup-dns-servers.cpp b/android-qemu2-glue/qemu-setup-dns-servers.cpp
new file mode 100644
index 0000000..108e53d
--- /dev/null
+++ b/android-qemu2-glue/qemu-setup-dns-servers.cpp
@@ -0,0 +1,175 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "android-qemu2-glue/qemu-setup.h"
+
+#include "android/base/Log.h"
+#include "android/utils/debug.h"
+
+#ifdef _WIN32
+// This includes must happen before qemu/osdep.h to avoid compiler
+// errors regarding FD_SETSIZE being redefined.
+#include "android/base/sockets/Winsock.h"
+#include "android/base/sockets/SocketErrors.h"
+#else
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+
+extern "C" {
+#include "qemu/osdep.h"
+#include "net/slirp.h"
+#include "slirp/libslirp.h"
+}  // extern "C"
+
+#include <vector>
+
+#include <errno.h>
+
+#define MAX_DNS_SERVERS 8
+
+static int s_num_dns_server_addresses = 0;
+static sockaddr_storage s_dns_server_addresses[MAX_DNS_SERVERS] = {};
+
+// Resolve host name |hostName| into a list of sockaddr_storage.
+// On success, return true and append the names to |*out|. On failure
+// return false, leave |*out| untouched, and sets errno.
+static bool resolveHostNameToList(
+        const char* hostName, std::vector<sockaddr_storage>* out) {
+    addrinfo* res = nullptr;
+    addrinfo hints = {};
+    hints.ai_family = AF_UNSPEC;
+    int ret = ::getaddrinfo(hostName, nullptr, &hints, &res);
+    if (ret != 0) {
+        // Handle errors.
+        int err = 0;
+        switch (ret) {
+            case EAI_AGAIN:  // server is down
+            case EAI_FAIL:   // server is sick
+                err = EHOSTDOWN;
+                break;
+/* NOTE that in x86_64-w64-mingw32 both EAI_NODATA and EAI_NONAME are the same */
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+            case EAI_NODATA:
+#endif
+            case EAI_NONAME:
+                err = ENOENT;
+                break;
+
+            case EAI_MEMORY:
+                err = ENOMEM;
+                break;
+
+            default:
+                err = EINVAL;
+        }
+        errno = err;
+        return false;
+    }
+
+    int count = 0;
+
+    for (auto r = res; r != nullptr; r = r->ai_next) {
+        sockaddr_storage addr = {};
+        switch (r->ai_family) {
+            case AF_INET:
+                *(struct sockaddr_in *)&addr =
+                        *(const struct sockaddr_in *)r->ai_addr;
+                break;
+
+            case AF_INET6:
+                *(struct sockaddr_in6 *)&addr =
+                        *(const struct sockaddr_in6 *)r->ai_addr;
+                break;
+            default:
+                continue;
+        }
+        out->emplace_back(std::move(addr));
+        count++;
+    }
+    ::freeaddrinfo(res);
+
+    return (count > 0);
+}
+
+bool qemu_android_emulation_setup_dns_servers(const char* dns_servers,
+                                              int* pcount4, int* pcount6) {
+    CHECK(net_slirp_state() != nullptr) << "slirp stack should be inited!";
+
+    if (!dns_servers || !dns_servers[0]) {
+        // Empty list, use the default behaviour.
+        return 0;
+    }
+
+    std::vector<sockaddr_storage> server_addresses;
+
+    // Separate individual DNS server names, then resolve each one of them
+    // into one or more IP addresses. Support both IPv4 and IPv6 at the same
+    // time.
+    const char* p = dns_servers;
+    while (*p) {
+        const char* next_p;
+        const char* comma = strchr(p, ',');
+        if (!comma) {
+            comma = p + strlen(p);
+            next_p = comma;
+        } else {
+            next_p = comma + 1;
+        }
+        while (p < comma && *p == ' ') p++;
+        while (p < comma && comma[-1] == ' ') comma--;
+
+        if (comma > p) {
+            // Extract single server name.
+            std::string server(p, comma - p);
+            if (!resolveHostNameToList(server.c_str(), &server_addresses)) {
+                dwarning("Ignoring ivalid DNS address: [%s]\n", server.c_str());
+            }
+        }
+        p = next_p;
+    }
+
+    int count = static_cast<int>(server_addresses.size());
+    if (!count) {
+        return 0;
+    }
+
+    // Save it for qemu_android_emulator_init_slirp().
+    s_num_dns_server_addresses = count;
+    memcpy(s_dns_server_addresses, &server_addresses[0],
+           count * sizeof(server_addresses[0]));
+
+    // Count number of IPv4 and IPv6 DNS servers.
+    int count4 = 0;
+    int count6 = 0;
+    for (const auto& item : server_addresses) {
+        if (item.ss_family == AF_INET) {
+            count4 += 1;
+        } else if (item.ss_family == AF_INET6) {
+            count6 += 1;
+        }
+    }
+
+    *pcount4 = count4;
+    *pcount6 = count6;
+
+    return true;
+}
+
+void qemu_android_emulation_init_slirp(void) {
+    slirp_init_custom_dns_servers(static_cast<Slirp*>(net_slirp_state()),
+                                  s_dns_server_addresses,
+                                  s_num_dns_server_addresses);
+}
+
diff --git a/android-qemu2-glue/qemu-setup.cpp b/android-qemu2-glue/qemu-setup.cpp
index 0bbdb77..bdb0af8 100644
--- a/android-qemu2-glue/qemu-setup.cpp
+++ b/android-qemu2-glue/qemu-setup.cpp
@@ -18,27 +18,36 @@
 #include "android/base/Log.h"
 #include "android/console.h"
 #include "android-qemu2-glue/emulation/android_pipe_device.h"
-#include "android-qemu2-glue/emulation/VmLock.h"
-#include "android-qemu2-glue/qemu-control-impl.h"
+#include "android-qemu2-glue/emulation/charpipe.h"
 #include "android-qemu2-glue/emulation/goldfish_sync.h"
+#include "android-qemu2-glue/emulation/VmLock.h"
+#include "android-qemu2-glue/looper-qemu.h"
+#include "android-qemu2-glue/android_qemud.h"
+#include "android-qemu2-glue/net-android.h"
+#include "android-qemu2-glue/qemu-control-impl.h"
 
 extern "C" {
+#include "qemu/osdep.h"
+#include "qemu-common.h"
 #include "qemu/main-loop.h"
+#include "qemu/thread.h"
 }  // extern "C"
 
 using android::VmLock;
 
-bool qemu_android_emulation_setup() {
-    static const AndroidConsoleAgents consoleAgents = {
-            gQAndroidBatteryAgent,
-            gQAndroidFingerAgent,
-            gQAndroidLocationAgent,
-            gQAndroidTelephonyAgent,
-            gQAndroidUserEventAgent,
-            gQAndroidVmOperations,
-            gQAndroidNetAgent
-    };
+bool qemu_android_emulation_early_setup() {
+    // Ensure that the looper is set for the main thread and for any
+    // future thread created by QEMU.
+    qemu_looper_setForThread();
+    qemu_thread_register_setup_callback(qemu_looper_setForThread);
 
+    // Ensure charpipes i/o are handled properly.
+    main_loop_register_poll_callback(qemu_charpipe_poll);
+
+    // Register qemud-related snapshot callbacks.
+    android_qemu2_qemud_init();
+
+    // Ensure the VmLock implementation is setup.
     VmLock* vmLock = new qemu2::VmLock();
     VmLock* prevVmLock = VmLock::set(vmLock);
     CHECK(prevVmLock == nullptr) << "Another VmLock was already installed!";
@@ -48,9 +57,30 @@
         return false;
     }
 
+    // Initialize host sync service.
     if (!qemu_android_sync_init(vmLock)) {
         return false;
     }
 
+    return true;
+}
+
+bool qemu_android_emulation_setup() {
+    android_qemu_init_slirp_shapers();
+
+    // Initialize UI/console agents.
+    static const AndroidConsoleAgents consoleAgents = {
+            gQAndroidBatteryAgent,
+            gQAndroidFingerAgent,
+            gQAndroidLocationAgent,
+            gQAndroidTelephonyAgent,
+            gQAndroidUserEventAgent,
+            gQAndroidVmOperations,
+            gQAndroidNetAgent,
+    };
+
     return android_emulation_setup(&consoleAgents);
 }
+
+void qemu_android_emulation_teardown() {
+}
diff --git a/android-qemu2-glue/qemu-setup.h b/android-qemu2-glue/qemu-setup.h
index 1be84b4..aaf2f0d 100644
--- a/android-qemu2-glue/qemu-setup.h
+++ b/android-qemu2-glue/qemu-setup.h
@@ -20,6 +20,32 @@
 
 ANDROID_BEGIN_HEADER
 
+/* Call this function at the start of the QEMU main() function to perform
+ * early setup of Android emulation. This will ensure the glue will inject
+ * all relevant callbacks into QEMU2. As well as setup the looper for the
+ * main thread. Return true on success, false otherwise. */
+extern bool qemu_android_emulation_early_setup(void);
+
+/* Call this function to setup a list of custom DNS servers to be used
+ * by the network stack. |dns_servers| must be the content of the
+ * -dns-server option, i.e. a comma-separated list of DNS server addresses.
+ * On success, return true and set |*count4| and |*count6| to the number
+ * of IPv4 and IPv6 IP addresses, respectively. Return false on failure. */
+extern bool qemu_android_emulation_setup_dns_servers(const char* dns_servers,
+                                                     int* count4,
+                                                     int* count6);
+
+/* Call this function after the slirp stack has been initialized, typically
+ * by calling net_init_clients() in vl.c, to inject Android-specific features
+ * (e.g. custom DNS server list) into the network stack. */
+extern void qemu_android_emulation_init_slirp(void);
+
+/* Call this function after the QEMU main() function has inited the
+ * machine, but before it has started it. */
 extern bool qemu_android_emulation_setup(void);
 
+/* Call this function at the end of the QEMU main() function, just
+ * after the main loop has returned due to a machine exit. */
+extern void qemu_android_emulation_teardown(void);
+
 ANDROID_END_HEADER
diff --git a/android-qemu2-glue/qemu-user-event-agent-impl.c b/android-qemu2-glue/qemu-user-event-agent-impl.c
index a19f1e1..c43e68c 100644
--- a/android-qemu2-glue/qemu-user-event-agent-impl.c
+++ b/android-qemu2-glue/qemu-user-event-agent-impl.c
@@ -13,6 +13,8 @@
 
 #include "android/multitouch-screen.h"
 #include "android/utils/debug.h"
+
+#include "qemu/osdep.h"
 #include "hw/input/goldfish_events.h"
 #include "ui/console.h"
 
diff --git a/android-qemu2-glue/qemu-vm-operations-impl.c b/android-qemu2-glue/qemu-vm-operations-impl.c
index 8cf1587..2f745ba 100644
--- a/android-qemu2-glue/qemu-vm-operations-impl.c
+++ b/android-qemu2-glue/qemu-vm-operations-impl.c
@@ -16,8 +16,8 @@
 
 #include "android/emulation/control/callbacks.h"
 #include "android/emulation/control/vm_operations.h"
-//#include "cpu.h"
-//#include "monitor/monitor.h"
+
+#include "qemu/osdep.h"
 #include "sysemu/sysemu.h"
 
 #include <stdlib.h>
diff --git a/android-qemu2-glue/qemu-window-agent-impl.c b/android-qemu2-glue/qemu-window-agent-impl.c
index 9687956..82b4996 100644
--- a/android-qemu2-glue/qemu-window-agent-impl.c
+++ b/android-qemu2-glue/qemu-window-agent-impl.c
@@ -21,4 +21,3 @@
 
 const QAndroidEmulatorWindowAgent* const gQAndroidEmulatorWindowAgent =
     &sQAndroidEmulatorWindowAgent;
-
diff --git a/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py b/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py
index 0404ba8..a951a0a 100755
--- a/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py
+++ b/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py
@@ -26,29 +26,28 @@
 LINK_QEMU_PREFIX = 'LINK-qemu-system-'
 IGNORED_OBJECTS = [
     '../audio/sdlaudio.o',
-    '../disas/arm-a64.o',
-    '../disas/libvixl/a64/decoder-a64.o',
-    '../disas/libvixl/a64/disasm-a64.o',
-    '../disas/libvixl/a64/instructions-a64.o',
-    '../disas/libvixl/utils.o',
     'gdbstub-xml.o',
-    '../hw/display/framebuffer.o',
-    'hw/misc/android_boot_properties.o',
-    'hw/misc/android_pipe_opengles.o',
+    'hw/i386/acpi-build.o',
+    'hw/i386/pc_piix.o',
+    '../qmp-introspect.o',
     '../qmp-marshal.o',
     'trace/generated-helpers.o',
     '../ui/sdl_zoom.o',
     '../ui/sdl.o',
     '../ui/sdl2.o',
+    '../ui/sdl2-2d.o',
+    '../ui/sdl2-input.o',
+    '../vl.o',
     '/version.o',   # something from the Windows build
     ]
 
 CC_OBJECTS = [
     'disas/arm-a64.o',
-    'disas/libvixl/a64/decoder-a64.o',
-    'disas/libvixl/a64/disasm-a64.o',
-    'disas/libvixl/a64/instructions-a64.o',
-    'disas/libvixl/utils.o',
+    'disas/libvixl/vixl/a64/decoder-a64.o',
+    'disas/libvixl/vixl/a64/disasm-a64.o',
+    'disas/libvixl/vixl/a64/instructions-a64.o',
+    'disas/libvixl/vixl/compiler-intrinsics.o',
+    'disas/libvixl/vixl/utils.o',
     ]
 
 # objects which have to be moved to *TARGET files,
diff --git a/android-qemu2-glue/stubs/win32-stubs.c b/android-qemu2-glue/stubs/win32-stubs.c
new file mode 100644
index 0000000..aecdc29
--- /dev/null
+++ b/android-qemu2-glue/stubs/win32-stubs.c
@@ -0,0 +1,54 @@
+#include "qemu/osdep.h"
+
+#include "android/utils/win32_unicode.h"
+
+HANDLE win32CreateFile(
+        LPCTSTR               lpFileName,
+        DWORD                 dwDesiredAccess,
+        DWORD                 dwShareMode,
+        LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+        DWORD                 dwCreationDisposition,
+        DWORD                 dwFlagsAndAttributes,
+        HANDLE                hTemplateFile)
+{
+    HANDLE result = INVALID_HANDLE_VALUE;
+    wchar_t* wide_name = win32_utf8_to_utf16_str(lpFileName);
+    if (wide_name != NULL) {
+        result = CreateFileW(wide_name, dwDesiredAccess,
+                             dwShareMode, lpSecurityAttributes,
+                             dwCreationDisposition, dwFlagsAndAttributes,
+                             hTemplateFile);
+        free(wide_name);
+    }
+    return result;
+}
+
+DWORD win32GetCurrentDirectory(
+        DWORD  nBufferLength,
+        LPTSTR lpBuffer)
+{
+    wchar_t wide_buffer[MAX_PATH];
+    DWORD ret = GetCurrentDirectoryW(MAX_PATH, wide_buffer);
+    if (ret == 0 || ret > MAX_PATH) {
+        return ret;
+    }
+    int ret2 = win32_utf16_to_utf8_buf(wide_buffer, lpBuffer, nBufferLength);
+    return (ret2 < 0 || (DWORD)ret2 > nBufferLength) ? 0 : (DWORD)ret2;
+}
+
+DWORD win32GetModuleFileName(
+        HMODULE hModule,
+        LPTSTR  lpFilename,
+        DWORD   nSize)
+{
+    wchar_t wide_buffer[MAX_PATH];
+    if (!GetModuleFileNameW(hModule, wide_buffer, MAX_PATH)) {
+        return 0;
+    }
+
+    int ret = win32_utf16_to_utf8_buf(wide_buffer, lpFilename, nSize);
+    if (ret < 0 || ret >= nSize) {
+        return 0;
+    }
+    return (DWORD)ret;
+}
diff --git a/android-qemu2-glue/telephony/modem_init.c b/android-qemu2-glue/telephony/modem_init.c
index 0377c25..0e397a6 100644
--- a/android-qemu2-glue/telephony/modem_init.c
+++ b/android-qemu2-glue/telephony/modem_init.c
@@ -14,8 +14,11 @@
 #include "android/telephony/modem_driver.h"
 #include "android-qemu2-glue/utils/stream.h"
 
+#include "qemu/osdep.h"
 #include "hw/hw.h"
 
+#include <assert.h>
+
 #define MODEM_DEV_STATE_SAVE_VERSION 1
 
 static void modem_state_save(QEMUFile* file, void* opaque)
@@ -41,13 +44,13 @@
 void qemu_android_modem_init(int base_port) {
     android_modem_init(base_port);
 
-    if (android_modem_serial_line != NULL) {
-        register_savevm(NULL,
-                        "android_modem",
-                        0,
-                        MODEM_DEV_STATE_SAVE_VERSION,
-                        modem_state_save,
-                        modem_state_load,
-                        android_modem);
-    }
+    assert(android_modem_serial_line != NULL);
+
+    register_savevm(NULL,
+                    "android_modem",
+                    0,
+                    MODEM_DEV_STATE_SAVE_VERSION,
+                    modem_state_save,
+                    modem_state_load,
+                    android_modem);
 }
diff --git a/arch_init.c b/arch_init.c
index b94d23f..1d09f32 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -21,45 +21,19 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include <stdint.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#ifndef _WIN32
-#include <sys/types.h>
-#include <sys/mman.h>
-#endif
-#include "config.h"
-#include "monitor/monitor.h"
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
 #include "sysemu/sysemu.h"
-#include "qemu/bitops.h"
-#include "qemu/bitmap.h"
 #include "sysemu/arch_init.h"
-#include "audio/audio.h"
-#include "hw/i386/pc.h"
 #include "hw/pci/pci.h"
 #include "hw/audio/audio.h"
-#include "sysemu/kvm.h"
-#include "migration/migration.h"
-#include "hw/i386/smbios.h"
-#include "exec/address-spaces.h"
-#include "hw/audio/pcspk.h"
-#include "migration/page_cache.h"
+#include "hw/smbios/smbios.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "qmp-commands.h"
-#include "trace.h"
-#include "exec/cpu-all.h"
-#include "exec/ram_addr.h"
 #include "hw/acpi/acpi.h"
-#include "qemu/host-utils.h"
-
-#ifdef DEBUG_ARCH_INIT
-#define DPRINTF(fmt, ...) \
-    do { fprintf(stdout, "arch_init: " fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-    do { } while (0)
-#endif
+#include "qemu/help_option.h"
 
 #ifdef TARGET_SPARC
 int graphic_width = 1024;
@@ -109,23 +83,6 @@
 #endif
 
 const uint32_t arch_type = QEMU_ARCH;
-static bool mig_throttle_on;
-static int dirty_rate_high_cnt;
-static void check_guest_throttling(void);
-
-static uint64_t bitmap_sync_count;
-
-/***********************************************************/
-/* ram save/restore */
-
-#define RAM_SAVE_FLAG_FULL     0x01 /* Obsolete, not used anymore */
-#define RAM_SAVE_FLAG_COMPRESS 0x02
-#define RAM_SAVE_FLAG_MEM_SIZE 0x04
-#define RAM_SAVE_FLAG_PAGE     0x08
-#define RAM_SAVE_FLAG_EOS      0x10
-#define RAM_SAVE_FLAG_CONTINUE 0x20
-#define RAM_SAVE_FLAG_XBZRLE   0x40
-/* 0x80 is reserved in migration.h start with 0x100 next */
 
 static struct defconfig_file {
     const char *filename;
@@ -133,12 +90,9 @@
     bool userconfig;
 } default_config_files[] = {
     { CONFIG_QEMU_CONFDIR "/qemu.conf",                   true },
-    { CONFIG_QEMU_CONFDIR "/target-" TARGET_NAME ".conf", true },
     { NULL }, /* end of list */
 };
 
-static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
-
 int qemu_read_default_config_files(bool userconfig)
 {
     int ret;
@@ -157,1026 +111,6 @@
     return 0;
 }
 
-static inline bool is_zero_range(uint8_t *p, uint64_t size)
-{
-    return buffer_find_nonzero_offset(p, size) == size;
-}
-
-/* struct contains XBZRLE cache and a static page
-   used by the compression */
-static struct {
-    /* buffer used for XBZRLE encoding */
-    uint8_t *encoded_buf;
-    /* buffer for storing page content */
-    uint8_t *current_buf;
-    /* Cache for XBZRLE, Protected by lock. */
-    PageCache *cache;
-    QemuMutex lock;
-} XBZRLE;
-
-/* buffer used for XBZRLE decoding */
-static uint8_t *xbzrle_decoded_buf;
-
-static void XBZRLE_cache_lock(void)
-{
-    if (migrate_use_xbzrle())
-        qemu_mutex_lock(&XBZRLE.lock);
-}
-
-static void XBZRLE_cache_unlock(void)
-{
-    if (migrate_use_xbzrle())
-        qemu_mutex_unlock(&XBZRLE.lock);
-}
-
-/*
- * called from qmp_migrate_set_cache_size in main thread, possibly while
- * a migration is in progress.
- * A running migration maybe using the cache and might finish during this
- * call, hence changes to the cache are protected by XBZRLE.lock().
- */
-int64_t xbzrle_cache_resize(int64_t new_size)
-{
-    PageCache *new_cache;
-    int64_t ret;
-
-    if (new_size < TARGET_PAGE_SIZE) {
-        return -1;
-    }
-
-    XBZRLE_cache_lock();
-
-    if (XBZRLE.cache != NULL) {
-        if (pow2floor(new_size) == migrate_xbzrle_cache_size()) {
-            goto out_new_size;
-        }
-        new_cache = cache_init(new_size / TARGET_PAGE_SIZE,
-                                        TARGET_PAGE_SIZE);
-        if (!new_cache) {
-            error_report("Error creating cache");
-            ret = -1;
-            goto out;
-        }
-
-        cache_fini(XBZRLE.cache);
-        XBZRLE.cache = new_cache;
-    }
-
-out_new_size:
-    ret = pow2floor(new_size);
-out:
-    XBZRLE_cache_unlock();
-    return ret;
-}
-
-/* accounting for migration statistics */
-typedef struct AccountingInfo {
-    uint64_t dup_pages;
-    uint64_t skipped_pages;
-    uint64_t norm_pages;
-    uint64_t iterations;
-    uint64_t xbzrle_bytes;
-    uint64_t xbzrle_pages;
-    uint64_t xbzrle_cache_miss;
-    double xbzrle_cache_miss_rate;
-    uint64_t xbzrle_overflows;
-} AccountingInfo;
-
-static AccountingInfo acct_info;
-
-static void acct_clear(void)
-{
-    memset(&acct_info, 0, sizeof(acct_info));
-}
-
-uint64_t dup_mig_bytes_transferred(void)
-{
-    return acct_info.dup_pages * TARGET_PAGE_SIZE;
-}
-
-uint64_t dup_mig_pages_transferred(void)
-{
-    return acct_info.dup_pages;
-}
-
-uint64_t skipped_mig_bytes_transferred(void)
-{
-    return acct_info.skipped_pages * TARGET_PAGE_SIZE;
-}
-
-uint64_t skipped_mig_pages_transferred(void)
-{
-    return acct_info.skipped_pages;
-}
-
-uint64_t norm_mig_bytes_transferred(void)
-{
-    return acct_info.norm_pages * TARGET_PAGE_SIZE;
-}
-
-uint64_t norm_mig_pages_transferred(void)
-{
-    return acct_info.norm_pages;
-}
-
-uint64_t xbzrle_mig_bytes_transferred(void)
-{
-    return acct_info.xbzrle_bytes;
-}
-
-uint64_t xbzrle_mig_pages_transferred(void)
-{
-    return acct_info.xbzrle_pages;
-}
-
-uint64_t xbzrle_mig_pages_cache_miss(void)
-{
-    return acct_info.xbzrle_cache_miss;
-}
-
-double xbzrle_mig_cache_miss_rate(void)
-{
-    return acct_info.xbzrle_cache_miss_rate;
-}
-
-uint64_t xbzrle_mig_pages_overflow(void)
-{
-    return acct_info.xbzrle_overflows;
-}
-
-static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
-                             int cont, int flag)
-{
-    size_t size;
-
-    qemu_put_be64(f, offset | cont | flag);
-    size = 8;
-
-    if (!cont) {
-        qemu_put_byte(f, strlen(block->idstr));
-        qemu_put_buffer(f, (uint8_t *)block->idstr,
-                        strlen(block->idstr));
-        size += 1 + strlen(block->idstr);
-    }
-    return size;
-}
-
-/* This is the last block that we have visited serching for dirty pages
- */
-static RAMBlock *last_seen_block;
-/* This is the last block from where we have sent data */
-static RAMBlock *last_sent_block;
-static ram_addr_t last_offset;
-static unsigned long *migration_bitmap;
-static uint64_t migration_dirty_pages;
-static uint32_t last_version;
-static bool ram_bulk_stage;
-
-/* Update the xbzrle cache to reflect a page that's been sent as all 0.
- * The important thing is that a stale (not-yet-0'd) page be replaced
- * by the new data.
- * As a bonus, if the page wasn't in the cache it gets added so that
- * when a small write is made into the 0'd page it gets XBZRLE sent
- */
-static void xbzrle_cache_zero_page(ram_addr_t current_addr)
-{
-    if (ram_bulk_stage || !migrate_use_xbzrle()) {
-        return;
-    }
-
-    /* We don't care if this fails to allocate a new cache page
-     * as long as it updated an old one */
-    cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
-}
-
-#define ENCODING_FLAG_XBZRLE 0x1
-
-static int save_xbzrle_page(QEMUFile *f, uint8_t **current_data,
-                            ram_addr_t current_addr, RAMBlock *block,
-                            ram_addr_t offset, int cont, bool last_stage)
-{
-    int encoded_len = 0, bytes_sent = -1;
-    uint8_t *prev_cached_page;
-
-    if (!cache_is_cached(XBZRLE.cache, current_addr)) {
-        acct_info.xbzrle_cache_miss++;
-        if (!last_stage) {
-            if (cache_insert(XBZRLE.cache, current_addr, *current_data) == -1) {
-                return -1;
-            } else {
-                /* update *current_data when the page has been
-                   inserted into cache */
-                *current_data = get_cached_data(XBZRLE.cache, current_addr);
-            }
-        }
-        return -1;
-    }
-
-    prev_cached_page = get_cached_data(XBZRLE.cache, current_addr);
-
-    /* save current buffer into memory */
-    memcpy(XBZRLE.current_buf, *current_data, TARGET_PAGE_SIZE);
-
-    /* XBZRLE encoding (if there is no overflow) */
-    encoded_len = xbzrle_encode_buffer(prev_cached_page, XBZRLE.current_buf,
-                                       TARGET_PAGE_SIZE, XBZRLE.encoded_buf,
-                                       TARGET_PAGE_SIZE);
-    if (encoded_len == 0) {
-        DPRINTF("Skipping unmodified page\n");
-        return 0;
-    } else if (encoded_len == -1) {
-        DPRINTF("Overflow\n");
-        acct_info.xbzrle_overflows++;
-        /* update data in the cache */
-        if (!last_stage) {
-            memcpy(prev_cached_page, *current_data, TARGET_PAGE_SIZE);
-            *current_data = prev_cached_page;
-        }
-        return -1;
-    }
-
-    /* we need to update the data in the cache, in order to get the same data */
-    if (!last_stage) {
-        memcpy(prev_cached_page, XBZRLE.current_buf, TARGET_PAGE_SIZE);
-    }
-
-    /* Send XBZRLE based compressed page */
-    bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE);
-    qemu_put_byte(f, ENCODING_FLAG_XBZRLE);
-    qemu_put_be16(f, encoded_len);
-    qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
-    bytes_sent += encoded_len + 1 + 2;
-    acct_info.xbzrle_pages++;
-    acct_info.xbzrle_bytes += bytes_sent;
-
-    return bytes_sent;
-}
-
-static inline
-ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
-                                                 ram_addr_t start)
-{
-    unsigned long base = mr->ram_addr >> TARGET_PAGE_BITS;
-    unsigned long nr = base + (start >> TARGET_PAGE_BITS);
-    uint64_t mr_size = TARGET_PAGE_ALIGN(memory_region_size(mr));
-    unsigned long size = base + (mr_size >> TARGET_PAGE_BITS);
-
-    unsigned long next;
-
-    if (ram_bulk_stage && nr > base) {
-        next = nr + 1;
-    } else {
-        next = find_next_bit(migration_bitmap, size, nr);
-    }
-
-    if (next < size) {
-        clear_bit(next, migration_bitmap);
-        migration_dirty_pages--;
-    }
-    return (next - base) << TARGET_PAGE_BITS;
-}
-
-static inline bool migration_bitmap_set_dirty(ram_addr_t addr)
-{
-    bool ret;
-    int nr = addr >> TARGET_PAGE_BITS;
-
-    ret = test_and_set_bit(nr, migration_bitmap);
-
-    if (!ret) {
-        migration_dirty_pages++;
-    }
-    return ret;
-}
-
-static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
-{
-    ram_addr_t addr;
-    unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
-
-    /* start address is aligned at the start of a word? */
-    if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) {
-        int k;
-        int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS);
-        unsigned long *src = ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION];
-
-        for (k = page; k < page + nr; k++) {
-            if (src[k]) {
-                unsigned long new_dirty;
-                new_dirty = ~migration_bitmap[k];
-                migration_bitmap[k] |= src[k];
-                new_dirty &= src[k];
-                migration_dirty_pages += ctpopl(new_dirty);
-                src[k] = 0;
-            }
-        }
-    } else {
-        for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
-            if (cpu_physical_memory_get_dirty(start + addr,
-                                              TARGET_PAGE_SIZE,
-                                              DIRTY_MEMORY_MIGRATION)) {
-                cpu_physical_memory_reset_dirty(start + addr,
-                                                TARGET_PAGE_SIZE,
-                                                DIRTY_MEMORY_MIGRATION);
-                migration_bitmap_set_dirty(start + addr);
-            }
-        }
-    }
-}
-
-
-/* Needs iothread lock! */
-/* Fix me: there are too many global variables used in migration process. */
-static int64_t start_time;
-static int64_t bytes_xfer_prev;
-static int64_t num_dirty_pages_period;
-
-static void migration_bitmap_sync_init(void)
-{
-    start_time = 0;
-    bytes_xfer_prev = 0;
-    num_dirty_pages_period = 0;
-}
-
-static void migration_bitmap_sync(void)
-{
-    RAMBlock *block;
-    uint64_t num_dirty_pages_init = migration_dirty_pages;
-    MigrationState *s = migrate_get_current();
-    int64_t end_time;
-    int64_t bytes_xfer_now;
-    static uint64_t xbzrle_cache_miss_prev;
-    static uint64_t iterations_prev;
-
-    bitmap_sync_count++;
-
-    if (!bytes_xfer_prev) {
-        bytes_xfer_prev = ram_bytes_transferred();
-    }
-
-    if (!start_time) {
-        start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
-    }
-
-    trace_migration_bitmap_sync_start();
-    address_space_sync_dirty_bitmap(&address_space_memory);
-
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-        migration_bitmap_sync_range(block->mr->ram_addr, block->length);
-    }
-    trace_migration_bitmap_sync_end(migration_dirty_pages
-                                    - num_dirty_pages_init);
-    num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
-    end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
-
-    /* more than 1 second = 1000 millisecons */
-    if (end_time > start_time + 1000) {
-        if (migrate_auto_converge()) {
-            /* The following detection logic can be refined later. For now:
-               Check to see if the dirtied bytes is 50% more than the approx.
-               amount of bytes that just got transferred since the last time we
-               were in this routine. If that happens >N times (for now N==4)
-               we turn on the throttle down logic */
-            bytes_xfer_now = ram_bytes_transferred();
-            if (s->dirty_pages_rate &&
-               (num_dirty_pages_period * TARGET_PAGE_SIZE >
-                   (bytes_xfer_now - bytes_xfer_prev)/2) &&
-               (dirty_rate_high_cnt++ > 4)) {
-                    trace_migration_throttle();
-                    mig_throttle_on = true;
-                    dirty_rate_high_cnt = 0;
-             }
-             bytes_xfer_prev = bytes_xfer_now;
-        } else {
-             mig_throttle_on = false;
-        }
-        if (migrate_use_xbzrle()) {
-            if (iterations_prev != 0) {
-                acct_info.xbzrle_cache_miss_rate =
-                   (double)(acct_info.xbzrle_cache_miss -
-                            xbzrle_cache_miss_prev) /
-                   (acct_info.iterations - iterations_prev);
-            }
-            iterations_prev = acct_info.iterations;
-            xbzrle_cache_miss_prev = acct_info.xbzrle_cache_miss;
-        }
-        s->dirty_pages_rate = num_dirty_pages_period * 1000
-            / (end_time - start_time);
-        s->dirty_bytes_rate = s->dirty_pages_rate * TARGET_PAGE_SIZE;
-        start_time = end_time;
-        num_dirty_pages_period = 0;
-        s->dirty_sync_count = bitmap_sync_count;
-    }
-}
-
-/*
- * ram_save_page: Send the given page to the stream
- *
- * Returns: Number of bytes written.
- */
-static int ram_save_page(QEMUFile *f, RAMBlock* block, ram_addr_t offset,
-                         bool last_stage)
-{
-    int bytes_sent;
-    int cont;
-    ram_addr_t current_addr;
-    MemoryRegion *mr = block->mr;
-    uint8_t *p;
-    int ret;
-    bool send_async = true;
-
-    cont = (block == last_sent_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
-
-    p = memory_region_get_ram_ptr(mr) + offset;
-
-    /* In doubt sent page as normal */
-    bytes_sent = -1;
-    ret = ram_control_save_page(f, block->offset,
-                           offset, TARGET_PAGE_SIZE, &bytes_sent);
-
-    XBZRLE_cache_lock();
-
-    current_addr = block->offset + offset;
-    if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
-        if (ret != RAM_SAVE_CONTROL_DELAYED) {
-            if (bytes_sent > 0) {
-                acct_info.norm_pages++;
-            } else if (bytes_sent == 0) {
-                acct_info.dup_pages++;
-            }
-        }
-    } else if (is_zero_range(p, TARGET_PAGE_SIZE)) {
-        acct_info.dup_pages++;
-        bytes_sent = save_block_hdr(f, block, offset, cont,
-                                    RAM_SAVE_FLAG_COMPRESS);
-        qemu_put_byte(f, 0);
-        bytes_sent++;
-        /* Must let xbzrle know, otherwise a previous (now 0'd) cached
-         * page would be stale
-         */
-        xbzrle_cache_zero_page(current_addr);
-    } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
-        bytes_sent = save_xbzrle_page(f, &p, current_addr, block,
-                                      offset, cont, last_stage);
-        if (!last_stage) {
-            /* Can't send this cached data async, since the cache page
-             * might get updated before it gets to the wire
-             */
-            send_async = false;
-        }
-    }
-
-    /* XBZRLE overflow or normal page */
-    if (bytes_sent == -1) {
-        bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
-        if (send_async) {
-            qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
-        } else {
-            qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
-        }
-        bytes_sent += TARGET_PAGE_SIZE;
-        acct_info.norm_pages++;
-    }
-
-    XBZRLE_cache_unlock();
-
-    return bytes_sent;
-}
-
-/*
- * ram_find_and_save_block: Finds a page to send and sends it to f
- *
- * Returns:  The number of bytes written.
- *           0 means no dirty pages
- */
-
-static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
-{
-    RAMBlock *block = last_seen_block;
-    ram_addr_t offset = last_offset;
-    bool complete_round = false;
-    int bytes_sent = 0;
-    MemoryRegion *mr;
-
-    if (!block)
-        block = QTAILQ_FIRST(&ram_list.blocks);
-
-    while (true) {
-        mr = block->mr;
-        offset = migration_bitmap_find_and_reset_dirty(mr, offset);
-        if (complete_round && block == last_seen_block &&
-            offset >= last_offset) {
-            break;
-        }
-        if (offset >= block->length) {
-            offset = 0;
-            block = QTAILQ_NEXT(block, next);
-            if (!block) {
-                block = QTAILQ_FIRST(&ram_list.blocks);
-                complete_round = true;
-                ram_bulk_stage = false;
-            }
-        } else {
-            bytes_sent = ram_save_page(f, block, offset, last_stage);
-
-            /* if page is unmodified, continue to the next */
-            if (bytes_sent > 0) {
-                last_sent_block = block;
-                break;
-            }
-        }
-    }
-    last_seen_block = block;
-    last_offset = offset;
-
-    return bytes_sent;
-}
-
-static uint64_t bytes_transferred;
-
-void acct_update_position(QEMUFile *f, size_t size, bool zero)
-{
-    uint64_t pages = size / TARGET_PAGE_SIZE;
-    if (zero) {
-        acct_info.dup_pages += pages;
-    } else {
-        acct_info.norm_pages += pages;
-        bytes_transferred += size;
-        qemu_update_position(f, size);
-    }
-}
-
-static ram_addr_t ram_save_remaining(void)
-{
-    return migration_dirty_pages;
-}
-
-uint64_t ram_bytes_remaining(void)
-{
-    return ram_save_remaining() * TARGET_PAGE_SIZE;
-}
-
-uint64_t ram_bytes_transferred(void)
-{
-    return bytes_transferred;
-}
-
-uint64_t ram_bytes_total(void)
-{
-    RAMBlock *block;
-    uint64_t total = 0;
-
-    QTAILQ_FOREACH(block, &ram_list.blocks, next)
-        total += block->length;
-
-    return total;
-}
-
-void free_xbzrle_decoded_buf(void)
-{
-    g_free(xbzrle_decoded_buf);
-    xbzrle_decoded_buf = NULL;
-}
-
-static void migration_end(void)
-{
-    if (migration_bitmap) {
-        memory_global_dirty_log_stop();
-        g_free(migration_bitmap);
-        migration_bitmap = NULL;
-    }
-
-    XBZRLE_cache_lock();
-    if (XBZRLE.cache) {
-        cache_fini(XBZRLE.cache);
-        g_free(XBZRLE.encoded_buf);
-        g_free(XBZRLE.current_buf);
-        XBZRLE.cache = NULL;
-        XBZRLE.encoded_buf = NULL;
-        XBZRLE.current_buf = NULL;
-    }
-    XBZRLE_cache_unlock();
-}
-
-static void ram_migration_cancel(void *opaque)
-{
-    migration_end();
-}
-
-static void reset_ram_globals(void)
-{
-    last_seen_block = NULL;
-    last_sent_block = NULL;
-    last_offset = 0;
-    last_version = ram_list.version;
-    ram_bulk_stage = true;
-}
-
-#define MAX_WAIT 50 /* ms, half buffered_file limit */
-
-static int ram_save_setup(QEMUFile *f, void *opaque)
-{
-    RAMBlock *block;
-    int64_t ram_bitmap_pages; /* Size of bitmap in pages, including gaps */
-
-    mig_throttle_on = false;
-    dirty_rate_high_cnt = 0;
-    bitmap_sync_count = 0;
-    migration_bitmap_sync_init();
-
-    if (migrate_use_xbzrle()) {
-        XBZRLE_cache_lock();
-        XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
-                                  TARGET_PAGE_SIZE,
-                                  TARGET_PAGE_SIZE);
-        if (!XBZRLE.cache) {
-            XBZRLE_cache_unlock();
-            error_report("Error creating cache");
-            return -1;
-        }
-        XBZRLE_cache_unlock();
-
-        /* We prefer not to abort if there is no memory */
-        XBZRLE.encoded_buf = g_try_malloc0(TARGET_PAGE_SIZE);
-        if (!XBZRLE.encoded_buf) {
-            error_report("Error allocating encoded_buf");
-            return -1;
-        }
-
-        XBZRLE.current_buf = g_try_malloc(TARGET_PAGE_SIZE);
-        if (!XBZRLE.current_buf) {
-            error_report("Error allocating current_buf");
-            g_free(XBZRLE.encoded_buf);
-            XBZRLE.encoded_buf = NULL;
-            return -1;
-        }
-
-        acct_clear();
-    }
-
-    qemu_mutex_lock_iothread();
-    qemu_mutex_lock_ramlist();
-    bytes_transferred = 0;
-    reset_ram_globals();
-
-    ram_bitmap_pages = last_ram_offset() >> TARGET_PAGE_BITS;
-    migration_bitmap = bitmap_new(ram_bitmap_pages);
-    bitmap_set(migration_bitmap, 0, ram_bitmap_pages);
-
-    /*
-     * Count the total number of pages used by ram blocks not including any
-     * gaps due to alignment or unplugs.
-     */
-    migration_dirty_pages = 0;
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-        uint64_t block_pages;
-
-        block_pages = block->length >> TARGET_PAGE_BITS;
-        migration_dirty_pages += block_pages;
-    }
-
-    memory_global_dirty_log_start();
-    migration_bitmap_sync();
-    qemu_mutex_unlock_iothread();
-
-    qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
-
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-        qemu_put_byte(f, strlen(block->idstr));
-        qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
-        qemu_put_be64(f, block->length);
-    }
-
-    qemu_mutex_unlock_ramlist();
-
-    ram_control_before_iterate(f, RAM_CONTROL_SETUP);
-    ram_control_after_iterate(f, RAM_CONTROL_SETUP);
-
-    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
-
-    return 0;
-}
-
-static int ram_save_iterate(QEMUFile *f, void *opaque)
-{
-    int ret;
-    int i;
-    int64_t t0;
-    int total_sent = 0;
-
-    qemu_mutex_lock_ramlist();
-
-    if (ram_list.version != last_version) {
-        reset_ram_globals();
-    }
-
-    ram_control_before_iterate(f, RAM_CONTROL_ROUND);
-
-    t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-    i = 0;
-    while ((ret = qemu_file_rate_limit(f)) == 0) {
-        int bytes_sent;
-
-        bytes_sent = ram_find_and_save_block(f, false);
-        /* no more blocks to sent */
-        if (bytes_sent == 0) {
-            break;
-        }
-        total_sent += bytes_sent;
-        acct_info.iterations++;
-        check_guest_throttling();
-        /* we want to check in the 1st loop, just in case it was the 1st time
-           and we had to sync the dirty bitmap.
-           qemu_get_clock_ns() is a bit expensive, so we only check each some
-           iterations
-        */
-        if ((i & 63) == 0) {
-            uint64_t t1 = (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - t0) / 1000000;
-            if (t1 > MAX_WAIT) {
-                DPRINTF("big wait: %" PRIu64 " milliseconds, %d iterations\n",
-                        t1, i);
-                break;
-            }
-        }
-        i++;
-    }
-
-    qemu_mutex_unlock_ramlist();
-
-    /*
-     * Must occur before EOS (or any QEMUFile operation)
-     * because of RDMA protocol.
-     */
-    ram_control_after_iterate(f, RAM_CONTROL_ROUND);
-
-    bytes_transferred += total_sent;
-
-    /*
-     * Do not count these 8 bytes into total_sent, so that we can
-     * return 0 if no page had been dirtied.
-     */
-    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
-    bytes_transferred += 8;
-
-    ret = qemu_file_get_error(f);
-    if (ret < 0) {
-        return ret;
-    }
-
-    return total_sent;
-}
-
-static int ram_save_complete(QEMUFile *f, void *opaque)
-{
-    qemu_mutex_lock_ramlist();
-    migration_bitmap_sync();
-
-    ram_control_before_iterate(f, RAM_CONTROL_FINISH);
-
-    /* try transferring iterative blocks of memory */
-
-    /* flush all remaining blocks regardless of rate limiting */
-    while (true) {
-        int bytes_sent;
-
-        bytes_sent = ram_find_and_save_block(f, true);
-        /* no more blocks to sent */
-        if (bytes_sent == 0) {
-            break;
-        }
-        bytes_transferred += bytes_sent;
-    }
-
-    ram_control_after_iterate(f, RAM_CONTROL_FINISH);
-    migration_end();
-
-    qemu_mutex_unlock_ramlist();
-    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
-
-    return 0;
-}
-
-static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
-{
-    uint64_t remaining_size;
-
-    remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE;
-
-    if (remaining_size < max_size) {
-        qemu_mutex_lock_iothread();
-        migration_bitmap_sync();
-        qemu_mutex_unlock_iothread();
-        remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE;
-    }
-    return remaining_size;
-}
-
-static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
-{
-    unsigned int xh_len;
-    int xh_flags;
-
-    if (!xbzrle_decoded_buf) {
-        xbzrle_decoded_buf = g_malloc(TARGET_PAGE_SIZE);
-    }
-
-    /* extract RLE header */
-    xh_flags = qemu_get_byte(f);
-    xh_len = qemu_get_be16(f);
-
-    if (xh_flags != ENCODING_FLAG_XBZRLE) {
-        error_report("Failed to load XBZRLE page - wrong compression!");
-        return -1;
-    }
-
-    if (xh_len > TARGET_PAGE_SIZE) {
-        error_report("Failed to load XBZRLE page - len overflow!");
-        return -1;
-    }
-    /* load data and decode */
-    qemu_get_buffer(f, xbzrle_decoded_buf, xh_len);
-
-    /* decode RLE */
-    if (xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host,
-                             TARGET_PAGE_SIZE) == -1) {
-        error_report("Failed to load XBZRLE page - decode error!");
-        return -1;
-    }
-
-    return 0;
-}
-
-static inline void *host_from_stream_offset(QEMUFile *f,
-                                            ram_addr_t offset,
-                                            int flags)
-{
-    static RAMBlock *block = NULL;
-    char id[256];
-    uint8_t len;
-
-    if (flags & RAM_SAVE_FLAG_CONTINUE) {
-        if (!block || block->length <= offset) {
-            error_report("Ack, bad migration stream!");
-            return NULL;
-        }
-
-        return memory_region_get_ram_ptr(block->mr) + offset;
-    }
-
-    len = qemu_get_byte(f);
-    qemu_get_buffer(f, (uint8_t *)id, len);
-    id[len] = 0;
-
-    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-        if (!strncmp(id, block->idstr, sizeof(id)) && block->length > offset) {
-            return memory_region_get_ram_ptr(block->mr) + offset;
-        }
-    }
-
-    error_report("Can't find block %s!", id);
-    return NULL;
-}
-
-/*
- * If a page (or a whole RDMA chunk) has been
- * determined to be zero, then zap it.
- */
-void ram_handle_compressed(void *host, uint8_t ch, uint64_t size)
-{
-    if (ch != 0 || !is_zero_range(host, size)) {
-        memset(host, ch, size);
-    }
-}
-
-static int ram_load(QEMUFile *f, void *opaque, int version_id)
-{
-    int flags = 0, ret = 0;
-    static uint64_t seq_iter;
-
-    seq_iter++;
-
-    if (version_id != 4) {
-        ret = -EINVAL;
-    }
-
-    while (!ret && !(flags & RAM_SAVE_FLAG_EOS)) {
-        ram_addr_t addr, total_ram_bytes;
-        void *host;
-        uint8_t ch;
-
-        addr = qemu_get_be64(f);
-        flags = addr & ~TARGET_PAGE_MASK;
-        addr &= TARGET_PAGE_MASK;
-
-        switch (flags & ~RAM_SAVE_FLAG_CONTINUE) {
-        case RAM_SAVE_FLAG_MEM_SIZE:
-            /* Synchronize RAM block list */
-            total_ram_bytes = addr;
-            while (!ret && total_ram_bytes) {
-                RAMBlock *block;
-                uint8_t len;
-                char id[256];
-                ram_addr_t length;
-
-                len = qemu_get_byte(f);
-                qemu_get_buffer(f, (uint8_t *)id, len);
-                id[len] = 0;
-                length = qemu_get_be64(f);
-
-                QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-                    if (!strncmp(id, block->idstr, sizeof(id))) {
-                        if (block->length != length) {
-                            error_report("Length mismatch: %s: 0x" RAM_ADDR_FMT
-                                         " in != 0x" RAM_ADDR_FMT, id, length,
-                                         block->length);
-                            ret =  -EINVAL;
-                        }
-                        break;
-                    }
-                }
-
-                if (!block) {
-                    error_report("Unknown ramblock \"%s\", cannot "
-                                 "accept migration", id);
-                    ret = -EINVAL;
-                }
-
-                total_ram_bytes -= length;
-            }
-            break;
-        case RAM_SAVE_FLAG_COMPRESS:
-            host = host_from_stream_offset(f, addr, flags);
-            if (!host) {
-                error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
-                ret = -EINVAL;
-                break;
-            }
-
-            ch = qemu_get_byte(f);
-            ram_handle_compressed(host, ch, TARGET_PAGE_SIZE);
-            break;
-        case RAM_SAVE_FLAG_PAGE:
-            host = host_from_stream_offset(f, addr, flags);
-            if (!host) {
-                error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
-                ret = -EINVAL;
-                break;
-            }
-
-            qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
-            break;
-        case RAM_SAVE_FLAG_XBZRLE:
-            host = host_from_stream_offset(f, addr, flags);
-            if (!host) {
-                error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
-                ret = -EINVAL;
-                break;
-            }
-
-            if (load_xbzrle(f, addr, host) < 0) {
-                error_report("Failed to decompress XBZRLE page at "
-                             RAM_ADDR_FMT, addr);
-                ret = -EINVAL;
-                break;
-            }
-            break;
-        case RAM_SAVE_FLAG_EOS:
-            /* normal exit */
-            break;
-        default:
-            if (flags & RAM_SAVE_FLAG_HOOK) {
-                ram_control_load_hook(f, flags);
-            } else {
-                error_report("Unknown combination of migration flags: %#x",
-                             flags);
-                ret = -EINVAL;
-            }
-        }
-        if (!ret) {
-            ret = qemu_file_get_error(f);
-        }
-    }
-
-    DPRINTF("Completed load of VM with exit code %d seq iteration "
-            "%" PRIu64 "\n", ret, seq_iter);
-    return ret;
-}
-
-static SaveVMHandlers savevm_ram_handlers = {
-    .save_live_setup = ram_save_setup,
-    .save_live_iterate = ram_save_iterate,
-    .save_live_complete = ram_save_complete,
-    .save_live_pending = ram_save_pending,
-    .load_state = ram_load,
-    .cancel = ram_migration_cancel,
-};
-
-void ram_mig_init(void)
-{
-    qemu_mutex_init(&XBZRLE.lock);
-    register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, NULL);
-}
-
 struct soundhw {
     const char *name;
     const char *descr;
@@ -1329,9 +263,7 @@
 
     acpi_table_add(opts, &err);
     if (err) {
-        error_report("Wrong acpi table provided: %s",
-                     error_get_pretty(err));
-        error_free(err);
+        error_reportf_err(err, "Wrong acpi table provided: ");
         exit(1);
     }
 #endif
@@ -1344,13 +276,6 @@
 #endif
 }
 
-void cpudef_init(void)
-{
-#if defined(cpudef_setup)
-    cpudef_setup(); /* parse cpu definitions in target config file */
-#endif
-}
-
 int kvm_available(void)
 {
 #ifdef CONFIG_KVM
@@ -1386,52 +311,3 @@
 
     return info;
 }
-
-/* Stub function that's gets run on the vcpu when its brought out of the
-   VM to run inside qemu via async_run_on_cpu()*/
-static void mig_sleep_cpu(void *opq)
-{
-    qemu_mutex_unlock_iothread();
-    g_usleep(30*1000);
-    qemu_mutex_lock_iothread();
-}
-
-/* To reduce the dirty rate explicitly disallow the VCPUs from spending
-   much time in the VM. The migration thread will try to catchup.
-   Workload will experience a performance drop.
-*/
-static void mig_throttle_guest_down(void)
-{
-    CPUState *cpu;
-
-    qemu_mutex_lock_iothread();
-    CPU_FOREACH(cpu) {
-        async_run_on_cpu(cpu, mig_sleep_cpu, NULL);
-    }
-    qemu_mutex_unlock_iothread();
-}
-
-static void check_guest_throttling(void)
-{
-    static int64_t t0;
-    int64_t        t1;
-
-    if (!mig_throttle_on) {
-        return;
-    }
-
-    if (!t0)  {
-        t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-        return;
-    }
-
-    t1 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-
-    /* If it has been more than 40 ms since the last time the guest
-     * was throttled then do it again.
-     */
-    if (40 < (t1-t0)/1000000) {
-        mig_throttle_guest_down();
-        t0 = t1;
-    }
-}
diff --git a/async.c b/async.c
index 6e1b282..3bca9b0 100644
--- a/async.c
+++ b/async.c
@@ -22,11 +22,14 @@
  * THE SOFTWARE.
  */
 
+#include "qemu/osdep.h"
+#include "qapi/error.h"
 #include "qemu-common.h"
 #include "block/aio.h"
 #include "block/thread-pool.h"
 #include "qemu/main-loop.h"
 #include "qemu/atomic.h"
+#include "block/raw-aio.h"
 
 /***********************************************************/
 /* bottom halves (can be seen as timers which expire ASAP) */
@@ -44,10 +47,12 @@
 QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
 {
     QEMUBH *bh;
-    bh = g_malloc0(sizeof(QEMUBH));
-    bh->ctx = ctx;
-    bh->cb = cb;
-    bh->opaque = opaque;
+    bh = g_new(QEMUBH, 1);
+    *bh = (QEMUBH){
+        .ctx = ctx,
+        .cb = cb,
+        .opaque = opaque,
+    };
     qemu_mutex_lock(&ctx->bh_lock);
     bh->next = ctx->first_bh;
     /* Make sure that the members are ready before putting bh into list */
@@ -57,6 +62,11 @@
     return bh;
 }
 
+void aio_bh_call(QEMUBH *bh)
+{
+    bh->cb(bh->opaque);
+}
+
 /* Multiple occurrences of aio_bh_poll cannot be called concurrently */
 int aio_bh_poll(AioContext *ctx)
 {
@@ -70,16 +80,19 @@
         /* Make sure that fetching bh happens before accessing its members */
         smp_read_barrier_depends();
         next = bh->next;
-        if (!bh->deleted && bh->scheduled) {
-            bh->scheduled = 0;
-            /* Paired with write barrier in bh schedule to ensure reading for
-             * idle & callbacks coming after bh's scheduling.
-             */
-            smp_rmb();
-            if (!bh->idle)
+        /* The atomic_xchg is paired with the one in qemu_bh_schedule.  The
+         * implicit memory barrier ensures that the callback sees all writes
+         * done by the scheduling thread.  It also ensures that the scheduling
+         * thread sees the zero before bh->cb has run, and thus will call
+         * aio_notify again if necessary.
+         */
+        if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) {
+            /* Idle BHs and the notify BH don't count as progress */
+            if (!bh->idle && bh != ctx->notify_dummy_bh) {
                 ret = 1;
+            }
             bh->idle = 0;
-            bh->cb(bh->opaque);
+            aio_bh_call(bh);
         }
     }
 
@@ -106,33 +119,28 @@
 
 void qemu_bh_schedule_idle(QEMUBH *bh)
 {
-    if (bh->scheduled)
-        return;
     bh->idle = 1;
     /* Make sure that idle & any writes needed by the callback are done
      * before the locations are read in the aio_bh_poll.
      */
-    smp_wmb();
-    bh->scheduled = 1;
+    atomic_mb_set(&bh->scheduled, 1);
 }
 
 void qemu_bh_schedule(QEMUBH *bh)
 {
     AioContext *ctx;
 
-    if (bh->scheduled)
-        return;
     ctx = bh->ctx;
     bh->idle = 0;
-    /* Make sure that:
+    /* The memory barrier implicit in atomic_xchg makes sure that:
      * 1. idle & any writes needed by the callback are done before the
      *    locations are read in the aio_bh_poll.
      * 2. ctx is loaded before scheduled is set and the callback has a chance
      *    to execute.
      */
-    smp_mb();
-    bh->scheduled = 1;
-    aio_notify(ctx);
+    if (atomic_xchg(&bh->scheduled, 1) == 0) {
+        aio_notify(ctx);
+    }
 }
 
 
@@ -186,6 +194,8 @@
 {
     AioContext *ctx = (AioContext *) source;
 
+    atomic_or(&ctx->notify_me, 1);
+
     /* We assume there is no timeout already supplied */
     *timeout = qemu_timeout_ns_to_ms(aio_compute_timeout(ctx));
 
@@ -202,10 +212,13 @@
     AioContext *ctx = (AioContext *) source;
     QEMUBH *bh;
 
+    atomic_and(&ctx->notify_me, ~1);
+    aio_notify_accept(ctx);
+
     for (bh = ctx->first_bh; bh; bh = bh->next) {
         if (!bh->deleted && bh->scheduled) {
             return true;
-	}
+        }
     }
     return aio_pending(ctx) || (timerlistgroup_deadline_ns(&ctx->tlg) == 0);
 }
@@ -227,12 +240,33 @@
 {
     AioContext *ctx = (AioContext *) source;
 
+    qemu_bh_delete(ctx->notify_dummy_bh);
     thread_pool_free(ctx->thread_pool);
-    aio_set_event_notifier(ctx, &ctx->notifier, NULL);
+
+#ifdef CONFIG_LINUX_AIO
+    if (ctx->linux_aio) {
+        laio_detach_aio_context(ctx->linux_aio, ctx);
+        laio_cleanup(ctx->linux_aio);
+        ctx->linux_aio = NULL;
+    }
+#endif
+
+    qemu_mutex_lock(&ctx->bh_lock);
+    while (ctx->first_bh) {
+        QEMUBH *next = ctx->first_bh->next;
+
+        /* qemu_bh_delete() must have been called on BHs in this AioContext */
+        assert(ctx->first_bh->deleted);
+
+        g_free(ctx->first_bh);
+        ctx->first_bh = next;
+    }
+    qemu_mutex_unlock(&ctx->bh_lock);
+
+    aio_set_event_notifier(ctx, &ctx->notifier, false, NULL);
     event_notifier_cleanup(&ctx->notifier);
     rfifolock_destroy(&ctx->lock);
     qemu_mutex_destroy(&ctx->bh_lock);
-    g_array_free(ctx->pollfds, TRUE);
     timerlistgroup_deinit(&ctx->tlg);
 }
 
@@ -257,24 +291,33 @@
     return ctx->thread_pool;
 }
 
-void aio_set_dispatching(AioContext *ctx, bool dispatching)
+#ifdef CONFIG_LINUX_AIO
+LinuxAioState *aio_get_linux_aio(AioContext *ctx)
 {
-    ctx->dispatching = dispatching;
-    if (!dispatching) {
-        /* Write ctx->dispatching before reading e.g. bh->scheduled.
-         * Optimization: this is only needed when we're entering the "unsafe"
-         * phase where other threads must call event_notifier_set.
-         */
-        smp_mb();
+    if (!ctx->linux_aio) {
+        ctx->linux_aio = laio_init();
+        laio_attach_aio_context(ctx->linux_aio, ctx);
     }
+    return ctx->linux_aio;
 }
+#endif
 
 void aio_notify(AioContext *ctx)
 {
-    /* Write e.g. bh->scheduled before reading ctx->dispatching.  */
+    /* Write e.g. bh->scheduled before reading ctx->notify_me.  Pairs
+     * with atomic_or in aio_ctx_prepare or atomic_add in aio_poll.
+     */
     smp_mb();
-    if (!ctx->dispatching) {
+    if (ctx->notify_me) {
         event_notifier_set(&ctx->notifier);
+        atomic_mb_set(&ctx->notified, true);
+    }
+}
+
+void aio_notify_accept(AioContext *ctx)
+{
+    if (atomic_xchg(&ctx->notified, false)) {
+        event_notifier_test_and_clear(&ctx->notifier);
     }
 }
 
@@ -285,31 +328,53 @@
 
 static void aio_rfifolock_cb(void *opaque)
 {
+    AioContext *ctx = opaque;
+
     /* Kick owner thread in case they are blocked in aio_poll() */
-    aio_notify(opaque);
+    qemu_bh_schedule(ctx->notify_dummy_bh);
+}
+
+static void notify_dummy_bh(void *opaque)
+{
+    /* Do nothing, we were invoked just to force the event loop to iterate */
+}
+
+static void event_notifier_dummy_cb(EventNotifier *e)
+{
 }
 
 AioContext *aio_context_new(Error **errp)
 {
     int ret;
     AioContext *ctx;
+
     ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
+    aio_context_setup(ctx);
+
     ret = event_notifier_init(&ctx->notifier, false);
     if (ret < 0) {
-        g_source_destroy(&ctx->source);
         error_setg_errno(errp, -ret, "Failed to initialize event notifier");
-        return NULL;
+        goto fail;
     }
+    g_source_set_can_recurse(&ctx->source, true);
     aio_set_event_notifier(ctx, &ctx->notifier,
+                           false,
                            (EventNotifierHandler *)
-                           event_notifier_test_and_clear);
-    ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
+                           event_notifier_dummy_cb);
+#ifdef CONFIG_LINUX_AIO
+    ctx->linux_aio = NULL;
+#endif
     ctx->thread_pool = NULL;
     qemu_mutex_init(&ctx->bh_lock);
     rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx);
     timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
 
+    ctx->notify_dummy_bh = aio_bh_new(ctx, notify_dummy_bh, NULL);
+
     return ctx;
+fail:
+    g_source_destroy(&ctx->source);
+    return NULL;
 }
 
 void aio_context_ref(AioContext *ctx)
diff --git a/audio/Makefile.objs b/audio/Makefile.objs
index b495cb4..fb8e7a3 100644
--- a/audio/Makefile.objs
+++ b/audio/Makefile.objs
@@ -5,14 +5,10 @@
 common-obj-$(CONFIG_COREAUDIO) += coreaudio.o
 common-obj-$(CONFIG_ALSA) += alsaaudio.o
 common-obj-$(CONFIG_DSOUND) += dsoundaudio.o
-common-obj-$(CONFIG_FMOD) += fmodaudio.o
-common-obj-$(CONFIG_ESD) += esdaudio.o
 common-obj-$(CONFIG_PA) += paaudio.o
-common-obj-$(CONFIG_WINWAVE) += winwaveaudio.o
-common-obj-$(CONFIG_WINAUDIO) += winaudio.o
 common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o
 common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
 common-obj-y += wavcapture.o
+common-obj-$(CONFIG_WINAUDIO) += winaudio.o
 
-$(obj)/audio.o $(obj)/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
 sdlaudio.o-cflags := $(SDL_CFLAGS)
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 74ead97..3652a7b 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -21,10 +21,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
 #include <alsa/asoundlib.h>
 #include "qemu-common.h"
 #include "qemu/main-loop.h"
 #include "audio.h"
+#include "trace.h"
 
 #if QEMU_GNUC_PREREQ(4, 3)
 #pragma GCC diagnostic ignored "-Waddress"
@@ -33,9 +35,28 @@
 #define AUDIO_CAP "alsa"
 #include "audio_int.h"
 
+typedef struct ALSAConf {
+    int size_in_usec_in;
+    int size_in_usec_out;
+    const char *pcm_name_in;
+    const char *pcm_name_out;
+    unsigned int buffer_size_in;
+    unsigned int period_size_in;
+    unsigned int buffer_size_out;
+    unsigned int period_size_out;
+    unsigned int threshold;
+
+    int buffer_size_in_overridden;
+    int period_size_in_overridden;
+
+    int buffer_size_out_overridden;
+    int period_size_out_overridden;
+} ALSAConf;
+
 struct pollhlp {
     snd_pcm_t *handle;
     struct pollfd *pfds;
+    ALSAConf *conf;
     int count;
     int mask;
 };
@@ -56,30 +77,6 @@
     struct pollhlp pollhlp;
 } ALSAVoiceIn;
 
-static struct {
-    int size_in_usec_in;
-    int size_in_usec_out;
-    const char *pcm_name_in;
-    const char *pcm_name_out;
-    unsigned int buffer_size_in;
-    unsigned int period_size_in;
-    unsigned int buffer_size_out;
-    unsigned int period_size_out;
-    unsigned int threshold;
-
-    int buffer_size_in_overridden;
-    int period_size_in_overridden;
-
-    int buffer_size_out_overridden;
-    int period_size_out_overridden;
-    int verbose;
-} conf = {
-    .buffer_size_out = 4096,
-    .period_size_out = 1024,
-    .pcm_name_out = "default",
-    .pcm_name_in = "default",
-};
-
 struct alsa_params_req {
     int freq;
     snd_pcm_format_t fmt;
@@ -205,9 +202,7 @@
     }
 
     if (!(revents & hlp->mask)) {
-        if (conf.verbose) {
-            dolog ("revents = %d\n", revents);
-        }
+        trace_alsa_revents(revents);
         return;
     }
 
@@ -266,31 +261,14 @@
 
     for (i = 0; i < count; ++i) {
         if (pfds[i].events & POLLIN) {
-            err = qemu_set_fd_handler (pfds[i].fd, alsa_poll_handler,
-                                       NULL, hlp);
+            qemu_set_fd_handler (pfds[i].fd, alsa_poll_handler, NULL, hlp);
         }
         if (pfds[i].events & POLLOUT) {
-            if (conf.verbose) {
-                dolog ("POLLOUT %d %d\n", i, pfds[i].fd);
-            }
-            err = qemu_set_fd_handler (pfds[i].fd, NULL,
-                                       alsa_poll_handler, hlp);
+            trace_alsa_pollout(i, pfds[i].fd);
+            qemu_set_fd_handler (pfds[i].fd, NULL, alsa_poll_handler, hlp);
         }
-        if (conf.verbose) {
-            dolog ("Set handler events=%#x index=%d fd=%d err=%d\n",
-                   pfds[i].events, i, pfds[i].fd, err);
-        }
+        trace_alsa_set_handler(pfds[i].events, i, pfds[i].fd, err);
 
-        if (err) {
-            dolog ("Failed to set handler events=%#x index=%d fd=%d err=%d\n",
-                   pfds[i].events, i, pfds[i].fd, err);
-
-            while (i--) {
-                qemu_set_fd_handler (pfds[i].fd, NULL, NULL, NULL);
-            }
-            g_free (pfds);
-            return -1;
-        }
     }
     hlp->pfds = pfds;
     hlp->count = count;
@@ -476,14 +454,15 @@
 }
 
 static int alsa_open (int in, struct alsa_params_req *req,
-                      struct alsa_params_obt *obt, snd_pcm_t **handlep)
+                      struct alsa_params_obt *obt, snd_pcm_t **handlep,
+                      ALSAConf *conf)
 {
     snd_pcm_t *handle;
     snd_pcm_hw_params_t *hw_params;
     int err;
     int size_in_usec;
     unsigned int freq, nchannels;
-    const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
+    const char *pcm_name = in ? conf->pcm_name_in : conf->pcm_name_out;
     snd_pcm_uframes_t obt_buffer_size;
     const char *typ = in ? "ADC" : "DAC";
     snd_pcm_format_t obtfmt;
@@ -522,7 +501,7 @@
     }
 
     err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
-    if (err < 0 && conf.verbose) {
+    if (err < 0) {
         alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
     }
 
@@ -654,7 +633,7 @@
         goto err;
     }
 
-    if (!in && conf.threshold) {
+    if (!in && conf->threshold) {
         snd_pcm_uframes_t threshold;
         int bytes_per_sec;
 
@@ -676,7 +655,7 @@
             break;
         }
 
-        threshold = (conf.threshold * bytes_per_sec) / 1000;
+        threshold = (conf->threshold * bytes_per_sec) / 1000;
         alsa_set_threshold (handle, threshold);
     }
 
@@ -686,10 +665,9 @@
 
     *handlep = handle;
 
-    if (conf.verbose &&
-        (obtfmt != req->fmt ||
+    if (obtfmt != req->fmt ||
          obt->nchannels != req->nchannels ||
-         obt->freq != req->freq)) {
+         obt->freq != req->freq) {
         dolog ("Audio parameters for %s\n", typ);
         alsa_dump_info (req, obt, obtfmt);
     }
@@ -743,9 +721,7 @@
             if (written <= 0) {
                 switch (written) {
                 case 0:
-                    if (conf.verbose) {
-                        dolog ("Failed to write %d frames (wrote zero)\n", len);
-                    }
+                    trace_alsa_wrote_zero(len);
                     return;
 
                 case -EPIPE:
@@ -754,9 +730,7 @@
                                      len);
                         return;
                     }
-                    if (conf.verbose) {
-                        dolog ("Recovering from playback xrun\n");
-                    }
+                    trace_alsa_xrun_out();
                     continue;
 
                 case -ESTRPIPE:
@@ -767,9 +741,7 @@
                                      len);
                         return;
                     }
-                    if (conf.verbose) {
-                        dolog ("Resuming suspended output stream\n");
-                    }
+                    trace_alsa_resume_out();
                     continue;
 
                 case -EAGAIN:
@@ -819,25 +791,27 @@
     alsa->pcm_buf = NULL;
 }
 
-static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as,
+                         void *drv_opaque)
 {
     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
     struct alsa_params_req req;
     struct alsa_params_obt obt;
     snd_pcm_t *handle;
     struct audsettings obt_as;
+    ALSAConf *conf = drv_opaque;
 
     req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
     req.freq = as->freq;
     req.nchannels = as->nchannels;
-    req.period_size = conf.period_size_out;
-    req.buffer_size = conf.buffer_size_out;
-    req.size_in_usec = conf.size_in_usec_out;
+    req.period_size = conf->period_size_out;
+    req.buffer_size = conf->buffer_size_out;
+    req.size_in_usec = conf->size_in_usec_out;
     req.override_mask =
-        (conf.period_size_out_overridden ? 1 : 0) |
-        (conf.buffer_size_out_overridden ? 2 : 0);
+        (conf->period_size_out_overridden ? 1 : 0) |
+        (conf->buffer_size_out_overridden ? 2 : 0);
 
-    if (alsa_open (0, &req, &obt, &handle)) {
+    if (alsa_open (0, &req, &obt, &handle, conf)) {
         return -1;
     }
 
@@ -858,6 +832,7 @@
     }
 
     alsa->handle = handle;
+    alsa->pollhlp.conf = conf;
     return 0;
 }
 
@@ -928,25 +903,26 @@
     return -1;
 }
 
-static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
     struct alsa_params_req req;
     struct alsa_params_obt obt;
     snd_pcm_t *handle;
     struct audsettings obt_as;
+    ALSAConf *conf = drv_opaque;
 
     req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
     req.freq = as->freq;
     req.nchannels = as->nchannels;
-    req.period_size = conf.period_size_in;
-    req.buffer_size = conf.buffer_size_in;
-    req.size_in_usec = conf.size_in_usec_in;
+    req.period_size = conf->period_size_in;
+    req.buffer_size = conf->buffer_size_in;
+    req.size_in_usec = conf->size_in_usec_in;
     req.override_mask =
-        (conf.period_size_in_overridden ? 1 : 0) |
-        (conf.buffer_size_in_overridden ? 2 : 0);
+        (conf->period_size_in_overridden ? 1 : 0) |
+        (conf->buffer_size_in_overridden ? 2 : 0);
 
-    if (alsa_open (1, &req, &obt, &handle)) {
+    if (alsa_open (1, &req, &obt, &handle, conf)) {
         return -1;
     }
 
@@ -967,6 +943,7 @@
     }
 
     alsa->handle = handle;
+    alsa->pollhlp.conf = conf;
     return 0;
 }
 
@@ -1022,14 +999,10 @@
                 dolog ("Failed to resume suspended input stream\n");
                 return 0;
             }
-            if (conf.verbose) {
-                dolog ("Resuming suspended input stream\n");
-            }
+            trace_alsa_resume_in();
             break;
         default:
-            if (conf.verbose) {
-                dolog ("No frames available and ALSA state is %d\n", state);
-            }
+            trace_alsa_no_frames(state);
             return 0;
         }
     }
@@ -1064,9 +1037,7 @@
             if (nread <= 0) {
                 switch (nread) {
                 case 0:
-                    if (conf.verbose) {
-                        dolog ("Failed to read %ld frames (read zero)\n", len);
-                    }
+                    trace_alsa_read_zero(len);
                     goto exit;
 
                 case -EPIPE:
@@ -1074,9 +1045,7 @@
                         alsa_logerr (nread, "Failed to read %ld frames\n", len);
                         goto exit;
                     }
-                    if (conf.verbose) {
-                        dolog ("Recovering from capture xrun\n");
-                    }
+                    trace_alsa_xrun_in();
                     continue;
 
                 case -EAGAIN:
@@ -1148,82 +1117,85 @@
     return -1;
 }
 
+static ALSAConf glob_conf = {
+    .buffer_size_out = 4096,
+    .period_size_out = 1024,
+    .pcm_name_out = "default",
+    .pcm_name_in = "default",
+};
+
 static void *alsa_audio_init (void)
 {
-    return &conf;
+    ALSAConf *conf = g_malloc(sizeof(ALSAConf));
+    *conf = glob_conf;
+    return conf;
 }
 
 static void alsa_audio_fini (void *opaque)
 {
-    (void) opaque;
+    g_free(opaque);
 }
 
 static struct audio_option alsa_options[] = {
     {
         .name        = "DAC_SIZE_IN_USEC",
         .tag         = AUD_OPT_BOOL,
-        .valp        = &conf.size_in_usec_out,
+        .valp        = &glob_conf.size_in_usec_out,
         .descr       = "DAC period/buffer size in microseconds (otherwise in frames)"
     },
     {
         .name        = "DAC_PERIOD_SIZE",
         .tag         = AUD_OPT_INT,
-        .valp        = &conf.period_size_out,
+        .valp        = &glob_conf.period_size_out,
         .descr       = "DAC period size (0 to go with system default)",
-        .overriddenp = &conf.period_size_out_overridden
+        .overriddenp = &glob_conf.period_size_out_overridden
     },
     {
         .name        = "DAC_BUFFER_SIZE",
         .tag         = AUD_OPT_INT,
-        .valp        = &conf.buffer_size_out,
+        .valp        = &glob_conf.buffer_size_out,
         .descr       = "DAC buffer size (0 to go with system default)",
-        .overriddenp = &conf.buffer_size_out_overridden
+        .overriddenp = &glob_conf.buffer_size_out_overridden
     },
     {
         .name        = "ADC_SIZE_IN_USEC",
         .tag         = AUD_OPT_BOOL,
-        .valp        = &conf.size_in_usec_in,
+        .valp        = &glob_conf.size_in_usec_in,
         .descr       =
         "ADC period/buffer size in microseconds (otherwise in frames)"
     },
     {
         .name        = "ADC_PERIOD_SIZE",
         .tag         = AUD_OPT_INT,
-        .valp        = &conf.period_size_in,
+        .valp        = &glob_conf.period_size_in,
         .descr       = "ADC period size (0 to go with system default)",
-        .overriddenp = &conf.period_size_in_overridden
+        .overriddenp = &glob_conf.period_size_in_overridden
     },
     {
         .name        = "ADC_BUFFER_SIZE",
         .tag         = AUD_OPT_INT,
-        .valp        = &conf.buffer_size_in,
+        .valp        = &glob_conf.buffer_size_in,
         .descr       = "ADC buffer size (0 to go with system default)",
-        .overriddenp = &conf.buffer_size_in_overridden
+        .overriddenp = &glob_conf.buffer_size_in_overridden
     },
     {
         .name        = "THRESHOLD",
         .tag         = AUD_OPT_INT,
-        .valp        = &conf.threshold,
+        .valp        = &glob_conf.threshold,
         .descr       = "(undocumented)"
     },
     {
         .name        = "DAC_DEV",
         .tag         = AUD_OPT_STR,
-        .valp        = &conf.pcm_name_out,
+        .valp        = &glob_conf.pcm_name_out,
         .descr       = "DAC device name (for instance dmix)"
     },
     {
         .name        = "ADC_DEV",
         .tag         = AUD_OPT_STR,
-        .valp        = &conf.pcm_name_in,
+        .valp        = &glob_conf.pcm_name_in,
         .descr       = "ADC device name"
     },
-    {
-        .name        = "VERBOSE",
-        .tag         = AUD_OPT_BOOL,
-        .valp        = &conf.verbose,
-        .descr       = "Behave in a more verbose way"
-    },
     { /* End of list */ }
 };
 
diff --git a/audio/audio.c b/audio/audio.c
index 9d018e9..c845a44 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -21,16 +21,17 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
 #include "hw/hw.h"
 #include "audio.h"
 #include "monitor/monitor.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
+#include "qemu/cutils.h"
 
 #define AUDIO_CAP "audio"
 #include "audio_int.h"
 
-/* #define DEBUG_PLIVE */
 /* #define DEBUG_LIVE */
 /* #define DEBUG_OUT */
 /* #define DEBUG_CAPTURE */
@@ -66,8 +67,6 @@
         int hertz;
         int64_t ticks;
     } period;
-    int plive;
-    int log_to_monitor;
     int try_poll_in;
     int try_poll_out;
 } conf = {
@@ -96,8 +95,6 @@
     },
 
     .period = { .hertz = 100 },
-    .plive = 0,
-    .log_to_monitor = 0,
     .try_poll_in = 1,
     .try_poll_out = 1,
 };
@@ -331,20 +328,11 @@
 
 void AUD_vlog (const char *cap, const char *fmt, va_list ap)
 {
-    if (conf.log_to_monitor) {
-        if (cap) {
-            monitor_printf(default_mon, "%s: ", cap);
-        }
-
-        monitor_vprintf(default_mon, fmt, ap);
+    if (cap) {
+        fprintf(stderr, "%s: ", cap);
     }
-    else {
-        if (cap) {
-            fprintf (stderr, "%s: ", cap);
-        }
 
-        vfprintf (stderr, fmt, ap);
-    }
+    vfprintf(stderr, fmt, ap);
 }
 
 void AUD_log (const char *cap, const char *fmt, ...)
@@ -1143,8 +1131,6 @@
  */
 int AUD_write (SWVoiceOut *sw, void *buf, int size)
 {
-    int bytes;
-
     if (!sw) {
         /* XXX: Consider options */
         return size;
@@ -1155,14 +1141,11 @@
         return 0;
     }
 
-    bytes = sw->hw->pcm_ops->write (sw, buf, size);
-    return bytes;
+    return sw->hw->pcm_ops->write(sw, buf, size);
 }
 
 int AUD_read (SWVoiceIn *sw, void *buf, int size)
 {
-    int bytes;
-
     if (!sw) {
         /* XXX: Consider options */
         return size;
@@ -1173,8 +1156,7 @@
         return 0;
     }
 
-    bytes = sw->hw->pcm_ops->read (sw, buf, size);
-    return bytes;
+    return sw->hw->pcm_ops->read(sw, buf, size);
 }
 
 int AUD_get_buffer_size_out (SWVoiceOut *sw)
@@ -1454,9 +1436,6 @@
             while (sw) {
                 sw1 = sw->entries.le_next;
                 if (!sw->active && !sw->callback.fn) {
-#ifdef DEBUG_PLIVE
-                    dolog ("Finishing with old voice\n");
-#endif
                     audio_close_out (sw);
                 }
                 sw = sw1;
@@ -1648,18 +1627,6 @@
         .valp  = &conf.period.hertz,
         .descr = "Timer period in HZ (0 - use lowest possible)"
     },
-    {
-        .name  = "PLIVE",
-        .tag   = AUD_OPT_BOOL,
-        .valp  = &conf.plive,
-        .descr = "(undocumented)"
-    },
-    {
-        .name  = "LOG_TO_MONITOR",
-        .tag   = AUD_OPT_BOOL,
-        .valp  = &conf.log_to_monitor,
-        .descr = "Print logging messages to monitor instead of stderr"
-    },
     { /* End of list */ }
 };
 
@@ -1772,13 +1739,21 @@
     audio_reset_timer (s);
 }
 
-static void audio_atexit (void)
+static bool is_cleaning_up;
+
+bool audio_is_cleaning_up(void)
+{
+    return is_cleaning_up;
+}
+
+void audio_cleanup(void)
 {
     AudioState *s = &glob_audio_state;
-    HWVoiceOut *hwo = NULL;
-    HWVoiceIn *hwi = NULL;
+    HWVoiceOut *hwo, *hwon;
+    HWVoiceIn *hwi, *hwin;
 
-    while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
+    is_cleaning_up = true;
+    QLIST_FOREACH_SAFE(hwo, &glob_audio_state.hw_head_out, entries, hwon) {
         SWVoiceCap *sc;
 
         if (hwo->enabled) {
@@ -1794,17 +1769,20 @@
                 cb->ops.destroy (cb->opaque);
             }
         }
+        QLIST_REMOVE(hwo, entries);
     }
 
-    while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
+    QLIST_FOREACH_SAFE(hwi, &glob_audio_state.hw_head_in, entries, hwin) {
         if (hwi->enabled) {
             hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
         }
         hwi->pcm_ops->fini_in (hwi);
+        QLIST_REMOVE(hwi, entries);
     }
 
     if (s->drv) {
         s->drv->fini (s->drv_opaque);
+        s->drv = NULL;
     }
 }
 
@@ -1832,12 +1810,9 @@
     QLIST_INIT (&s->hw_head_out);
     QLIST_INIT (&s->hw_head_in);
     QLIST_INIT (&s->cap_head);
-    atexit (audio_atexit);
+    atexit(audio_cleanup);
 
     s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
-    if (!s->ts) {
-        hw_error("Could not create audio timer\n");
-    }
 
     audio_process_options ("AUDIO", audio_options);
 
@@ -1888,12 +1863,8 @@
 
     if (!done) {
         done = !audio_driver_init (s, &no_audio_driver);
-        if (!done) {
-            hw_error("Could not initialize audio subsystem\n");
-        }
-        else {
-            dolog ("warning: Using timer based audio emulation\n");
-        }
+        assert(done);
+        dolog("warning: Using timer based audio emulation\n");
     }
 
     if (conf.period.hertz <= 0) {
@@ -1904,8 +1875,7 @@
         }
         conf.period.ticks = 1;
     } else {
-        conf.period.ticks =
-            muldiv64 (1, get_ticks_per_sec (), conf.period.hertz);
+        conf.period.ticks = NANOSECONDS_PER_SECOND / conf.period.hertz;
     }
 
     e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
@@ -2007,8 +1977,7 @@
         QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
         QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
 
-        hw = NULL;
-        while ((hw = audio_pcm_hw_find_any_out (hw))) {
+        QLIST_FOREACH(hw, &glob_audio_state.hw_head_out, entries) {
             audio_attach_capture (hw);
         }
         return cap;
diff --git a/audio/audio.h b/audio/audio.h
index e7ea397..c3c5198 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -21,10 +21,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
 #ifndef QEMU_AUDIO_H
 #define QEMU_AUDIO_H
 
-#include "config-host.h"
 #include "qemu/queue.h"
 
 typedef void (*audio_callback_fn) (void *opaque, int avail);
@@ -163,4 +163,7 @@
 int wav_start_capture (CaptureState *s, const char *path, int freq,
                        int bits, int nchannels);
 
-#endif  /* audio.h */
+bool audio_is_cleaning_up(void);
+void audio_cleanup(void);
+
+#endif /* QEMU_AUDIO_H */
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 031eb6e..6c6236a 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -21,6 +21,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
 #ifndef QEMU_AUDIO_INT_H
 #define QEMU_AUDIO_INT_H
 
@@ -156,13 +157,13 @@
 };
 
 struct audio_pcm_ops {
-    int  (*init_out)(HWVoiceOut *hw, struct audsettings *as);
+    int  (*init_out)(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque);
     void (*fini_out)(HWVoiceOut *hw);
     int  (*run_out) (HWVoiceOut *hw, int live);
     int  (*write)   (SWVoiceOut *sw, void *buf, int size);
     int  (*ctl_out) (HWVoiceOut *hw, int cmd, ...);
 
-    int  (*init_in) (HWVoiceIn *hw, struct audsettings *as);
+    int  (*init_in) (HWVoiceIn *hw, struct audsettings *as, void *drv_opaque);
     void (*fini_in) (HWVoiceIn *hw);
     int  (*run_in)  (HWVoiceIn *hw);
     int  (*read)    (SWVoiceIn *sw, void *buf, int size);
@@ -206,14 +207,11 @@
 extern struct audio_driver oss_audio_driver;
 extern struct audio_driver sdl_audio_driver;
 extern struct audio_driver wav_audio_driver;
-extern struct audio_driver fmod_audio_driver;
 extern struct audio_driver alsa_audio_driver;
 extern struct audio_driver coreaudio_audio_driver;
 extern struct audio_driver dsound_audio_driver;
-extern struct audio_driver esd_audio_driver;
 extern struct audio_driver pa_audio_driver;
 extern struct audio_driver spice_audio_driver;
-extern struct audio_driver winwave_audio_driver;
 extern struct audio_driver winaudio_audio_driver;
 extern const struct mixeng_volume nominal_volume;
 
@@ -261,4 +259,4 @@
 #define AUDIO_FUNC __FILE__ ":" AUDIO_STRINGIFY (__LINE__)
 #endif
 
-#endif /* audio_int.h */
+#endif /* QEMU_AUDIO_INT_H */
diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c
index 9a9c306..21ff9c5 100644
--- a/audio/audio_pt_int.c
+++ b/audio/audio_pt_int.c
@@ -1,3 +1,4 @@
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "audio.h"
 
diff --git a/audio/audio_pt_int.h b/audio/audio_pt_int.h
index 0dfff76..4c0c15b 100644
--- a/audio/audio_pt_int.h
+++ b/audio/audio_pt_int.h
@@ -19,4 +19,4 @@
 int audio_pt_unlock_and_signal (struct audio_pt *, const char *);
 int audio_pt_join (struct audio_pt *, void **, const char *);
 
-#endif /* audio_pt_int.h */
+#endif /* QEMU_AUDIO_PT_INT_H */
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 8173188..99b27b2 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -191,9 +191,9 @@
         audio_detach_capture (hw);
 #endif
         QLIST_REMOVE (hw, entries);
+        glue (hw->pcm_ops->fini_, TYPE) (hw);
         glue (s->nb_hw_voices_, TYPE) += 1;
         glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
-        glue (hw->pcm_ops->fini_, TYPE) (hw);
         g_free (hw);
         *hwp = NULL;
     }
@@ -262,7 +262,7 @@
 #ifdef DAC
     QLIST_INIT (&hw->cap_head);
 #endif
-    if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
+    if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) {
         goto err0;
     }
 
@@ -398,10 +398,6 @@
     )
 {
     AudioState *s = &glob_audio_state;
-#ifdef DAC
-    int live = 0;
-    SW *old_sw = NULL;
-#endif
 
     if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) {
         dolog ("card=%p name=%p callback_fn=%p as=%p\n",
@@ -426,29 +422,6 @@
         return sw;
     }
 
-#ifdef DAC
-    if (conf.plive && sw && (!sw->active && !sw->empty)) {
-        live = sw->total_hw_samples_mixed;
-
-#ifdef DEBUG_PLIVE
-        dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
-        dolog ("Old %s freq %d, bits %d, channels %d\n",
-               SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
-        dolog ("New %s freq %d, bits %d, channels %d\n",
-               name,
-               as->freq,
-               (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) ? 16 : 8,
-               as->nchannels);
-#endif
-
-        if (live) {
-            old_sw = sw;
-            old_sw->callback.fn = NULL;
-            sw = NULL;
-        }
-    }
-#endif
-
     if (!glue (conf.fixed_, TYPE).enabled && sw) {
         glue (AUD_close_, TYPE) (card, sw);
         sw = NULL;
@@ -481,20 +454,6 @@
     sw->callback.fn = callback_fn;
     sw->callback.opaque = callback_opaque;
 
-#ifdef DAC
-    if (live) {
-        int mixed =
-            (live << old_sw->info.shift)
-            * old_sw->info.bytes_per_second
-            / sw->info.bytes_per_second;
-
-#ifdef DEBUG_PLIVE
-        dolog ("Silence will be mixed %d\n", mixed);
-#endif
-        sw->total_hw_samples_mixed += mixed;
-    }
-#endif
-
 #ifdef DEBUG_AUDIO
     dolog ("%s\n", name);
     audio_pcm_print_info ("hw", &sw->hw->info);
diff --git a/audio/audio_win_int.c b/audio/audio_win_int.c
index e132405..6900008 100644
--- a/audio/audio_win_int.c
+++ b/audio/audio_win_int.c
@@ -1,5 +1,6 @@
 /* public domain */
 
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 
 #define AUDIO_CAP "win-int"
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 8304a38..9ef76c4 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -23,8 +23,8 @@
  * THE SOFTWARE.
  */
 
+#include "qemu/osdep.h"
 #include <CoreAudio/CoreAudio.h>
-#include <string.h>             /* strerror */
 #include <pthread.h>            /* pthread_X */
 
 #include "qemu-common.h"
@@ -33,33 +33,290 @@
 #define AUDIO_CAP "coreaudio"
 #include "audio_int.h"
 
-#if 0
-#  define  D(...)  fprintf(stderr, __VA_ARGS__)
-#else
-#  define  D(...)  ((void)0)
+#ifndef MAC_OS_X_VERSION_10_6
+#define MAC_OS_X_VERSION_10_6 1060
 #endif
 
-struct {
-    int out_buffer_frames;
-    int out_nbuffers;
-    int in_buffer_frames;
-    int in_nbuffers;
-    int isAtexit;
-} conf = {
-    .out_buffer_frames = 512,
-    .out_nbuffers = 4,
-    .in_buffer_frames = 512,
-    .in_nbuffers = 4,
-    .isAtexit = 0
-};
+typedef struct {
+    int buffer_frames;
+    int nbuffers;
+} CoreaudioConf;
 
-/***************************************************************************************/
-/***************************************************************************************/
-/***                                                                                 ***/
-/***       U T I L I T Y   R O U T I N E S                                           ***/
-/***                                                                                 ***/
-/***************************************************************************************/
-/***************************************************************************************/
+typedef struct coreaudioVoiceBase {
+    pthread_mutex_t mutex;
+    AudioDeviceID deviceID;
+    UInt32 audioDevicePropertyBufferFrameSize;
+    AudioStreamBasicDescription streamBasicDescription;
+    AudioDeviceIOProcID ioprocid;
+    Boolean isInput;
+    int live;
+    int decr;
+    int pos;
+} coreaudioVoiceBase;
+
+typedef struct coreaudioVoiceOut {
+    HWVoiceOut hw;
+    coreaudioVoiceBase core;
+} coreaudioVoiceOut;
+
+typedef struct coreaudioVoiceIn {
+    HWVoiceIn hw;
+    coreaudioVoiceBase core;
+} coreaudioVoiceIn;
+
+// Set to true when atexit() is running.
+static bool gIsAtExit = false;
+
+static void coreaudio_atexit(void) {
+    gIsAtExit = true;
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+/* The APIs used here only become available from 10.6 */
+
+static OSStatus coreaudio_get_voice(AudioDeviceID *id, Boolean isInput)
+{
+    UInt32 size = sizeof(*id);
+    AudioObjectPropertyAddress addr = {
+        isInput ? kAudioHardwarePropertyDefaultInputDevice
+                : kAudioHardwarePropertyDefaultOutputDevice,
+        kAudioObjectPropertyScopeGlobal,
+        kAudioObjectPropertyElementMaster
+    };
+
+    return AudioObjectGetPropertyData(kAudioObjectSystemObject,
+                                      &addr,
+                                      0,
+                                      NULL,
+                                      &size,
+                                      id);
+}
+
+static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
+                                             AudioValueRange *framerange,
+                                             Boolean isInput)
+{
+    UInt32 size = sizeof(*framerange);
+    AudioObjectPropertyAddress addr = {
+        kAudioDevicePropertyBufferFrameSizeRange,
+        isInput ? kAudioDevicePropertyScopeInput
+                : kAudioDevicePropertyScopeOutput,
+        kAudioObjectPropertyElementMaster
+    };
+
+    return AudioObjectGetPropertyData(id,
+                                      &addr,
+                                      0,
+                                      NULL,
+                                      &size,
+                                      framerange);
+}
+
+static OSStatus coreaudio_get_framesize(AudioDeviceID id,
+                                        UInt32 *framesize,
+                                        Boolean isInput)
+{
+    UInt32 size = sizeof(*framesize);
+    AudioObjectPropertyAddress addr = {
+        kAudioDevicePropertyBufferFrameSize,
+        isInput ? kAudioDevicePropertyScopeInput
+                : kAudioDevicePropertyScopeOutput,
+        kAudioObjectPropertyElementMaster
+    };
+
+    return AudioObjectGetPropertyData(id,
+                                      &addr,
+                                      0,
+                                      NULL,
+                                      &size,
+                                      framesize);
+}
+
+static OSStatus coreaudio_set_framesize(AudioDeviceID id,
+                                        UInt32 *framesize,
+                                        Boolean isInput)
+{
+    UInt32 size = sizeof(*framesize);
+    AudioObjectPropertyAddress addr = {
+        kAudioDevicePropertyBufferFrameSize,
+        isInput ? kAudioDevicePropertyScopeInput
+                : kAudioDevicePropertyScopeOutput,
+        kAudioObjectPropertyElementMaster
+    };
+
+    return AudioObjectSetPropertyData(id,
+                                      &addr,
+                                      0,
+                                      NULL,
+                                      size,
+                                      framesize);
+}
+
+static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
+                                           AudioStreamBasicDescription *d,
+                                           Boolean isInput)
+{
+    UInt32 size = sizeof(*d);
+    AudioObjectPropertyAddress addr = {
+        kAudioDevicePropertyStreamFormat,
+        isInput ? kAudioDevicePropertyScopeInput
+                : kAudioDevicePropertyScopeOutput,
+        kAudioObjectPropertyElementMaster
+    };
+
+    return AudioObjectGetPropertyData(id,
+                                      &addr,
+                                      0,
+                                      NULL,
+                                      &size,
+                                      d);
+}
+
+static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
+                                           AudioStreamBasicDescription *d,
+                                           Boolean isInput)
+{
+    UInt32 size = sizeof(*d);
+    AudioObjectPropertyAddress addr = {
+        kAudioDevicePropertyStreamFormat,
+        isInput ? kAudioDevicePropertyScopeInput
+                : kAudioDevicePropertyScopeOutput,
+        kAudioObjectPropertyElementMaster
+    };
+
+    return AudioObjectSetPropertyData(id,
+                                      &addr,
+                                      0,
+                                      NULL,
+                                      size,
+                                      d);
+}
+
+static OSStatus coreaudio_get_isrunning(AudioDeviceID id,
+                                        UInt32 *result,
+                                        Boolean isInput)
+{
+    UInt32 size = sizeof(*result);
+    AudioObjectPropertyAddress addr = {
+        kAudioDevicePropertyDeviceIsRunning,
+        isInput ? kAudioDevicePropertyScopeInput
+                : kAudioDevicePropertyScopeOutput,
+        kAudioObjectPropertyElementMaster
+    };
+
+    return AudioObjectGetPropertyData(id,
+                                      &addr,
+                                      0,
+                                      NULL,
+                                      &size,
+                                      result);
+}
+#else
+/* Legacy versions of functions using deprecated APIs */
+
+static OSStatus coreaudio_get_voice(AudioDeviceID *id, Boolean isInput)
+{
+    UInt32 size = sizeof(*id);
+
+    return AudioHardwareGetProperty(
+        isInput ? kAudioHardwarePropertyDefaultInputDevice
+                : kAudioHardwarePropertyDefaultOutputDevice,
+        &size,
+        id);
+}
+
+static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
+                                             AudioValueRange *framerange,
+                                             Boolean isInput)
+{
+    UInt32 size = sizeof(*framerange);
+
+    return AudioDeviceGetProperty(
+        id,
+        0,
+        isInput,
+        kAudioDevicePropertyBufferFrameSizeRange,
+        &size,
+        framerange);
+}
+
+static OSStatus coreaudio_get_framesize(AudioDeviceID id,
+                                        UInt32 *framesize,
+                                        Boolean isInput)
+{
+    UInt32 size = sizeof(*framesize);
+
+    return AudioDeviceGetProperty(
+        id,
+        0,
+        isInput,
+        kAudioDevicePropertyBufferFrameSize,
+        &size,
+        framesize);
+}
+
+static OSStatus coreaudio_set_framesize(AudioDeviceID id,
+                                        UInt32 *framesize,
+                                        Boolean isInput)
+{
+    UInt32 size = sizeof(*framesize);
+
+    return AudioDeviceSetProperty(
+        id,
+        NULL,
+        0,
+        isInput,
+        kAudioDevicePropertyBufferFrameSize,
+        size,
+        framesize);
+}
+
+static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
+                                           AudioStreamBasicDescription *d,
+                                           Boolean isInput)
+{
+    UInt32 size = sizeof(*d);
+
+    return AudioDeviceGetProperty(
+        id,
+        0,
+        isInput,
+        kAudioDevicePropertyStreamFormat,
+        &size,
+        d);
+}
+
+static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
+                                           AudioStreamBasicDescription *d,
+                                           Boolean isInput)
+{
+    UInt32 size = sizeof(*d);
+
+    return AudioDeviceSetProperty(
+        id,
+        0,
+        0,
+        isInput,
+        kAudioDevicePropertyStreamFormat,
+        size,
+        d);
+}
+
+static OSStatus coreaudio_get_isrunning(AudioDeviceID id,
+                                        UInt32 *result,
+                                        Boolean isInput)
+{
+    UInt32 size = sizeof(*result);
+
+    return AudioDeviceGetProperty(
+        id,
+        0,
+        isInput,
+        kAudioDevicePropertyDeviceIsRunning,
+        &size,
+        result);
+}
+#endif
 
 static void coreaudio_logstatus (OSStatus status)
 {
@@ -151,34 +408,11 @@
     coreaudio_logstatus (status);
 }
 
-/***************************************************************************************/
-/***************************************************************************************/
-/***                                                                                 ***/
-/***       S H A R E D   I N / O U T   V O I C E                                     ***/
-/***                                                                                 ***/
-/***************************************************************************************/
-/***************************************************************************************/
-
-typedef struct coreAudioVoice {
-    pthread_mutex_t              mutex;
-    AudioDeviceID                deviceID;
-    Boolean                      isInput;
-    UInt32                       bufferFrameSize;
-    AudioStreamBasicDescription  streamBasicDescription;
-    AudioDeviceIOProc            ioproc;
-    int                          live;
-    int                          decr;
-    int                          pos;
-} coreaudioVoice;
-
-static inline UInt32 coreaudio_voice_isPlaying (coreaudioVoice *core)
+static inline UInt32 isPlaying (AudioDeviceID deviceID, Boolean isInput)
 {
     OSStatus status;
     UInt32 result = 0;
-    UInt32 propertySize = sizeof(core->deviceID);
-    status = AudioDeviceGetProperty(
-        core->deviceID, 0, core->isInput,
-        kAudioDevicePropertyDeviceIsRunning, &propertySize, &result);
+    status = coreaudio_get_isrunning(deviceID, &result, isInput);
     if (status != kAudioHardwareNoError) {
         coreaudio_logerr(status,
                          "Could not determine whether Device is playing\n");
@@ -186,12 +420,7 @@
     return result;
 }
 
-static void coreaudio_atexit (void)
-{
-    conf.isAtexit = 1;
-}
-
-static int coreaudio_voice_lock (coreaudioVoice *core, const char *fn_name)
+static int coreaudio_lock (coreaudioVoiceBase *core, const char *fn_name)
 {
     int err;
 
@@ -204,7 +433,7 @@
     return 0;
 }
 
-static int coreaudio_voice_unlock (coreaudioVoice *core, const char *fn_name)
+static int coreaudio_unlock (coreaudioVoiceBase *core, const char *fn_name)
 {
     int err;
 
@@ -217,78 +446,20 @@
     return 0;
 }
 
-static int coreaudio_voice_ctl (coreaudioVoice *core, int cmd)
-{
-    OSStatus status;
-
-    switch (cmd) {
-    case VOICE_ENABLE:
-        /* start playback */
-        D("%s: %s started\n", __FUNCTION__, core->isInput ? "input" : "output");
-        if (!coreaudio_voice_isPlaying(core)) {
-            status = AudioDeviceStart(core->deviceID, core->ioproc);
-            if (status != kAudioHardwareNoError) {
-                coreaudio_logerr (status, "Could not resume playback\n");
-            }
-        }
-        break;
-
-    case VOICE_DISABLE:
-        /* stop playback */
-        D("%s: %s stopped\n", __FUNCTION__, core->isInput ? "input" : "output");
-        if (!conf.isAtexit) {
-            if (coreaudio_voice_isPlaying(core)) {
-                status = AudioDeviceStop(core->deviceID, core->ioproc);
-                if (status != kAudioHardwareNoError) {
-                    coreaudio_logerr (status, "Could not pause playback\n");
-                }
-            }
-        }
-        break;
-    }
-    return 0;
-}
-
-static void coreaudio_voice_fini (coreaudioVoice *core)
+static int coreaudio_init_base(coreaudioVoiceBase *core,
+                               struct audsettings *as,
+                               void *drv_opaque,
+                               AudioDeviceIOProc ioproc,
+                               void *hw,
+                               Boolean isInput)
 {
     OSStatus status;
     int err;
-
-    pthread_mutex_lock(&core->mutex);
-
-    /* stop playback */
-    coreaudio_voice_ctl(core, VOICE_DISABLE);
-
-    /* remove callback */
-    status = AudioDeviceRemoveIOProc(core->deviceID, core->ioproc);
-    if (status != kAudioHardwareNoError) {
-        coreaudio_logerr (status, "Could not remove IOProc\n");
-    }
-
-    core->deviceID = kAudioDeviceUnknown;
-
-    pthread_mutex_unlock(&core->mutex);
-
-    /* destroy mutex */
-    err = pthread_mutex_destroy(&core->mutex);
-    if (err) {
-        dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
-    }
-}
-
-
-static int coreaudio_voice_init (coreaudioVoice *core, struct audsettings *as,
-                                 int frameSize, AudioDeviceIOProc ioproc,
-                                 void *hw, int input)
-{
-    OSStatus  status;
-    UInt32    propertySize;
-    int       err;
-    int       bits = 8;
+    const char *typ = isInput ? "record" : "playback";
     AudioValueRange frameRange;
-    const char*  typ = input ? "input" : "playback";
+    CoreaudioConf *conf = drv_opaque;
 
-    core->isInput = input ? true : false;
+    core->isInput = isInput;
 
     /* create mutex */
     err = pthread_mutex_init(&core->mutex, NULL);
@@ -297,22 +468,9 @@
         return -1;
     }
 
-    if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
-        bits = 16;
-    }
+    // audio_pcm_init_info (&hw->info, as);
 
-    // TODO: audio_pcm_init_info (&hw->info, as);
-    /* open default output device */
-    /* note: we use DefaultSystemOutputDevice because DefaultOutputDevice seems to
-     * always link to the internal speakers, and not the ones selected through system properties
-     * go figure...
-     */
-    propertySize = sizeof(core->deviceID);
-    status = AudioHardwareGetProperty(
-        input ? kAudioHardwarePropertyDefaultInputDevice :
-                kAudioHardwarePropertyDefaultSystemOutputDevice,
-        &propertySize,
-        &core->deviceID);
+    status = coreaudio_get_voice(&core->deviceID, isInput);
     if (status != kAudioHardwareNoError) {
         coreaudio_logerr2 (status, typ,
                            "Could not get default %s device\n", typ);
@@ -324,74 +482,52 @@
     }
 
     /* get minimum and maximum buffer frame sizes */
-    propertySize = sizeof(frameRange);
-    status = AudioDeviceGetProperty(
-        core->deviceID,
-        0,
-        core->isInput,
-        kAudioDevicePropertyBufferFrameSizeRange,
-        &propertySize,
-        &frameRange);
+    status = coreaudio_get_framesizerange(core->deviceID,
+                                          &frameRange, isInput);
     if (status != kAudioHardwareNoError) {
         coreaudio_logerr2 (status, typ,
                            "Could not get device buffer frame range\n");
         return -1;
     }
 
-    if (frameRange.mMinimum > frameSize) {
-        core->bufferFrameSize = (UInt32) frameRange.mMinimum;
-        dolog ("warning: Upsizing Output Buffer Frames to %f\n", frameRange.mMinimum);
+    if (frameRange.mMinimum > conf->buffer_frames) {
+        core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
+        dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
     }
-    else if (frameRange.mMaximum < frameSize) {
-        core->bufferFrameSize = (UInt32) frameRange.mMaximum;
-        dolog ("warning: Downsizing Output Buffer Frames to %f\n", frameRange.mMaximum);
+    else if (frameRange.mMaximum < conf->buffer_frames) {
+        core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
+        dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
     }
     else {
-        core->bufferFrameSize = frameSize;
+        core->audioDevicePropertyBufferFrameSize = conf->buffer_frames;
     }
 
     /* set Buffer Frame Size */
-    propertySize = sizeof(core->bufferFrameSize);
-    status = AudioDeviceSetProperty(
-        core->deviceID,
-        NULL,
-        0,
-        core->isInput,
-        kAudioDevicePropertyBufferFrameSize,
-        propertySize,
-        &core->bufferFrameSize);
+    status = coreaudio_set_framesize(core->deviceID,
+                                     &core->audioDevicePropertyBufferFrameSize,
+                                     isInput);
     if (status != kAudioHardwareNoError) {
         coreaudio_logerr2 (status, typ,
                            "Could not set device buffer frame size %" PRIu32 "\n",
-                           (uint32_t)core->bufferFrameSize);
+                           (uint32_t)core->audioDevicePropertyBufferFrameSize);
         return -1;
     }
 
     /* get Buffer Frame Size */
-    propertySize = sizeof(core->bufferFrameSize);
-    status = AudioDeviceGetProperty(
-        core->deviceID,
-        0,
-        core->isInput,
-        kAudioDevicePropertyBufferFrameSize,
-        &propertySize,
-        &core->bufferFrameSize);
+    status = coreaudio_get_framesize(core->deviceID,
+                                     &core->audioDevicePropertyBufferFrameSize,
+                                     isInput);
     if (status != kAudioHardwareNoError) {
         coreaudio_logerr2 (status, typ,
                            "Could not get device buffer frame size\n");
         return -1;
     }
-    // TODO: hw->samples = *pNBuffers * core->bufferFrameSize;
+    // hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize;
 
     /* get StreamFormat */
-    propertySize = sizeof(core->streamBasicDescription);
-    status = AudioDeviceGetProperty(
-        core->deviceID,
-        0,
-        core->isInput,
-        kAudioDevicePropertyStreamFormat,
-        &propertySize,
-        &core->streamBasicDescription);
+    status = coreaudio_get_streamformat(core->deviceID,
+                                        &core->streamBasicDescription,
+                                        isInput);
     if (status != kAudioHardwareNoError) {
         coreaudio_logerr2 (status, typ,
                            "Could not get Device Stream properties\n");
@@ -401,15 +537,9 @@
 
     /* set Samplerate */
     core->streamBasicDescription.mSampleRate = (Float64) as->freq;
-    propertySize = sizeof(core->streamBasicDescription);
-    status = AudioDeviceSetProperty(
-        core->deviceID,
-        0,
-        0,
-        core->isInput,
-        kAudioDevicePropertyStreamFormat,
-        propertySize,
-        &core->streamBasicDescription);
+    status = coreaudio_set_streamformat(core->deviceID,
+                                        &core->streamBasicDescription,
+                                        isInput);
     if (status != kAudioHardwareNoError) {
         coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
                            as->freq);
@@ -418,20 +548,23 @@
     }
 
     /* set Callback */
-    core->ioproc = ioproc;
-    status = AudioDeviceAddIOProc(core->deviceID, ioproc, hw);
-    if (status != kAudioHardwareNoError) {
+    core->ioprocid = NULL;
+    status = AudioDeviceCreateIOProcID(core->deviceID,
+                                       ioproc,
+                                       hw,
+                                       &core->ioprocid);
+    if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
         coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
         core->deviceID = kAudioDeviceUnknown;
         return -1;
     }
 
     /* start Playback */
-    if (!input && !coreaudio_voice_isPlaying(core)) {
-        status = AudioDeviceStart(core->deviceID, core->ioproc);
+    if (!isPlaying(core->deviceID, isInput)) {
+        status = AudioDeviceStart(core->deviceID, core->ioprocid);
         if (status != kAudioHardwareNoError) {
             coreaudio_logerr2 (status, typ, "Could not start playback\n");
-            AudioDeviceRemoveIOProc(core->deviceID, core->ioproc);
+            AudioDeviceDestroyIOProcID(core->deviceID, core->ioprocid);
             core->deviceID = kAudioDeviceUnknown;
             return -1;
         }
@@ -440,29 +573,76 @@
     return 0;
 }
 
+static void coreaudio_fini_base (coreaudioVoiceBase *core)
+{
+    OSStatus status;
+    int err;
 
-/***************************************************************************************/
-/***************************************************************************************/
-/***                                                                                 ***/
-/***       O U T P U T   V O I C E                                                   ***/
-/***                                                                                 ***/
-/***************************************************************************************/
-/***************************************************************************************/
+    if (!audio_is_cleaning_up()) {
+        /* stop playback */
+        if (isPlaying(core->deviceID, core->isInput)) {
+            status = AudioDeviceStop(core->deviceID, core->ioprocid);
+            if (status != kAudioHardwareNoError) {
+                coreaudio_logerr (status, "Could not stop %s\n",
+                                  core->isInput ? "recording" : "playback");
+            }
+        }
 
-typedef struct coreaudioVoiceOut {
-    HWVoiceOut                   hw;
-    coreaudioVoice               core[1];
-} coreaudioVoiceOut;
+        /* remove callback */
+        status = AudioDeviceDestroyIOProcID(core->deviceID,
+                                            core->ioprocid);
+        if (status != kAudioHardwareNoError) {
+            coreaudio_logerr (status, "Could not remove IOProc\n");
+        }
+    }
+    core->deviceID = kAudioDeviceUnknown;
 
-#define  CORE_OUT(hw)  ((coreaudioVoiceOut*)(hw))->core
+    /* destroy mutex */
+    err = pthread_mutex_destroy(&core->mutex);
+    if (err) {
+        dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
+    }
+}
 
+static int coreaudio_ctl_base (coreaudioVoiceBase *core, int cmd)
+{
+    OSStatus status;
+
+    switch (cmd) {
+    case VOICE_ENABLE:
+        /* start playback */
+        if (!isPlaying(core->deviceID, core->isInput)) {
+            status = AudioDeviceStart(core->deviceID, core->ioprocid);
+            if (status != kAudioHardwareNoError) {
+                coreaudio_logerr (status, "Could not resume %s\n",
+                                  core->isInput ? "recording" : "playback");
+            }
+        }
+        break;
+
+    case VOICE_DISABLE:
+        /* stop playback */
+        if (!audio_is_cleaning_up()) {
+            if (isPlaying(core->deviceID, core->isInput)) {
+                status = AudioDeviceStop(core->deviceID,
+                                         core->ioprocid);
+                if (status != kAudioHardwareNoError) {
+                    coreaudio_logerr (status, "Could not pause %s\n",
+                                      core->isInput ? "recording" : "playback");
+                }
+            }
+        }
+        break;
+    }
+    return 0;
+}
 
 static int coreaudio_run_out (HWVoiceOut *hw, int live)
 {
     int decr;
-    coreaudioVoice *core = CORE_OUT(hw);
+    coreaudioVoiceBase *core = &((coreaudioVoiceOut *)hw)->core;
 
-    if (conf.isAtexit || coreaudio_voice_lock (core, "coreaudio_run_out")) {
+    if (coreaudio_lock (core, "coreaudio_run_out")) {
         return 0;
     }
 
@@ -479,12 +659,12 @@
     core->live = live - decr;
     hw->rpos = core->pos;
 
-    coreaudio_voice_unlock (core, "coreaudio_run_out");
+    coreaudio_unlock (core, "coreaudio_run_out");
     return decr;
 }
 
 /* callback to feed audiooutput buffer */
-static OSStatus audioOutDeviceIOProc(
+static OSStatus audioOutputDeviceIOProc(
     AudioDeviceID inDevice,
     const AudioTimeStamp* inNow,
     const AudioBufferList* inInputData,
@@ -496,7 +676,7 @@
     UInt32 frame, frameCount;
     float *out = outOutputData->mBuffers[0].mData;
     HWVoiceOut *hw = hwptr;
-    coreaudioVoice *core = CORE_OUT(hw);
+    coreaudioVoiceBase *core = &((coreaudioVoiceOut *) hw)->core;
     int rpos, live;
     struct st_sample *src;
 #ifndef FLOAT_MIXENG
@@ -507,18 +687,18 @@
 #endif
 #endif
 
-    if (coreaudio_voice_lock (core, "audioDeviceIOProc")) {
+    if (coreaudio_lock (core, "audioOutputDeviceIOProc")) {
         inInputTime = 0;
         return 0;
     }
 
-    frameCount = core->bufferFrameSize;
+    frameCount = core->audioDevicePropertyBufferFrameSize;
     live = core->live;
 
     /* if there are not enough samples, set signal and return */
-    if (live < (int)frameCount) {
+    if (live < frameCount) {
         inInputTime = 0;
-        coreaudio_voice_unlock (core, "audioDeviceIOProc(empty)");
+        coreaudio_unlock (core, "audioOutputDeviceIOProc(empty)");
         return 0;
     }
 
@@ -545,7 +725,7 @@
     core->decr += frameCount;
     core->pos = rpos;
 
-    coreaudio_voice_unlock (core, "audioDeviceIOProc");
+    coreaudio_unlock (core, "audioOutputDeviceIOProc");
     return 0;
 }
 
@@ -554,75 +734,54 @@
     return audio_pcm_sw_write (sw, buf, len);
 }
 
-static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
+                              void *drv_opaque)
 {
-    coreaudioVoice *core = CORE_OUT(hw);
-    int err;
+    coreaudioVoiceBase *core = &((coreaudioVoiceOut *) hw)->core;
+    CoreaudioConf *conf = drv_opaque;
 
     audio_pcm_init_info (&hw->info, as);
 
-    err = coreaudio_voice_init (core, as, conf.out_buffer_frames, audioOutDeviceIOProc, hw, 0);
-    if (err < 0)
-        return err;
+    if (coreaudio_init_base(core, as, drv_opaque,
+                            audioOutputDeviceIOProc, hw, false) < 0) {
+        return -1;
+    }
 
-    hw->samples = core->bufferFrameSize * conf.out_nbuffers;
+    hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize;
+
     return 0;
 }
-
 static void coreaudio_fini_out (HWVoiceOut *hw)
 {
-    coreaudioVoice *core = CORE_OUT(hw);
-
-    coreaudio_voice_fini (core);
+    coreaudioVoiceBase *core = &((coreaudioVoiceOut *) hw)->core;
+    coreaudio_fini_base(core);
 }
 
-static int
-coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
+static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
 {
-    coreaudioVoice *core = CORE_OUT(hw);
-
-    return coreaudio_voice_ctl (core, cmd);
+    coreaudioVoiceBase *core = &((coreaudioVoiceOut *) hw)->core;
+    return coreaudio_ctl_base(core, cmd);
 }
 
-/***************************************************************************************/
-/***************************************************************************************/
-/***                                                                                 ***/
-/***       I N P U T   V O I C E                                                     ***/
-/***                                                                                 ***/
-/***************************************************************************************/
-/***************************************************************************************/
-
-
-
-typedef struct coreaudioVoiceIn {
-    HWVoiceIn        hw;
-    coreaudioVoice   core[1];
-} coreaudioVoiceIn;
-
-#define  CORE_IN(hw)  ((coreaudioVoiceIn *) (hw))->core
-
-
 static int coreaudio_run_in (HWVoiceIn *hw)
 {
     int decr;
 
-    coreaudioVoice *core = CORE_IN(hw);
+    coreaudioVoiceBase *core = &((coreaudioVoiceIn *)hw)->core;
 
-    if (conf.isAtexit || coreaudio_voice_lock (core, "coreaudio_run_in")) {
+    if (gIsAtExit || coreaudio_lock (core, "coreaudio_run_in")) {
         return 0;
     }
-    D("%s: core.decr=%d core.pos=%d\n", __FUNCTION__, core->decr, core->pos);
     decr        = core->decr;
     core->decr -= decr;
     hw->wpos    = core->pos;
 
-    coreaudio_voice_unlock (core, "coreaudio_run_in");
+    coreaudio_unlock (core, "coreaudio_run_in");
     return decr;
 }
 
-
-/* callback to feed audiooutput buffer */
-static OSStatus audioInDeviceIOProc(
+/* callback to feed audioinput buffer */
+static OSStatus audioInputDeviceIOProc(
     AudioDeviceID inDevice,
     const AudioTimeStamp* inNow,
     const AudioBufferList* inInputData,
@@ -634,7 +793,7 @@
     UInt32 frame, frameCount;
     float *in = inInputData->mBuffers[0].mData;
     HWVoiceIn *hw = hwptr;
-    coreaudioVoice *core = CORE_IN(hw);
+    coreaudioVoiceBase *core = &((coreaudioVoiceIn *)hw)->core;
     int wpos, avail;
     struct st_sample *dst;
 #ifndef FLOAT_MIXENG
@@ -645,21 +804,18 @@
 #endif
 #endif
 
-    if (coreaudio_voice_lock (core, "audioDeviceIOProc")) {
+    if (coreaudio_lock (core, "audioInputDeviceIOProc")) {
         inInputTime = 0;
         return 0;
     }
 
-    frameCount = core->bufferFrameSize;
+    frameCount = core->audioDevicePropertyBufferFrameSize;
     avail      = hw->samples - hw->total_samples_captured - core->decr;
 
-    D("%s: enter avail=%d core.decr=%d core.pos=%d hw.samples=%d hw.total_samples_captured=%d frameCount=%d\n",
-      __FUNCTION__, avail, core->decr, core->pos, hw->samples, hw->total_samples_captured, (int)frameCount);
-
     /* if there are not enough samples, set signal and return */
     if (avail < (int)frameCount) {
         inInputTime = 0;
-        coreaudio_voice_unlock (core, "audioDeviceIOProc(empty)");
+        coreaudio_unlock (core, "audioInputDeviceIOProc(empty)");
         return 0;
     }
 
@@ -686,84 +842,75 @@
     core->decr += frameCount;
     core->pos   = wpos;
 
-    D("exit: core.decr=%d core.pos=%d\n", core->decr, core->pos);
-    coreaudio_voice_unlock (core, "audioDeviceIOProc");
+    coreaudio_unlock (core, "audioInputDeviceIOProc");
     return 0;
 }
 
 static int coreaudio_read (SWVoiceIn *sw, void *buf, int len)
 {
-    int  result = audio_pcm_sw_read (sw, buf, len);
-    D("%s: audio_pcm_sw_read(%d) returned %d\n", __FUNCTION__, len, result);
-    return result;
+    return audio_pcm_sw_read (sw, buf, len);
 }
 
-static int coreaudio_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int coreaudio_init_in(HWVoiceIn *hw, struct audsettings *as,
+                             void *drv_opaque)
 {
-    coreaudioVoice*  core = CORE_IN(hw);
-    int              err;
+    coreaudioVoiceBase *core = &((coreaudioVoiceIn *) hw)->core;
+    CoreaudioConf *conf = drv_opaque;
 
     audio_pcm_init_info (&hw->info, as);
 
-    err = coreaudio_voice_init (core, as, conf.in_buffer_frames, audioInDeviceIOProc, hw, 1);
-    if (err < 0) {
-        return err;
+    if (coreaudio_init_base(core, as, drv_opaque,
+                            audioInputDeviceIOProc, hw, true) < 0) {
+        return -1;
     }
 
-    hw->samples = core->bufferFrameSize * conf.in_nbuffers;
+    hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize;
+
     return 0;
 }
-
 static void coreaudio_fini_in (HWVoiceIn *hw)
 {
-
-    coreaudioVoice*  core = CORE_IN(hw);
-
-    coreaudio_voice_fini(core);
+    coreaudioVoiceBase *core = &((coreaudioVoiceIn *) hw)->core;
+    coreaudio_fini_base(core);
 }
 
 static int coreaudio_ctl_in (HWVoiceIn *hw, int cmd, ...)
 {
-    coreaudioVoice*  core = CORE_IN(hw);
-
-    return coreaudio_voice_ctl(core, cmd);
+    coreaudioVoiceBase *core = &((coreaudioVoiceIn *) hw)->core;
+    return coreaudio_ctl_base(core, cmd);
 }
 
+static CoreaudioConf glob_conf = {
+    .buffer_frames = 512,
+    .nbuffers = 4,
+};
+
 static void *coreaudio_audio_init (void)
 {
+    CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf));
+    *conf = glob_conf;
+
     atexit(coreaudio_atexit);
-    return &coreaudio_audio_init;
+    return conf;
 }
 
 static void coreaudio_audio_fini (void *opaque)
 {
-    (void) opaque;
+    g_free(opaque);
 }
 
 static struct audio_option coreaudio_options[] = {
     {
-        .name  = "OUT_BUFFER_SIZE",
+        .name  = "BUFFER_SIZE",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.out_buffer_frames,
-        .descr = "Size of the output buffer in frames"
+        .valp  = &glob_conf.buffer_frames,
+        .descr = "Size of the buffer in frames"
     },
     {
-        .name  = "OUT_BUFFER_COUNT",
+        .name  = "BUFFER_COUNT",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.out_nbuffers,
-        .descr = "Number of output buffers"
-    },
-    {
-        .name  = "IN_BUFFER_SIZE",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.in_buffer_frames,
-        .descr = "Size of the input buffer in frames"
-    },
-    {
-        .name  = "IN_BUFFER_COUNT",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.in_nbuffers,
-        .descr = "Number of input buffers"
+        .valp  = &glob_conf.nbuffers,
+        .descr = "Number of buffers"
     },
     { /* End of list */ }
 };
diff --git a/audio/dsound_template.h b/audio/dsound_template.h
index 8b37d16..b439f33 100644
--- a/audio/dsound_template.h
+++ b/audio/dsound_template.h
@@ -67,11 +67,11 @@
     LPVOID *p2p,
     DWORD *blen1p,
     DWORD *blen2p,
-    int entire
+    int entire,
+    dsound *s
     )
 {
     HRESULT hr;
-    int i;
     LPVOID p1 = NULL, p2 = NULL;
     DWORD blen1 = 0, blen2 = 0;
     DWORD flag;
@@ -81,37 +81,18 @@
 #else
     flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
 #endif
-    for (i = 0; i < conf.lock_retries; ++i) {
-        hr = glue (IFACE, _Lock) (
-            buf,
-            pos,
-            len,
-            &p1,
-            &blen1,
-            &p2,
-            &blen2,
-            flag
-            );
+    hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag);
 
-        if (FAILED (hr)) {
+    if (FAILED (hr)) {
 #ifndef DSBTYPE_IN
-            if (hr == DSERR_BUFFERLOST) {
-                if (glue (dsound_restore_, TYPE) (buf)) {
-                    dsound_logerr (hr, "Could not lock " NAME "\n");
-                    goto fail;
-                }
-                continue;
+        if (hr == DSERR_BUFFERLOST) {
+            if (glue (dsound_restore_, TYPE) (buf, s)) {
+                dsound_logerr (hr, "Could not lock " NAME "\n");
             }
-#endif
-            dsound_logerr (hr, "Could not lock " NAME "\n");
             goto fail;
         }
-
-        break;
-    }
-
-    if (i == conf.lock_retries) {
-        dolog ("%d attempts to lock " NAME " failed\n", i);
+#endif
+        dsound_logerr (hr, "Could not lock " NAME "\n");
         goto fail;
     }
 
@@ -174,16 +155,19 @@
 }
 
 #ifdef DSBTYPE_IN
-static int dsound_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
+                          void *drv_opaque)
 #else
-static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
+                           void *drv_opaque)
 #endif
 {
     int err;
     HRESULT hr;
-    dsound *s = &glob_dsound;
+    dsound *s = drv_opaque;
     WAVEFORMATEX wfx;
     struct audsettings obt_as;
+    DSoundConf *conf = &s->conf;
 #ifdef DSBTYPE_IN
     const char *typ = "ADC";
     DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
@@ -210,7 +194,7 @@
     bd.dwSize = sizeof (bd);
     bd.lpwfxFormat = &wfx;
 #ifdef DSBTYPE_IN
-    bd.dwBufferBytes = conf.bufsize_in;
+    bd.dwBufferBytes = conf->bufsize_in;
     hr = IDirectSoundCapture_CreateCaptureBuffer (
         s->dsound_capture,
         &bd,
@@ -219,7 +203,7 @@
         );
 #else
     bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
-    bd.dwBufferBytes = conf.bufsize_out;
+    bd.dwBufferBytes = conf->bufsize_out;
     hr = IDirectSound_CreateSoundBuffer (
         s->dsound,
         &bd,
@@ -269,6 +253,7 @@
             );
     }
     hw->samples = bc.dwBufferBytes >> hw->info.shift;
+    ds->s = s;
 
 #ifdef DEBUG_DSOUND
     dolog ("caps %ld, desc %ld\n",
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index e2d89fd..516846e 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -26,6 +26,7 @@
  * SEAL 1.07 by Carlos 'pel' Hasan was used as documentation
  */
 
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "audio.h"
 
@@ -41,42 +42,25 @@
 
 /* #define DEBUG_DSOUND */
 
-static struct {
-    int lock_retries;
-    int restore_retries;
-    int getstatus_retries;
-    int set_primary;
+typedef struct {
     int bufsize_in;
     int bufsize_out;
-    struct audsettings settings;
     int latency_millis;
-} conf = {
-    .lock_retries       = 1,
-    .restore_retries    = 1,
-    .getstatus_retries  = 1,
-    .set_primary        = 0,
-    .bufsize_in         = 16384,
-    .bufsize_out        = 16384,
-    .settings.freq      = 44100,
-    .settings.nchannels = 2,
-    .settings.fmt       = AUD_FMT_S16,
-    .latency_millis     = 10
-};
+} DSoundConf;
 
 typedef struct {
     LPDIRECTSOUND dsound;
     LPDIRECTSOUNDCAPTURE dsound_capture;
-    LPDIRECTSOUNDBUFFER dsound_primary_buffer;
     struct audsettings settings;
+    DSoundConf conf;
 } dsound;
 
-static dsound glob_dsound;
-
 typedef struct {
     HWVoiceOut hw;
     LPDIRECTSOUNDBUFFER dsound_buffer;
     DWORD old_pos;
     int first_time;
+    dsound *s;
 #ifdef DEBUG_DSOUND
     DWORD old_ppos;
     DWORD played;
@@ -88,6 +72,7 @@
     HWVoiceIn hw;
     int first_time;
     LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
+    dsound *s;
 } DSoundVoiceIn;
 
 static void dsound_log_hresult (HRESULT hr)
@@ -281,29 +266,17 @@
 }
 #endif
 
-static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb)
+static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, dsound *s)
 {
     HRESULT hr;
-    int i;
 
-    for (i = 0; i < conf.restore_retries; ++i) {
-        hr = IDirectSoundBuffer_Restore (dsb);
+    hr = IDirectSoundBuffer_Restore (dsb);
 
-        switch (hr) {
-        case DS_OK:
-            return 0;
-
-        case DSERR_BUFFERLOST:
-            continue;
-
-        default:
-            dsound_logerr (hr, "Could not restore playback buffer\n");
-            return -1;
-        }
+    if (hr != DS_OK) {
+        dsound_logerr (hr, "Could not restore playback buffer\n");
+        return -1;
     }
-
-    dolog ("%d attempts to restore playback buffer failed\n", i);
-    return -1;
+    return 0;
 }
 
 #include "dsound_template.h"
@@ -311,25 +284,20 @@
 #include "dsound_template.h"
 #undef DSBTYPE_IN
 
-static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp)
+static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp,
+                                  dsound *s)
 {
     HRESULT hr;
-    int i;
 
-    for (i = 0; i < conf.getstatus_retries; ++i) {
-        hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not get playback buffer status\n");
-            return -1;
-        }
+    hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
+    if (FAILED (hr)) {
+        dsound_logerr (hr, "Could not get playback buffer status\n");
+        return -1;
+    }
 
-        if (*statusp & DSERR_BUFFERLOST) {
-            if (dsound_restore_out (dsb)) {
-                return -1;
-            }
-            continue;
-        }
-        break;
+    if (*statusp & DSERR_BUFFERLOST) {
+        dsound_restore_out(dsb, s);
+        return -1;
     }
 
     return 0;
@@ -376,7 +344,8 @@
     hw->rpos = pos % hw->samples;
 }
 
-static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)
+static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb,
+                                 dsound *s)
 {
     int err;
     LPVOID p1, p2;
@@ -389,7 +358,8 @@
         hw->samples << hw->info.shift,
         &p1, &p2,
         &blen1, &blen2,
-        1
+        1,
+        s
         );
     if (err) {
         return;
@@ -415,25 +385,9 @@
     dsound_unlock_out (dsb, p1, p2, blen1, blen2);
 }
 
-static void dsound_close (dsound *s)
-{
-    HRESULT hr;
-
-    if (s->dsound_primary_buffer) {
-        hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not release primary buffer\n");
-        }
-        s->dsound_primary_buffer = NULL;
-    }
-}
-
 static int dsound_open (dsound *s)
 {
-    int err;
     HRESULT hr;
-    WAVEFORMATEX wfx;
-    DSBUFFERDESC dsbd;
     HWND hwnd;
 
     hwnd = GetForegroundWindow ();
@@ -449,63 +403,7 @@
         return -1;
     }
 
-    if (!conf.set_primary) {
-        return 0;
-    }
-
-    err = waveformat_from_audio_settings (&wfx, &conf.settings);
-    if (err) {
-        return -1;
-    }
-
-    memset (&dsbd, 0, sizeof (dsbd));
-    dsbd.dwSize = sizeof (dsbd);
-    dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
-    dsbd.dwBufferBytes = 0;
-    dsbd.lpwfxFormat = NULL;
-
-    hr = IDirectSound_CreateSoundBuffer (
-        s->dsound,
-        &dsbd,
-        &s->dsound_primary_buffer,
-        NULL
-        );
-    if (FAILED (hr)) {
-        dsound_logerr (hr, "Could not create primary playback buffer\n");
-        return -1;
-    }
-
-    hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx);
-    if (FAILED (hr)) {
-        dsound_logerr (hr, "Could not set primary playback buffer format\n");
-    }
-
-    hr = IDirectSoundBuffer_GetFormat (
-        s->dsound_primary_buffer,
-        &wfx,
-        sizeof (wfx),
-        NULL
-        );
-    if (FAILED (hr)) {
-        dsound_logerr (hr, "Could not get primary playback buffer format\n");
-        goto fail0;
-    }
-
-#ifdef DEBUG_DSOUND
-    dolog ("Primary\n");
-    print_wave_format (&wfx);
-#endif
-
-    err = waveformat_to_audio_settings (&wfx, &s->settings);
-    if (err) {
-        goto fail0;
-    }
-
     return 0;
-
- fail0:
-    dsound_close (s);
-    return -1;
 }
 
 static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
@@ -514,6 +412,7 @@
     DWORD status;
     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
     LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
+    dsound *s = ds->s;
 
     if (!dsb) {
         dolog ("Attempt to control voice without a buffer\n");
@@ -522,7 +421,7 @@
 
     switch (cmd) {
     case VOICE_ENABLE:
-        if (dsound_get_status_out (dsb, &status)) {
+        if (dsound_get_status_out (dsb, &status, s)) {
             return -1;
         }
 
@@ -531,7 +430,7 @@
             return 0;
         }
 
-        dsound_clear_sample (hw, dsb);
+        dsound_clear_sample (hw, dsb, s);
 
         hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING);
         if (FAILED (hr)) {
@@ -541,7 +440,7 @@
         break;
 
     case VOICE_DISABLE:
-        if (dsound_get_status_out (dsb, &status)) {
+        if (dsound_get_status_out (dsb, &status, s)) {
             return -1;
         }
 
@@ -578,6 +477,8 @@
     DWORD wpos, ppos, old_pos;
     LPVOID p1, p2;
     int bufsize;
+    dsound *s = ds->s;
+    DSoundConf *conf = &s->conf;
 
     if (!dsb) {
         dolog ("Attempt to run empty with playback buffer\n");
@@ -600,14 +501,14 @@
     len = live << hwshift;
 
     if (ds->first_time) {
-        if (conf.latency_millis) {
+        if (conf->latency_millis) {
             DWORD cur_blat;
 
             cur_blat = audio_ring_dist (wpos, ppos, bufsize);
             ds->first_time = 0;
             old_pos = wpos;
             old_pos +=
-                millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat;
+                millis_to_bytes (&hw->info, conf->latency_millis) - cur_blat;
             old_pos %= bufsize;
             old_pos &= ~hw->info.align;
         }
@@ -663,7 +564,8 @@
         len,
         &p1, &p2,
         &blen1, &blen2,
-        0
+        0,
+        s
         );
     if (err) {
         return 0;
@@ -766,6 +668,7 @@
     DWORD cpos, rpos;
     LPVOID p1, p2;
     int hwshift;
+    dsound *s = ds->s;
 
     if (!dscb) {
         dolog ("Attempt to run without capture buffer\n");
@@ -820,7 +723,8 @@
         &p2,
         &blen1,
         &blen2,
-        0
+        0,
+        s
         );
     if (err) {
         return 0;
@@ -843,12 +747,19 @@
     return decr;
 }
 
+static DSoundConf glob_conf = {
+    .bufsize_in         = 16384,
+    .bufsize_out        = 16384,
+    .latency_millis     = 10
+};
+
 static void dsound_audio_fini (void *opaque)
 {
     HRESULT hr;
     dsound *s = opaque;
 
     if (!s->dsound) {
+        g_free(s);
         return;
     }
 
@@ -859,6 +770,7 @@
     s->dsound = NULL;
 
     if (!s->dsound_capture) {
+        g_free(s);
         return;
     }
 
@@ -867,17 +779,21 @@
         dsound_logerr (hr, "Could not release DirectSoundCapture\n");
     }
     s->dsound_capture = NULL;
+
+    g_free(s);
 }
 
 static void *dsound_audio_init (void)
 {
     int err;
     HRESULT hr;
-    dsound *s = &glob_dsound;
+    dsound *s = g_malloc0(sizeof(dsound));
 
+    s->conf = glob_conf;
     hr = CoInitialize (NULL);
     if (FAILED (hr)) {
         dsound_logerr (hr, "Could not initialize COM\n");
+        g_free(s);
         return NULL;
     }
 
@@ -890,6 +806,7 @@
         );
     if (FAILED (hr)) {
         dsound_logerr (hr, "Could not create DirectSound instance\n");
+        g_free(s);
         return NULL;
     }
 
@@ -901,7 +818,7 @@
         if (FAILED (hr)) {
             dsound_logerr (hr, "Could not release DirectSound\n");
         }
-        s->dsound = NULL;
+        g_free(s);
         return NULL;
     }
 
@@ -939,63 +856,21 @@
 
 static struct audio_option dsound_options[] = {
     {
-        .name  = "LOCK_RETRIES",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.lock_retries,
-        .descr = "Number of times to attempt locking the buffer"
-    },
-    {
-        .name  = "RESTOURE_RETRIES",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.restore_retries,
-        .descr = "Number of times to attempt restoring the buffer"
-    },
-    {
-        .name  = "GETSTATUS_RETRIES",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.getstatus_retries,
-        .descr = "Number of times to attempt getting status of the buffer"
-    },
-    {
-        .name  = "SET_PRIMARY",
-        .tag   = AUD_OPT_BOOL,
-        .valp  = &conf.set_primary,
-        .descr = "Set the parameters of primary buffer"
-    },
-    {
         .name  = "LATENCY_MILLIS",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.latency_millis,
+        .valp  = &glob_conf.latency_millis,
         .descr = "(undocumented)"
     },
     {
-        .name  = "PRIMARY_FREQ",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.settings.freq,
-        .descr = "Primary buffer frequency"
-    },
-    {
-        .name  = "PRIMARY_CHANNELS",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.settings.nchannels,
-        .descr = "Primary buffer number of channels (1 - mono, 2 - stereo)"
-    },
-    {
-        .name  = "PRIMARY_FMT",
-        .tag   = AUD_OPT_FMT,
-        .valp  = &conf.settings.fmt,
-        .descr = "Primary buffer format"
-    },
-    {
         .name  = "BUFSIZE_OUT",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.bufsize_out,
+        .valp  = &glob_conf.bufsize_out,
         .descr = "(undocumented)"
     },
     {
         .name  = "BUFSIZE_IN",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.bufsize_in,
+        .valp  = &glob_conf.bufsize_in,
         .descr = "(undocumented)"
     },
     { /* End of list */ }
diff --git a/audio/esdaudio.c b/audio/esdaudio.c
deleted file mode 100644
index eea9cce..0000000
--- a/audio/esdaudio.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * QEMU ESD audio driver
- *
- * Copyright (c) 2006 Frederick Reeve (brushed up by malc)
- *
- * 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 <esd.h>
-#include "qemu-common.h"
-#include "audio.h"
-
-#define AUDIO_CAP "esd"
-#include "audio_int.h"
-#include "audio_pt_int.h"
-
-typedef struct {
-    HWVoiceOut hw;
-    int done;
-    int live;
-    int decr;
-    int rpos;
-    void *pcm_buf;
-    int fd;
-    struct audio_pt pt;
-} ESDVoiceOut;
-
-typedef struct {
-    HWVoiceIn hw;
-    int done;
-    int dead;
-    int incr;
-    int wpos;
-    void *pcm_buf;
-    int fd;
-    struct audio_pt pt;
-} ESDVoiceIn;
-
-static struct {
-    int samples;
-    int divisor;
-    char *dac_host;
-    char *adc_host;
-} conf = {
-    .samples = 1024,
-    .divisor = 2,
-};
-
-static void GCC_FMT_ATTR (2, 3) qesd_logerr (int err, const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start (ap, fmt);
-    AUD_vlog (AUDIO_CAP, fmt, ap);
-    va_end (ap);
-
-    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
-}
-
-/* playback */
-static void *qesd_thread_out (void *arg)
-{
-    ESDVoiceOut *esd = arg;
-    HWVoiceOut *hw = &esd->hw;
-    int threshold;
-
-    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
-
-    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
-        return NULL;
-    }
-
-    for (;;) {
-        int decr, to_mix, rpos;
-
-        for (;;) {
-            if (esd->done) {
-                goto exit;
-            }
-
-            if (esd->live > threshold) {
-                break;
-            }
-
-            if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
-                goto exit;
-            }
-        }
-
-        decr = to_mix = esd->live;
-        rpos = hw->rpos;
-
-        if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
-            return NULL;
-        }
-
-        while (to_mix) {
-            ssize_t written;
-            int chunk = audio_MIN (to_mix, hw->samples - rpos);
-            struct st_sample *src = hw->mix_buf + rpos;
-
-            hw->clip (esd->pcm_buf, src, chunk);
-
-        again:
-            written = write (esd->fd, esd->pcm_buf, chunk << hw->info.shift);
-            if (written == -1) {
-                if (errno == EINTR || errno == EAGAIN) {
-                    goto again;
-                }
-                qesd_logerr (errno, "write failed\n");
-                return NULL;
-            }
-
-            if (written != chunk << hw->info.shift) {
-                int wsamples = written >> hw->info.shift;
-                int wbytes = wsamples << hw->info.shift;
-                if (wbytes != written) {
-                    dolog ("warning: Misaligned write %d (requested %zd), "
-                           "alignment %d\n",
-                           wbytes, written, hw->info.align + 1);
-                }
-                to_mix -= wsamples;
-                rpos = (rpos + wsamples) % hw->samples;
-                break;
-            }
-
-            rpos = (rpos + chunk) % hw->samples;
-            to_mix -= chunk;
-        }
-
-        if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
-            return NULL;
-        }
-
-        esd->rpos = rpos;
-        esd->live -= decr;
-        esd->decr += decr;
-    }
-
- exit:
-    audio_pt_unlock (&esd->pt, AUDIO_FUNC);
-    return NULL;
-}
-
-static int qesd_run_out (HWVoiceOut *hw, int live)
-{
-    int decr;
-    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
-
-    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
-        return 0;
-    }
-
-    decr = audio_MIN (live, esd->decr);
-    esd->decr -= decr;
-    esd->live = live - decr;
-    hw->rpos = esd->rpos;
-    if (esd->live > 0) {
-        audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
-    }
-    else {
-        audio_pt_unlock (&esd->pt, AUDIO_FUNC);
-    }
-    return decr;
-}
-
-static int qesd_write (SWVoiceOut *sw, void *buf, int len)
-{
-    return audio_pcm_sw_write (sw, buf, len);
-}
-
-static int qesd_init_out (HWVoiceOut *hw, struct audsettings *as)
-{
-    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
-    struct audsettings obt_as = *as;
-    int esdfmt = ESD_STREAM | ESD_PLAY;
-
-    esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
-    switch (as->fmt) {
-    case AUD_FMT_S8:
-    case AUD_FMT_U8:
-        esdfmt |= ESD_BITS8;
-        obt_as.fmt = AUD_FMT_U8;
-        break;
-
-    case AUD_FMT_S32:
-    case AUD_FMT_U32:
-        dolog ("Will use 16 instead of 32 bit samples\n");
-        /* fall through */
-    case AUD_FMT_S16:
-    case AUD_FMT_U16:
-    deffmt:
-        esdfmt |= ESD_BITS16;
-        obt_as.fmt = AUD_FMT_S16;
-        break;
-
-    default:
-        dolog ("Internal logic error: Bad audio format %d\n", as->fmt);
-        goto deffmt;
-
-    }
-    obt_as.endianness = AUDIO_HOST_ENDIANNESS;
-
-    audio_pcm_init_info (&hw->info, &obt_as);
-
-    hw->samples = conf.samples;
-    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
-    if (!esd->pcm_buf) {
-        dolog ("Could not allocate buffer (%d bytes)\n",
-               hw->samples << hw->info.shift);
-        return -1;
-    }
-
-    esd->fd = esd_play_stream (esdfmt, as->freq, conf.dac_host, NULL);
-    if (esd->fd < 0) {
-        qesd_logerr (errno, "esd_play_stream failed\n");
-        goto fail1;
-    }
-
-    if (audio_pt_init (&esd->pt, qesd_thread_out, esd, AUDIO_CAP, AUDIO_FUNC)) {
-        goto fail2;
-    }
-
-    return 0;
-
- fail2:
-    if (close (esd->fd)) {
-        qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
-                     AUDIO_FUNC, esd->fd);
-    }
-    esd->fd = -1;
-
- fail1:
-    g_free (esd->pcm_buf);
-    esd->pcm_buf = NULL;
-    return -1;
-}
-
-static void qesd_fini_out (HWVoiceOut *hw)
-{
-    void *ret;
-    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
-
-    audio_pt_lock (&esd->pt, AUDIO_FUNC);
-    esd->done = 1;
-    audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
-    audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
-
-    if (esd->fd >= 0) {
-        if (close (esd->fd)) {
-            qesd_logerr (errno, "failed to close esd socket\n");
-        }
-        esd->fd = -1;
-    }
-
-    audio_pt_fini (&esd->pt, AUDIO_FUNC);
-
-    g_free (esd->pcm_buf);
-    esd->pcm_buf = NULL;
-}
-
-static int qesd_ctl_out (HWVoiceOut *hw, int cmd, ...)
-{
-    (void) hw;
-    (void) cmd;
-    return 0;
-}
-
-/* capture */
-static void *qesd_thread_in (void *arg)
-{
-    ESDVoiceIn *esd = arg;
-    HWVoiceIn *hw = &esd->hw;
-    int threshold;
-
-    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
-
-    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
-        return NULL;
-    }
-
-    for (;;) {
-        int incr, to_grab, wpos;
-
-        for (;;) {
-            if (esd->done) {
-                goto exit;
-            }
-
-            if (esd->dead > threshold) {
-                break;
-            }
-
-            if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
-                goto exit;
-            }
-        }
-
-        incr = to_grab = esd->dead;
-        wpos = hw->wpos;
-
-        if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
-            return NULL;
-        }
-
-        while (to_grab) {
-            ssize_t nread;
-            int chunk = audio_MIN (to_grab, hw->samples - wpos);
-            void *buf = advance (esd->pcm_buf, wpos);
-
-        again:
-            nread = read (esd->fd, buf, chunk << hw->info.shift);
-            if (nread == -1) {
-                if (errno == EINTR || errno == EAGAIN) {
-                    goto again;
-                }
-                qesd_logerr (errno, "read failed\n");
-                return NULL;
-            }
-
-            if (nread != chunk << hw->info.shift) {
-                int rsamples = nread >> hw->info.shift;
-                int rbytes = rsamples << hw->info.shift;
-                if (rbytes != nread) {
-                    dolog ("warning: Misaligned write %d (requested %zd), "
-                           "alignment %d\n",
-                           rbytes, nread, hw->info.align + 1);
-                }
-                to_grab -= rsamples;
-                wpos = (wpos + rsamples) % hw->samples;
-                break;
-            }
-
-            hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift);
-            wpos = (wpos + chunk) % hw->samples;
-            to_grab -= chunk;
-        }
-
-        if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
-            return NULL;
-        }
-
-        esd->wpos = wpos;
-        esd->dead -= incr;
-        esd->incr += incr;
-    }
-
- exit:
-    audio_pt_unlock (&esd->pt, AUDIO_FUNC);
-    return NULL;
-}
-
-static int qesd_run_in (HWVoiceIn *hw)
-{
-    int live, incr, dead;
-    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
-
-    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
-        return 0;
-    }
-
-    live = audio_pcm_hw_get_live_in (hw);
-    dead = hw->samples - live;
-    incr = audio_MIN (dead, esd->incr);
-    esd->incr -= incr;
-    esd->dead = dead - incr;
-    hw->wpos = esd->wpos;
-    if (esd->dead > 0) {
-        audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
-    }
-    else {
-        audio_pt_unlock (&esd->pt, AUDIO_FUNC);
-    }
-    return incr;
-}
-
-static int qesd_read (SWVoiceIn *sw, void *buf, int len)
-{
-    return audio_pcm_sw_read (sw, buf, len);
-}
-
-static int qesd_init_in (HWVoiceIn *hw, struct audsettings *as)
-{
-    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
-    struct audsettings obt_as = *as;
-    int esdfmt = ESD_STREAM | ESD_RECORD;
-
-    esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
-    switch (as->fmt) {
-    case AUD_FMT_S8:
-    case AUD_FMT_U8:
-        esdfmt |= ESD_BITS8;
-        obt_as.fmt = AUD_FMT_U8;
-        break;
-
-    case AUD_FMT_S16:
-    case AUD_FMT_U16:
-        esdfmt |= ESD_BITS16;
-        obt_as.fmt = AUD_FMT_S16;
-        break;
-
-    case AUD_FMT_S32:
-    case AUD_FMT_U32:
-        dolog ("Will use 16 instead of 32 bit samples\n");
-        esdfmt |= ESD_BITS16;
-        obt_as.fmt = AUD_FMT_S16;
-        break;
-    }
-    obt_as.endianness = AUDIO_HOST_ENDIANNESS;
-
-    audio_pcm_init_info (&hw->info, &obt_as);
-
-    hw->samples = conf.samples;
-    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
-    if (!esd->pcm_buf) {
-        dolog ("Could not allocate buffer (%d bytes)\n",
-               hw->samples << hw->info.shift);
-        return -1;
-    }
-
-    esd->fd = esd_record_stream (esdfmt, as->freq, conf.adc_host, NULL);
-    if (esd->fd < 0) {
-        qesd_logerr (errno, "esd_record_stream failed\n");
-        goto fail1;
-    }
-
-    if (audio_pt_init (&esd->pt, qesd_thread_in, esd, AUDIO_CAP, AUDIO_FUNC)) {
-        goto fail2;
-    }
-
-    return 0;
-
- fail2:
-    if (close (esd->fd)) {
-        qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
-                     AUDIO_FUNC, esd->fd);
-    }
-    esd->fd = -1;
-
- fail1:
-    g_free (esd->pcm_buf);
-    esd->pcm_buf = NULL;
-    return -1;
-}
-
-static void qesd_fini_in (HWVoiceIn *hw)
-{
-    void *ret;
-    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
-
-    audio_pt_lock (&esd->pt, AUDIO_FUNC);
-    esd->done = 1;
-    audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
-    audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
-
-    if (esd->fd >= 0) {
-        if (close (esd->fd)) {
-            qesd_logerr (errno, "failed to close esd socket\n");
-        }
-        esd->fd = -1;
-    }
-
-    audio_pt_fini (&esd->pt, AUDIO_FUNC);
-
-    g_free (esd->pcm_buf);
-    esd->pcm_buf = NULL;
-}
-
-static int qesd_ctl_in (HWVoiceIn *hw, int cmd, ...)
-{
-    (void) hw;
-    (void) cmd;
-    return 0;
-}
-
-/* common */
-static void *qesd_audio_init (void)
-{
-    return &conf;
-}
-
-static void qesd_audio_fini (void *opaque)
-{
-    (void) opaque;
-    ldebug ("esd_fini");
-}
-
-struct audio_option qesd_options[] = {
-    {
-        .name  = "SAMPLES",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.samples,
-        .descr = "buffer size in samples"
-    },
-    {
-        .name  = "DIVISOR",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.divisor,
-        .descr = "threshold divisor"
-    },
-    {
-        .name  = "DAC_HOST",
-        .tag   = AUD_OPT_STR,
-        .valp  = &conf.dac_host,
-        .descr = "playback host"
-    },
-    {
-        .name  = "ADC_HOST",
-        .tag   = AUD_OPT_STR,
-        .valp  = &conf.adc_host,
-        .descr = "capture host"
-    },
-    { /* End of list */ }
-};
-
-static struct audio_pcm_ops qesd_pcm_ops = {
-    .init_out = qesd_init_out,
-    .fini_out = qesd_fini_out,
-    .run_out  = qesd_run_out,
-    .write    = qesd_write,
-    .ctl_out  = qesd_ctl_out,
-
-    .init_in  = qesd_init_in,
-    .fini_in  = qesd_fini_in,
-    .run_in   = qesd_run_in,
-    .read     = qesd_read,
-    .ctl_in   = qesd_ctl_in,
-};
-
-struct audio_driver esd_audio_driver = {
-    .name           = "esd",
-    .descr          = "http://en.wikipedia.org/wiki/Esound",
-    .options        = qesd_options,
-    .init           = qesd_audio_init,
-    .fini           = qesd_audio_fini,
-    .pcm_ops        = &qesd_pcm_ops,
-    .can_be_default = 0,
-    .max_voices_out = INT_MAX,
-    .max_voices_in  = INT_MAX,
-    .voice_size_out = sizeof (ESDVoiceOut),
-    .voice_size_in  = sizeof (ESDVoiceIn)
-};
diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c
deleted file mode 100644
index fabf84d..0000000
--- a/audio/fmodaudio.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * QEMU FMOD audio driver
- *
- * Copyright (c) 2004-2005 Vassili Karpov (malc)
- *
- * 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 <fmod.h>
-#include <fmod_errors.h>
-#include "qemu-common.h"
-#include "audio.h"
-
-#define AUDIO_CAP "fmod"
-#include "audio_int.h"
-
-typedef struct FMODVoiceOut {
-    HWVoiceOut hw;
-    unsigned int old_pos;
-    FSOUND_SAMPLE *fmod_sample;
-    int channel;
-} FMODVoiceOut;
-
-typedef struct FMODVoiceIn {
-    HWVoiceIn hw;
-    FSOUND_SAMPLE *fmod_sample;
-} FMODVoiceIn;
-
-static struct {
-    const char *drvname;
-    int nb_samples;
-    int freq;
-    int nb_channels;
-    int bufsize;
-    int broken_adc;
-} conf = {
-    .nb_samples  = 2048 * 2,
-    .freq        = 44100,
-    .nb_channels = 2,
-};
-
-static void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start (ap, fmt);
-    AUD_vlog (AUDIO_CAP, fmt, ap);
-    va_end (ap);
-
-    AUD_log (AUDIO_CAP, "Reason: %s\n",
-             FMOD_ErrorString (FSOUND_GetError ()));
-}
-
-static void GCC_FMT_ATTR (2, 3) fmod_logerr2 (
-    const char *typ,
-    const char *fmt,
-    ...
-    )
-{
-    va_list ap;
-
-    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
-
-    va_start (ap, fmt);
-    AUD_vlog (AUDIO_CAP, fmt, ap);
-    va_end (ap);
-
-    AUD_log (AUDIO_CAP, "Reason: %s\n",
-             FMOD_ErrorString (FSOUND_GetError ()));
-}
-
-static int fmod_write (SWVoiceOut *sw, void *buf, int len)
-{
-    return audio_pcm_sw_write (sw, buf, len);
-}
-
-static void fmod_clear_sample (FMODVoiceOut *fmd)
-{
-    HWVoiceOut *hw = &fmd->hw;
-    int status;
-    void *p1 = 0, *p2 = 0;
-    unsigned int len1 = 0, len2 = 0;
-
-    status = FSOUND_Sample_Lock (
-        fmd->fmod_sample,
-        0,
-        hw->samples << hw->info.shift,
-        &p1,
-        &p2,
-        &len1,
-        &len2
-        );
-
-    if (!status) {
-        fmod_logerr ("Failed to lock sample\n");
-        return;
-    }
-
-    if ((len1 & hw->info.align) || (len2 & hw->info.align)) {
-        dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
-               len1, len2, hw->info.align + 1);
-        goto fail;
-    }
-
-    if ((len1 + len2) - (hw->samples << hw->info.shift)) {
-        dolog ("Lock returned incomplete length %d, %d\n",
-               len1 + len2, hw->samples << hw->info.shift);
-        goto fail;
-    }
-
-    audio_pcm_info_clear_buf (&hw->info, p1, hw->samples);
-
- fail:
-    status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
-    if (!status) {
-        fmod_logerr ("Failed to unlock sample\n");
-    }
-}
-
-static void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
-{
-    int src_len1 = dst_len;
-    int src_len2 = 0;
-    int pos = hw->rpos + dst_len;
-    struct st_sample *src1 = hw->mix_buf + hw->rpos;
-    struct st_sample *src2 = NULL;
-
-    if (pos > hw->samples) {
-        src_len1 = hw->samples - hw->rpos;
-        src2 = hw->mix_buf;
-        src_len2 = dst_len - src_len1;
-        pos = src_len2;
-    }
-
-    if (src_len1) {
-        hw->clip (dst, src1, src_len1);
-    }
-
-    if (src_len2) {
-        dst = advance (dst, src_len1 << hw->info.shift);
-        hw->clip (dst, src2, src_len2);
-    }
-
-    hw->rpos = pos % hw->samples;
-}
-
-static int fmod_unlock_sample (FSOUND_SAMPLE *sample, void *p1, void *p2,
-                               unsigned int blen1, unsigned int blen2)
-{
-    int status = FSOUND_Sample_Unlock (sample, p1, p2, blen1, blen2);
-    if (!status) {
-        fmod_logerr ("Failed to unlock sample\n");
-        return -1;
-    }
-    return 0;
-}
-
-static int fmod_lock_sample (
-    FSOUND_SAMPLE *sample,
-    struct audio_pcm_info *info,
-    int pos,
-    int len,
-    void **p1,
-    void **p2,
-    unsigned int *blen1,
-    unsigned int *blen2
-    )
-{
-    int status;
-
-    status = FSOUND_Sample_Lock (
-        sample,
-        pos << info->shift,
-        len << info->shift,
-        p1,
-        p2,
-        blen1,
-        blen2
-        );
-
-    if (!status) {
-        fmod_logerr ("Failed to lock sample\n");
-        return -1;
-    }
-
-    if ((*blen1 & info->align) || (*blen2 & info->align)) {
-        dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
-               *blen1, *blen2, info->align + 1);
-
-        fmod_unlock_sample (sample, *p1, *p2, *blen1, *blen2);
-
-        *p1 = NULL - 1;
-        *p2 = NULL - 1;
-        *blen1 = ~0U;
-        *blen2 = ~0U;
-        return -1;
-    }
-
-    if (!*p1 && *blen1) {
-        dolog ("warning: !p1 && blen1=%d\n", *blen1);
-        *blen1 = 0;
-    }
-
-    if (!p2 && *blen2) {
-        dolog ("warning: !p2 && blen2=%d\n", *blen2);
-        *blen2 = 0;
-    }
-
-    return 0;
-}
-
-static int fmod_run_out (HWVoiceOut *hw, int live)
-{
-    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
-    int decr;
-    void *p1 = 0, *p2 = 0;
-    unsigned int blen1 = 0, blen2 = 0;
-    unsigned int len1 = 0, len2 = 0;
-
-    if (!hw->pending_disable) {
-        return 0;
-    }
-
-    decr = live;
-
-    if (fmd->channel >= 0) {
-        int len = decr;
-        int old_pos = fmd->old_pos;
-        int ppos = FSOUND_GetCurrentPosition (fmd->channel);
-
-        if (ppos == old_pos || !ppos) {
-            return 0;
-        }
-
-        if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
-            len = ppos - old_pos;
-        }
-        else {
-            if ((old_pos > ppos) && ((old_pos + len) > (ppos + hw->samples))) {
-                len = hw->samples - old_pos + ppos;
-            }
-        }
-        decr = len;
-
-        if (audio_bug (AUDIO_FUNC, decr < 0)) {
-            dolog ("decr=%d live=%d ppos=%d old_pos=%d len=%d\n",
-                   decr, live, ppos, old_pos, len);
-            return 0;
-        }
-    }
-
-
-    if (!decr) {
-        return 0;
-    }
-
-    if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
-                          fmd->old_pos, decr,
-                          &p1, &p2,
-                          &blen1, &blen2)) {
-        return 0;
-    }
-
-    len1 = blen1 >> hw->info.shift;
-    len2 = blen2 >> hw->info.shift;
-    ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
-    decr = len1 + len2;
-
-    if (p1 && len1) {
-        fmod_write_sample (hw, p1, len1);
-    }
-
-    if (p2 && len2) {
-        fmod_write_sample (hw, p2, len2);
-    }
-
-    fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
-
-    fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
-    return decr;
-}
-
-static int aud_to_fmodfmt (audfmt_e fmt, int stereo)
-{
-    int mode = FSOUND_LOOP_NORMAL;
-
-    switch (fmt) {
-    case AUD_FMT_S8:
-        mode |= FSOUND_SIGNED | FSOUND_8BITS;
-        break;
-
-    case AUD_FMT_U8:
-        mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
-        break;
-
-    case AUD_FMT_S16:
-        mode |= FSOUND_SIGNED | FSOUND_16BITS;
-        break;
-
-    case AUD_FMT_U16:
-        mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
-        break;
-
-    default:
-        dolog ("Internal logic error: Bad audio format %d\n", fmt);
-#ifdef DEBUG_FMOD
-        abort ();
-#endif
-        mode |= FSOUND_8BITS;
-    }
-    mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
-    return mode;
-}
-
-static void fmod_fini_out (HWVoiceOut *hw)
-{
-    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
-
-    if (fmd->fmod_sample) {
-        FSOUND_Sample_Free (fmd->fmod_sample);
-        fmd->fmod_sample = 0;
-
-        if (fmd->channel >= 0) {
-            FSOUND_StopSound (fmd->channel);
-        }
-    }
-}
-
-static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as)
-{
-    int mode, channel;
-    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
-    struct audsettings obt_as = *as;
-
-    mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
-    fmd->fmod_sample = FSOUND_Sample_Alloc (
-        FSOUND_FREE,            /* index */
-        conf.nb_samples,        /* length */
-        mode,                   /* mode */
-        as->freq,               /* freq */
-        255,                    /* volume */
-        128,                    /* pan */
-        255                     /* priority */
-        );
-
-    if (!fmd->fmod_sample) {
-        fmod_logerr2 ("DAC", "Failed to allocate FMOD sample\n");
-        return -1;
-    }
-
-    channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1);
-    if (channel < 0) {
-        fmod_logerr2 ("DAC", "Failed to start playing sound\n");
-        FSOUND_Sample_Free (fmd->fmod_sample);
-        return -1;
-    }
-    fmd->channel = channel;
-
-    /* FMOD always operates on little endian frames? */
-    obt_as.endianness = 0;
-    audio_pcm_init_info (&hw->info, &obt_as);
-    hw->samples = conf.nb_samples;
-    return 0;
-}
-
-static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...)
-{
-    int status;
-    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
-
-    switch (cmd) {
-    case VOICE_ENABLE:
-        fmod_clear_sample (fmd);
-        status = FSOUND_SetPaused (fmd->channel, 0);
-        if (!status) {
-            fmod_logerr ("Failed to resume channel %d\n", fmd->channel);
-        }
-        break;
-
-    case VOICE_DISABLE:
-        status = FSOUND_SetPaused (fmd->channel, 1);
-        if (!status) {
-            fmod_logerr ("Failed to pause channel %d\n", fmd->channel);
-        }
-        break;
-    }
-    return 0;
-}
-
-static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as)
-{
-    int mode;
-    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
-    struct audsettings obt_as = *as;
-
-    if (conf.broken_adc) {
-        return -1;
-    }
-
-    mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
-    fmd->fmod_sample = FSOUND_Sample_Alloc (
-        FSOUND_FREE,            /* index */
-        conf.nb_samples,        /* length */
-        mode,                   /* mode */
-        as->freq,               /* freq */
-        255,                    /* volume */
-        128,                    /* pan */
-        255                     /* priority */
-        );
-
-    if (!fmd->fmod_sample) {
-        fmod_logerr2 ("ADC", "Failed to allocate FMOD sample\n");
-        return -1;
-    }
-
-    /* FMOD always operates on little endian frames? */
-    obt_as.endianness = 0;
-    audio_pcm_init_info (&hw->info, &obt_as);
-    hw->samples = conf.nb_samples;
-    return 0;
-}
-
-static void fmod_fini_in (HWVoiceIn *hw)
-{
-    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
-
-    if (fmd->fmod_sample) {
-        FSOUND_Record_Stop ();
-        FSOUND_Sample_Free (fmd->fmod_sample);
-        fmd->fmod_sample = 0;
-    }
-}
-
-static int fmod_run_in (HWVoiceIn *hw)
-{
-    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
-    int hwshift = hw->info.shift;
-    int live, dead, new_pos, len;
-    unsigned int blen1 = 0, blen2 = 0;
-    unsigned int len1, len2;
-    unsigned int decr;
-    void *p1, *p2;
-
-    live = audio_pcm_hw_get_live_in (hw);
-    dead = hw->samples - live;
-    if (!dead) {
-        return 0;
-    }
-
-    new_pos = FSOUND_Record_GetPosition ();
-    if (new_pos < 0) {
-        fmod_logerr ("Could not get recording position\n");
-        return 0;
-    }
-
-    len = audio_ring_dist (new_pos,  hw->wpos, hw->samples);
-    if (!len) {
-        return 0;
-    }
-    len = audio_MIN (len, dead);
-
-    if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
-                          hw->wpos, len,
-                          &p1, &p2,
-                          &blen1, &blen2)) {
-        return 0;
-    }
-
-    len1 = blen1 >> hwshift;
-    len2 = blen2 >> hwshift;
-    decr = len1 + len2;
-
-    if (p1 && blen1) {
-        hw->conv (hw->conv_buf + hw->wpos, p1, len1);
-    }
-    if (p2 && len2) {
-        hw->conv (hw->conv_buf, p2, len2);
-    }
-
-    fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
-    hw->wpos = (hw->wpos + decr) % hw->samples;
-    return decr;
-}
-
-static struct {
-    const char *name;
-    int type;
-} drvtab[] = {
-    { .name = "none",   .type = FSOUND_OUTPUT_NOSOUND },
-#ifdef _WIN32
-    { .name = "winmm",  .type = FSOUND_OUTPUT_WINMM   },
-    { .name = "dsound", .type = FSOUND_OUTPUT_DSOUND  },
-    { .name = "a3d",    .type = FSOUND_OUTPUT_A3D     },
-    { .name = "asio",   .type = FSOUND_OUTPUT_ASIO    },
-#endif
-#ifdef __linux__
-    { .name = "oss",    .type = FSOUND_OUTPUT_OSS     },
-    { .name = "alsa",   .type = FSOUND_OUTPUT_ALSA    },
-    { .name = "esd",    .type = FSOUND_OUTPUT_ESD     },
-#endif
-#ifdef __APPLE__
-    { .name = "mac",    .type = FSOUND_OUTPUT_MAC     },
-#endif
-#if 0
-    { .name = "xbox",   .type = FSOUND_OUTPUT_XBOX    },
-    { .name = "ps2",    .type = FSOUND_OUTPUT_PS2     },
-    { .name = "gcube",  .type = FSOUND_OUTPUT_GC      },
-#endif
-    { .name = "none-realtime", .type = FSOUND_OUTPUT_NOSOUND_NONREALTIME }
-};
-
-static void *fmod_audio_init (void)
-{
-    size_t i;
-    double ver;
-    int status;
-    int output_type = -1;
-    const char *drv = conf.drvname;
-
-    ver = FSOUND_GetVersion ();
-    if (ver < FMOD_VERSION) {
-        dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION);
-        return NULL;
-    }
-
-#ifdef __linux__
-    if (ver < 3.75) {
-        dolog ("FMOD before 3.75 has bug preventing ADC from working\n"
-               "ADC will be disabled.\n");
-        conf.broken_adc = 1;
-    }
-#endif
-
-    if (drv) {
-        int found = 0;
-        for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
-            if (!strcmp (drv, drvtab[i].name)) {
-                output_type = drvtab[i].type;
-                found = 1;
-                break;
-            }
-        }
-        if (!found) {
-            dolog ("Unknown FMOD driver `%s'\n", drv);
-            dolog ("Valid drivers:\n");
-            for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
-                dolog ("  %s\n", drvtab[i].name);
-            }
-        }
-    }
-
-    if (output_type != -1) {
-        status = FSOUND_SetOutput (output_type);
-        if (!status) {
-            fmod_logerr ("FSOUND_SetOutput(%d) failed\n", output_type);
-            return NULL;
-        }
-    }
-
-    if (conf.bufsize) {
-        status = FSOUND_SetBufferSize (conf.bufsize);
-        if (!status) {
-            fmod_logerr ("FSOUND_SetBufferSize (%d) failed\n", conf.bufsize);
-        }
-    }
-
-    status = FSOUND_Init (conf.freq, conf.nb_channels, 0);
-    if (!status) {
-        fmod_logerr ("FSOUND_Init failed\n");
-        return NULL;
-    }
-
-    return &conf;
-}
-
-static int fmod_read (SWVoiceIn *sw, void *buf, int size)
-{
-    return audio_pcm_sw_read (sw, buf, size);
-}
-
-static int fmod_ctl_in (HWVoiceIn *hw, int cmd, ...)
-{
-    int status;
-    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
-
-    switch (cmd) {
-    case VOICE_ENABLE:
-        status = FSOUND_Record_StartSample (fmd->fmod_sample, 1);
-        if (!status) {
-            fmod_logerr ("Failed to start recording\n");
-        }
-        break;
-
-    case VOICE_DISABLE:
-        status = FSOUND_Record_Stop ();
-        if (!status) {
-            fmod_logerr ("Failed to stop recording\n");
-        }
-        break;
-    }
-    return 0;
-}
-
-static void fmod_audio_fini (void *opaque)
-{
-    (void) opaque;
-    FSOUND_Close ();
-}
-
-static struct audio_option fmod_options[] = {
-    {
-        .name  = "DRV",
-        .tag   = AUD_OPT_STR,
-        .valp  = &conf.drvname,
-        .descr = "FMOD driver"
-    },
-    {
-        .name  = "FREQ",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.freq,
-        .descr = "Default frequency"
-    },
-    {
-        .name  = "SAMPLES",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.nb_samples,
-        .descr = "Buffer size in samples"
-    },
-    {
-        .name  = "CHANNELS",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.nb_channels,
-        .descr = "Number of default channels (1 - mono, 2 - stereo)"
-    },
-    {
-        .name  = "BUFSIZE",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.bufsize,
-        .descr = "(undocumented)"
-    },
-    { /* End of list */ }
-};
-
-static struct audio_pcm_ops fmod_pcm_ops = {
-    .init_out = fmod_init_out,
-    .fini_out = fmod_fini_out,
-    .run_out  = fmod_run_out,
-    .write    = fmod_write,
-    .ctl_out  = fmod_ctl_out,
-
-    .init_in  = fmod_init_in,
-    .fini_in  = fmod_fini_in,
-    .run_in   = fmod_run_in,
-    .read     = fmod_read,
-    .ctl_in   = fmod_ctl_in
-};
-
-struct audio_driver fmod_audio_driver = {
-    .name           = "fmod",
-    .descr          = "FMOD 3.xx http://www.fmod.org",
-    .options        = fmod_options,
-    .init           = fmod_audio_init,
-    .fini           = fmod_audio_fini,
-    .pcm_ops        = &fmod_pcm_ops,
-    .can_be_default = 1,
-    .max_voices_out = INT_MAX,
-    .max_voices_in  = INT_MAX,
-    .voice_size_out = sizeof (FMODVoiceOut),
-    .voice_size_in  = sizeof (FMODVoiceIn)
-};
diff --git a/audio/mixeng.c b/audio/mixeng.c
index 0e4976f..66c0328 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -22,7 +22,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/bswap.h"
 #include "audio.h"
 
 #define AUDIO_CAP "mixeng"
@@ -269,7 +271,7 @@
  * August 21, 1998
  * Copyright 1998 Fabrice Bellard.
  *
- * [Rewrote completly the code of Lance Norskog And Sundry
+ * [Rewrote completely the code of Lance Norskog And Sundry
  * Contributors with a more efficient algorithm.]
  *
  * This source code is freely redistributable and may be used for
diff --git a/audio/mixeng.h b/audio/mixeng.h
index 9de443b..b53a5ef 100644
--- a/audio/mixeng.h
+++ b/audio/mixeng.h
@@ -21,6 +21,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
 #ifndef QEMU_MIXENG_H
 #define QEMU_MIXENG_H
 
@@ -48,4 +49,4 @@
 void mixeng_clear (struct st_sample *buf, int len);
 void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol);
 
-#endif  /* mixeng.h */
+#endif /* QEMU_MIXENG_H */
diff --git a/audio/noaudio.c b/audio/noaudio.c
index cb38662..9ca9eaf 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -21,7 +21,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/host-utils.h"
 #include "audio.h"
 #include "qemu/timer.h"
 
@@ -48,8 +50,8 @@
 
     now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     ticks = now - no->old_ticks;
-    bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
-    bytes = audio_MIN (bytes, INT_MAX);
+    bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
+    bytes = audio_MIN(bytes, INT_MAX);
     samples = bytes >> hw->info.shift;
 
     no->old_ticks = now;
@@ -60,10 +62,10 @@
 
 static int no_write (SWVoiceOut *sw, void *buf, int len)
 {
-    return audio_pcm_sw_write (sw, buf, len);
+    return audio_pcm_sw_write(sw, buf, len);
 }
 
-static int no_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
 {
     audio_pcm_init_info (&hw->info, as);
     hw->samples = 1024;
@@ -82,7 +84,7 @@
     return 0;
 }
 
-static int no_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
     audio_pcm_init_info (&hw->info, as);
     hw->samples = 1024;
@@ -105,7 +107,7 @@
         int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
         int64_t ticks = now - no->old_ticks;
         int64_t bytes =
-            muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
+            muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
 
         no->old_ticks = now;
         bytes = audio_MIN (bytes, INT_MAX);
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 4db2ca6..0edd7ea 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -21,15 +21,14 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/types.h>
+#include "qemu/osdep.h"
 #include <sys/ioctl.h>
 #include <sys/soundcard.h>
 #include "qemu-common.h"
 #include "qemu/main-loop.h"
 #include "qemu/host-utils.h"
 #include "audio.h"
+#include "trace.h"
 
 #define AUDIO_CAP "oss"
 #include "audio_int.h"
@@ -38,6 +37,16 @@
 #define USE_DSP_POLICY
 #endif
 
+typedef struct OSSConf {
+    int try_mmap;
+    int nfrags;
+    int fragsize;
+    const char *devpath_out;
+    const char *devpath_in;
+    int exclusive;
+    int policy;
+} OSSConf;
+
 typedef struct OSSVoiceOut {
     HWVoiceOut hw;
     void *pcm_buf;
@@ -47,6 +56,7 @@
     int fragsize;
     int mmapped;
     int pending;
+    OSSConf *conf;
 } OSSVoiceOut;
 
 typedef struct OSSVoiceIn {
@@ -55,28 +65,9 @@
     int fd;
     int nfrags;
     int fragsize;
+    OSSConf *conf;
 } OSSVoiceIn;
 
-static struct {
-    int try_mmap;
-    int nfrags;
-    int fragsize;
-    const char *devpath_out;
-    const char *devpath_in;
-    int debug;
-    int exclusive;
-    int policy;
-} conf = {
-    .try_mmap = 0,
-    .nfrags = 4,
-    .fragsize = 4096,
-    .devpath_out = "/dev/dsp",
-    .devpath_in = "/dev/dsp",
-    .debug = 0,
-    .exclusive = 0,
-    .policy = 5
-};
-
 struct oss_params {
     int freq;
     audfmt_e fmt;
@@ -138,18 +129,18 @@
     audio_run ("oss_poll_in");
 }
 
-static int oss_poll_out (HWVoiceOut *hw)
+static void oss_poll_out (HWVoiceOut *hw)
 {
     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
 
-    return qemu_set_fd_handler (oss->fd, NULL, oss_helper_poll_out, NULL);
+    qemu_set_fd_handler (oss->fd, NULL, oss_helper_poll_out, NULL);
 }
 
-static int oss_poll_in (HWVoiceIn *hw)
+static void oss_poll_in (HWVoiceIn *hw)
 {
     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
 
-    return qemu_set_fd_handler (oss->fd, oss_helper_poll_in, NULL, NULL);
+    qemu_set_fd_handler (oss->fd, oss_helper_poll_in, NULL, NULL);
 }
 
 static int oss_write (SWVoiceOut *sw, void *buf, int len)
@@ -272,18 +263,18 @@
 #endif
 
 static int oss_open (int in, struct oss_params *req,
-                     struct oss_params *obt, int *pfd)
+                     struct oss_params *obt, int *pfd, OSSConf* conf)
 {
     int fd;
-    int oflags = conf.exclusive ? O_EXCL : 0;
+    int oflags = conf->exclusive ? O_EXCL : 0;
     audio_buf_info abinfo;
     int fmt, freq, nchannels;
     int setfragment = 1;
-    const char *dspname = in ? conf.devpath_in : conf.devpath_out;
+    const char *dspname = in ? conf->devpath_in : conf->devpath_out;
     const char *typ = in ? "ADC" : "DAC";
 
     /* Kludge needed to have working mmap on Linux */
-    oflags |= conf.try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
+    oflags |= conf->try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
 
     fd = open (dspname, oflags | O_NONBLOCK);
     if (-1 == fd) {
@@ -317,20 +308,18 @@
     }
 
 #ifdef USE_DSP_POLICY
-    if (conf.policy >= 0) {
+    if (conf->policy >= 0) {
         int version;
 
         if (!oss_get_version (fd, &version, typ)) {
-            if (conf.debug) {
-                dolog ("OSS version = %#x\n", version);
-            }
+            trace_oss_version(version);
 
             if (version >= 0x040000) {
-                int policy = conf.policy;
+                int policy = conf->policy;
                 if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
                     oss_logerr2 (errno, typ,
                                  "Failed to set timing policy to %d\n",
-                                 conf.policy);
+                                 conf->policy);
                     goto err;
                 }
                 setfragment = 0;
@@ -458,19 +447,12 @@
         }
 
         if (abinfo.bytes > bufsize) {
-            if (conf.debug) {
-                dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
-                       "please report your OS/audio hw to av1474@comtv.ru\n",
-                       abinfo.bytes, bufsize);
-            }
+            trace_oss_invalid_available_size(abinfo.bytes, bufsize);
             abinfo.bytes = bufsize;
         }
 
         if (abinfo.bytes < 0) {
-            if (conf.debug) {
-                dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
-                       abinfo.bytes, bufsize);
-            }
+            trace_oss_invalid_available_size(abinfo.bytes, bufsize);
             return 0;
         }
 
@@ -510,7 +492,8 @@
     }
 }
 
-static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
+                        void *drv_opaque)
 {
     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
     struct oss_params req, obt;
@@ -519,16 +502,17 @@
     int fd;
     audfmt_e effective_fmt;
     struct audsettings obt_as;
+    OSSConf *conf = drv_opaque;
 
     oss->fd = -1;
 
     req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
     req.freq = as->freq;
     req.nchannels = as->nchannels;
-    req.fragsize = conf.fragsize;
-    req.nfrags = conf.nfrags;
+    req.fragsize = conf->fragsize;
+    req.nfrags = conf->nfrags;
 
-    if (oss_open (0, &req, &obt, &fd)) {
+    if (oss_open (0, &req, &obt, &fd, conf)) {
         return -1;
     }
 
@@ -555,7 +539,7 @@
     hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
 
     oss->mmapped = 0;
-    if (conf.try_mmap) {
+    if (conf->try_mmap) {
         oss->pcm_buf = mmap (
             NULL,
             hw->samples << hw->info.shift,
@@ -615,6 +599,7 @@
     }
 
     oss->fd = fd;
+    oss->conf = conf;
     return 0;
 }
 
@@ -634,7 +619,8 @@
             va_end (ap);
 
             ldebug ("enabling voice\n");
-            if (poll_mode && oss_poll_out (hw)) {
+            if (poll_mode) {
+                oss_poll_out (hw);
                 poll_mode = 0;
             }
             hw->poll_mode = poll_mode;
@@ -676,7 +662,7 @@
     return 0;
 }
 
-static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
     struct oss_params req, obt;
@@ -685,15 +671,16 @@
     int fd;
     audfmt_e effective_fmt;
     struct audsettings obt_as;
+    OSSConf *conf = drv_opaque;
 
     oss->fd = -1;
 
     req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
     req.freq = as->freq;
     req.nchannels = as->nchannels;
-    req.fragsize = conf.fragsize;
-    req.nfrags = conf.nfrags;
-    if (oss_open (1, &req, &obt, &fd)) {
+    req.fragsize = conf->fragsize;
+    req.nfrags = conf->nfrags;
+    if (oss_open (1, &req, &obt, &fd, conf)) {
         return -1;
     }
 
@@ -727,6 +714,7 @@
     }
 
     oss->fd = fd;
+    oss->conf = conf;
     return 0;
 }
 
@@ -828,7 +816,8 @@
             poll_mode = va_arg (ap, int);
             va_end (ap);
 
-            if (poll_mode && oss_poll_in (hw)) {
+            if (poll_mode) {
+                oss_poll_in (hw);
                 poll_mode = 0;
             }
             hw->poll_mode = poll_mode;
@@ -845,71 +834,79 @@
     return 0;
 }
 
+static OSSConf glob_conf = {
+    .try_mmap = 0,
+    .nfrags = 4,
+    .fragsize = 4096,
+    .devpath_out = "/dev/dsp",
+    .devpath_in = "/dev/dsp",
+    .exclusive = 0,
+    .policy = 5
+};
+
 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) {
+    OSSConf *conf = g_malloc(sizeof(OSSConf));
+    *conf = glob_conf;
+
+    if (access(conf->devpath_in, R_OK | W_OK) < 0 ||
+        access(conf->devpath_out, R_OK | W_OK) < 0) {
+        g_free(conf);
         return NULL;
     }
-    return &conf;
+    return conf;
 }
 
 static void oss_audio_fini (void *opaque)
 {
-    (void) opaque;
+    g_free(opaque);
 }
 
 static struct audio_option oss_options[] = {
     {
         .name  = "FRAGSIZE",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.fragsize,
+        .valp  = &glob_conf.fragsize,
         .descr = "Fragment size in bytes"
     },
     {
         .name  = "NFRAGS",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.nfrags,
+        .valp  = &glob_conf.nfrags,
         .descr = "Number of fragments"
     },
     {
         .name  = "MMAP",
         .tag   = AUD_OPT_BOOL,
-        .valp  = &conf.try_mmap,
+        .valp  = &glob_conf.try_mmap,
         .descr = "Try using memory mapped access"
     },
     {
         .name  = "DAC_DEV",
         .tag   = AUD_OPT_STR,
-        .valp  = &conf.devpath_out,
+        .valp  = &glob_conf.devpath_out,
         .descr = "Path to DAC device"
     },
     {
         .name  = "ADC_DEV",
         .tag   = AUD_OPT_STR,
-        .valp  = &conf.devpath_in,
+        .valp  = &glob_conf.devpath_in,
         .descr = "Path to ADC device"
     },
     {
         .name  = "EXCLUSIVE",
         .tag   = AUD_OPT_BOOL,
-        .valp  = &conf.exclusive,
-        .descr = "Open device in exclusive mode (vmix wont work)"
+        .valp  = &glob_conf.exclusive,
+        .descr = "Open device in exclusive mode (vmix won't work)"
     },
 #ifdef USE_DSP_POLICY
     {
         .name  = "POLICY",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.policy,
+        .valp  = &glob_conf.policy,
         .descr = "Set the timing policy of the device, -1 to use fragment mode",
     },
 #endif
-    {
-        .name  = "DEBUG",
-        .tag   = AUD_OPT_BOOL,
-        .valp  = &conf.debug,
-        .descr = "Turn on some debugging messages"
-    },
     { /* End of list */ }
 };
 
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 887a5db..b69dc2d 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -1,4 +1,5 @@
 /* public domain */
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "audio.h"
 
@@ -9,6 +10,19 @@
 #include "audio_pt_int.h"
 
 typedef struct {
+    int samples;
+    char *server;
+    char *sink;
+    char *source;
+} PAConf;
+
+typedef struct {
+    PAConf conf;
+    pa_threaded_mainloop *mainloop;
+    pa_context *context;
+} paaudio;
+
+typedef struct {
     HWVoiceOut hw;
     int done;
     int live;
@@ -17,6 +31,7 @@
     pa_stream *stream;
     void *pcm_buf;
     struct audio_pt pt;
+    paaudio *g;
 } PAVoiceOut;
 
 typedef struct {
@@ -30,20 +45,10 @@
     struct audio_pt pt;
     const void *read_data;
     size_t read_index, read_length;
+    paaudio *g;
 } PAVoiceIn;
 
-typedef struct {
-    int samples;
-    char *server;
-    char *sink;
-    char *source;
-    pa_threaded_mainloop *mainloop;
-    pa_context *context;
-} paaudio;
-
-static paaudio glob_paaudio = {
-    .samples = 4096,
-};
+static void qpa_audio_fini(void *opaque);
 
 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
 {
@@ -106,7 +111,7 @@
 
 static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
 {
-    paaudio *g = &glob_paaudio;
+    paaudio *g = p->g;
 
     pa_threaded_mainloop_lock (g->mainloop);
 
@@ -160,7 +165,7 @@
 
 static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror)
 {
-    paaudio *g = &glob_paaudio;
+    paaudio *g = p->g;
 
     pa_threaded_mainloop_lock (g->mainloop);
 
@@ -222,7 +227,7 @@
             }
         }
 
-        decr = to_mix = audio_MIN (pa->live, glob_paaudio.samples >> 2);
+        decr = to_mix = audio_MIN (pa->live, pa->g->conf.samples >> 2);
         rpos = pa->rpos;
 
         if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
@@ -314,7 +319,7 @@
             }
         }
 
-        incr = to_grab = audio_MIN (pa->dead, glob_paaudio.samples >> 2);
+        incr = to_grab = audio_MIN (pa->dead, pa->g->conf.samples >> 2);
         wpos = pa->wpos;
 
         if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
@@ -430,7 +435,7 @@
 
 static void context_state_cb (pa_context *c, void *userdata)
 {
-    paaudio *g = &glob_paaudio;
+    paaudio *g = userdata;
 
     switch (pa_context_get_state(c)) {
     case PA_CONTEXT_READY:
@@ -449,7 +454,7 @@
 
 static void stream_state_cb (pa_stream *s, void * userdata)
 {
-    paaudio *g = &glob_paaudio;
+    paaudio *g = userdata;
 
     switch (pa_stream_get_state (s)) {
 
@@ -467,23 +472,21 @@
 
 static void stream_request_cb (pa_stream *s, size_t length, void *userdata)
 {
-    paaudio *g = &glob_paaudio;
+    paaudio *g = userdata;
 
     pa_threaded_mainloop_signal (g->mainloop, 0);
 }
 
 static pa_stream *qpa_simple_new (
-        const char *server,
+        paaudio *g,
         const char *name,
         pa_stream_direction_t dir,
         const char *dev,
-        const char *stream_name,
         const pa_sample_spec *ss,
         const pa_channel_map *map,
         const pa_buffer_attr *attr,
         int *rerror)
 {
-    paaudio *g = &glob_paaudio;
     int r;
     pa_stream *stream;
 
@@ -535,13 +538,15 @@
     return NULL;
 }
 
-static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
+                        void *drv_opaque)
 {
     int error;
-    static pa_sample_spec ss;
-    static pa_buffer_attr ba;
+    pa_sample_spec ss;
+    pa_buffer_attr ba;
     struct audsettings obt_as = *as;
     PAVoiceOut *pa = (PAVoiceOut *) hw;
+    paaudio *g = pa->g = drv_opaque;
 
     ss.format = audfmt_to_pa (as->fmt, as->endianness);
     ss.channels = as->nchannels;
@@ -559,11 +564,10 @@
     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
 
     pa->stream = qpa_simple_new (
-        glob_paaudio.server,
+        g,
         "qemu",
         PA_STREAM_PLAYBACK,
-        glob_paaudio.sink,
-        "pcm.playback",
+        g->conf.sink,
         &ss,
         NULL,                   /* channel map */
         &ba,                    /* buffering attributes */
@@ -575,7 +579,7 @@
     }
 
     audio_pcm_init_info (&hw->info, &obt_as);
-    hw->samples = glob_paaudio.samples;
+    hw->samples = g->conf.samples;
     pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
     pa->rpos = hw->rpos;
     if (!pa->pcm_buf) {
@@ -602,13 +606,14 @@
     return -1;
 }
 
-static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
+static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
     int error;
-    static pa_sample_spec ss;
-    static pa_buffer_attr ba;
+    pa_sample_spec ss;
+    pa_buffer_attr ba;
     struct audsettings obt_as = *as;
     PAVoiceIn *pa = (PAVoiceIn *) hw;
+    paaudio *g = pa->g = drv_opaque;
 
     ss.format = audfmt_to_pa (as->fmt, as->endianness);
     ss.channels = as->nchannels;
@@ -624,14 +629,13 @@
     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
 
     pa->stream = qpa_simple_new (
-        glob_paaudio.server,
+        g,
         "qemu",
         PA_STREAM_RECORD,
-        glob_paaudio.source,
-        "pcm.capture",
+        g->conf.source,
         &ss,
         NULL,                   /* channel map */
-        &ba,                   /* buffering attributes */
+        &ba,                    /* buffering attributes */
         &error
         );
     if (!pa->stream) {
@@ -640,7 +644,7 @@
     }
 
     audio_pcm_init_info (&hw->info, &obt_as);
-    hw->samples = glob_paaudio.samples;
+    hw->samples = g->conf.samples;
     pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
     pa->wpos = hw->wpos;
     if (!pa->pcm_buf) {
@@ -713,7 +717,7 @@
     PAVoiceOut *pa = (PAVoiceOut *) hw;
     pa_operation *op;
     pa_cvolume v;
-    paaudio *g = &glob_paaudio;
+    paaudio *g = pa->g;
 
 #ifdef PA_CHECK_VERSION    /* macro is present in 0.9.16+ */
     pa_cvolume_init (&v);  /* function is present in 0.9.13+ */
@@ -765,7 +769,7 @@
     PAVoiceIn *pa = (PAVoiceIn *) hw;
     pa_operation *op;
     pa_cvolume v;
-    paaudio *g = &glob_paaudio;
+    paaudio *g = pa->g;
 
 #ifdef PA_CHECK_VERSION
     pa_cvolume_init (&v);
@@ -837,23 +841,31 @@
 }
 
 /* common */
+static PAConf glob_conf = {
+    .samples = 4096,
+};
+
 static void *qpa_audio_init (void)
 {
-    paaudio *g = &glob_paaudio;
+    paaudio *g = g_malloc(sizeof(paaudio));
+    g->conf = glob_conf;
+    g->mainloop = NULL;
+    g->context = NULL;
 
     g->mainloop = pa_threaded_mainloop_new ();
     if (!g->mainloop) {
         goto fail;
     }
 
-    g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop), glob_paaudio.server);
+    g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop),
+                                 g->conf.server);
     if (!g->context) {
         goto fail;
     }
 
     pa_context_set_state_callback (g->context, context_state_cb, g);
 
-    if (pa_context_connect (g->context, glob_paaudio.server, 0, NULL) < 0) {
+    if (pa_context_connect (g->context, g->conf.server, 0, NULL) < 0) {
         qpa_logerr (pa_context_errno (g->context),
                     "pa_context_connect() failed\n");
         goto fail;
@@ -886,12 +898,13 @@
 
     pa_threaded_mainloop_unlock (g->mainloop);
 
-    return &glob_paaudio;
+    return g;
 
 unlock_and_fail:
     pa_threaded_mainloop_unlock (g->mainloop);
 fail:
     AUD_log (AUDIO_CAP, "Failed to initialize PA context");
+    qpa_audio_fini(g);
     return NULL;
 }
 
@@ -906,39 +919,38 @@
     if (g->context) {
         pa_context_disconnect (g->context);
         pa_context_unref (g->context);
-        g->context = NULL;
     }
 
     if (g->mainloop) {
         pa_threaded_mainloop_free (g->mainloop);
     }
 
-    g->mainloop = NULL;
+    g_free(g);
 }
 
 struct audio_option qpa_options[] = {
     {
         .name  = "SAMPLES",
         .tag   = AUD_OPT_INT,
-        .valp  = &glob_paaudio.samples,
+        .valp  = &glob_conf.samples,
         .descr = "buffer size in samples"
     },
     {
         .name  = "SERVER",
         .tag   = AUD_OPT_STR,
-        .valp  = &glob_paaudio.server,
+        .valp  = &glob_conf.server,
         .descr = "server address"
     },
     {
         .name  = "SINK",
         .tag   = AUD_OPT_STR,
-        .valp  = &glob_paaudio.sink,
+        .valp  = &glob_conf.sink,
         .descr = "sink device name"
     },
     {
         .name  = "SOURCE",
         .tag   = AUD_OPT_STR,
-        .valp  = &glob_paaudio.source,
+        .valp  = &glob_conf.source,
         .descr = "source device name"
     },
     { /* End of list */ }
diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index d24daa5..db69fe1 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -21,6 +21,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
 #include <SDL.h>
 #include <SDL_thread.h>
 #include "qemu-common.h"
@@ -55,6 +56,7 @@
     SDL_mutex *mutex;
     SDL_sem *sem;
     int initialized;
+    bool driver_created;
 } glob_sdl;
 typedef struct SDLAudioState SDLAudioState;
 
@@ -332,7 +334,8 @@
     sdl_close (&glob_sdl);
 }
 
-static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
+                        void *drv_opaque)
 {
     SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
     SDLAudioState *s = &glob_sdl;
@@ -392,6 +395,10 @@
 static void *sdl_audio_init (void)
 {
     SDLAudioState *s = &glob_sdl;
+    if (s->driver_created) {
+        sdl_logerr("Can't create multiple sdl backends\n");
+        return NULL;
+    }
 
     if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
         sdl_logerr ("SDL failed to initialize audio subsystem\n");
@@ -413,6 +420,7 @@
         return NULL;
     }
 
+    s->driver_created = true;
     return s;
 }
 
@@ -423,6 +431,7 @@
     SDL_DestroySemaphore (s->sem);
     SDL_DestroyMutex (s->mutex);
     SDL_QuitSubSystem (SDL_INIT_AUDIO);
+    s->driver_created = false;
 }
 
 static struct audio_option sdl_options[] = {
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index 7b79bed..5580e76 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -17,7 +17,10 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "qemu/osdep.h"
 #include "hw/hw.h"
+#include "qemu/host-utils.h"
+#include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "ui/qemu-spice.h"
 
@@ -102,11 +105,11 @@
 
     now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     ticks = now - rate->start_ticks;
-    bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
+    bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
     samples = (bytes - rate->bytes_sent) >> info->shift;
     if (samples < 0 || samples > 65536) {
         error_report("Resetting rate control (%" PRId64 " samples)", samples);
-        rate_start (rate);
+        rate_start(rate);
         samples = 0;
     }
     rate->bytes_sent += samples << info->shift;
@@ -115,7 +118,8 @@
 
 /* playback */
 
-static int line_out_init (HWVoiceOut *hw, struct audsettings *as)
+static int line_out_init(HWVoiceOut *hw, struct audsettings *as,
+                         void *drv_opaque)
 {
     SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);
     struct audsettings settings;
@@ -243,7 +247,7 @@
 
 /* record */
 
-static int line_in_init (HWVoiceIn *hw, struct audsettings *as)
+static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
     SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
     struct audsettings settings;
diff --git a/audio/trace-events b/audio/trace-events
new file mode 100644
index 0000000..5173590
--- /dev/null
+++ b/audio/trace-events
@@ -0,0 +1,17 @@
+# See docs/tracing.txt for syntax documentation.
+
+# audio/alsaaudio.c
+alsa_revents(int revents) "revents = %d"
+alsa_pollout(int i, int fd) "i = %d fd = %d"
+alsa_set_handler(int events, int index, int fd, int err) "events=%#x index=%d fd=%d err=%d"
+alsa_wrote_zero(int len) "Failed to write %d frames (wrote zero)"
+alsa_read_zero(long len) "Failed to read %ld frames (read zero)"
+alsa_xrun_out(void) "Recovering from playback xrun"
+alsa_xrun_in(void) "Recovering from capture xrun"
+alsa_resume_out(void) "Resuming suspended output stream"
+alsa_resume_in(void) "Resuming suspended input stream"
+alsa_no_frames(int state) "No frames available and ALSA state is %d"
+
+# audio/ossaudio.c
+oss_version(int version) "OSS version = %#x"
+oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d"
diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index 6846a1a..341eec3 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -21,7 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw/hw.h"
+#include "qemu/osdep.h"
+#include "qemu/host-utils.h"
 #include "qemu/timer.h"
 #include "audio.h"
 
@@ -36,15 +37,10 @@
     int total_samples;
 } WAVVoiceOut;
 
-static struct {
+typedef struct {
     struct audsettings settings;
     const char *wav_path;
-} conf = {
-    .settings.freq      = 44100,
-    .settings.nchannels = 2,
-    .settings.fmt       = AUD_FMT_S16,
-    .wav_path           = "qemu.wav"
-};
+} WAVConf;
 
 static int wav_run_out (HWVoiceOut *hw, int live)
 {
@@ -55,7 +51,7 @@
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     int64_t ticks = now - wav->old_ticks;
     int64_t bytes =
-        muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
+        muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
 
     if (bytes > INT_MAX) {
         samples = INT_MAX >> hw->info.shift;
@@ -105,7 +101,8 @@
     }
 }
 
-static int wav_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int wav_init_out(HWVoiceOut *hw, struct audsettings *as,
+                        void *drv_opaque)
 {
     WAVVoiceOut *wav = (WAVVoiceOut *) hw;
     int bits16 = 0, stereo = 0;
@@ -115,9 +112,8 @@
         0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
         0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
     };
-    struct audsettings wav_as = conf.settings;
-
-    (void) as;
+    WAVConf *conf = drv_opaque;
+    struct audsettings wav_as = conf->settings;
 
     stereo = wav_as.nchannels == 2;
     switch (wav_as.fmt) {
@@ -155,10 +151,10 @@
     le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
     le_store (hdr + 32, 1 << (bits16 + stereo), 2);
 
-    wav->f = fopen (conf.wav_path, "wb");
+    wav->f = fopen (conf->wav_path, "wb");
     if (!wav->f) {
         dolog ("Failed to open wave file `%s'\nReason: %s\n",
-               conf.wav_path, strerror (errno));
+               conf->wav_path, strerror (errno));
         g_free (wav->pcm_buf);
         wav->pcm_buf = NULL;
         return -1;
@@ -226,40 +222,49 @@
     return 0;
 }
 
+static WAVConf glob_conf = {
+    .settings.freq      = 44100,
+    .settings.nchannels = 2,
+    .settings.fmt       = AUD_FMT_S16,
+    .wav_path           = "qemu.wav"
+};
+
 static void *wav_audio_init (void)
 {
-    return &conf;
+    WAVConf *conf = g_malloc(sizeof(WAVConf));
+    *conf = glob_conf;
+    return conf;
 }
 
 static void wav_audio_fini (void *opaque)
 {
-    (void) opaque;
     ldebug ("wav_fini");
+    g_free(opaque);
 }
 
 static struct audio_option wav_options[] = {
     {
         .name  = "FREQUENCY",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.settings.freq,
+        .valp  = &glob_conf.settings.freq,
         .descr = "Frequency"
     },
     {
         .name  = "FORMAT",
         .tag   = AUD_OPT_FMT,
-        .valp  = &conf.settings.fmt,
+        .valp  = &glob_conf.settings.fmt,
         .descr = "Format"
     },
     {
         .name  = "DAC_FIXED_CHANNELS",
         .tag   = AUD_OPT_INT,
-        .valp  = &conf.settings.nchannels,
+        .valp  = &glob_conf.settings.nchannels,
         .descr = "Number of channels (1 - mono, 2 - stereo)"
     },
     {
         .name  = "PATH",
         .tag   = AUD_OPT_STR,
-        .valp  = &conf.wav_path,
+        .valp  = &glob_conf.wav_path,
         .descr = "Path to wave file"
     },
     { /* End of list */ }
diff --git a/audio/wavcapture.c b/audio/wavcapture.c
index 6f6d792..8bfb9e7 100644
--- a/audio/wavcapture.c
+++ b/audio/wavcapture.c
@@ -1,5 +1,7 @@
+#include "qemu/osdep.h"
 #include "hw/hw.h"
 #include "monitor/monitor.h"
+#include "qemu/error-report.h"
 #include "audio.h"
 
 typedef struct {
diff --git a/audio/winaudio.c b/audio/winaudio.c
index 6aec129..63f923f 100644
--- a/audio/winaudio.c
+++ b/audio/winaudio.c
@@ -23,6 +23,7 @@
  * THE SOFTWARE.
  */
 
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "sysemu/sysemu.h"
 #include "audio.h"
@@ -161,7 +162,7 @@
 
 
 static int
-winaudio_out_init (HWVoiceOut *hw, struct audsettings *as)
+winaudio_out_init (HWVoiceOut *hw, struct audsettings *as, void* drv_opaque)
 {
     WinAudioOut*   s = (WinAudioOut*) hw;
     MMRESULT       result;
@@ -296,14 +297,6 @@
             played       += wav_samples;
             s->write_pos += wav_bytes;
             if (s->write_pos == s->write_size) {
-#if DEBUG
-                int64_t  now  = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - start_time;
-                int64_t  diff = now - last_time;
-
-                D("run_out: (%7.3f:%7d):waveOutWrite buffer:%d\n",
-                   now/1e9, (now-last_time)/1e9, s->write_index);
-                last_time = now;
-#endif
                 waveOutWrite( s->waveout, wav_buffer, sizeof(*wav_buffer) );
                 s->write_pos    = 0;
                 s->write_index += 1;
@@ -407,7 +400,7 @@
 
 
 static int
-winaudio_in_init (HWVoiceIn *hw, struct audsettings *as)
+winaudio_in_init (HWVoiceIn *hw, struct audsettings *as, void* drv_opaque)
 {
     WinAudioIn*   s = (WinAudioIn*) hw;
     MMRESULT       result;
diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c
deleted file mode 100644
index 8dbd145..0000000
--- a/audio/winwaveaudio.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/* public domain */
-
-#include "qemu-common.h"
-#include "sysemu/sysemu.h"
-#include "audio.h"
-
-#define AUDIO_CAP "winwave"
-#include "audio_int.h"
-
-#include <windows.h>
-#include <mmsystem.h>
-
-#include "audio_win_int.h"
-
-static struct {
-    int dac_headers;
-    int dac_samples;
-    int adc_headers;
-    int adc_samples;
-} conf = {
-    .dac_headers = 4,
-    .dac_samples = 1024,
-    .adc_headers = 4,
-    .adc_samples = 1024
-};
-
-typedef struct {
-    HWVoiceOut hw;
-    HWAVEOUT hwo;
-    WAVEHDR *hdrs;
-    HANDLE event;
-    void *pcm_buf;
-    int avail;
-    int pending;
-    int curhdr;
-    int paused;
-    CRITICAL_SECTION crit_sect;
-} WaveVoiceOut;
-
-typedef struct {
-    HWVoiceIn hw;
-    HWAVEIN hwi;
-    WAVEHDR *hdrs;
-    HANDLE event;
-    void *pcm_buf;
-    int curhdr;
-    int paused;
-    int rpos;
-    int avail;
-    CRITICAL_SECTION crit_sect;
-} WaveVoiceIn;
-
-static void winwave_log_mmresult (MMRESULT mr)
-{
-    const char *str = "BUG";
-
-    switch (mr) {
-    case MMSYSERR_NOERROR:
-        str = "Success";
-        break;
-
-    case MMSYSERR_INVALHANDLE:
-        str = "Specified device handle is invalid";
-        break;
-
-    case MMSYSERR_BADDEVICEID:
-        str = "Specified device id is out of range";
-        break;
-
-    case MMSYSERR_NODRIVER:
-        str = "No device driver is present";
-        break;
-
-    case MMSYSERR_NOMEM:
-        str = "Unable to allocate or lock memory";
-        break;
-
-    case WAVERR_SYNC:
-        str = "Device is synchronous but waveOutOpen was called "
-            "without using the WINWAVE_ALLOWSYNC flag";
-        break;
-
-    case WAVERR_UNPREPARED:
-        str = "The data block pointed to by the pwh parameter "
-            "hasn't been prepared";
-        break;
-
-    case WAVERR_STILLPLAYING:
-        str = "There are still buffers in the queue";
-        break;
-
-    default:
-        dolog ("Reason: Unknown (MMRESULT %#x)\n", mr);
-        return;
-    }
-
-    dolog ("Reason: %s\n", str);
-}
-
-static void GCC_FMT_ATTR (2, 3) winwave_logerr (
-    MMRESULT mr,
-    const char *fmt,
-    ...
-    )
-{
-    va_list ap;
-
-    va_start (ap, fmt);
-    AUD_vlog (AUDIO_CAP, fmt, ap);
-    va_end (ap);
-
-    AUD_log (NULL, " failed\n");
-    winwave_log_mmresult (mr);
-}
-
-static void winwave_anal_close_out (WaveVoiceOut *wave)
-{
-    MMRESULT mr;
-
-    mr = waveOutClose (wave->hwo);
-    if (mr != MMSYSERR_NOERROR) {
-        winwave_logerr (mr, "waveOutClose");
-    }
-    wave->hwo = NULL;
-}
-
-static void CALLBACK winwave_callback_out (
-    HWAVEOUT hwo,
-    UINT msg,
-    DWORD_PTR dwInstance,
-    DWORD_PTR dwParam1,
-    DWORD_PTR dwParam2
-    )
-{
-    WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance;
-
-    switch (msg) {
-    case WOM_DONE:
-        {
-            WAVEHDR *h = (WAVEHDR *) dwParam1;
-            if (!h->dwUser) {
-                h->dwUser = 1;
-                EnterCriticalSection (&wave->crit_sect);
-                {
-                    wave->avail += conf.dac_samples;
-                }
-                LeaveCriticalSection (&wave->crit_sect);
-                if (wave->hw.poll_mode) {
-                    if (!SetEvent (wave->event)) {
-                        dolog ("DAC SetEvent failed %lx\n", GetLastError ());
-                    }
-                }
-            }
-        }
-        break;
-
-    case WOM_CLOSE:
-    case WOM_OPEN:
-        break;
-
-    default:
-        dolog ("unknown wave out callback msg %x\n", msg);
-    }
-}
-
-static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as)
-{
-    int i;
-    int err;
-    MMRESULT mr;
-    WAVEFORMATEX wfx;
-    WaveVoiceOut *wave;
-
-    wave = (WaveVoiceOut *) hw;
-
-    InitializeCriticalSection (&wave->crit_sect);
-
-    err = waveformat_from_audio_settings (&wfx, as);
-    if (err) {
-        goto err0;
-    }
-
-    mr = waveOutOpen (&wave->hwo, WAVE_MAPPER, &wfx,
-                      (DWORD_PTR) winwave_callback_out,
-                      (DWORD_PTR) wave, CALLBACK_FUNCTION);
-    if (mr != MMSYSERR_NOERROR) {
-        winwave_logerr (mr, "waveOutOpen");
-        goto err1;
-    }
-
-    wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
-                               sizeof (*wave->hdrs));
-    if (!wave->hdrs) {
-        goto err2;
-    }
-
-    audio_pcm_init_info (&hw->info, as);
-    hw->samples = conf.dac_samples * conf.dac_headers;
-    wave->avail = hw->samples;
-
-    wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.dac_samples,
-                                  conf.dac_headers << hw->info.shift);
-    if (!wave->pcm_buf) {
-        goto err3;
-    }
-
-    for (i = 0; i < conf.dac_headers; ++i) {
-        WAVEHDR *h = &wave->hdrs[i];
-
-        h->dwUser = 0;
-        h->dwBufferLength = conf.dac_samples << hw->info.shift;
-        h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
-        h->dwFlags = 0;
-
-        mr = waveOutPrepareHeader (wave->hwo, h, sizeof (*h));
-        if (mr != MMSYSERR_NOERROR) {
-            winwave_logerr (mr, "waveOutPrepareHeader(%d)", i);
-            goto err4;
-        }
-    }
-
-    return 0;
-
- err4:
-    g_free (wave->pcm_buf);
- err3:
-    g_free (wave->hdrs);
- err2:
-    winwave_anal_close_out (wave);
- err1:
- err0:
-    return -1;
-}
-
-static int winwave_write (SWVoiceOut *sw, void *buf, int len)
-{
-    return audio_pcm_sw_write (sw, buf, len);
-}
-
-static int winwave_run_out (HWVoiceOut *hw, int live)
-{
-    WaveVoiceOut *wave = (WaveVoiceOut *) hw;
-    int decr;
-    int doreset;
-
-    EnterCriticalSection (&wave->crit_sect);
-    {
-        decr = audio_MIN (live, wave->avail);
-        decr = audio_pcm_hw_clip_out (hw, wave->pcm_buf, decr, wave->pending);
-        wave->pending += decr;
-        wave->avail -= decr;
-    }
-    LeaveCriticalSection (&wave->crit_sect);
-
-    doreset = hw->poll_mode && (wave->pending >= conf.dac_samples);
-    if (doreset && !ResetEvent (wave->event)) {
-        dolog ("DAC ResetEvent failed %lx\n", GetLastError ());
-    }
-
-    while (wave->pending >= conf.dac_samples) {
-        MMRESULT mr;
-        WAVEHDR *h = &wave->hdrs[wave->curhdr];
-
-        h->dwUser = 0;
-        mr = waveOutWrite (wave->hwo, h, sizeof (*h));
-        if (mr != MMSYSERR_NOERROR) {
-            winwave_logerr (mr, "waveOutWrite(%d)", wave->curhdr);
-            break;
-        }
-
-        wave->pending -= conf.dac_samples;
-        wave->curhdr = (wave->curhdr + 1) % conf.dac_headers;
-    }
-
-    return decr;
-}
-
-static void winwave_poll (void *opaque)
-{
-    (void) opaque;
-    audio_run ("winwave_poll");
-}
-
-static void winwave_fini_out (HWVoiceOut *hw)
-{
-    int i;
-    MMRESULT mr;
-    WaveVoiceOut *wave = (WaveVoiceOut *) hw;
-
-    mr = waveOutReset (wave->hwo);
-    if (mr != MMSYSERR_NOERROR) {
-        winwave_logerr (mr, "waveOutReset");
-    }
-
-    for (i = 0; i < conf.dac_headers; ++i) {
-        mr = waveOutUnprepareHeader (wave->hwo, &wave->hdrs[i],
-                                     sizeof (wave->hdrs[i]));
-        if (mr != MMSYSERR_NOERROR) {
-            winwave_logerr (mr, "waveOutUnprepareHeader(%d)", i);
-        }
-    }
-
-    winwave_anal_close_out (wave);
-
-    if (wave->event) {
-        qemu_del_wait_object (wave->event, winwave_poll, wave);
-        if (!CloseHandle (wave->event)) {
-            dolog ("DAC CloseHandle failed %lx\n", GetLastError ());
-        }
-        wave->event = NULL;
-    }
-
-    g_free (wave->pcm_buf);
-    wave->pcm_buf = NULL;
-
-    g_free (wave->hdrs);
-    wave->hdrs = NULL;
-}
-
-static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
-{
-    MMRESULT mr;
-    WaveVoiceOut *wave = (WaveVoiceOut *) hw;
-
-    switch (cmd) {
-    case VOICE_ENABLE:
-        {
-            va_list ap;
-            int poll_mode;
-
-            va_start (ap, cmd);
-            poll_mode = va_arg (ap, int);
-            va_end (ap);
-
-            if (poll_mode && !wave->event) {
-                wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
-                if (!wave->event) {
-                    dolog ("DAC CreateEvent: %lx, poll mode will be disabled\n",
-                           GetLastError ());
-                }
-            }
-
-            if (wave->event) {
-                int ret;
-
-                ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
-                hw->poll_mode = (ret == 0);
-            }
-            else {
-                hw->poll_mode = 0;
-            }
-            wave->paused = 0;
-        }
-        return 0;
-
-    case VOICE_DISABLE:
-        if (!wave->paused) {
-            mr = waveOutReset (wave->hwo);
-            if (mr != MMSYSERR_NOERROR) {
-                winwave_logerr (mr, "waveOutReset");
-            }
-            else {
-                wave->paused = 1;
-            }
-        }
-        if (wave->event) {
-            qemu_del_wait_object (wave->event, winwave_poll, wave);
-        }
-        return 0;
-    }
-    return -1;
-}
-
-static void winwave_anal_close_in (WaveVoiceIn *wave)
-{
-    MMRESULT mr;
-
-    mr = waveInClose (wave->hwi);
-    if (mr != MMSYSERR_NOERROR) {
-        winwave_logerr (mr, "waveInClose");
-    }
-    wave->hwi = NULL;
-}
-
-static void CALLBACK winwave_callback_in (
-    HWAVEIN *hwi,
-    UINT msg,
-    DWORD_PTR dwInstance,
-    DWORD_PTR dwParam1,
-    DWORD_PTR dwParam2
-    )
-{
-    WaveVoiceIn *wave = (WaveVoiceIn *) dwInstance;
-
-    switch (msg) {
-    case WIM_DATA:
-        {
-            WAVEHDR *h = (WAVEHDR *) dwParam1;
-            if (!h->dwUser) {
-                h->dwUser = 1;
-                EnterCriticalSection (&wave->crit_sect);
-                {
-                    wave->avail += conf.adc_samples;
-                }
-                LeaveCriticalSection (&wave->crit_sect);
-                if (wave->hw.poll_mode) {
-                    if (!SetEvent (wave->event)) {
-                        dolog ("ADC SetEvent failed %lx\n", GetLastError ());
-                    }
-                }
-            }
-        }
-        break;
-
-    case WIM_CLOSE:
-    case WIM_OPEN:
-        break;
-
-    default:
-        dolog ("unknown wave in callback msg %x\n", msg);
-    }
-}
-
-static void winwave_add_buffers (WaveVoiceIn *wave, int samples)
-{
-    int doreset;
-
-    doreset = wave->hw.poll_mode && (samples >= conf.adc_samples);
-    if (doreset && !ResetEvent (wave->event)) {
-        dolog ("ADC ResetEvent failed %lx\n", GetLastError ());
-    }
-
-    while (samples >= conf.adc_samples) {
-        MMRESULT mr;
-        WAVEHDR *h = &wave->hdrs[wave->curhdr];
-
-        h->dwUser = 0;
-        mr = waveInAddBuffer (wave->hwi, h, sizeof (*h));
-        if (mr != MMSYSERR_NOERROR) {
-            winwave_logerr (mr, "waveInAddBuffer(%d)", wave->curhdr);
-        }
-        wave->curhdr = (wave->curhdr + 1) % conf.adc_headers;
-        samples -= conf.adc_samples;
-    }
-}
-
-static int winwave_init_in (HWVoiceIn *hw, struct audsettings *as)
-{
-    int i;
-    int err;
-    MMRESULT mr;
-    WAVEFORMATEX wfx;
-    WaveVoiceIn *wave;
-
-    wave = (WaveVoiceIn *) hw;
-
-    InitializeCriticalSection (&wave->crit_sect);
-
-    err = waveformat_from_audio_settings (&wfx, as);
-    if (err) {
-        goto err0;
-    }
-
-    mr = waveInOpen (&wave->hwi, WAVE_MAPPER, &wfx,
-                     (DWORD_PTR) winwave_callback_in,
-                     (DWORD_PTR) wave, CALLBACK_FUNCTION);
-    if (mr != MMSYSERR_NOERROR) {
-        winwave_logerr (mr, "waveInOpen");
-        goto err1;
-    }
-
-    wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
-                               sizeof (*wave->hdrs));
-    if (!wave->hdrs) {
-        goto err2;
-    }
-
-    audio_pcm_init_info (&hw->info, as);
-    hw->samples = conf.adc_samples * conf.adc_headers;
-    wave->avail = 0;
-
-    wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.adc_samples,
-                                  conf.adc_headers << hw->info.shift);
-    if (!wave->pcm_buf) {
-        goto err3;
-    }
-
-    for (i = 0; i < conf.adc_headers; ++i) {
-        WAVEHDR *h = &wave->hdrs[i];
-
-        h->dwUser = 0;
-        h->dwBufferLength = conf.adc_samples << hw->info.shift;
-        h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
-        h->dwFlags = 0;
-
-        mr = waveInPrepareHeader (wave->hwi, h, sizeof (*h));
-        if (mr != MMSYSERR_NOERROR) {
-            winwave_logerr (mr, "waveInPrepareHeader(%d)", i);
-            goto err4;
-        }
-    }
-
-    wave->paused = 1;
-    winwave_add_buffers (wave, hw->samples);
-    return 0;
-
- err4:
-    g_free (wave->pcm_buf);
- err3:
-    g_free (wave->hdrs);
- err2:
-    winwave_anal_close_in (wave);
- err1:
- err0:
-    return -1;
-}
-
-static void winwave_fini_in (HWVoiceIn *hw)
-{
-    int i;
-    MMRESULT mr;
-    WaveVoiceIn *wave = (WaveVoiceIn *) hw;
-
-    mr = waveInReset (wave->hwi);
-    if (mr != MMSYSERR_NOERROR) {
-        winwave_logerr (mr, "waveInReset");
-    }
-
-    for (i = 0; i < conf.adc_headers; ++i) {
-        mr = waveInUnprepareHeader (wave->hwi, &wave->hdrs[i],
-                                     sizeof (wave->hdrs[i]));
-        if (mr != MMSYSERR_NOERROR) {
-            winwave_logerr (mr, "waveInUnprepareHeader(%d)", i);
-        }
-    }
-
-    winwave_anal_close_in (wave);
-
-    if (wave->event) {
-        qemu_del_wait_object (wave->event, winwave_poll, wave);
-        if (!CloseHandle (wave->event)) {
-            dolog ("ADC CloseHandle failed %lx\n", GetLastError ());
-        }
-        wave->event = NULL;
-    }
-
-    g_free (wave->pcm_buf);
-    wave->pcm_buf = NULL;
-
-    g_free (wave->hdrs);
-    wave->hdrs = NULL;
-}
-
-static int winwave_run_in (HWVoiceIn *hw)
-{
-    WaveVoiceIn *wave = (WaveVoiceIn *) hw;
-    int live = audio_pcm_hw_get_live_in (hw);
-    int dead = hw->samples - live;
-    int decr, ret;
-
-    if (!dead) {
-        return 0;
-    }
-
-    EnterCriticalSection (&wave->crit_sect);
-    {
-        decr = audio_MIN (dead, wave->avail);
-        wave->avail -= decr;
-    }
-    LeaveCriticalSection (&wave->crit_sect);
-
-    ret = decr;
-    while (decr) {
-        int left = hw->samples - hw->wpos;
-        int conv = audio_MIN (left, decr);
-        hw->conv (hw->conv_buf + hw->wpos,
-                  advance (wave->pcm_buf, wave->rpos << hw->info.shift),
-                  conv);
-
-        wave->rpos = (wave->rpos + conv) % hw->samples;
-        hw->wpos = (hw->wpos + conv) % hw->samples;
-        decr -= conv;
-    }
-
-    winwave_add_buffers (wave, ret);
-    return ret;
-}
-
-static int winwave_read (SWVoiceIn *sw, void *buf, int size)
-{
-    return audio_pcm_sw_read (sw, buf, size);
-}
-
-static int winwave_ctl_in (HWVoiceIn *hw, int cmd, ...)
-{
-    MMRESULT mr;
-    WaveVoiceIn *wave = (WaveVoiceIn *) hw;
-
-    switch (cmd) {
-    case VOICE_ENABLE:
-        {
-            va_list ap;
-            int poll_mode;
-
-            va_start (ap, cmd);
-            poll_mode = va_arg (ap, int);
-            va_end (ap);
-
-            if (poll_mode && !wave->event) {
-                wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
-                if (!wave->event) {
-                    dolog ("ADC CreateEvent: %lx, poll mode will be disabled\n",
-                           GetLastError ());
-                }
-            }
-
-            if (wave->event) {
-                int ret;
-
-                ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
-                hw->poll_mode = (ret == 0);
-            }
-            else {
-                hw->poll_mode = 0;
-            }
-            if (wave->paused) {
-                mr = waveInStart (wave->hwi);
-                if (mr != MMSYSERR_NOERROR) {
-                    winwave_logerr (mr, "waveInStart");
-                }
-                wave->paused = 0;
-            }
-        }
-        return 0;
-
-    case VOICE_DISABLE:
-        if (!wave->paused) {
-            mr = waveInStop (wave->hwi);
-            if (mr != MMSYSERR_NOERROR) {
-                winwave_logerr (mr, "waveInStop");
-            }
-            else {
-                wave->paused = 1;
-            }
-        }
-        if (wave->event) {
-            qemu_del_wait_object (wave->event, winwave_poll, wave);
-        }
-        return 0;
-    }
-    return 0;
-}
-
-static void *winwave_audio_init (void)
-{
-    return &conf;
-}
-
-static void winwave_audio_fini (void *opaque)
-{
-    (void) opaque;
-}
-
-static struct audio_option winwave_options[] = {
-    {
-        .name        = "DAC_HEADERS",
-        .tag         = AUD_OPT_INT,
-        .valp        = &conf.dac_headers,
-        .descr       = "DAC number of headers",
-    },
-    {
-        .name        = "DAC_SAMPLES",
-        .tag         = AUD_OPT_INT,
-        .valp        = &conf.dac_samples,
-        .descr       = "DAC number of samples per header",
-    },
-    {
-        .name        = "ADC_HEADERS",
-        .tag         = AUD_OPT_INT,
-        .valp        = &conf.adc_headers,
-        .descr       = "ADC number of headers",
-    },
-    {
-        .name        = "ADC_SAMPLES",
-        .tag         = AUD_OPT_INT,
-        .valp        = &conf.adc_samples,
-        .descr       = "ADC number of samples per header",
-    },
-    { /* End of list */ }
-};
-
-static struct audio_pcm_ops winwave_pcm_ops = {
-    .init_out = winwave_init_out,
-    .fini_out = winwave_fini_out,
-    .run_out  = winwave_run_out,
-    .write    = winwave_write,
-    .ctl_out  = winwave_ctl_out,
-    .init_in  = winwave_init_in,
-    .fini_in  = winwave_fini_in,
-    .run_in   = winwave_run_in,
-    .read     = winwave_read,
-    .ctl_in   = winwave_ctl_in
-};
-
-struct audio_driver winwave_audio_driver = {
-    .name           = "winwave",
-    .descr          = "Windows Waveform Audio http://msdn.microsoft.com",
-    .options        = winwave_options,
-    .init           = winwave_audio_init,
-    .fini           = winwave_audio_fini,
-    .pcm_ops        = &winwave_pcm_ops,
-    .can_be_default = 1,
-    .max_voices_out = INT_MAX,
-    .max_voices_in  = INT_MAX,
-    .voice_size_out = sizeof (WaveVoiceOut),
-    .voice_size_in  = sizeof (WaveVoiceIn)
-};
diff --git a/backends/baum.c b/backends/baum.c
index a69aaff..c537141 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -21,6 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
 #include "qemu-common.h"
 #include "sysemu/char.h"
 #include "qemu/timer.h"
@@ -303,7 +305,7 @@
                 return 0;
             cur++;
         }
-        DPRINTF("Dropped %d bytes!\n", cur - buf);
+        DPRINTF("Dropped %td bytes!\n", cur - buf);
     }
 
 #define EAT(c) do {\
@@ -335,7 +337,7 @@
 
         /* Allow 100ms to complete the DisplayData packet */
         timer_mod(baum->cellCount_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
-                       get_ticks_per_sec() / 10);
+                       NANOSECONDS_PER_SECOND / 10);
         for (i = 0; i < baum->x * baum->y ; i++) {
             EAT(c);
             cells[i] = c;
@@ -561,8 +563,12 @@
     g_free(baum);
 }
 
-CharDriverState *chr_baum_init(void)
+static CharDriverState *chr_baum_init(const char *id,
+                                      ChardevBackend *backend,
+                                      ChardevReturn *ret,
+                                      Error **errp)
 {
+    ChardevCommon *common = backend->u.braille.data;
     BaumDriverState *baum;
     CharDriverState *chr;
     brlapi_handle_t *handle;
@@ -573,8 +579,12 @@
 #endif
     int tty;
 
+    chr = qemu_chr_alloc(common, errp);
+    if (!chr) {
+        return NULL;
+    }
     baum = g_malloc0(sizeof(BaumDriverState));
-    baum->chr = chr = qemu_chr_alloc();
+    baum->chr = chr;
 
     chr->opaque = baum;
     chr->chr_write = baum_write;
@@ -586,14 +596,16 @@
 
     baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
     if (baum->brlapi_fd == -1) {
-        brlapi_perror("baum_init: brlapi_openConnection");
+        error_setg(errp, "brlapi__openConnection: %s",
+                   brlapi_strerror(brlapi_error_location()));
         goto fail_handle;
     }
 
     baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum);
 
     if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
-        brlapi_perror("baum_init: brlapi_getDisplaySize");
+        error_setg(errp, "brlapi__getDisplaySize: %s",
+                   brlapi_strerror(brlapi_error_location()));
         goto fail;
     }
 
@@ -609,7 +621,8 @@
         tty = BRLAPI_TTY_DEFAULT;
 
     if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
-        brlapi_perror("baum_init: brlapi_enterTtyMode");
+        error_setg(errp, "brlapi__enterTtyMode: %s",
+                   brlapi_strerror(brlapi_error_location()));
         goto fail;
     }
 
@@ -629,7 +642,8 @@
 
 static void register_types(void)
 {
-    register_char_driver("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL);
+    register_char_driver("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL,
+                         chr_baum_init);
 }
 
 type_init(register_types);
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index 5179994..5c4b808 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -9,6 +9,8 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
 #include "qemu-common.h"
 #include "sysemu/hostmem.h"
 #include "sysemu/sysemu.h"
@@ -43,18 +45,21 @@
         return;
     }
     if (!fb->mem_path) {
-        error_setg(errp, "mem_path property not set");
+        error_setg(errp, "mem-path property not set");
         return;
     }
 #ifndef CONFIG_LINUX
     error_setg(errp, "-mem-path not supported on this host");
 #else
     if (!memory_region_size(&backend->mr)) {
+        gchar *path;
         backend->force_prealloc = mem_prealloc;
+        path = object_get_canonical_path(OBJECT(backend));
         memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
-                                 object_get_canonical_path(OBJECT(backend)),
+                                 path,
                                  backend->size, fb->share,
                                  fb->mem_path, errp);
+        g_free(path);
     }
 #endif
 }
@@ -83,9 +88,7 @@
         error_setg(errp, "cannot change property value");
         return;
     }
-    if (fb->mem_path) {
-        g_free(fb->mem_path);
-    }
+    g_free(fb->mem_path);
     fb->mem_path = g_strdup(str);
 }
 
@@ -118,11 +121,19 @@
                             set_mem_path, NULL);
 }
 
+static void file_backend_instance_finalize(Object *o)
+{
+    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
+
+    g_free(fb->mem_path);
+}
+
 static const TypeInfo file_backend_info = {
     .name = TYPE_MEMORY_BACKEND_FILE,
     .parent = TYPE_MEMORY_BACKEND,
     .class_init = file_backend_class_init,
     .instance_init = file_backend_instance_init,
+    .instance_finalize = file_backend_instance_finalize,
     .instance_size = sizeof(HostMemoryBackendFile),
 };
 
diff --git a/backends/hostmem-ram.c b/backends/hostmem-ram.c
index a67a134..04a7ac3 100644
--- a/backends/hostmem-ram.c
+++ b/backends/hostmem-ram.c
@@ -9,7 +9,9 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
+#include "qemu/osdep.h"
 #include "sysemu/hostmem.h"
+#include "qapi/error.h"
 #include "qom/object_interfaces.h"
 
 #define TYPE_MEMORY_BACKEND_RAM "memory-backend-ram"
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 99e8f99..b7a208d 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -9,11 +9,13 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
+#include "qemu/osdep.h"
 #include "sysemu/hostmem.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "qapi-types.h"
 #include "qapi-visit.h"
-#include "qapi/qmp/qerror.h"
 #include "qemu/config-file.h"
 #include "qom/object_interfaces.h"
 
@@ -26,18 +28,18 @@
 #endif
 
 static void
-host_memory_backend_get_size(Object *obj, Visitor *v, void *opaque,
-                             const char *name, Error **errp)
+host_memory_backend_get_size(Object *obj, Visitor *v, const char *name,
+                             void *opaque, Error **errp)
 {
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
     uint64_t value = backend->size;
 
-    visit_type_size(v, &value, name, errp);
+    visit_type_size(v, name, &value, errp);
 }
 
 static void
-host_memory_backend_set_size(Object *obj, Visitor *v, void *opaque,
-                             const char *name, Error **errp)
+host_memory_backend_set_size(Object *obj, Visitor *v, const char *name,
+                             void *opaque, Error **errp)
 {
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
     Error *local_err = NULL;
@@ -48,7 +50,7 @@
         goto out;
     }
 
-    visit_type_size(v, &value, name, &local_err);
+    visit_type_size(v, name, &value, &local_err);
     if (local_err) {
         goto out;
     }
@@ -62,9 +64,17 @@
     error_propagate(errp, local_err);
 }
 
+static uint16List **host_memory_append_node(uint16List **node,
+                                            unsigned long value)
+{
+     *node = g_malloc0(sizeof(**node));
+     (*node)->value = value;
+     return &(*node)->next;
+}
+
 static void
-host_memory_backend_get_host_nodes(Object *obj, Visitor *v, void *opaque,
-                                   const char *name, Error **errp)
+host_memory_backend_get_host_nodes(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
 {
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
     uint16List *host_nodes = NULL;
@@ -72,13 +82,12 @@
     unsigned long value;
 
     value = find_first_bit(backend->host_nodes, MAX_NODES);
-    if (value == MAX_NODES) {
-        return;
-    }
 
-    *node = g_malloc0(sizeof(**node));
-    (*node)->value = value;
-    node = &(*node)->next;
+    node = host_memory_append_node(node, value);
+
+    if (value == MAX_NODES) {
+        goto out;
+    }
 
     do {
         value = find_next_bit(backend->host_nodes, MAX_NODES, value + 1);
@@ -86,23 +95,22 @@
             break;
         }
 
-        *node = g_malloc0(sizeof(**node));
-        (*node)->value = value;
-        node = &(*node)->next;
+        node = host_memory_append_node(node, value);
     } while (true);
 
-    visit_type_uint16List(v, &host_nodes, name, errp);
+out:
+    visit_type_uint16List(v, name, &host_nodes, errp);
 }
 
 static void
-host_memory_backend_set_host_nodes(Object *obj, Visitor *v, void *opaque,
-                                   const char *name, Error **errp)
+host_memory_backend_set_host_nodes(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
 {
 #ifdef CONFIG_NUMA
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
     uint16List *l = NULL;
 
-    visit_type_uint16List(v, &l, name, errp);
+    visit_type_uint16List(v, name, &l, errp);
 
     while (l) {
         bitmap_set(backend->host_nodes, l->value, 1);
@@ -113,24 +121,17 @@
 #endif
 }
 
-static void
-host_memory_backend_get_policy(Object *obj, Visitor *v, void *opaque,
-                               const char *name, Error **errp)
+static int
+host_memory_backend_get_policy(Object *obj, Error **errp G_GNUC_UNUSED)
 {
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
-    int policy = backend->policy;
-
-    visit_type_enum(v, &policy, HostMemPolicy_lookup, NULL, name, errp);
+    return backend->policy;
 }
 
 static void
-host_memory_backend_set_policy(Object *obj, Visitor *v, void *opaque,
-                               const char *name, Error **errp)
+host_memory_backend_set_policy(Object *obj, int policy, Error **errp)
 {
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
-    int policy;
-
-    visit_type_enum(v, &policy, HostMemPolicy_lookup, NULL, name, errp);
     backend->policy = policy;
 
 #ifndef CONFIG_NUMA
@@ -202,6 +203,7 @@
 static void host_memory_backend_set_prealloc(Object *obj, bool value,
                                              Error **errp)
 {
+    Error *local_err = NULL;
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 
     if (backend->force_prealloc) {
@@ -222,7 +224,11 @@
         void *ptr = memory_region_get_ram_ptr(&backend->mr);
         uint64_t sz = memory_region_size(&backend->mr);
 
-        os_mem_prealloc(fd, ptr, sz);
+        os_mem_prealloc(fd, ptr, sz, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
         backend->prealloc = true;
     }
 }
@@ -230,11 +236,10 @@
 static void host_memory_backend_init(Object *obj)
 {
     HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+    MachineState *machine = MACHINE(qdev_get_machine());
 
-    backend->merge = qemu_opt_get_bool(qemu_get_machine_opts(),
-                                       "mem-merge", true);
-    backend->dump = qemu_opt_get_bool(qemu_get_machine_opts(),
-                                      "dump-guest-core", true);
+    backend->merge = machine_mem_merge(machine);
+    backend->dump = machine_dump_guest_core(machine);
     backend->prealloc = mem_prealloc;
 
     object_property_add_bool(obj, "merge",
@@ -252,9 +257,10 @@
     object_property_add(obj, "host-nodes", "int",
                         host_memory_backend_get_host_nodes,
                         host_memory_backend_set_host_nodes, NULL, NULL, NULL);
-    object_property_add(obj, "policy", "str",
-                        host_memory_backend_get_policy,
-                        host_memory_backend_set_policy, NULL, NULL, NULL);
+    object_property_add_enum(obj, "policy", "HostMemPolicy",
+                             HostMemPolicy_lookup,
+                             host_memory_backend_get_policy,
+                             host_memory_backend_set_policy, NULL);
 }
 
 MemoryRegion *
@@ -263,6 +269,16 @@
     return memory_region_size(&backend->mr) ? &backend->mr : NULL;
 }
 
+void host_memory_backend_set_mapped(HostMemoryBackend *backend, bool mapped)
+{
+    backend->is_mapped = mapped;
+}
+
+bool host_memory_backend_is_mapped(HostMemoryBackend *backend)
+{
+    return backend->is_mapped;
+}
+
 static void
 host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
 {
@@ -275,8 +291,7 @@
     if (bc->alloc) {
         bc->alloc(backend, &local_err);
         if (local_err) {
-            error_propagate(errp, local_err);
-            return;
+            goto out;
         }
 
         ptr = memory_region_get_ram_ptr(&backend->mr);
@@ -320,9 +335,11 @@
         assert(maxnode <= MAX_NODES);
         if (mbind(ptr, sz, backend->policy,
                   maxnode ? backend->host_nodes : NULL, maxnode + 1, flags)) {
-            error_setg_errno(errp, errno,
-                             "cannot bind memory to host NUMA nodes");
-            return;
+            if (backend->policy != MPOL_DEFAULT || errno != ENOSYS) {
+                error_setg_errno(errp, errno,
+                                 "cannot bind memory to host NUMA nodes");
+                return;
+            }
         }
 #endif
         /* Preallocate memory after the NUMA policy has been instantiated.
@@ -330,9 +347,25 @@
          * specified NUMA policy in place.
          */
         if (backend->prealloc) {
-            os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz);
+            os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz,
+                            &local_err);
+            if (local_err) {
+                goto out;
+            }
         }
     }
+out:
+    error_propagate(errp, local_err);
+}
+
+static bool
+host_memory_backend_can_be_deleted(UserCreatable *uc, Error **errp)
+{
+    if (host_memory_backend_is_mapped(MEMORY_BACKEND(uc))) {
+        return false;
+    } else {
+        return true;
+    }
 }
 
 static void
@@ -341,6 +374,7 @@
     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 
     ucc->complete = host_memory_backend_memory_complete;
+    ucc->can_be_deleted = host_memory_backend_can_be_deleted;
 }
 
 static const TypeInfo host_memory_backend_info = {
diff --git a/backends/msmouse.c b/backends/msmouse.c
index 0119110..aeb9055 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -21,20 +21,55 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include <stdlib.h>
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "sysemu/char.h"
 #include "ui/console.h"
+#include "ui/input.h"
 
 #define MSMOUSE_LO6(n) ((n) & 0x3f)
 #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
 
-static void msmouse_event(void *opaque,
-                          int dx, int dy, int dz, int buttons_state)
-{
-    CharDriverState *chr = (CharDriverState *)opaque;
+typedef struct {
+    CharDriverState *chr;
+    QemuInputHandlerState *hs;
+    int axis[INPUT_AXIS__MAX];
+    bool btns[INPUT_BUTTON__MAX];
+    bool btnc[INPUT_BUTTON__MAX];
+    uint8_t outbuf[32];
+    int outlen;
+} MouseState;
 
+static void msmouse_chr_accept_input(CharDriverState *chr)
+{
+    MouseState *mouse = chr->opaque;
+    int len;
+
+    len = qemu_chr_be_can_write(chr);
+    if (len > mouse->outlen) {
+        len = mouse->outlen;
+    }
+    if (!len) {
+        return;
+    }
+
+    qemu_chr_be_write(chr, mouse->outbuf, len);
+    mouse->outlen -= len;
+    if (mouse->outlen) {
+        memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen);
+    }
+}
+
+static void msmouse_queue_event(MouseState *mouse)
+{
     unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
+    int dx, dy, count = 3;
+
+    dx = mouse->axis[INPUT_AXIS_X];
+    mouse->axis[INPUT_AXIS_X] = 0;
+
+    dy = mouse->axis[INPUT_AXIS_Y];
+    mouse->axis[INPUT_AXIS_Y] = 0;
 
     /* Movement deltas */
     bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
@@ -42,14 +77,54 @@
     bytes[2] |= MSMOUSE_LO6(dy);
 
     /* Buttons */
-    bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
-    bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
-    bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
+    bytes[0] |= (mouse->btns[INPUT_BUTTON_LEFT]   ? 0x20 : 0x00);
+    bytes[0] |= (mouse->btns[INPUT_BUTTON_RIGHT]  ? 0x10 : 0x00);
+    if (mouse->btns[INPUT_BUTTON_MIDDLE] ||
+        mouse->btnc[INPUT_BUTTON_MIDDLE]) {
+        bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00);
+        mouse->btnc[INPUT_BUTTON_MIDDLE] = false;
+        count = 4;
+    }
 
-    /* We always send the packet of, so that we do not have to keep track
-       of previous state of the middle button. This can potentially confuse
-       some very old drivers for two button mice though. */
-    qemu_chr_be_write(chr, bytes, 4);
+    if (mouse->outlen <= sizeof(mouse->outbuf) - count) {
+        memcpy(mouse->outbuf + mouse->outlen, bytes, count);
+        mouse->outlen += count;
+    } else {
+        /* queue full -> drop event */
+    }
+}
+
+static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
+                                InputEvent *evt)
+{
+    MouseState *mouse = (MouseState *)dev;
+    InputMoveEvent *move;
+    InputBtnEvent *btn;
+
+    switch (evt->type) {
+    case INPUT_EVENT_KIND_REL:
+        move = evt->u.rel.data;
+        mouse->axis[move->axis] += move->value;
+        break;
+
+    case INPUT_EVENT_KIND_BTN:
+        btn = evt->u.btn.data;
+        mouse->btns[btn->button] = btn->down;
+        mouse->btnc[btn->button] = true;
+        break;
+
+    default:
+        /* keep gcc happy */
+        break;
+    }
+}
+
+static void msmouse_input_sync(DeviceState *dev)
+{
+    MouseState *mouse = (MouseState *)dev;
+
+    msmouse_queue_event(mouse);
+    msmouse_chr_accept_input(mouse->chr);
 }
 
 static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
@@ -60,26 +135,49 @@
 
 static void msmouse_chr_close (struct CharDriverState *chr)
 {
-    g_free (chr);
+    MouseState *mouse = chr->opaque;
+
+    qemu_input_handler_unregister(mouse->hs);
+    g_free(mouse);
+    g_free(chr);
 }
 
-CharDriverState *qemu_chr_open_msmouse(void)
+static QemuInputHandler msmouse_handler = {
+    .name  = "QEMU Microsoft Mouse",
+    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
+    .event = msmouse_input_event,
+    .sync  = msmouse_input_sync,
+};
+
+static CharDriverState *qemu_chr_open_msmouse(const char *id,
+                                              ChardevBackend *backend,
+                                              ChardevReturn *ret,
+                                              Error **errp)
 {
+    ChardevCommon *common = backend->u.msmouse.data;
+    MouseState *mouse;
     CharDriverState *chr;
 
-    chr = qemu_chr_alloc();
+    chr = qemu_chr_alloc(common, errp);
     chr->chr_write = msmouse_chr_write;
     chr->chr_close = msmouse_chr_close;
+    chr->chr_accept_input = msmouse_chr_accept_input;
     chr->explicit_be_open = true;
 
-    qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
+    mouse = g_new0(MouseState, 1);
+    mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
+                                            &msmouse_handler);
+
+    mouse->chr = chr;
+    chr->opaque = mouse;
 
     return chr;
 }
 
 static void register_types(void)
 {
-    register_char_driver("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE, NULL);
+    register_char_driver("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE, NULL,
+                         qemu_chr_open_msmouse);
 }
 
 type_init(register_types);
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index 2962795..7a1b924 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -10,8 +10,10 @@
  * See the COPYING file in the top-level directory.
  */
 
+#include "qemu/osdep.h"
 #include "sysemu/rng.h"
 #include "sysemu/char.h"
+#include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "hw/qdev.h" /* just for DEFINE_PROP_CHR */
 
@@ -24,33 +26,12 @@
 
     CharDriverState *chr;
     char *chr_name;
-
-    GSList *requests;
 } RngEgd;
 
-typedef struct RngRequest
-{
-    EntropyReceiveFunc *receive_entropy;
-    uint8_t *data;
-    void *opaque;
-    size_t offset;
-    size_t size;
-} RngRequest;
-
-static void rng_egd_request_entropy(RngBackend *b, size_t size,
-                                    EntropyReceiveFunc *receive_entropy,
-                                    void *opaque)
+static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
 {
     RngEgd *s = RNG_EGD(b);
-    RngRequest *req;
-
-    req = g_malloc(sizeof(*req));
-
-    req->offset = 0;
-    req->size = size;
-    req->receive_entropy = receive_entropy;
-    req->opaque = opaque;
-    req->data = g_malloc(req->size);
+    size_t size = req->size;
 
     while (size > 0) {
         uint8_t header[2];
@@ -64,24 +45,15 @@
 
         size -= len;
     }
-
-    s->requests = g_slist_append(s->requests, req);
-}
-
-static void rng_egd_free_request(RngRequest *req)
-{
-    g_free(req->data);
-    g_free(req);
 }
 
 static int rng_egd_chr_can_read(void *opaque)
 {
     RngEgd *s = RNG_EGD(opaque);
-    GSList *i;
+    RngRequest *req;
     int size = 0;
 
-    for (i = s->requests; i; i = i->next) {
-        RngRequest *req = i->data;
+    QSIMPLEQ_FOREACH(req, &s->parent.requests, next) {
         size += req->size - req->offset;
     }
 
@@ -93,8 +65,8 @@
     RngEgd *s = RNG_EGD(opaque);
     size_t buf_offset = 0;
 
-    while (size > 0 && s->requests) {
-        RngRequest *req = s->requests->data;
+    while (size > 0 && !QSIMPLEQ_EMPTY(&s->parent.requests)) {
+        RngRequest *req = QSIMPLEQ_FIRST(&s->parent.requests);
         int len = MIN(size, req->size - req->offset);
 
         memcpy(req->data + req->offset, buf + buf_offset, len);
@@ -103,56 +75,32 @@
         size -= len;
 
         if (req->offset == req->size) {
-            s->requests = g_slist_remove_link(s->requests, s->requests);
-
             req->receive_entropy(req->opaque, req->data, req->size);
 
-            rng_egd_free_request(req);
+            rng_backend_finalize_request(&s->parent, req);
         }
     }
 }
 
-static void rng_egd_free_requests(RngEgd *s)
-{
-    GSList *i;
-
-    for (i = s->requests; i; i = i->next) {
-        rng_egd_free_request(i->data);
-    }
-
-    g_slist_free(s->requests);
-    s->requests = NULL;
-}
-
-static void rng_egd_cancel_requests(RngBackend *b)
-{
-    RngEgd *s = RNG_EGD(b);
-
-    /* We simply delete the list of pending requests.  If there is data in the 
-     * queue waiting to be read, this is okay, because there will always be
-     * more data than we requested originally
-     */
-    rng_egd_free_requests(s);
-}
-
 static void rng_egd_opened(RngBackend *b, Error **errp)
 {
     RngEgd *s = RNG_EGD(b);
 
     if (s->chr_name == NULL) {
-        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
-                  "chardev", "a valid character device");
+        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+                   "chardev", "a valid character device");
         return;
     }
 
     s->chr = qemu_chr_find(s->chr_name);
     if (s->chr == NULL) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, s->chr_name);
+        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+                  "Device '%s' not found", s->chr_name);
         return;
     }
 
     if (qemu_chr_fe_claim(s->chr) != 0) {
-        error_set(errp, QERR_DEVICE_IN_USE, s->chr_name);
+        error_setg(errp, QERR_DEVICE_IN_USE, s->chr_name);
         return;
     }
 
@@ -167,7 +115,7 @@
     RngEgd *s = RNG_EGD(b);
 
     if (b->opened) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        error_setg(errp, QERR_PERMISSION_DENIED);
     } else {
         g_free(s->chr_name);
         s->chr_name = g_strdup(value);
@@ -202,8 +150,6 @@
     }
 
     g_free(s->chr_name);
-
-    rng_egd_free_requests(s);
 }
 
 static void rng_egd_class_init(ObjectClass *klass, void *data)
@@ -211,7 +157,6 @@
     RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
 
     rbc->request_entropy = rng_egd_request_entropy;
-    rbc->cancel_requests = rng_egd_cancel_requests;
     rbc->opened = rng_egd_opened;
 }
 
diff --git a/backends/rng-random.c b/backends/rng-random.c
index 601d9dc..e2a49b0 100644
--- a/backends/rng-random.c
+++ b/backends/rng-random.c
@@ -10,21 +10,19 @@
  * See the COPYING file in the top-level directory.
  */
 
+#include "qemu/osdep.h"
 #include "sysemu/rng-random.h"
 #include "sysemu/rng.h"
+#include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/main-loop.h"
 
-struct RndRandom
+struct RngRandom
 {
     RngBackend parent;
 
     int fd;
     char *filename;
-
-    EntropyReceiveFunc *receive_func;
-    void *opaque;
-    size_t size;
 };
 
 /**
@@ -36,46 +34,45 @@
 
 static void entropy_available(void *opaque)
 {
-    RndRandom *s = RNG_RANDOM(opaque);
-    uint8_t buffer[s->size];
-    ssize_t len;
+    RngRandom *s = RNG_RANDOM(opaque);
 
-    len = read(s->fd, buffer, s->size);
-    if (len < 0 && errno == EAGAIN) {
-        return;
+    while (!QSIMPLEQ_EMPTY(&s->parent.requests)) {
+        RngRequest *req = QSIMPLEQ_FIRST(&s->parent.requests);
+        ssize_t len;
+
+        len = read(s->fd, req->data, req->size);
+        if (len < 0 && errno == EAGAIN) {
+            return;
+        }
+        g_assert(len != -1);
+
+        req->receive_entropy(req->opaque, req->data, len);
+
+        rng_backend_finalize_request(&s->parent, req);
     }
-    g_assert(len != -1);
 
-    s->receive_func(s->opaque, buffer, len);
-    s->receive_func = NULL;
-
+    /* We've drained all requests, the fd handler can be reset. */
     qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
 }
 
-static void rng_random_request_entropy(RngBackend *b, size_t size,
-                                        EntropyReceiveFunc *receive_entropy,
-                                        void *opaque)
+static void rng_random_request_entropy(RngBackend *b, RngRequest *req)
 {
-    RndRandom *s = RNG_RANDOM(b);
+    RngRandom *s = RNG_RANDOM(b);
 
-    if (s->receive_func) {
-        s->receive_func(s->opaque, NULL, 0);
+    if (QSIMPLEQ_EMPTY(&s->parent.requests)) {
+        /* If there are no pending requests yet, we need to
+         * install our fd handler. */
+        qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
     }
-
-    s->receive_func = receive_entropy;
-    s->opaque = opaque;
-    s->size = size;
-
-    qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
 }
 
 static void rng_random_opened(RngBackend *b, Error **errp)
 {
-    RndRandom *s = RNG_RANDOM(b);
+    RngRandom *s = RNG_RANDOM(b);
 
     if (s->filename == NULL) {
-        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
-                  "filename", "a valid filename");
+        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+                   "filename", "a valid filename");
     } else {
         s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK);
         if (s->fd == -1) {
@@ -86,23 +83,19 @@
 
 static char *rng_random_get_filename(Object *obj, Error **errp)
 {
-    RndRandom *s = RNG_RANDOM(obj);
+    RngRandom *s = RNG_RANDOM(obj);
 
-    if (s->filename) {
-        return g_strdup(s->filename);
-    }
-
-    return NULL;
+    return g_strdup(s->filename);
 }
 
 static void rng_random_set_filename(Object *obj, const char *filename,
                                  Error **errp)
 {
     RngBackend *b = RNG_BACKEND(obj);
-    RndRandom *s = RNG_RANDOM(obj);
+    RngRandom *s = RNG_RANDOM(obj);
 
     if (b->opened) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        error_setg(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
@@ -112,7 +105,7 @@
 
 static void rng_random_init(Object *obj)
 {
-    RndRandom *s = RNG_RANDOM(obj);
+    RngRandom *s = RNG_RANDOM(obj);
 
     object_property_add_str(obj, "filename",
                             rng_random_get_filename,
@@ -125,7 +118,7 @@
 
 static void rng_random_finalize(Object *obj)
 {
-    RndRandom *s = RNG_RANDOM(obj);
+    RngRandom *s = RNG_RANDOM(obj);
 
     if (s->fd != -1) {
         qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
@@ -146,7 +139,7 @@
 static const TypeInfo rng_random_info = {
     .name = TYPE_RNG_RANDOM,
     .parent = TYPE_RNG_BACKEND,
-    .instance_size = sizeof(RndRandom),
+    .instance_size = sizeof(RngRandom),
     .class_init = rng_random_class_init,
     .instance_init = rng_random_init,
     .instance_finalize = rng_random_finalize,
diff --git a/backends/rng.c b/backends/rng.c
index 0f2fc11..398ebe4 100644
--- a/backends/rng.c
+++ b/backends/rng.c
@@ -10,7 +10,9 @@
  * See the COPYING file in the top-level directory.
  */
 
+#include "qemu/osdep.h"
 #include "sysemu/rng.h"
+#include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qom/object_interfaces.h"
 
@@ -19,18 +21,20 @@
                                  void *opaque)
 {
     RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+    RngRequest *req;
 
     if (k->request_entropy) {
-        k->request_entropy(s, size, receive_entropy, opaque);
-    }
-}
+        req = g_malloc(sizeof(*req));
 
-void rng_backend_cancel_requests(RngBackend *s)
-{
-    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+        req->offset = 0;
+        req->size = size;
+        req->receive_entropy = receive_entropy;
+        req->opaque = opaque;
+        req->data = g_malloc(req->size);
 
-    if (k->cancel_requests) {
-        k->cancel_requests(s);
+        k->request_entropy(s, req);
+
+        QSIMPLEQ_INSERT_TAIL(&s->requests, req, next);
     }
 }
 
@@ -57,7 +61,7 @@
     }
 
     if (!value && s->opened) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        error_setg(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
@@ -72,14 +76,48 @@
     s->opened = true;
 }
 
+static void rng_backend_free_request(RngRequest *req)
+{
+    g_free(req->data);
+    g_free(req);
+}
+
+static void rng_backend_free_requests(RngBackend *s)
+{
+    RngRequest *req, *next;
+
+    QSIMPLEQ_FOREACH_SAFE(req, &s->requests, next, next) {
+        rng_backend_free_request(req);
+    }
+
+    QSIMPLEQ_INIT(&s->requests);
+}
+
+void rng_backend_finalize_request(RngBackend *s, RngRequest *req)
+{
+    QSIMPLEQ_REMOVE(&s->requests, req, RngRequest, next);
+    rng_backend_free_request(req);
+}
+
 static void rng_backend_init(Object *obj)
 {
+    RngBackend *s = RNG_BACKEND(obj);
+
+    QSIMPLEQ_INIT(&s->requests);
+
     object_property_add_bool(obj, "opened",
                              rng_backend_prop_get_opened,
                              rng_backend_prop_set_opened,
                              NULL);
 }
 
+static void rng_backend_finalize(Object *obj)
+{
+    RngBackend *s = RNG_BACKEND(obj);
+
+    rng_backend_free_requests(s);
+}
+
 static void rng_backend_class_init(ObjectClass *oc, void *data)
 {
     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
@@ -92,6 +130,7 @@
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(RngBackend),
     .instance_init = rng_backend_init,
+    .instance_finalize = rng_backend_finalize,
     .class_size = sizeof(RngBackendClass),
     .class_init = rng_backend_class_init,
     .abstract = true,
diff --git a/backends/testdev.c b/backends/testdev.c
index eba396a..3ab1c90 100644
--- a/backends/testdev.c
+++ b/backends/testdev.c
@@ -23,6 +23,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "sysemu/char.h"
 
@@ -108,13 +109,16 @@
     g_free(testdev);
 }
 
-CharDriverState *chr_testdev_init(void)
+static CharDriverState *chr_testdev_init(const char *id,
+                                         ChardevBackend *backend,
+                                         ChardevReturn *ret,
+                                         Error **errp)
 {
     TestdevCharState *testdev;
     CharDriverState *chr;
 
-    testdev = g_malloc0(sizeof(TestdevCharState));
-    testdev->chr = chr = g_malloc0(sizeof(CharDriverState));
+    testdev = g_new0(TestdevCharState, 1);
+    testdev->chr = chr = g_new0(CharDriverState, 1);
 
     chr->opaque = testdev;
     chr->chr_write = testdev_write;
@@ -125,7 +129,8 @@
 
 static void register_types(void)
 {
-    register_char_driver("testdev", CHARDEV_BACKEND_KIND_TESTDEV, NULL);
+    register_char_driver("testdev", CHARDEV_BACKEND_KIND_TESTDEV, NULL,
+                         chr_testdev_init);
 }
 
 type_init(register_types);
diff --git a/backends/tpm.c b/backends/tpm.c
index 01860c4..536f262 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -12,7 +12,9 @@
  * Based on backends/rng.c by Anthony Liguori
  */
 
+#include "qemu/osdep.h"
 #include "sysemu/tpm_backend.h"
+#include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/tpm.h"
 #include "qemu/thread.h"
@@ -36,7 +38,7 @@
 {
     TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
 
-    return k->ops->destroy(s);
+    k->ops->destroy(s);
 }
 
 int tpm_backend_init(TPMBackend *s, TPMState *state,
@@ -96,6 +98,20 @@
     return k->ops->get_tpm_established_flag(s);
 }
 
+int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->reset_tpm_established_flag(s, locty);
+}
+
+TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->get_tpm_version(s);
+}
+
 static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
 {
     TPMBackend *s = TPM_BACKEND(obj);
@@ -119,7 +135,7 @@
     }
 
     if (!value && s->opened) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        error_setg(errp, QERR_PERMISSION_DENIED);
         return;
     }
 
@@ -165,17 +181,6 @@
     }
 }
 
-void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt,
-                                  GFunc func, gpointer user_data)
-{
-    if (!tbt->pool) {
-        tpm_backend_thread_create(tbt, func, user_data);
-    } else {
-        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_TPM_RESET,
-                           NULL);
-    }
-}
-
 static const TypeInfo tpm_backend_info = {
     .name = TYPE_TPM_BACKEND,
     .parent = TYPE_OBJECT,
diff --git a/balloon.c b/balloon.c
index b70da4f..f2ef50c 100644
--- a/balloon.c
+++ b/balloon.c
@@ -24,17 +24,45 @@
  * THE SOFTWARE.
  */
 
-#include "monitor/monitor.h"
+#include "qemu/osdep.h"
+#include "qemu-common.h"
 #include "exec/cpu-common.h"
 #include "sysemu/kvm.h"
 #include "sysemu/balloon.h"
 #include "trace.h"
 #include "qmp-commands.h"
+#include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qjson.h"
 
 static QEMUBalloonEvent *balloon_event_fn;
 static QEMUBalloonStatus *balloon_stat_fn;
 static void *balloon_opaque;
+static bool balloon_inhibited;
+
+bool qemu_balloon_is_inhibited(void)
+{
+    return balloon_inhibited;
+}
+
+void qemu_balloon_inhibit(bool state)
+{
+    balloon_inhibited = state;
+}
+
+static bool have_balloon(Error **errp)
+{
+    if (kvm_enabled() && !kvm_has_sync_mmu()) {
+        error_set(errp, ERROR_CLASS_KVM_MISSING_CAP,
+                  "Using KVM without synchronous MMU, balloon unavailable");
+        return false;
+    }
+    if (!balloon_event_fn) {
+        error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE,
+                  "No balloon device has been activated");
+        return false;
+    }
+    return true;
+}
 
 int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
                              QEMUBalloonStatus *stat_func, void *opaque)
@@ -43,7 +71,6 @@
         /* We're already registered one balloon handler.  How many can
          * a guest really have?
          */
-        error_report("Another balloon device already registered");
         return -1;
     }
     balloon_event_fn = event_func;
@@ -62,58 +89,30 @@
     balloon_opaque = NULL;
 }
 
-static int qemu_balloon(ram_addr_t target)
-{
-    if (!balloon_event_fn) {
-        return 0;
-    }
-    trace_balloon_event(balloon_opaque, target);
-    balloon_event_fn(balloon_opaque, target);
-    return 1;
-}
-
-static int qemu_balloon_status(BalloonInfo *info)
-{
-    if (!balloon_stat_fn) {
-        return 0;
-    }
-    balloon_stat_fn(balloon_opaque, info);
-    return 1;
-}
-
 BalloonInfo *qmp_query_balloon(Error **errp)
 {
     BalloonInfo *info;
 
-    if (kvm_enabled() && !kvm_has_sync_mmu()) {
-        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+    if (!have_balloon(errp)) {
         return NULL;
     }
 
     info = g_malloc0(sizeof(*info));
-
-    if (qemu_balloon_status(info) == 0) {
-        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
-        qapi_free_BalloonInfo(info);
-        return NULL;
-    }
-
+    balloon_stat_fn(balloon_opaque, info);
     return info;
 }
 
-void qmp_balloon(int64_t value, Error **errp)
+void qmp_balloon(int64_t target, Error **errp)
 {
-    if (kvm_enabled() && !kvm_has_sync_mmu()) {
-        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+    if (!have_balloon(errp)) {
         return;
     }
 
-    if (value <= 0) {
-        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "target", "a size");
+    if (target <= 0) {
+        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "target", "a size");
         return;
     }
-    
-    if (qemu_balloon(value) == 0) {
-        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
-    }
+
+    trace_balloon_event(balloon_opaque, target);
+    balloon_event_fn(balloon_opaque, target);
 }
diff --git a/block-migration.c b/block-migration.c
deleted file mode 100644
index 08db01a..0000000
--- a/block-migration.c
+++ /dev/null
@@ -1,884 +0,0 @@
-/*
- * QEMU live block migration
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Liran Schour   <lirans@il.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu-common.h"
-#include "block/block.h"
-#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
-#include "hw/hw.h"
-#include "qemu/queue.h"
-#include "qemu/timer.h"
-#include "migration/block.h"
-#include "migration/migration.h"
-#include "sysemu/blockdev.h"
-#include <assert.h>
-
-#define BLOCK_SIZE                       (1 << 20)
-#define BDRV_SECTORS_PER_DIRTY_CHUNK     (BLOCK_SIZE >> BDRV_SECTOR_BITS)
-
-#define BLK_MIG_FLAG_DEVICE_BLOCK       0x01
-#define BLK_MIG_FLAG_EOS                0x02
-#define BLK_MIG_FLAG_PROGRESS           0x04
-#define BLK_MIG_FLAG_ZERO_BLOCK         0x08
-
-#define MAX_IS_ALLOCATED_SEARCH 65536
-
-//#define DEBUG_BLK_MIGRATION
-
-#ifdef DEBUG_BLK_MIGRATION
-#define DPRINTF(fmt, ...) \
-    do { printf("blk_migration: " fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-    do { } while (0)
-#endif
-
-typedef struct BlkMigDevState {
-    /* Written during setup phase.  Can be read without a lock.  */
-    BlockDriverState *bs;
-    int shared_base;
-    int64_t total_sectors;
-    QSIMPLEQ_ENTRY(BlkMigDevState) entry;
-
-    /* Only used by migration thread.  Does not need a lock.  */
-    int bulk_completed;
-    int64_t cur_sector;
-    int64_t cur_dirty;
-
-    /* Protected by block migration lock.  */
-    unsigned long *aio_bitmap;
-    int64_t completed_sectors;
-    BdrvDirtyBitmap *dirty_bitmap;
-    Error *blocker;
-} BlkMigDevState;
-
-typedef struct BlkMigBlock {
-    /* Only used by migration thread.  */
-    uint8_t *buf;
-    BlkMigDevState *bmds;
-    int64_t sector;
-    int nr_sectors;
-    struct iovec iov;
-    QEMUIOVector qiov;
-    BlockAIOCB *aiocb;
-
-    /* Protected by block migration lock.  */
-    int ret;
-    QSIMPLEQ_ENTRY(BlkMigBlock) entry;
-} BlkMigBlock;
-
-typedef struct BlkMigState {
-    /* Written during setup phase.  Can be read without a lock.  */
-    int blk_enable;
-    int shared_base;
-    QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
-    int64_t total_sector_sum;
-    bool zero_blocks;
-
-    /* Protected by lock.  */
-    QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
-    int submitted;
-    int read_done;
-
-    /* Only used by migration thread.  Does not need a lock.  */
-    int transferred;
-    int prev_progress;
-    int bulk_completed;
-
-    /* Lock must be taken _inside_ the iothread lock.  */
-    QemuMutex lock;
-} BlkMigState;
-
-static BlkMigState block_mig_state;
-
-static void blk_mig_lock(void)
-{
-    qemu_mutex_lock(&block_mig_state.lock);
-}
-
-static void blk_mig_unlock(void)
-{
-    qemu_mutex_unlock(&block_mig_state.lock);
-}
-
-/* Must run outside of the iothread lock during the bulk phase,
- * or the VM will stall.
- */
-
-static void blk_send(QEMUFile *f, BlkMigBlock * blk)
-{
-    int len;
-    uint64_t flags = BLK_MIG_FLAG_DEVICE_BLOCK;
-
-    if (block_mig_state.zero_blocks &&
-        buffer_is_zero(blk->buf, BLOCK_SIZE)) {
-        flags |= BLK_MIG_FLAG_ZERO_BLOCK;
-    }
-
-    /* sector number and flags */
-    qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS)
-                     | flags);
-
-    /* device name */
-    len = strlen(bdrv_get_device_name(blk->bmds->bs));
-    qemu_put_byte(f, len);
-    qemu_put_buffer(f, (uint8_t *)bdrv_get_device_name(blk->bmds->bs), len);
-
-    /* if a block is zero we need to flush here since the network
-     * bandwidth is now a lot higher than the storage device bandwidth.
-     * thus if we queue zero blocks we slow down the migration */
-    if (flags & BLK_MIG_FLAG_ZERO_BLOCK) {
-        qemu_fflush(f);
-        return;
-    }
-
-    qemu_put_buffer(f, blk->buf, BLOCK_SIZE);
-}
-
-int blk_mig_active(void)
-{
-    return !QSIMPLEQ_EMPTY(&block_mig_state.bmds_list);
-}
-
-uint64_t blk_mig_bytes_transferred(void)
-{
-    BlkMigDevState *bmds;
-    uint64_t sum = 0;
-
-    blk_mig_lock();
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        sum += bmds->completed_sectors;
-    }
-    blk_mig_unlock();
-    return sum << BDRV_SECTOR_BITS;
-}
-
-uint64_t blk_mig_bytes_remaining(void)
-{
-    return blk_mig_bytes_total() - blk_mig_bytes_transferred();
-}
-
-uint64_t blk_mig_bytes_total(void)
-{
-    BlkMigDevState *bmds;
-    uint64_t sum = 0;
-
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        sum += bmds->total_sectors;
-    }
-    return sum << BDRV_SECTOR_BITS;
-}
-
-
-/* Called with migration lock held.  */
-
-static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
-{
-    int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
-
-    if (sector < bdrv_nb_sectors(bmds->bs)) {
-        return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] &
-            (1UL << (chunk % (sizeof(unsigned long) * 8))));
-    } else {
-        return 0;
-    }
-}
-
-/* Called with migration lock held.  */
-
-static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num,
-                             int nb_sectors, int set)
-{
-    int64_t start, end;
-    unsigned long val, idx, bit;
-
-    start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK;
-    end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK;
-
-    for (; start <= end; start++) {
-        idx = start / (sizeof(unsigned long) * 8);
-        bit = start % (sizeof(unsigned long) * 8);
-        val = bmds->aio_bitmap[idx];
-        if (set) {
-            val |= 1UL << bit;
-        } else {
-            val &= ~(1UL << bit);
-        }
-        bmds->aio_bitmap[idx] = val;
-    }
-}
-
-static void alloc_aio_bitmap(BlkMigDevState *bmds)
-{
-    BlockDriverState *bs = bmds->bs;
-    int64_t bitmap_size;
-
-    bitmap_size = bdrv_nb_sectors(bs) + BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
-    bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8;
-
-    bmds->aio_bitmap = g_malloc0(bitmap_size);
-}
-
-/* Never hold migration lock when yielding to the main loop!  */
-
-static void blk_mig_read_cb(void *opaque, int ret)
-{
-    BlkMigBlock *blk = opaque;
-
-    blk_mig_lock();
-    blk->ret = ret;
-
-    QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
-    bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
-
-    block_mig_state.submitted--;
-    block_mig_state.read_done++;
-    assert(block_mig_state.submitted >= 0);
-    blk_mig_unlock();
-}
-
-/* Called with no lock taken.  */
-
-static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
-{
-    int64_t total_sectors = bmds->total_sectors;
-    int64_t cur_sector = bmds->cur_sector;
-    BlockDriverState *bs = bmds->bs;
-    BlkMigBlock *blk;
-    int nr_sectors;
-
-    if (bmds->shared_base) {
-        qemu_mutex_lock_iothread();
-        while (cur_sector < total_sectors &&
-               !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
-                                  &nr_sectors)) {
-            cur_sector += nr_sectors;
-        }
-        qemu_mutex_unlock_iothread();
-    }
-
-    if (cur_sector >= total_sectors) {
-        bmds->cur_sector = bmds->completed_sectors = total_sectors;
-        return 1;
-    }
-
-    bmds->completed_sectors = cur_sector;
-
-    cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);
-
-    /* we are going to transfer a full block even if it is not allocated */
-    nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
-
-    if (total_sectors - cur_sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
-        nr_sectors = total_sectors - cur_sector;
-    }
-
-    blk = g_new(BlkMigBlock, 1);
-    blk->buf = g_malloc(BLOCK_SIZE);
-    blk->bmds = bmds;
-    blk->sector = cur_sector;
-    blk->nr_sectors = nr_sectors;
-
-    blk->iov.iov_base = blk->buf;
-    blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
-    qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
-
-    blk_mig_lock();
-    block_mig_state.submitted++;
-    blk_mig_unlock();
-
-    qemu_mutex_lock_iothread();
-    blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
-                                nr_sectors, blk_mig_read_cb, blk);
-
-    bdrv_reset_dirty(bs, cur_sector, nr_sectors);
-    qemu_mutex_unlock_iothread();
-
-    bmds->cur_sector = cur_sector + nr_sectors;
-    return (bmds->cur_sector >= total_sectors);
-}
-
-/* Called with iothread lock taken.  */
-
-static int set_dirty_tracking(void)
-{
-    BlkMigDevState *bmds;
-    int ret;
-
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,
-                                                      NULL);
-        if (!bmds->dirty_bitmap) {
-            ret = -errno;
-            goto fail;
-        }
-    }
-    return 0;
-
-fail:
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        if (bmds->dirty_bitmap) {
-            bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
-        }
-    }
-    return ret;
-}
-
-static void unset_dirty_tracking(void)
-{
-    BlkMigDevState *bmds;
-
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
-    }
-}
-
-static void init_blk_migration(QEMUFile *f)
-{
-    BlockDriverState *bs;
-    BlkMigDevState *bmds;
-    int64_t sectors;
-
-    block_mig_state.submitted = 0;
-    block_mig_state.read_done = 0;
-    block_mig_state.transferred = 0;
-    block_mig_state.total_sector_sum = 0;
-    block_mig_state.prev_progress = -1;
-    block_mig_state.bulk_completed = 0;
-    block_mig_state.zero_blocks = migrate_zero_blocks();
-
-    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
-        if (bdrv_is_read_only(bs)) {
-            continue;
-        }
-
-        sectors = bdrv_nb_sectors(bs);
-        if (sectors <= 0) {
-            return;
-        }
-
-        bmds = g_new0(BlkMigDevState, 1);
-        bmds->bs = bs;
-        bmds->bulk_completed = 0;
-        bmds->total_sectors = sectors;
-        bmds->completed_sectors = 0;
-        bmds->shared_base = block_mig_state.shared_base;
-        alloc_aio_bitmap(bmds);
-        error_setg(&bmds->blocker, "block device is in use by migration");
-        bdrv_op_block_all(bs, bmds->blocker);
-        bdrv_ref(bs);
-
-        block_mig_state.total_sector_sum += sectors;
-
-        if (bmds->shared_base) {
-            DPRINTF("Start migration for %s with shared base image\n",
-                    bdrv_get_device_name(bs));
-        } else {
-            DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs));
-        }
-
-        QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
-    }
-}
-
-/* Called with no lock taken.  */
-
-static int blk_mig_save_bulked_block(QEMUFile *f)
-{
-    int64_t completed_sector_sum = 0;
-    BlkMigDevState *bmds;
-    int progress;
-    int ret = 0;
-
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        if (bmds->bulk_completed == 0) {
-            if (mig_save_device_bulk(f, bmds) == 1) {
-                /* completed bulk section for this device */
-                bmds->bulk_completed = 1;
-            }
-            completed_sector_sum += bmds->completed_sectors;
-            ret = 1;
-            break;
-        } else {
-            completed_sector_sum += bmds->completed_sectors;
-        }
-    }
-
-    if (block_mig_state.total_sector_sum != 0) {
-        progress = completed_sector_sum * 100 /
-                   block_mig_state.total_sector_sum;
-    } else {
-        progress = 100;
-    }
-    if (progress != block_mig_state.prev_progress) {
-        block_mig_state.prev_progress = progress;
-        qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
-                         | BLK_MIG_FLAG_PROGRESS);
-        DPRINTF("Completed %d %%\r", progress);
-    }
-
-    return ret;
-}
-
-static void blk_mig_reset_dirty_cursor(void)
-{
-    BlkMigDevState *bmds;
-
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        bmds->cur_dirty = 0;
-    }
-}
-
-/* Called with iothread lock taken.  */
-
-static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
-                                 int is_async)
-{
-    BlkMigBlock *blk;
-    int64_t total_sectors = bmds->total_sectors;
-    int64_t sector;
-    int nr_sectors;
-    int ret = -EIO;
-
-    for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
-        blk_mig_lock();
-        if (bmds_aio_inflight(bmds, sector)) {
-            blk_mig_unlock();
-            bdrv_drain_all();
-        } else {
-            blk_mig_unlock();
-        }
-        if (bdrv_get_dirty(bmds->bs, bmds->dirty_bitmap, sector)) {
-
-            if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
-                nr_sectors = total_sectors - sector;
-            } else {
-                nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
-            }
-            blk = g_new(BlkMigBlock, 1);
-            blk->buf = g_malloc(BLOCK_SIZE);
-            blk->bmds = bmds;
-            blk->sector = sector;
-            blk->nr_sectors = nr_sectors;
-
-            if (is_async) {
-                blk->iov.iov_base = blk->buf;
-                blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
-                qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
-
-                blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
-                                            nr_sectors, blk_mig_read_cb, blk);
-
-                blk_mig_lock();
-                block_mig_state.submitted++;
-                bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
-                blk_mig_unlock();
-            } else {
-                ret = bdrv_read(bmds->bs, sector, blk->buf, nr_sectors);
-                if (ret < 0) {
-                    goto error;
-                }
-                blk_send(f, blk);
-
-                g_free(blk->buf);
-                g_free(blk);
-            }
-
-            bdrv_reset_dirty(bmds->bs, sector, nr_sectors);
-            break;
-        }
-        sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
-        bmds->cur_dirty = sector;
-    }
-
-    return (bmds->cur_dirty >= bmds->total_sectors);
-
-error:
-    DPRINTF("Error reading sector %" PRId64 "\n", sector);
-    g_free(blk->buf);
-    g_free(blk);
-    return ret;
-}
-
-/* Called with iothread lock taken.
- *
- * return value:
- * 0: too much data for max_downtime
- * 1: few enough data for max_downtime
-*/
-static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
-{
-    BlkMigDevState *bmds;
-    int ret = 1;
-
-    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        ret = mig_save_device_dirty(f, bmds, is_async);
-        if (ret <= 0) {
-            break;
-        }
-    }
-
-    return ret;
-}
-
-/* Called with no locks taken.  */
-
-static int flush_blks(QEMUFile *f)
-{
-    BlkMigBlock *blk;
-    int ret = 0;
-
-    DPRINTF("%s Enter submitted %d read_done %d transferred %d\n",
-            __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
-            block_mig_state.transferred);
-
-    blk_mig_lock();
-    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
-        if (qemu_file_rate_limit(f)) {
-            break;
-        }
-        if (blk->ret < 0) {
-            ret = blk->ret;
-            break;
-        }
-
-        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
-        blk_mig_unlock();