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 = ®isterUpdateListener
+ .getFrameBuffer = &getFrameBuffer,
+ .registerUpdateListener = ®isterUpdateListener
};
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();