summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIskren Slavov <iskren.s@gmail.com>2011-02-09 12:05:42 +0200
committerIskren Slavov <iskren.s@gmail.com>2011-02-09 12:05:42 +0200
commit71f62bd7770688f4404df19694f50204475e15a6 (patch)
tree2816e8866cf511f7c8357e27b740df2f171fd089 /app-emulation
parentupdated flush to 0.9.9, added patched qbittorrent (diff)
downloadwish-71f62bd7770688f4404df19694f50204475e15a6.tar.gz
wish-71f62bd7770688f4404df19694f50204475e15a6.tar.bz2
wish-71f62bd7770688f4404df19694f50204475e15a6.zip
Removed obsolete playonlinux; added qemu-0.13 with Red Hat patches to support SPICE and QXL :)
Diffstat (limited to 'app-emulation')
-rw-r--r--app-emulation/playonlinux/Manifest2
-rw-r--r--app-emulation/playonlinux/playonlinux-3.8.3.ebuild90
-rw-r--r--app-emulation/qemu-kvm/ChangeLog301
-rw-r--r--app-emulation/qemu-kvm/Manifest10
-rw-r--r--app-emulation/qemu-kvm/files/qemu-0.11.0-mips64-user-fix.patch11
-rw-r--r--app-emulation/qemu-kvm/files/qemu-kvm2
-rw-r--r--app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-fix-crash-with-sdl.patch145
-rw-r--r--app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-include-madvise-defines.patch12
-rw-r--r--app-emulation/qemu-kvm/files/qemu-kvm-0.13.0-redhat-patches.patch11648
-rw-r--r--app-emulation/qemu-kvm/files/qemu-kvm-guest-hang-on-usb-add.patch100
-rw-r--r--app-emulation/qemu-kvm/metadata.xml26
-rw-r--r--app-emulation/qemu-kvm/qemu-kvm-0.13.0-r99.ebuild261
12 files changed, 12516 insertions, 92 deletions
diff --git a/app-emulation/playonlinux/Manifest b/app-emulation/playonlinux/Manifest
deleted file mode 100644
index b7036a4..0000000
--- a/app-emulation/playonlinux/Manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-DIST PlayOnLinux_3.8.3.tar.gz 2309646 RMD160 1a23a219a96c81d3d1f12e42c4e583cb151575b7 SHA1 e2e89fdbaa6feafb956e4b5b02ce4ac0c95f739e SHA256 ca84d080e5d6f11c43c754543289125c56162c8c5a9d9b3f128ea71a7f378763
-EBUILD playonlinux-3.8.3.ebuild 2621 RMD160 3f7884d4667659d39ea45abb27f92aae403e69bb SHA1 3a2d96d5568b589920c57d4e0bcafe724baaa2a4 SHA256 210969b2f4d9d7648946e23f928c880b16e3f59bdf2ab709c4959f477ceb97f2
diff --git a/app-emulation/playonlinux/playonlinux-3.8.3.ebuild b/app-emulation/playonlinux/playonlinux-3.8.3.ebuild
deleted file mode 100644
index 2531738..0000000
--- a/app-emulation/playonlinux/playonlinux-3.8.3.ebuild
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright 1999-2010 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI="2"
-
-inherit eutils python games
-
-MY_PN="PlayOnLinux"
-
-DESCRIPTION="Set of scripts to easily install and use Windows(tm) games and softwares"
-HOMEPAGE="http://playonlinux.com/"
-SRC_URI="http://www.playonlinux.com/script_files/${MY_PN}/${PV}/${MY_PN}_${PV}.tar.gz"
-
-LICENSE="GPL-3"
-SLOT="0"
-KEYWORDS="~amd64 ~x86"
-IUSE=""
-
-DEPEND=""
-RDEPEND="app-emulation/wine
- app-arch/cabextract
- app-arch/unzip
- dev-python/wxpython:2.8
- || ( media-gfx/imagemagick media-gfx/graphicsmagick[imagemagick] )
- x11-apps/mesa-progs
- x11-terms/xterm"
-
-S=${WORKDIR}/${PN}
-
-# TODO:
-# Having a real install script and let playonlinux use standard filesystem
-# architecture to prevent having everything installed into GAMES_DATADIR
-# It will let using LANGUAGES easily
-# How to deal with Microsoft Fonts installation asked every time ?
-# How to deal with wine version installed ? (have a better mgmt of system one)
-# Look at debian pkg: http://packages.debian.org/sid/playonlinux
-
-src_prepare() {
- einfo "Removing temporary files..."
- rm -f $(find . -name *.pyc) || die "rm -f doesn't die"
- rm -f $(find . -name *~) || die "rm -f doesn't die"
-}
-
-src_install() {
- # all things without exec permissions
- insinto "${GAMES_DATADIR}/${PN}"
- doins -r themes lang lib etc || die "doins failed"
-
- # bash/ bash/terminals/ bash/expert/ python/ install
- for dir in 'bash' 'bash/terminals' 'bash/expert' 'python'
- do
- exeinto "${GAMES_DATADIR}/${PN}/${dir}"
- doexe ${dir}/* || die "doexe failed for ${dir}"
- done
-
- # lib/ python/lib/ plugins/ install
- for dir in 'lib' 'python/lib' 'plugins'
- do
- insinto "${GAMES_DATADIR}/${PN}/${dir}"
- doins ${dir}/* || die "doexe failed for ${dir}"
- done
-
- # main executable files
- exeinto "${GAMES_DATADIR}/${PN}"
- doexe ${PN}{,-pkg,-daemon,-cmd,-shell} || die "doexe failed"
-
- # making a script to run app from ${GAMES_BINDIR}
- echo "#!/bin/bash" > ${PN}_launcher
- echo "cd \"${GAMES_DATADIR}/${PN}\" && ./${PN}" >> ${PN}_launcher
- newgamesbin playonlinux_launcher playonlinux || die "newgamesbin failed"
-
- dodoc CHANGELOG || die "dodoc failed"
-
- doicon etc/${PN}.png || die "doicon failed"
- domenu etc/${MY_PN}.desktop || die "domenu failed"
- prepgamesdirs
-}
-
-pkg_postinst() {
- games_pkg_postinst
- python_mod_optimize "${GAMES_DATADIR}/${PN}"
-}
-
-pkg_postrm() {
- python_mod_cleanup "${GAMES_DATADIR}/${PN}"
-
- ewarn "Installed softwares and games with playonlinux have not been removed."
- ewarn "To remove them, you can re-install playonlinux and remove them using it"
- ewarn "or do it manually."
-}
diff --git a/app-emulation/qemu-kvm/ChangeLog b/app-emulation/qemu-kvm/ChangeLog
new file mode 100644
index 0000000..c3c0b53
--- /dev/null
+++ b/app-emulation/qemu-kvm/ChangeLog
@@ -0,0 +1,301 @@
+# ChangeLog for app-emulation/qemu-kvm
+# Copyright 1999-2011 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu-kvm/ChangeLog,v 1.50 2011/01/21 13:49:43 dev-zero Exp $
+
+ 21 Jan 2011; Tiziano Müller <dev-zero@gentoo.org> qemu-kvm-9999.ebuild,
+ metadata.xml:
+ spice (resp. the QXL graphics device) support has been finally merged at
+ qemu-upstream, added a USE flag for it. Added USE flags to toggle vhost-net
+ support (which requires newer kernel-headers) and rados block device storage
+ backend support.
+
+ 17 Jan 2011; Jory A. Pratt <anarchy@gentoo.org> qemu-kvm-0.13.0-r1.ebuild,
+ qemu-kvm-0.13.0-r2.ebuild, qemu-kvm-9999.ebuild:
+ convert to virtual/jpeg instead of forcing media-libs/jpeg
+
+ 05 Jan 2011; Markos Chandras <hwoarang@gentoo.org> qemu-kvm-0.13.0-r2.ebuild:
+ Stable on amd64 wrt bug #346681
+
+ 25 Nov 2010; Christian Faulhammer <fauli@gentoo.org>
+ qemu-kvm-0.13.0-r2.ebuild:
+ stable x86, bug 346681
+
+*qemu-kvm-0.13.0-r2 (03 Nov 2010)
+
+ 03 Nov 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ -qemu-kvm-0.11.1-r1.ebuild,
+ -files/qemu-kvm-0.12.2-virtio-large-iovecs.patch,
+ -qemu-kvm-0.12.3-r1.ebuild, -qemu-kvm-0.12.4-r1.ebuild,
+ -files/qemu-kvm-0.12.4-large-virtio-corruption.patch,
+ -qemu-kvm-0.13.0.ebuild, qemu-kvm-0.13.0-r1.ebuild,
+ +qemu-kvm-0.13.0-r2.ebuild, metadata.xml:
+ Fixed the non installation of binaries due to a bad variable declaration -
+ bug 343951.
+ Updated dtc dep to fix the build failures on amd64 - bug 339044.
+ Restricted parallel build until we fix it - bug 343175.
+ Dropped old ebuilds and files.
+
+*qemu-kvm-0.13.0-r1 (02 Nov 2010)
+
+ 02 Nov 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ -files/qemu-kvm-0.12.1-kvm_save_mpstate-workaround.patch,
+ -qemu-kvm-0.12.5.ebuild, +qemu-kvm-0.13.0-r1.ebuild, qemu-kvm-9999.ebuild,
+ +files/qemu-kvm-guest-hang-on-usb-add.patch:
+ Synced the qemu-kvm-0.13.0-r1 ebuild with qemu-kvm-9999 ebuild.
+ Added missing jpeg and png use flags. Dropped the non-existent kvm-trace
+ use flag - fixes bug 343317.
+ Moved some checks from pkg_setup to src_configure. Applied the fix to the
+ $(prefix)/etc issue.
+ Dropped unused qemu-kvm-0.12.1-kvm_save_mpstate-workaround.patch file -
+ fixes bug 340727.
+ Included patch file to fix issues with usb, bug 337988 , but won't use it
+ until upstream commits it to the git tree or gives an ok.
+ Dropped old version.
+
+*qemu-kvm-0.13.0 (28 Oct 2010)
+
+ 28 Oct 2010; Luca Barbato <lu_zero@gentoo.org> +qemu-kvm-0.13.0.ebuild:
+ New version, user targets support improved
+
+ 06 Sep 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-9999.ebuild:
+ [app-emulation/qemu-kvm-9999] Synced to latest qemu-kvm-0.12.5-r1.
+ Sorted IUSE flags.
+
+ 06 Sep 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-0.12.5-r1.ebuild, metadata.xml:
+ [app-emulation/qemu-kvm-0.12.5-r1] Synced the updates on qemu-kvm-9999.
+ Applied the gnutls to ssl use flag change - fixes bug 311627.
+
+ 06 Sep 2010; Luca Barbato <lu_zero@gentoo.org> qemu-kvm-0.12.5-r1.ebuild:
+ Fix typo in brltty vs brlapi
+
+ 06 Sep 2010; Patrick Lauer <patrick@gentoo.org> qemu-kvm-0.12.5-r1.ebuild:
+ Removing keywords from 0.12.5-r1 until it is fixed. See #336162
+
+ 06 Sep 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-9999.ebuild:
+ [app-emulation/qemu-kvm-9999] Updated ebuild to reflect changes in
+ upstream's build system.
+ Added use flags to enable jpeg and png compression on vnc.
+ Replaced gnu-tls with ssl use flag - bug 311627.
+ Added use flag to make accessbility support optional - bug 326491.
+ Currently it seems qemu-kvm won't build with -sasl - will check and
+ updated ebuild soon.
+
+ 06 Sep 2010; Luca Barbato <lu_zero@gentoo.org> qemu-kvm-0.12.5-r1.ebuild,
+ qemu-kvm-9999.ebuild:
+ Add dep for brltty, see #326491
+
+*qemu-kvm-0.12.5-r1 (26 Aug 2010)
+
+ 26 Aug 2010; Doug Goldstein <cardoe@gentoo.org>
+ +qemu-kvm-0.12.5-r1.ebuild:
+ Fix a few IDE issues related to the -drive option. fixes #332993
+
+ 12 Aug 2010; Tiziano Müller <dev-zero@gentoo.org>
+ qemu-kvm-0.11.1-r1.ebuild, qemu-kvm-0.12.3-r1.ebuild,
+ qemu-kvm-0.12.4-r1.ebuild, qemu-kvm-0.12.5.ebuild, qemu-kvm-9999.ebuild:
+ Disallow parallel installation with qemu-kvm-spice.
+
+ 05 Aug 2010; Doug Goldstein <cardoe@gentoo.org> -qemu-kvm-0.11.1.ebuild,
+ -qemu-kvm-0.12.3.ebuild, -qemu-kvm-0.12.4.ebuild,
+ -qemu-kvm-0.12.4-r2.ebuild, -qemu-kvm-0.12.4-r3.ebuild,
+ qemu-kvm-0.12.5.ebuild:
+ Remove older versions. Remove versions with broken epatch line. Fix epatch
+ line for future versions
+
+*qemu-kvm-0.12.5 (27 Jul 2010)
+
+ 27 Jul 2010; Doug Goldstein <cardoe@gentoo.org> +qemu-kvm-0.12.5.ebuild:
+ bump for upstream release
+
+*qemu-kvm-0.12.4-r3 (20 Jul 2010)
+
+ 20 Jul 2010; Doug Goldstein <cardoe@gentoo.org>
+ +qemu-kvm-0.12.4-r3.ebuild:
+ Missed an upstream patch for bug #325209 in the -r2 version
+
+*qemu-kvm-0.12.4-r2 (20 Jul 2010)
+
+ 20 Jul 2010; Doug Goldstein <cardoe@gentoo.org>
+ +qemu-kvm-0.12.4-r2.ebuild:
+ Pull in a lot of stable patches from upstream stable repos.
+
+ 30 Jun 2010; Harald van Dijk <truedfx@gentoo.org> qemu-kvm-0.11.1.ebuild,
+ qemu-kvm-0.11.1-r1.ebuild, qemu-kvm-0.12.3.ebuild,
+ qemu-kvm-0.12.3-r1.ebuild, qemu-kvm-0.12.4.ebuild,
+ qemu-kvm-0.12.4-r1.ebuild, qemu-kvm-9999.ebuild:
+ Fix quoting
+
+*qemu-kvm-0.12.4-r1 (15 Jun 2010)
+
+ 15 Jun 2010; Doug Goldstein <cardoe@gentoo.org>
+ +qemu-kvm-0.12.4-r1.ebuild,
+ +files/qemu-kvm-0.12.4-large-virtio-corruption.patch:
+ Fix issue with large virtio disks getting corrupted. bug #321005
+
+ 12 Jun 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-9999.ebuild:
+ [app-emulation/qemu-kvm-9999] Restricted targets to x86_64-softmmu after
+ upstream informed that's the only supported target for qemu-kvm.
+ Should fix bug 317205 and bug 318413.
+
+*qemu-kvm-0.12.4 (18 May 2010)
+
+ 18 May 2010; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ -qemu-kvm-0.12.2-r2.ebuild, +qemu-kvm-0.12.4.ebuild:
+ Version bump
+
+*qemu-kvm-0.12.3-r1 (03 Apr 2010)
+
+ 03 Apr 2010; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ +qemu-kvm-0.12.3-r1.ebuild,
+ +files/qemu-kvm-0.12.3-fix-crash-with-sdl.patch,
+ +files/qemu-kvm-0.12.3-include-madvise-defines.patch:
+ Include madvise defines, fixes bug 305785, include virtio-large-iovecs
+ patch, fixes bug 308451, include upstream fix for crash with sdl as
+ default sound option, fixes sound issues of bug 294269
+
+ 28 Mar 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-9999.ebuild, -files/qemu-kvm-9999-sysconfigdir.patch:
+ Remove the sysconfigdir patch from qemu-kvm-9999 as the fix was applied
+ upstream.
+ Fixes bug 310979 - thanks to Jeff Kowalczyk <jtk@yahoo.com>.
+
+ 19 Mar 2010; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ qemu-kvm-0.12.2-r2.ebuild, qemu-kvm-0.12.3.ebuild:
+ Also add warning and dont install useless files without
+ QEMU_SOFTMMU_TARGETS=x86_64
+
+ 19 Mar 2010; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ qemu-kvm-0.12.2-r2.ebuild, qemu-kvm-0.12.3.ebuild:
+ Die, when nothing from QEMU_SOFTMMU_TARGETS is defined, fixes bug 310243
+
+ 10 Mar 2010; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ qemu-kvm-0.12.2-r2.ebuild:
+ Also apply changes to 0.12.2-r2
+
+ 10 Mar 2010; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ -qemu-kvm-0.12.1.ebuild, -qemu-kvm-0.12.1.1.ebuild,
+ -qemu-kvm-0.12.1.2.ebuild, -qemu-kvm-0.12.2.ebuild,
+ -qemu-kvm-0.12.2-r1.ebuild, qemu-kvm-0.12.3.ebuild:
+ Add message, if no targets are defined (bug #298287), some cleanup, remove
+ older 0.12* versions
+
+ 07 Mar 2010; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-9999.ebuild, +files/qemu-kvm-9999-sysconfigdir.patch:
+ Added a patch to fix the support for --sysconfdir and updated
+ src_configure to prevent the default $prefix/etc.
+
+*qemu-kvm-0.12.3 (02 Mar 2010)
+
+ 02 Mar 2010; Doug Goldstein <cardoe@gentoo.org> +qemu-kvm-0.12.3.ebuild,
+ qemu-kvm-9999.ebuild, metadata.xml:
+ version bump. fix bug #304097 in the process
+
+*qemu-kvm-0.12.2-r2 (15 Feb 2010)
+
+ 15 Feb 2010; Doug Goldstein <cardoe@gentoo.org>
+ +qemu-kvm-0.12.2-r2.ebuild, qemu-kvm-9999.ebuild:
+ Correct building with the right compiler (tc-getBUILD_CC). Fix issue with
+ executable stacks by passing correct LDFLAGS option. Add support for
+ static builds. Fix issue with fdt being disabled, bug #297909
+
+ 12 Feb 2010; Doug Goldstein <cardoe@gentoo.org> qemu-kvm-0.11.1.ebuild,
+ qemu-kvm-0.11.1-r1.ebuild, qemu-kvm-0.12.1.ebuild,
+ qemu-kvm-0.12.1.1.ebuild, qemu-kvm-0.12.1.2.ebuild,
+ qemu-kvm-0.12.2.ebuild, qemu-kvm-0.12.2-r1.ebuild:
+ add missing depend on sys-apps/iproute2 and net-misc/bridge-utils for the
+ qemu/ifup script
+
+*qemu-kvm-0.11.1-r1 (08 Feb 2010)
+
+ 08 Feb 2010; Lance Albertson <ramereth@gentoo.org>
+ +qemu-kvm-0.11.1-r1.ebuild:
+ Add 'kvm' symlink so that other applications can still use it for
+ portability
+
+*qemu-kvm-0.12.2-r1 (03 Feb 2010)
+
+ 03 Feb 2010; Doug Goldstein <cardoe@gentoo.org>
+ +qemu-kvm-0.12.2-r1.ebuild,
+ +files/qemu-kvm-0.12.2-virtio-large-iovecs.patch:
+ upstream fix for virtio and certain use cases. Fixes issues people have
+ seen with Ubuntu 10.04 guests and other distros
+
+*qemu-kvm-0.12.2 (21 Jan 2010)
+
+ 21 Jan 2010; Doug Goldstein <cardoe@gentoo.org> +qemu-kvm-0.12.2.ebuild,
+ -qemu-kvm-0.12.2.build:
+ fix awesome typo
+
+ 20 Jan 2010; Doug Goldstein <cardoe@gentoo.org> +qemu-kvm-0.12.2.build:
+ version bump
+
+*qemu-kvm-0.12.1.2 (31 Dec 2009)
+
+ 31 Dec 2009; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-0.12.1.1.ebuild, +qemu-kvm-0.12.1.2.ebuild, qemu-kvm-9999.ebuild:
+ Version bump.
+
+*qemu-kvm-9999 (30 Dec 2009)
+
+ 30 Dec 2009; Jorge Manuel B. S. Vicetto <jmbsvicetto@gentoo.org>
+ qemu-kvm-0.12.1.1.ebuild, +qemu-kvm-9999.ebuild:
+ Added live qemu-kvm ebuild and sorted 0.12.1.1 deps.
+
+ 29 Dec 2009; Christian Faulhammer <fauli@gentoo.org> metadata.xml:
+ Write out acronym ftd, as requested on bug 298906 by Michael Orlitzky
+ <michael AT orlitzky DOT com>
+
+ 23 Dec 2009; Doug Goldstein <cardoe@gentoo.org> qemu-kvm-0.12.1.ebuild,
+ qemu-kvm-0.12.1.1.ebuild:
+ Xen backend support is broken in this release. Upstream is looking into
+ it.
+
+*qemu-kvm-0.12.1.1 (22 Dec 2009)
+
+ 22 Dec 2009; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ +qemu-kvm-0.12.1.1.ebuild:
+ Version bump
+
+ 21 Dec 2009; Doug Goldstein <cardoe@gentoo.org> qemu-kvm-0.12.1.ebuild:
+ Add Linux Async IO support. Add curl support for live migrations. Add back
+ support for fdt. Add support for KVM trace. Enable experimental support
+ for Xen backend. Use libuuid to generate proper uuid's. Fix compile failure
+ when missing paxctl. No longer require kernel to be present to build.
+
+*qemu-kvm-0.12.1 (21 Dec 2009)
+
+ 21 Dec 2009; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ -qemu-kvm-0.11.0.ebuild, +qemu-kvm-0.12.1.ebuild,
+ +files/qemu-kvm-0.12.1-kvm_save_mpstate-workaround.patch:
+ Version bump, drop old version
+
+ 18 Dec 2009; Thomas Sachau (Tommy[D]) <tommy@gentoo.org>
+ qemu-kvm-0.11.1.ebuild:
+ Comment out pie and stack-protector filtering, remove with next version,
+ if there are no complains
+
+ 15 Dec 2009; Doug Goldstein <cardoe@gentoo.org> metadata.xml:
+ change to qemu herd
+
+*qemu-kvm-0.11.1 (09 Dec 2009)
+
+ 09 Dec 2009; Luca Barbato <lu_zero@gentoo.org> +qemu-kvm-0.11.1.ebuild:
+ Version Bump
+
+ 22 Nov 2009; Doug Goldstein <cardoe@gentoo.org> qemu-kvm-0.11.0.ebuild:
+ fix bug #291007 and install the ifup and ifdown scripts in the correct
+ locations
+
+ 22 Nov 2009; Doug Goldstein <cardoe@gentoo.org> qemu-kvm-0.11.0.ebuild:
+ fix auto-magical depend against sasl
+
+*qemu-kvm-0.11.0 (22 Nov 2009)
+
+ 22 Nov 2009; Doug Goldstein <cardoe@gentoo.org> +qemu-kvm-0.11.0.ebuild,
+ +files/qemu-0.11.0-mips64-user-fix.patch, +metadata.xml:
+ add initial ebuild based on qemu-0.11.0
+
diff --git a/app-emulation/qemu-kvm/Manifest b/app-emulation/qemu-kvm/Manifest
new file mode 100644
index 0000000..52506b5
--- /dev/null
+++ b/app-emulation/qemu-kvm/Manifest
@@ -0,0 +1,10 @@
+AUX qemu-0.11.0-mips64-user-fix.patch 313 RMD160 db016e0a48990a435dd6cf6e807145b33ada4908 SHA1 2ea913b1bcd29734a6d4011794bdb4aa3599a184 SHA256 b4173fc177bd0d0ba67f5551a3512047a19a9b2c0a122f968e32fbd834848d2f
+AUX qemu-kvm 61 RMD160 83882e881a067065258f562ad1e60440666c85d3 SHA1 a965f19031e303d583bd541c9d8fff2214262e6b SHA256 211d51f0a7d3d2ba8c53016c75e2b483feadbb65e383b1eec81d9cebf6a22c29
+AUX qemu-kvm-0.12.3-fix-crash-with-sdl.patch 4003 RMD160 1e8965e94537e24d0903a7a096c91e35f7013118 SHA1 a6a36da9613d90d45148aa133392bd342b83d1cd SHA256 aeca9f133c021726c0e3ce2a58843ee12d592669143d0b75e46b8e301b5cf102
+AUX qemu-kvm-0.12.3-include-madvise-defines.patch 274 RMD160 2b2b454fabc3b5362c0479d581e5fb038e02aa97 SHA1 c34b51b9c0b5a69ab2ab7a8a64c804f7cbbbebf5 SHA256 0d33d22a853e9b1d19786c9ac53a515587a9753ff69a2f53e61c4764590e7821
+AUX qemu-kvm-0.13.0-redhat-patches.patch 352789 RMD160 8c64efeefd64ed0ac214a4ce494ddf93f41589a9 SHA1 11b027b11dc1707fbaae3b8552bee90fdc31c77d SHA256 1858b6f6afdec4e487af20c78f420403982d92a972624a937de978bb551e0251
+AUX qemu-kvm-guest-hang-on-usb-add.patch 3491 RMD160 7bc186c283b0eb220a47895f7cab50e191f1a3ea SHA1 00f36fd0197fa9d359e28a9ef2f56a1ee860fddf SHA256 d3068a419d69dbe44758830509fc13460d1497b14a5a10ffad910552da0c86b3
+DIST qemu-kvm-0.13.0.tar.gz 5153895 RMD160 7b8f4d8cdbb9730bb9d7fbf4cec165a8703696c4 SHA1 b8cfb8e8dbd403281a98a41f7d3eeaecc0aac8f1 SHA256 6db2600d7e3c1ed12feb6dc7596c23324bc2036a72f101cf580cef252ea9be53
+EBUILD qemu-kvm-0.13.0-r99.ebuild 8016 RMD160 31eddf30b690f05fd4d7bf61a04d62ab2ece2c71 SHA1 81015d90b4757689127eed0818e025a18c2d943d SHA256 50e8ef47050e48ef5e63f65a4adc80e8642ddffc37eab867a59d5f63ba44dc71
+MISC ChangeLog 11813 RMD160 a0d94b7b78f7f95155b76d710256abc04c0433d8 SHA1 60f4e896a64057a78431895df414a30691032118 SHA256 190cc1ff57d22594397b23014442ac048203703747a105d3909bf0379334990b
+MISC metadata.xml 1556 RMD160 8437c7ce85708abae6fa308da974a4bbf14e59fd SHA1 367e2957602139dc897a6379981537fb748a5f71 SHA256 a5675e07f50148cf3d8b76924d417fae0ed6d2d08a03133e4929659c98acd750
diff --git a/app-emulation/qemu-kvm/files/qemu-0.11.0-mips64-user-fix.patch b/app-emulation/qemu-kvm/files/qemu-0.11.0-mips64-user-fix.patch
new file mode 100644
index 0000000..c069f89
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/qemu-0.11.0-mips64-user-fix.patch
@@ -0,0 +1,11 @@
+--- qemu-0.11.0.orig/linux-user/main.c 2009-10-23 02:19:57.000000000 +0200
++++ qemu-0.11.0/linux-user/main.c 2009-10-23 02:47:09.000000000 +0200
+@@ -1469,6 +1469,8 @@
+
+ #ifdef TARGET_MIPS
+
++#define TARGET_QEMU_ESIGRETURN 255
++
+ #define MIPS_SYS(name, args) args,
+
+ static const uint8_t mips_syscall_args[] = {
diff --git a/app-emulation/qemu-kvm/files/qemu-kvm b/app-emulation/qemu-kvm/files/qemu-kvm
new file mode 100644
index 0000000..844147d
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/qemu-kvm
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/bin/qemu-system-x86_64 --enable-kvm "$@"
diff --git a/app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-fix-crash-with-sdl.patch b/app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-fix-crash-with-sdl.patch
new file mode 100644
index 0000000..909dead
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-fix-crash-with-sdl.patch
@@ -0,0 +1,145 @@
+From ff5414990645653bf43bf64adfc1ca77ffb9edcb Mon Sep 17 00:00:00 2001
+From: malc <av1474@comtv.ru>
+Date: Sun, 17 Jan 2010 00:25:29 +0300
+Subject: [PATCH] Revert "sdlaudio: make it suck less"
+
+This reverts commit 4839abe78fd466a3cf06faa7c362154afd5404f1.
+
+The commit was badly broken, Gentoo has sdl as the default driver,
+consequently 5 gentoo users have hit the breakage and were kind enough
+to report, so thank you:
+
+Claes Gyllenswrd
+vekin
+Chris
+
+But above all thanks to Toralf Foerster who actually provied enough
+information to pinpoint the breakage to sdlaudio.
+
+http://bugs.gentoo.org/show_bug.cgi?id=294269
+---
+ audio/sdlaudio.c | 80 +++++++++++++++++++++++++++++++++--------------------
+ 1 files changed, 50 insertions(+), 30 deletions(-)
+
+diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
+index aa39c33..8e7e5cb 100644
+--- a/audio/sdlaudio.c
++++ b/audio/sdlaudio.c
+@@ -41,8 +41,8 @@
+ typedef struct SDLVoiceOut {
+ HWVoiceOut hw;
+ int live;
++ int rpos;
+ int decr;
+- int pending;
+ } SDLVoiceOut;
+
+ static struct {
+@@ -225,10 +225,6 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
+ HWVoiceOut *hw = &sdl->hw;
+ int samples = len >> hw->info.shift;
+
+- if (sdl_lock (s, "sdl_callback")) {
+- return;
+- }
+-
+ if (s->exit) {
+ return;
+ }
+@@ -236,34 +232,49 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
+ while (samples) {
+ int to_mix, decr;
+
+- while (!sdl->pending) {
+- if (sdl_unlock (s, "sdl_callback")) {
+- return;
+- }
+-
+- sdl_wait (s, "sdl_callback");
+- if (s->exit) {
+- return;
+- }
+-
+- if (sdl_lock (s, "sdl_callback")) {
+- return;
+- }
+- sdl->pending += sdl->live;
+- sdl->live = 0;
++ /* dolog ("in callback samples=%d\n", samples); */
++ sdl_wait (s, "sdl_callback");
++ if (s->exit) {
++ return;
++ }
++
++ if (sdl_lock (s, "sdl_callback")) {
++ return;
++ }
++
++ if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) {
++ dolog ("sdl->live=%d hw->samples=%d\n",
++ sdl->live, hw->samples);
++ return;
++ }
++
++ if (!sdl->live) {
++ goto again;
+ }
+
+- to_mix = audio_MIN (samples, sdl->pending);
+- decr = audio_pcm_hw_clip_out (hw, buf, to_mix, 0);
+- buf += decr << hw->info.shift;
++ /* dolog ("in callback live=%d\n", live); */
++ to_mix = audio_MIN (samples, sdl->live);
++ decr = to_mix;
++ while (to_mix) {
++ int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
++ struct st_sample *src = hw->mix_buf + hw->rpos;
++
++ /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
++ hw->clip (buf, src, chunk);
++ sdl->rpos = (sdl->rpos + chunk) % hw->samples;
++ to_mix -= chunk;
++ buf += chunk << hw->info.shift;
++ }
+ samples -= decr;
++ sdl->live -= decr;
+ sdl->decr += decr;
+- sdl->pending -= decr;
+- }
+
+- if (sdl_unlock (s, "sdl_callback")) {
+- return;
++ again:
++ if (sdl_unlock (s, "sdl_callback")) {
++ return;
++ }
+ }
++ /* dolog ("done len=%d\n", len); */
+ }
+
+ static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
+@@ -281,9 +292,18 @@ static int sdl_run_out (HWVoiceOut *hw, int live)
+ return 0;
+ }
+
+- sdl->live = live;
+- decr = sdl->decr;
+- sdl->decr = 0;
++ if (sdl->decr > live) {
++ ldebug ("sdl->decr %d live %d sdl->live %d\n",
++ sdl->decr,
++ live,
++ sdl->live);
++ }
++
++ decr = audio_MIN (sdl->decr, live);
++ sdl->decr -= decr;
++
++ sdl->live = live - decr;
++ hw->rpos = sdl->rpos;
+
+ if (sdl->live > 0) {
+ sdl_unlock_and_post (s, "sdl_run_out");
+--
+1.7.0.4
+
diff --git a/app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-include-madvise-defines.patch b/app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-include-madvise-defines.patch
new file mode 100644
index 0000000..c50c717
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/qemu-kvm-0.12.3-include-madvise-defines.patch
@@ -0,0 +1,12 @@
+--- exec.c 2010-02-26 03:34:00.000000000 +0100
++++ exec.c.new 2010-04-03 15:31:53.000000000 +0200
+@@ -22,6 +22,9 @@
+ #else
+ #include <sys/types.h>
+ #include <sys/mman.h>
++#ifndef MADV_MERGEABLE
++#include <asm/mman.h>
++#endif
+ #endif
+ #include <stdlib.h>
+ #include <stdio.h>
diff --git a/app-emulation/qemu-kvm/files/qemu-kvm-0.13.0-redhat-patches.patch b/app-emulation/qemu-kvm/files/qemu-kvm-0.13.0-redhat-patches.patch
new file mode 100644
index 0000000..e63388d
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/qemu-kvm-0.13.0-redhat-patches.patch
@@ -0,0 +1,11648 @@
+diff -urN qemu-kvm-0.13.0.orig/audio/audio.c qemu-kvm-0.13.0/audio/audio.c
+--- qemu-kvm-0.13.0.orig/audio/audio.c 2011-02-09 11:01:45.805000327 +0200
++++ qemu-kvm-0.13.0/audio/audio.c 2011-02-09 11:08:02.779000327 +0200
+@@ -44,6 +44,9 @@
+ that we generate the list.
+ */
+ static struct audio_driver *drvtab[] = {
++#ifdef CONFIG_SPICE
++ &spice_audio_driver,
++#endif
+ CONFIG_AUDIO_DRIVERS
+ &no_audio_driver,
+ &wav_audio_driver
+diff -urN qemu-kvm-0.13.0.orig/audio/audio_int.h qemu-kvm-0.13.0/audio/audio_int.h
+--- qemu-kvm-0.13.0.orig/audio/audio_int.h 2011-02-09 11:01:45.806000327 +0200
++++ qemu-kvm-0.13.0/audio/audio_int.h 2011-02-09 11:08:02.780000327 +0200
+@@ -209,6 +209,7 @@
+ 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 mixeng_volume nominal_volume;
+
+diff -urN qemu-kvm-0.13.0.orig/audio/spiceaudio.c qemu-kvm-0.13.0/audio/spiceaudio.c
+--- qemu-kvm-0.13.0.orig/audio/spiceaudio.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/audio/spiceaudio.c 2011-02-09 11:08:02.781000327 +0200
+@@ -0,0 +1,312 @@
++#include "hw/hw.h"
++#include "qemu-timer.h"
++#include "qemu-spice.h"
++
++#define AUDIO_CAP "spice"
++#include "audio.h"
++#include "audio_int.h"
++
++#define LINE_IN_SAMPLES 1024
++#define LINE_OUT_SAMPLES 1024
++
++typedef struct SpiceVoiceOut {
++ HWVoiceOut hw;
++ SpicePlaybackInstance sin;
++ int64_t prev_ticks;
++ int active;
++ uint32_t *frame;
++ uint32_t *fpos;
++ uint32_t fsize;
++} SpiceVoiceOut;
++
++typedef struct SpiceVoiceIn {
++ HWVoiceIn hw;
++ SpiceRecordInstance sin;
++ int64_t prev_ticks;
++ int active;
++ uint32_t samples[LINE_IN_SAMPLES];
++} SpiceVoiceIn;
++
++static const SpicePlaybackInterface playback_sif = {
++ .base.type = SPICE_INTERFACE_PLAYBACK,
++ .base.description = "playback",
++ .base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR,
++};
++
++static const SpiceRecordInterface record_sif = {
++ .base.type = SPICE_INTERFACE_RECORD,
++ .base.description = "record",
++ .base.major_version = SPICE_INTERFACE_RECORD_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_RECORD_MINOR,
++};
++
++static void *spice_audio_init(void)
++{
++ if (!using_spice) {
++ return NULL;
++ }
++ return &spice_audio_init;
++}
++
++static void spice_audio_fini(void *opaque)
++{
++ /* nothing */
++}
++
++static int calculate_samples(struct audio_pcm_info *info, int64_t *old_ticks)
++{
++ int64_t now;
++ int64_t ticks;
++ int64_t bytes;
++ int samples;
++
++ now = qemu_get_clock (vm_clock);
++ ticks = now - *old_ticks;
++ *old_ticks = now;
++ bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
++ bytes = audio_MIN (bytes, INT_MAX);
++ samples = bytes >> info->shift;
++ return samples;
++}
++
++/* playback */
++
++static int line_out_init(HWVoiceOut *hw, struct audsettings *as)
++{
++ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
++ struct audsettings settings;
++
++ settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ;
++ settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN;
++ settings.fmt = AUD_FMT_S16;
++ settings.endianness = AUDIO_HOST_ENDIANNESS;
++
++ audio_pcm_init_info(&hw->info, &settings);
++ hw->samples = LINE_OUT_SAMPLES;
++ out->active = 0;
++
++ out->sin.base.sif = &playback_sif.base;
++ spice_server_add_interface(spice_server, &out->sin.base);
++ return 0;
++}
++
++static void line_out_fini(HWVoiceOut *hw)
++{
++ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
++
++ spice_server_remove_interface(&out->sin.base);
++}
++
++static int line_out_run(HWVoiceOut *hw, int live)
++{
++ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
++ int rpos, decr;
++ int samples;
++
++ if (!live) {
++ return 0;
++ }
++
++ decr = calculate_samples(&hw->info, &out->prev_ticks);
++ decr = audio_MIN(live, decr);
++
++ samples = decr;
++ rpos = hw->rpos;
++ while (samples) {
++ int left_till_end_samples = hw->samples - rpos;
++ int len = audio_MIN(samples, left_till_end_samples);
++
++ if (!out->frame) {
++ spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize);
++ out->fpos = out->frame;
++ }
++ if (out->frame) {
++ len = audio_MIN(len, out->fsize);
++ hw->clip(out->fpos, hw->mix_buf + rpos, len);
++ out->fsize -= len;
++ out->fpos += len;
++ if (out->fsize == 0) {
++ spice_server_playback_put_samples(&out->sin, out->frame);
++ out->frame = out->fpos = NULL;
++ }
++ }
++ rpos = (rpos + len) % hw->samples;
++ samples -= len;
++ }
++ hw->rpos = rpos;
++ return decr;
++}
++
++static int line_out_write(SWVoiceOut *sw, void *buf, int len)
++{
++ return audio_pcm_sw_write(sw, buf, len);
++}
++
++static int line_out_ctl(HWVoiceOut *hw, int cmd, ...)
++{
++ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
++
++ switch (cmd) {
++ case VOICE_ENABLE:
++ if (out->active) {
++ break;
++ }
++ out->active = 1;
++ out->prev_ticks = qemu_get_clock (vm_clock);
++ spice_server_playback_start(&out->sin);
++ break;
++ case VOICE_DISABLE:
++ if (!out->active) {
++ break;
++ }
++ out->active = 0;
++ if (out->frame) {
++ memset(out->fpos, 0, out->fsize << 2);
++ spice_server_playback_put_samples(&out->sin, out->frame);
++ out->frame = out->fpos = NULL;
++ }
++ spice_server_playback_stop(&out->sin);
++ break;
++ }
++ return 0;
++}
++
++/* record */
++
++static int line_in_init(HWVoiceIn *hw, struct audsettings *as)
++{
++ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
++ struct audsettings settings;
++
++ settings.freq = SPICE_INTERFACE_RECORD_FREQ;
++ settings.nchannels = SPICE_INTERFACE_RECORD_CHAN;
++ settings.fmt = AUD_FMT_S16;
++ settings.endianness = AUDIO_HOST_ENDIANNESS;
++
++ audio_pcm_init_info(&hw->info, &settings);
++ hw->samples = LINE_IN_SAMPLES;
++ in->active = 0;
++
++ in->sin.base.sif = &record_sif.base;
++ spice_server_add_interface(spice_server, &in->sin.base);
++ return 0;
++}
++
++static void line_in_fini(HWVoiceIn *hw)
++{
++ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
++
++ spice_server_remove_interface(&in->sin.base);
++}
++
++static int line_in_run(HWVoiceIn *hw)
++{
++ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
++ int num_samples;
++ int ready;
++ int len[2];
++ uint64_t delta_samp;
++ uint32_t *samples;
++
++ if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in(hw))) {
++ return 0;
++ }
++
++ delta_samp = calculate_samples(&hw->info, &in->prev_ticks);
++ num_samples = audio_MIN(num_samples, delta_samp);
++
++ ready = spice_server_record_get_samples(&in->sin, in->samples, num_samples);
++ samples = in->samples;
++ if (ready == 0) {
++ static uint32_t silence[LINE_IN_SAMPLES];
++ samples = silence;
++ ready = LINE_IN_SAMPLES;
++ }
++
++ num_samples = audio_MIN(ready, num_samples);
++
++ if (hw->wpos + num_samples > hw->samples) {
++ len[0] = hw->samples - hw->wpos;
++ len[1] = num_samples - len[0];
++ } else {
++ len[0] = num_samples;
++ len[1] = 0;
++ }
++
++ hw->conv(hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
++
++ if (len[1]) {
++ hw->conv(hw->conv_buf, samples + len[0], len[1],
++ &nominal_volume);
++ }
++
++ hw->wpos = (hw->wpos + num_samples) % hw->samples;
++
++ return num_samples;
++}
++
++static int line_in_read(SWVoiceIn *sw, void *buf, int size)
++{
++ return audio_pcm_sw_read(sw, buf, size);
++}
++
++static int line_in_ctl(HWVoiceIn *hw, int cmd, ...)
++{
++ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
++
++ switch (cmd) {
++ case VOICE_ENABLE:
++ if (in->active) {
++ break;
++ }
++ in->active = 1;
++ in->prev_ticks = qemu_get_clock (vm_clock);
++ spice_server_record_start(&in->sin);
++ break;
++ case VOICE_DISABLE:
++ if (!in->active) {
++ break;
++ }
++ in->active = 0;
++ spice_server_record_stop(&in->sin);
++ break;
++ }
++ return 0;
++}
++
++static struct audio_option audio_options[] = {
++ { /* end of list */ },
++};
++
++static struct audio_pcm_ops audio_callbacks = {
++ .init_out = line_out_init,
++ .fini_out = line_out_fini,
++ .run_out = line_out_run,
++ .write = line_out_write,
++ .ctl_out = line_out_ctl,
++
++ .init_in = line_in_init,
++ .fini_in = line_in_fini,
++ .run_in = line_in_run,
++ .read = line_in_read,
++ .ctl_in = line_in_ctl,
++};
++
++struct audio_driver spice_audio_driver = {
++ .name = "spice",
++ .descr = "spice audio driver",
++ .options = audio_options,
++ .init = spice_audio_init,
++ .fini = spice_audio_fini,
++ .pcm_ops = &audio_callbacks,
++ .max_voices_out = 1,
++ .max_voices_in = 1,
++ .voice_size_out = sizeof(SpiceVoiceOut),
++ .voice_size_in = sizeof(SpiceVoiceIn),
++};
++
++void qemu_spice_audio_init(void)
++{
++ spice_audio_driver.can_be_default = 1;
++}
+diff -urN qemu-kvm-0.13.0.orig/configure qemu-kvm-0.13.0/configure
+--- qemu-kvm-0.13.0.orig/configure 2011-02-09 11:01:45.652000327 +0200
++++ qemu-kvm-0.13.0/configure 2011-02-09 11:08:02.704000327 +0200
+@@ -16,15 +16,18 @@
+ TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
+
+ trap "rm -f $TMPC $TMPO $TMPE ; exit" EXIT INT QUIT TERM
++rm -f config.log
+
+ compile_object() {
+- $cc $QEMU_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null
++ echo $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log
++ $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log 2>&1
+ }
+
+ compile_prog() {
+ local_cflags="$1"
+ local_ldflags="$2"
+- $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags > /dev/null 2> /dev/null
++ echo $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log
++ $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log 2>&1
+ }
+
+ # check whether a command is available to this shell (may be either an
+@@ -328,6 +331,7 @@
+ check_utests="no"
+ user_pie="no"
+ zero_malloc=""
++spice=""
+
+ # OS specific
+ if check_define __linux__ ; then
+@@ -644,6 +648,10 @@
+ ;;
+ --enable-kvm-device-assignment) kvm_cap_device_assignment="yes"
+ ;;
++ --disable-spice) spice="no"
++ ;;
++ --enable-spice) spice="yes"
++ ;;
+ --enable-profiler) profiler="yes"
+ ;;
+ --enable-cocoa)
+@@ -930,6 +938,8 @@
+ echo " --disable-docs disable documentation build"
+ echo " --disable-vhost-net disable vhost-net acceleration support"
+ echo " --enable-vhost-net enable vhost-net acceleration support"
++echo " --disable-spice disable spice"
++echo " --enable-spice enable spice"
+ echo ""
+ echo "NOTE: The object files are built at the place where configure is launched"
+ exit 1
+@@ -2181,6 +2191,30 @@
+ gcc_attribute_warn_unused_result=yes
+ fi
+
++# spice probe
++if test "$spice" != "no" ; then
++ cat > $TMPC << EOF
++#include <spice.h>
++int main(void) { spice_server_new(); return 0; }
++EOF
++ spice_proto_ver=$($pkgconfig --modversion spice-protocol 2>/dev/null)
++ spice_server_ver=$($pkgconfig --modversion spice-server 2>/dev/null)
++ spice_cflags=$($pkgconfig --cflags spice-protocol spice-server 2>/dev/null)
++ spice_libs=$($pkgconfig --libs spice-protocol spice-server 2>/dev/null)
++ if compile_prog "$spice_cflags" "$spice_libs" ; then
++ spice="yes"
++ libs_softmmu="$libs_softmmu $spice_libs"
++ QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
++ else
++ if test "$spice" = "yes" ; then
++ feature_not_found "spice"
++ fi
++ spice="no"
++ fi
++fi
++
++##########################################
++
+ ##########################################
+ # check if we have fdatasync
+
+@@ -2326,6 +2360,7 @@
+ echo "fdatasync $fdatasync"
+ echo "uuid support $uuid"
+ echo "vhost-net support $vhost_net"
++echo "spice support $spice"
+
+ if test $sdl_too_old = "yes"; then
+ echo "-> Your SDL version is too old - please upgrade to have SDL support"
+@@ -2571,6 +2606,10 @@
+ echo "CONFIG_NO_CPU_EMULATION=y" >> $config_host_mak
+ fi
+
++if test "$spice" = "yes" ; then
++ echo "CONFIG_SPICE=y" >> $config_host_mak
++fi
++
+ # XXX: suppress that
+ if [ "$bsd" = "yes" ] ; then
+ echo "CONFIG_BSD=y" >> $config_host_mak
+diff -urN qemu-kvm-0.13.0.orig/hw/cirrus_vga.c qemu-kvm-0.13.0/hw/cirrus_vga.c
+--- qemu-kvm-0.13.0.orig/hw/cirrus_vga.c 2011-02-09 11:01:45.879000328 +0200
++++ qemu-kvm-0.13.0/hw/cirrus_vga.c 2011-02-09 11:08:02.752000327 +0200
+@@ -3206,6 +3206,10 @@
+ uint8_t *pci_conf = d->dev.config;
+ int device_id = CIRRUS_ID_CLGD5446;
+
++ if (dev->qdev.hotplugged) {
++ return -1;
++ }
++
+ /* setup VGA */
+ vga_common_init(&s->vga, VGA_RAM_SIZE);
+ cirrus_init_common(s, device_id, 1);
+diff -urN qemu-kvm-0.13.0.orig/hw/hw.h qemu-kvm-0.13.0/hw/hw.h
+--- qemu-kvm-0.13.0.orig/hw/hw.h 2011-02-09 11:01:45.837000328 +0200
++++ qemu-kvm-0.13.0/hw/hw.h 2011-02-09 11:08:02.763000327 +0200
+@@ -530,6 +530,17 @@
+ .start = (_start), \
+ }
+
++#define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _start, _field_size) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .field_exists = (_test), \
++ .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
++ .info = &vmstate_info_buffer, \
++ .flags = VMS_VBUFFER|VMS_POINTER, \
++ .offset = offsetof(_state, _field), \
++ .start = (_start), \
++}
++
+ #define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \
+ .name = (stringify(_field)), \
+ .version_id = (_version), \
+@@ -744,6 +755,9 @@
+ #define VMSTATE_PARTIAL_VBUFFER(_f, _s, _size) \
+ VMSTATE_VBUFFER(_f, _s, 0, NULL, 0, _size)
+
++#define VMSTATE_PARTIAL_VBUFFER_UINT32(_f, _s, _size) \
++ VMSTATE_VBUFFER_UINT32(_f, _s, 0, NULL, 0, _size)
++
+ #define VMSTATE_SUB_VBUFFER(_f, _s, _start, _size) \
+ VMSTATE_VBUFFER(_f, _s, 0, NULL, _start, _size)
+
+diff -urN qemu-kvm-0.13.0.orig/hw/hw.h.orig qemu-kvm-0.13.0/hw/hw.h.orig
+--- qemu-kvm-0.13.0.orig/hw/hw.h.orig 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/hw/hw.h.orig 2011-02-09 11:07:32.609000328 +0200
+@@ -0,0 +1,800 @@
++/* Declarations for use by hardware emulation. */
++#ifndef QEMU_HW_H
++#define QEMU_HW_H
++
++#include "qemu-common.h"
++
++#if defined(TARGET_PHYS_ADDR_BITS) && !defined(NEED_CPU_H)
++#include "cpu-common.h"
++#endif
++
++#include "ioport.h"
++#include "irq.h"
++
++/* VM Load/Save */
++
++/* This function writes a chunk of data to a file at the given position.
++ * The pos argument can be ignored if the file is only being used for
++ * streaming. The handler should try to write all of the data it can.
++ */
++typedef int (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
++ int64_t pos, int size);
++
++/* Read a chunk of data from a file at the given position. The pos argument
++ * can be ignored if the file is only be used for streaming. The number of
++ * bytes actually read should be returned.
++ */
++typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
++ int64_t pos, int size);
++
++/* Close a file and return an error code */
++typedef int (QEMUFileCloseFunc)(void *opaque);
++
++/* Called to determine if the file has exceeded it's bandwidth allocation. The
++ * bandwidth capping is a soft limit, not a hard limit.
++ */
++typedef int (QEMUFileRateLimit)(void *opaque);
++
++/* Called to change the current bandwidth allocation. This function must return
++ * the new actual bandwidth. It should be new_rate if everything goes ok, and
++ * the old rate otherwise
++ */
++typedef size_t (QEMUFileSetRateLimit)(void *opaque, size_t new_rate);
++typedef size_t (QEMUFileGetRateLimit)(void *opaque);
++
++QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
++ QEMUFileGetBufferFunc *get_buffer,
++ QEMUFileCloseFunc *close,
++ QEMUFileRateLimit *rate_limit,
++ QEMUFileSetRateLimit *set_rate_limit,
++ QEMUFileGetRateLimit *get_rate_limit);
++QEMUFile *qemu_fopen(const char *filename, const char *mode);
++QEMUFile *qemu_fdopen(int fd, const char *mode);
++QEMUFile *qemu_fopen_socket(int fd);
++QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
++QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
++int qemu_stdio_fd(QEMUFile *f);
++void qemu_fflush(QEMUFile *f);
++int qemu_fclose(QEMUFile *f);
++void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
++void qemu_put_byte(QEMUFile *f, int v);
++
++static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
++{
++ qemu_put_byte(f, (int)v);
++}
++
++#define qemu_put_sbyte qemu_put_byte
++
++void qemu_put_be16(QEMUFile *f, unsigned int v);
++void qemu_put_be32(QEMUFile *f, unsigned int v);
++void qemu_put_be64(QEMUFile *f, uint64_t v);
++int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
++int qemu_get_byte(QEMUFile *f);
++
++static inline unsigned int qemu_get_ubyte(QEMUFile *f)
++{
++ return (unsigned int)qemu_get_byte(f);
++}
++
++#define qemu_get_sbyte qemu_get_byte
++
++unsigned int qemu_get_be16(QEMUFile *f);
++unsigned int qemu_get_be32(QEMUFile *f);
++uint64_t qemu_get_be64(QEMUFile *f);
++int qemu_file_rate_limit(QEMUFile *f);
++size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate);
++size_t qemu_file_get_rate_limit(QEMUFile *f);
++int qemu_file_has_error(QEMUFile *f);
++void qemu_file_set_error(QEMUFile *f);
++
++/* Try to send any outstanding data. This function is useful when output is
++ * halted due to rate limiting or EAGAIN errors occur as it can be used to
++ * resume output. */
++void qemu_file_put_notify(QEMUFile *f);
++
++static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
++{
++ qemu_put_be64(f, *pv);
++}
++
++static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv)
++{
++ qemu_put_be32(f, *pv);
++}
++
++static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv)
++{
++ qemu_put_be16(f, *pv);
++}
++
++static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv)
++{
++ qemu_put_byte(f, *pv);
++}
++
++static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv)
++{
++ *pv = qemu_get_be64(f);
++}
++
++static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv)
++{
++ *pv = qemu_get_be32(f);
++}
++
++static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv)
++{
++ *pv = qemu_get_be16(f);
++}
++
++static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv)
++{
++ *pv = qemu_get_byte(f);
++}
++
++// Signed versions for type safety
++static inline void qemu_put_sbuffer(QEMUFile *f, const int8_t *buf, int size)
++{
++ qemu_put_buffer(f, (const uint8_t *)buf, size);
++}
++
++static inline void qemu_put_sbe16(QEMUFile *f, int v)
++{
++ qemu_put_be16(f, (unsigned int)v);
++}
++
++static inline void qemu_put_sbe32(QEMUFile *f, int v)
++{
++ qemu_put_be32(f, (unsigned int)v);
++}
++
++static inline void qemu_put_sbe64(QEMUFile *f, int64_t v)
++{
++ qemu_put_be64(f, (uint64_t)v);
++}
++
++static inline size_t qemu_get_sbuffer(QEMUFile *f, int8_t *buf, int size)
++{
++ return qemu_get_buffer(f, (uint8_t *)buf, size);
++}
++
++static inline int qemu_get_sbe16(QEMUFile *f)
++{
++ return (int)qemu_get_be16(f);
++}
++
++static inline int qemu_get_sbe32(QEMUFile *f)
++{
++ return (int)qemu_get_be32(f);
++}
++
++static inline int64_t qemu_get_sbe64(QEMUFile *f)
++{
++ return (int64_t)qemu_get_be64(f);
++}
++
++static inline void qemu_put_s8s(QEMUFile *f, const int8_t *pv)
++{
++ qemu_put_8s(f, (const uint8_t *)pv);
++}
++
++static inline void qemu_put_sbe16s(QEMUFile *f, const int16_t *pv)
++{
++ qemu_put_be16s(f, (const uint16_t *)pv);
++}
++
++static inline void qemu_put_sbe32s(QEMUFile *f, const int32_t *pv)
++{
++ qemu_put_be32s(f, (const uint32_t *)pv);
++}
++
++static inline void qemu_put_sbe64s(QEMUFile *f, const int64_t *pv)
++{
++ qemu_put_be64s(f, (const uint64_t *)pv);
++}
++
++static inline void qemu_get_s8s(QEMUFile *f, int8_t *pv)
++{
++ qemu_get_8s(f, (uint8_t *)pv);
++}
++
++static inline void qemu_get_sbe16s(QEMUFile *f, int16_t *pv)
++{
++ qemu_get_be16s(f, (uint16_t *)pv);
++}
++
++static inline void qemu_get_sbe32s(QEMUFile *f, int32_t *pv)
++{
++ qemu_get_be32s(f, (uint32_t *)pv);
++}
++
++static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv)
++{
++ qemu_get_be64s(f, (uint64_t *)pv);
++}
++
++#ifdef NEED_CPU_H
++#if TARGET_LONG_BITS == 64
++#define qemu_put_betl qemu_put_be64
++#define qemu_get_betl qemu_get_be64
++#define qemu_put_betls qemu_put_be64s
++#define qemu_get_betls qemu_get_be64s
++#define qemu_put_sbetl qemu_put_sbe64
++#define qemu_get_sbetl qemu_get_sbe64
++#define qemu_put_sbetls qemu_put_sbe64s
++#define qemu_get_sbetls qemu_get_sbe64s
++#else
++#define qemu_put_betl qemu_put_be32
++#define qemu_get_betl qemu_get_be32
++#define qemu_put_betls qemu_put_be32s
++#define qemu_get_betls qemu_get_be32s
++#define qemu_put_sbetl qemu_put_sbe32
++#define qemu_get_sbetl qemu_get_sbe32
++#define qemu_put_sbetls qemu_put_sbe32s
++#define qemu_get_sbetls qemu_get_sbe32s
++#endif
++#endif
++
++int64_t qemu_ftell(QEMUFile *f);
++int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence);
++
++typedef void SaveSetParamsHandler(int blk_enable, int shared, void * opaque);
++typedef void SaveStateHandler(QEMUFile *f, void *opaque);
++typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
++ void *opaque);
++typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
++
++int register_savevm(DeviceState *dev,
++ const char *idstr,
++ int instance_id,
++ int version_id,
++ SaveStateHandler *save_state,
++ LoadStateHandler *load_state,
++ void *opaque);
++
++int register_savevm_live(DeviceState *dev,
++ const char *idstr,
++ int instance_id,
++ int version_id,
++ SaveSetParamsHandler *set_params,
++ SaveLiveStateHandler *save_live_state,
++ SaveStateHandler *save_state,
++ LoadStateHandler *load_state,
++ void *opaque);
++
++void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
++void register_device_unmigratable(DeviceState *dev, const char *idstr,
++ void *opaque);
++
++typedef void QEMUResetHandler(void *opaque);
++
++void qemu_register_reset(QEMUResetHandler *func, void *opaque);
++void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
++
++/* handler to set the boot_device order for a specific type of QEMUMachine */
++/* return 0 if success */
++typedef int QEMUBootSetHandler(void *opaque, const char *boot_devices);
++void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque);
++int qemu_boot_set(const char *boot_devices);
++
++typedef struct VMStateInfo VMStateInfo;
++typedef struct VMStateDescription VMStateDescription;
++
++struct VMStateInfo {
++ const char *name;
++ int (*get)(QEMUFile *f, void *pv, size_t size);
++ void (*put)(QEMUFile *f, void *pv, size_t size);
++};
++
++enum VMStateFlags {
++ VMS_SINGLE = 0x001,
++ VMS_POINTER = 0x002,
++ VMS_ARRAY = 0x004,
++ VMS_STRUCT = 0x008,
++ VMS_VARRAY_INT32 = 0x010, /* Array with size in int32_t field*/
++ VMS_BUFFER = 0x020, /* static sized buffer */
++ VMS_ARRAY_OF_POINTER = 0x040,
++ VMS_VARRAY_UINT16 = 0x080, /* Array with size in uint16_t field */
++ VMS_VBUFFER = 0x100, /* Buffer with size in int32_t field */
++ VMS_MULTIPLY = 0x200, /* multiply "size" field by field_size */
++};
++
++typedef struct {
++ const char *name;
++ size_t offset;
++ size_t size;
++ size_t start;
++ int num;
++ size_t num_offset;
++ size_t size_offset;
++ const VMStateInfo *info;
++ enum VMStateFlags flags;
++ const VMStateDescription *vmsd;
++ int version_id;
++ bool (*field_exists)(void *opaque, int version_id);
++} VMStateField;
++
++typedef struct VMStateSubsection {
++ const VMStateDescription *vmsd;
++ bool (*needed)(void *opaque);
++} VMStateSubsection;
++
++struct VMStateDescription {
++ const char *name;
++ int version_id;
++ int minimum_version_id;
++ int minimum_version_id_old;
++ LoadStateHandler *load_state_old;
++ int (*pre_load)(void *opaque);
++ int (*post_load)(void *opaque, int version_id);
++ void (*pre_save)(void *opaque);
++ VMStateField *fields;
++ const VMStateSubsection *subsections;
++};
++
++extern const VMStateInfo vmstate_info_int8;
++extern const VMStateInfo vmstate_info_int16;
++extern const VMStateInfo vmstate_info_int32;
++extern const VMStateInfo vmstate_info_int64;
++
++extern const VMStateInfo vmstate_info_uint8_equal;
++extern const VMStateInfo vmstate_info_uint16_equal;
++extern const VMStateInfo vmstate_info_int32_equal;
++extern const VMStateInfo vmstate_info_int32_le;
++
++extern const VMStateInfo vmstate_info_uint8;
++extern const VMStateInfo vmstate_info_uint16;
++extern const VMStateInfo vmstate_info_uint32;
++extern const VMStateInfo vmstate_info_uint64;
++
++#ifdef __linux__
++extern const VMStateInfo vmstate_info_u64;
++#endif
++
++extern const VMStateInfo vmstate_info_timer;
++extern const VMStateInfo vmstate_info_ptimer;
++extern const VMStateInfo vmstate_info_buffer;
++extern const VMStateInfo vmstate_info_unused_buffer;
++
++#define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
++#define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0)
++
++#define vmstate_offset_value(_state, _field, _type) \
++ (offsetof(_state, _field) + \
++ type_check(_type, typeof_field(_state, _field)))
++
++#define vmstate_offset_pointer(_state, _field, _type) \
++ (offsetof(_state, _field) + \
++ type_check_pointer(_type, typeof_field(_state, _field)))
++
++#define vmstate_offset_array(_state, _field, _type, _num) \
++ (offsetof(_state, _field) + \
++ type_check_array(_type, typeof_field(_state, _field), _num))
++
++#define vmstate_offset_sub_array(_state, _field, _type, _start) \
++ (offsetof(_state, _field[_start]))
++
++#define vmstate_offset_buffer(_state, _field) \
++ vmstate_offset_array(_state, _field, uint8_t, \
++ sizeof(typeof_field(_state, _field)))
++
++#define VMSTATE_SINGLE_TEST(_field, _state, _test, _version, _info, _type) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .field_exists = (_test), \
++ .size = sizeof(_type), \
++ .info = &(_info), \
++ .flags = VMS_SINGLE, \
++ .offset = vmstate_offset_value(_state, _field, _type), \
++}
++
++#define VMSTATE_POINTER(_field, _state, _version, _info, _type) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .info = &(_info), \
++ .size = sizeof(_type), \
++ .flags = VMS_SINGLE|VMS_POINTER, \
++ .offset = vmstate_offset_value(_state, _field, _type), \
++}
++
++#define VMSTATE_ARRAY(_field, _state, _num, _version, _info, _type) {\
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .num = (_num), \
++ .info = &(_info), \
++ .size = sizeof(_type), \
++ .flags = VMS_ARRAY, \
++ .offset = vmstate_offset_array(_state, _field, _type, _num), \
++}
++
++#define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\
++ .name = (stringify(_field)), \
++ .field_exists = (_test), \
++ .num = (_num), \
++ .info = &(_info), \
++ .size = sizeof(_type), \
++ .flags = VMS_ARRAY, \
++ .offset = vmstate_offset_array(_state, _field, _type, _num),\
++}
++
++#define VMSTATE_SUB_ARRAY(_field, _state, _start, _num, _version, _info, _type) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .num = (_num), \
++ .info = &(_info), \
++ .size = sizeof(_type), \
++ .flags = VMS_ARRAY, \
++ .offset = vmstate_offset_sub_array(_state, _field, _type, _start), \
++}
++
++#define VMSTATE_VARRAY_INT32(_field, _state, _field_num, _version, _info, _type) {\
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
++ .info = &(_info), \
++ .size = sizeof(_type), \
++ .flags = VMS_VARRAY_INT32|VMS_POINTER, \
++ .offset = vmstate_offset_pointer(_state, _field, _type), \
++}
++
++#define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
++ .info = &(_info), \
++ .size = sizeof(_type), \
++ .flags = VMS_VARRAY_UINT16, \
++ .offset = offsetof(_state, _field), \
++}
++
++#define VMSTATE_STRUCT_TEST(_field, _state, _test, _version, _vmsd, _type) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .field_exists = (_test), \
++ .vmsd = &(_vmsd), \
++ .size = sizeof(_type), \
++ .flags = VMS_STRUCT, \
++ .offset = vmstate_offset_value(_state, _field, _type), \
++}
++
++#define VMSTATE_STRUCT_POINTER_TEST(_field, _state, _test, _vmsd, _type) { \
++ .name = (stringify(_field)), \
++ .field_exists = (_test), \
++ .vmsd = &(_vmsd), \
++ .size = sizeof(_type), \
++ .flags = VMS_STRUCT|VMS_POINTER, \
++ .offset = vmstate_offset_value(_state, _field, _type), \
++}
++
++#define VMSTATE_ARRAY_OF_POINTER(_field, _state, _num, _version, _info, _type) {\
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .num = (_num), \
++ .info = &(_info), \
++ .size = sizeof(_type), \
++ .flags = VMS_ARRAY|VMS_ARRAY_OF_POINTER, \
++ .offset = vmstate_offset_array(_state, _field, _type, _num), \
++}
++
++#define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) { \
++ .name = (stringify(_field)), \
++ .num = (_num), \
++ .version_id = (_version), \
++ .vmsd = &(_vmsd), \
++ .size = sizeof(_type), \
++ .flags = VMS_STRUCT|VMS_ARRAY, \
++ .offset = vmstate_offset_array(_state, _field, _type, _num), \
++}
++
++#define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
++ .name = (stringify(_field)), \
++ .num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \
++ .version_id = (_version), \
++ .vmsd = &(_vmsd), \
++ .size = sizeof(_type), \
++ .flags = VMS_STRUCT|VMS_VARRAY_INT32, \
++ .offset = offsetof(_state, _field), \
++}
++
++#define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .field_exists = (_test), \
++ .size = (_size - _start), \
++ .info = &vmstate_info_buffer, \
++ .flags = VMS_BUFFER, \
++ .offset = vmstate_offset_buffer(_state, _field) + _start, \
++}
++
++#define VMSTATE_BUFFER_MULTIPLY(_field, _state, _version, _test, _start, _field_size, _multiply) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .field_exists = (_test), \
++ .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
++ .size = (_multiply), \
++ .info = &vmstate_info_buffer, \
++ .flags = VMS_VBUFFER|VMS_MULTIPLY, \
++ .offset = offsetof(_state, _field), \
++ .start = (_start), \
++}
++
++#define VMSTATE_VBUFFER(_field, _state, _version, _test, _start, _field_size) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .field_exists = (_test), \
++ .size_offset = vmstate_offset_value(_state, _field_size, int32_t),\
++ .info = &vmstate_info_buffer, \
++ .flags = VMS_VBUFFER|VMS_POINTER, \
++ .offset = offsetof(_state, _field), \
++ .start = (_start), \
++}
++
++#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \
++ .name = (stringify(_field)), \
++ .version_id = (_version), \
++ .size = (_size), \
++ .info = &(_info), \
++ .flags = VMS_BUFFER, \
++ .offset = offsetof(_state, _field), \
++}
++
++#define VMSTATE_UNUSED_BUFFER(_test, _version, _size) { \
++ .name = "unused", \
++ .field_exists = (_test), \
++ .version_id = (_version), \
++ .size = (_size), \
++ .info = &vmstate_info_unused_buffer, \
++ .flags = VMS_BUFFER, \
++}
++extern const VMStateDescription vmstate_pci_device;
++
++#define VMSTATE_PCI_DEVICE(_field, _state) { \
++ .name = (stringify(_field)), \
++ .size = sizeof(PCIDevice), \
++ .vmsd = &vmstate_pci_device, \
++ .flags = VMS_STRUCT, \
++ .offset = vmstate_offset_value(_state, _field, PCIDevice), \
++}
++
++extern const VMStateDescription vmstate_pcie_device;
++
++#define VMSTATE_PCIE_DEVICE(_field, _state) { \
++ .name = (stringify(_field)), \
++ .version_id = 2, \
++ .size = sizeof(PCIDevice), \
++ .vmsd = &vmstate_pcie_device, \
++ .flags = VMS_STRUCT, \
++ .offset = vmstate_offset_value(_state, _field, PCIDevice), \
++}
++
++extern const VMStateDescription vmstate_i2c_slave;
++
++#define VMSTATE_I2C_SLAVE(_field, _state) { \
++ .name = (stringify(_field)), \
++ .size = sizeof(i2c_slave), \
++ .vmsd = &vmstate_i2c_slave, \
++ .flags = VMS_STRUCT, \
++ .offset = vmstate_offset_value(_state, _field, i2c_slave), \
++}
++
++#define vmstate_offset_macaddr(_state, _field) \
++ vmstate_offset_array(_state, _field.a, uint8_t, \
++ sizeof(typeof_field(_state, _field)))
++
++#define VMSTATE_MACADDR(_field, _state) { \
++ .name = (stringify(_field)), \
++ .size = sizeof(MACAddr), \
++ .info = &vmstate_info_buffer, \
++ .flags = VMS_BUFFER, \
++ .offset = vmstate_offset_macaddr(_state, _field), \
++}
++
++/* _f : field name
++ _f_n : num of elements field_name
++ _n : num of elements
++ _s : struct state name
++ _v : version
++*/
++
++#define VMSTATE_SINGLE(_field, _state, _version, _info, _type) \
++ VMSTATE_SINGLE_TEST(_field, _state, NULL, _version, _info, _type)
++
++#define VMSTATE_STRUCT(_field, _state, _version, _vmsd, _type) \
++ VMSTATE_STRUCT_TEST(_field, _state, NULL, _version, _vmsd, _type)
++
++#define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type) \
++ VMSTATE_STRUCT_POINTER_TEST(_field, _state, NULL, _vmsd, _type)
++
++#define VMSTATE_INT8_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int8, int8_t)
++#define VMSTATE_INT16_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int16, int16_t)
++#define VMSTATE_INT32_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int32, int32_t)
++#define VMSTATE_INT64_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int64, int64_t)
++
++#define VMSTATE_UINT8_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint8, uint8_t)
++#define VMSTATE_UINT16_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16, uint16_t)
++#define VMSTATE_UINT32_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32, uint32_t)
++#define VMSTATE_UINT64_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, uint64_t)
++
++#define VMSTATE_INT8(_f, _s) \
++ VMSTATE_INT8_V(_f, _s, 0)
++#define VMSTATE_INT16(_f, _s) \
++ VMSTATE_INT16_V(_f, _s, 0)
++#define VMSTATE_INT32(_f, _s) \
++ VMSTATE_INT32_V(_f, _s, 0)
++#define VMSTATE_INT64(_f, _s) \
++ VMSTATE_INT64_V(_f, _s, 0)
++
++#define VMSTATE_UINT8(_f, _s) \
++ VMSTATE_UINT8_V(_f, _s, 0)
++#define VMSTATE_UINT16(_f, _s) \
++ VMSTATE_UINT16_V(_f, _s, 0)
++#define VMSTATE_UINT32(_f, _s) \
++ VMSTATE_UINT32_V(_f, _s, 0)
++#define VMSTATE_UINT64(_f, _s) \
++ VMSTATE_UINT64_V(_f, _s, 0)
++
++/* This is needed because on linux __u64 is unsigned long long
++ and on glibc uint64_t is unsigned long on 64 bits */
++#ifdef __linux__
++#define VMSTATE_U64_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_u64, __u64)
++#define VMSTATE_U64(_f, _s) \
++ VMSTATE_U64_V(_f, _s, 0)
++#endif
++
++#define VMSTATE_UINT8_EQUAL(_f, _s) \
++ VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint8_equal, uint8_t)
++
++#define VMSTATE_UINT16_EQUAL(_f, _s) \
++ VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint16_equal, uint16_t)
++
++#define VMSTATE_UINT16_EQUAL_V(_f, _s, _v) \
++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16_equal, uint16_t)
++
++#define VMSTATE_INT32_EQUAL(_f, _s) \
++ VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_equal, int32_t)
++
++#define VMSTATE_INT32_LE(_f, _s) \
++ VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
++
++#define VMSTATE_UINT16_TEST(_f, _s, _t) \
++ VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint16, uint16_t)
++
++#define VMSTATE_UINT32_TEST(_f, _s, _t) \
++ VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint32, uint32_t)
++
++#define VMSTATE_TIMER_V(_f, _s, _v) \
++ VMSTATE_POINTER(_f, _s, _v, vmstate_info_timer, QEMUTimer *)
++
++#define VMSTATE_TIMER(_f, _s) \
++ VMSTATE_TIMER_V(_f, _s, 0)
++
++#define VMSTATE_TIMER_ARRAY(_f, _s, _n) \
++ VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *)
++
++#define VMSTATE_PTIMER_V(_f, _s, _v) \
++ VMSTATE_POINTER(_f, _s, _v, vmstate_info_ptimer, ptimer_state *)
++
++#define VMSTATE_PTIMER(_f, _s) \
++ VMSTATE_PTIMER_V(_f, _s, 0)
++
++#define VMSTATE_UINT16_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint16, uint16_t)
++
++#define VMSTATE_UINT16_ARRAY(_f, _s, _n) \
++ VMSTATE_UINT16_ARRAY_V(_f, _s, _n, 0)
++
++#define VMSTATE_UINT8_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint8, uint8_t)
++
++#define VMSTATE_UINT8_ARRAY(_f, _s, _n) \
++ VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0)
++
++#define VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint32, uint32_t)
++
++#define VMSTATE_UINT32_ARRAY(_f, _s, _n) \
++ VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0)
++
++#define VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint64, uint64_t)
++
++#define VMSTATE_UINT64_ARRAY(_f, _s, _n) \
++ VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0)
++
++#define VMSTATE_INT16_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int16, int16_t)
++
++#define VMSTATE_INT16_ARRAY(_f, _s, _n) \
++ VMSTATE_INT16_ARRAY_V(_f, _s, _n, 0)
++
++#define VMSTATE_INT32_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int32, int32_t)
++
++#define VMSTATE_INT32_ARRAY(_f, _s, _n) \
++ VMSTATE_INT32_ARRAY_V(_f, _s, _n, 0)
++
++#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num) \
++ VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t)
++
++#define VMSTATE_UINT32_ARRAY(_f, _s, _n) \
++ VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0)
++
++#define VMSTATE_BUFFER_V(_f, _s, _v) \
++ VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f)))
++
++#define VMSTATE_BUFFER(_f, _s) \
++ VMSTATE_BUFFER_V(_f, _s, 0)
++
++#define VMSTATE_PARTIAL_BUFFER(_f, _s, _size) \
++ VMSTATE_STATIC_BUFFER(_f, _s, 0, NULL, 0, _size)
++
++#define VMSTATE_BUFFER_START_MIDDLE(_f, _s, _start) \
++ VMSTATE_STATIC_BUFFER(_f, _s, 0, NULL, _start, sizeof(typeof_field(_s, _f)))
++
++#define VMSTATE_PARTIAL_VBUFFER(_f, _s, _size) \
++ VMSTATE_VBUFFER(_f, _s, 0, NULL, 0, _size)
++
++#define VMSTATE_SUB_VBUFFER(_f, _s, _start, _size) \
++ VMSTATE_VBUFFER(_f, _s, 0, NULL, _start, _size)
++
++#define VMSTATE_BUFFER_TEST(_f, _s, _test) \
++ VMSTATE_STATIC_BUFFER(_f, _s, 0, _test, 0, sizeof(typeof_field(_s, _f)))
++
++#define VMSTATE_BUFFER_UNSAFE(_field, _state, _version, _size) \
++ VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, vmstate_info_buffer, _size)
++
++#define VMSTATE_UNUSED_V(_v, _size) \
++ VMSTATE_UNUSED_BUFFER(NULL, _v, _size)
++
++#define VMSTATE_UNUSED(_size) \
++ VMSTATE_UNUSED_V(0, _size)
++
++#define VMSTATE_UNUSED_TEST(_test, _size) \
++ VMSTATE_UNUSED_BUFFER(_test, 0, _size)
++
++#ifdef NEED_CPU_H
++#if TARGET_LONG_BITS == 64
++#define VMSTATE_UINTTL_V(_f, _s, _v) \
++ VMSTATE_UINT64_V(_f, _s, _v)
++#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v)
++#else
++#define VMSTATE_UINTTL_V(_f, _s, _v) \
++ VMSTATE_UINT32_V(_f, _s, _v)
++#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
++ VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)
++#endif
++#define VMSTATE_UINTTL(_f, _s) \
++ VMSTATE_UINTTL_V(_f, _s, 0)
++#define VMSTATE_UINTTL_ARRAY(_f, _s, _n) \
++ VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0)
++
++#endif
++
++#define VMSTATE_END_OF_LIST() \
++ {}
++
++extern int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
++ void *opaque, int version_id);
++extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
++ void *opaque);
++extern int vmstate_register(DeviceState *dev, int instance_id,
++ const VMStateDescription *vmsd, void *base);
++extern int vmstate_register_with_alias_id(DeviceState *dev,
++ int instance_id,
++ const VMStateDescription *vmsd,
++ void *base, int alias_id,
++ int required_for_version);
++void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
++ void *opaque);
++#endif
+diff -urN qemu-kvm-0.13.0.orig/hw/msix.c qemu-kvm-0.13.0/hw/msix.c
+--- qemu-kvm-0.13.0.orig/hw/msix.c 2011-02-09 11:01:45.882000328 +0200
++++ qemu-kvm-0.13.0/hw/msix.c 2011-02-09 11:08:02.908000327 +0200
+@@ -300,10 +300,8 @@
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+ kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
+ }
+- if (was_masked != msix_is_masked(dev, vector) &&
+- dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
++ if (was_masked != msix_is_masked(dev, vector) && dev->msix_mask_notifier) {
+ int r = dev->msix_mask_notifier(dev, vector,
+- dev->msix_mask_notifier_opaque[vector],
+ msix_is_masked(dev, vector));
+ assert(r >= 0);
+ }
+@@ -351,9 +349,8 @@
+ int was_masked = msix_is_masked(dev, vector);
+ dev->msix_table_page[offset] |= MSIX_VECTOR_MASK;
+ if (was_masked != msix_is_masked(dev, vector) &&
+- dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
++ dev->msix_mask_notifier) {
+ r = dev->msix_mask_notifier(dev, vector,
+- dev->msix_mask_notifier_opaque[vector],
+ msix_is_masked(dev, vector));
+ assert(r >= 0);
+ }
+@@ -379,8 +376,6 @@
+ sizeof *dev->msix_irq_entries);
+ }
+ #endif
+- dev->msix_mask_notifier_opaque =
+- qemu_mallocz(nentries * sizeof *dev->msix_mask_notifier_opaque);
+ dev->msix_mask_notifier = NULL;
+ dev->msix_entry_used = qemu_mallocz(MSIX_MAX_ENTRIES *
+ sizeof *dev->msix_entry_used);
+@@ -444,8 +439,6 @@
+ dev->msix_entry_used = NULL;
+ qemu_free(dev->msix_irq_entries);
+ dev->msix_irq_entries = NULL;
+- qemu_free(dev->msix_mask_notifier_opaque);
+- dev->msix_mask_notifier_opaque = NULL;
+ dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
+ return 0;
+ }
+@@ -590,46 +583,65 @@
+ msix_free_irq_entries(dev);
+ }
+
+-int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque)
++/* Invoke the notifier if vector entry is used and unmasked. */
++static int msix_notify_if_unmasked(PCIDevice *dev, unsigned vector, int masked)
+ {
+- int r = 0;
+- if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
++ assert(dev->msix_mask_notifier);
++ if (!dev->msix_entry_used[vector] || msix_is_masked(dev, vector)) {
+ return 0;
++ }
++ return dev->msix_mask_notifier(dev, vector, masked);
++}
+
+- assert(dev->msix_mask_notifier);
+- assert(opaque);
+- assert(!dev->msix_mask_notifier_opaque[vector]);
++static int msix_set_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
++{
++ /* Notifier has been set. Invoke it on unmasked vectors. */
++ return msix_notify_if_unmasked(dev, vector, 0);
++}
++
++static int msix_unset_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
++{
++ /* Notifier will be unset. Invoke it to mask unmasked entries. */
++ return msix_notify_if_unmasked(dev, vector, 1);
++}
+
+- /* Unmask the new notifier unless vector is masked. */
+- if (!msix_is_masked(dev, vector)) {
+- r = dev->msix_mask_notifier(dev, vector, opaque, false);
++int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func f)
++{
++ int r, n;
++ assert(!dev->msix_mask_notifier);
++ dev->msix_mask_notifier = f;
++ for (n = 0; n < dev->msix_entries_nr; ++n) {
++ r = msix_set_mask_notifier_for_vector(dev, n);
+ if (r < 0) {
+- return r;
++ goto undo;
+ }
+ }
+- dev->msix_mask_notifier_opaque[vector] = opaque;
++ return 0;
++
++undo:
++ while (--n >= 0) {
++ msix_unset_mask_notifier_for_vector(dev, n);
++ }
++ dev->msix_mask_notifier = NULL;
+ return r;
+ }
+
+-int msix_unset_mask_notifier(PCIDevice *dev, unsigned vector)
++int msix_unset_mask_notifier(PCIDevice *dev)
+ {
+- int r = 0;
+- void *opaque;
+- if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
+- return 0;
+-
+- opaque = dev->msix_mask_notifier_opaque[vector];
+-
++ int r, n;
+ assert(dev->msix_mask_notifier);
+- assert(opaque);
+-
+- /* Mask the old notifier unless it is already masked. */
+- if (!msix_is_masked(dev, vector)) {
+- r = dev->msix_mask_notifier(dev, vector, opaque, true);
++ for (n = 0; n < dev->msix_entries_nr; ++n) {
++ r = msix_unset_mask_notifier_for_vector(dev, n);
+ if (r < 0) {
+- return r;
++ goto undo;
+ }
+ }
+- dev->msix_mask_notifier_opaque[vector] = NULL;
++ dev->msix_mask_notifier = NULL;
++ return 0;
++
++undo:
++ while (--n >= 0) {
++ msix_set_mask_notifier_for_vector(dev, n);
++ }
+ return r;
+ }
+diff -urN qemu-kvm-0.13.0.orig/hw/msix.h qemu-kvm-0.13.0/hw/msix.h
+--- qemu-kvm-0.13.0.orig/hw/msix.h 2011-02-09 11:01:45.839000328 +0200
++++ qemu-kvm-0.13.0/hw/msix.h 2011-02-09 11:08:02.908000327 +0200
+@@ -33,6 +33,6 @@
+
+ extern int msix_supported;
+
+-int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque);
+-int msix_unset_mask_notifier(PCIDevice *dev, unsigned vector);
++int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func);
++int msix_unset_mask_notifier(PCIDevice *dev);
+ #endif
+diff -urN qemu-kvm-0.13.0.orig/hw/pc.c qemu-kvm-0.13.0/hw/pc.c
+--- qemu-kvm-0.13.0.orig/hw/pc.c 2011-02-09 11:01:45.874000328 +0200
++++ qemu-kvm-0.13.0/hw/pc.c 2011-02-09 11:08:02.765000327 +0200
+@@ -41,6 +41,7 @@
+ #include "sysemu.h"
+ #include "device-assignment.h"
+ #include "kvm.h"
++#include "qemu-spice.h"
+
+ /* output Bochs bios info messages */
+ //#define DEBUG_BIOS
+@@ -1002,6 +1003,13 @@
+ pci_vmsvga_init(pci_bus);
+ else
+ fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
++#ifdef CONFIG_SPICE
++ } else if (qxl_enabled) {
++ if (pci_bus)
++ pci_create_simple(pci_bus, -1, "qxl");
++ else
++ fprintf(stderr, "%s: qxl: no PCI bus\n", __FUNCTION__);
++#endif
+ } else if (std_vga_enabled) {
+ if (pci_bus) {
+ pci_vga_init(pci_bus, 0, 0);
+diff -urN qemu-kvm-0.13.0.orig/hw/pci.h qemu-kvm-0.13.0/hw/pci.h
+--- qemu-kvm-0.13.0.orig/hw/pci.h 2011-02-09 11:01:45.843000328 +0200
++++ qemu-kvm-0.13.0/hw/pci.h 2011-02-09 11:08:02.909000327 +0200
+@@ -131,7 +131,7 @@
+ #define PCI_CAPABILITY_CONFIG_MSIX_LENGTH 0x10
+
+ typedef int (*msix_mask_notifier_func)(PCIDevice *, unsigned vector,
+- void *opaque, int masked);
++ int masked);
+
+ struct PCIDevice {
+ DeviceState qdev;
+@@ -198,7 +198,6 @@
+
+ struct kvm_irq_routing_entry *msix_irq_entries;
+
+- void **msix_mask_notifier_opaque;
+ msix_mask_notifier_func msix_mask_notifier;
+
+ /* Device capability configuration space */
+diff -urN qemu-kvm-0.13.0.orig/hw/qxl.c qemu-kvm-0.13.0/hw/qxl.c
+--- qemu-kvm-0.13.0.orig/hw/qxl.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/hw/qxl.c 2011-02-09 11:08:02.900000327 +0200
+@@ -0,0 +1,1470 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <string.h>
++#include <pthread.h>
++
++#include "qemu-common.h"
++#include "qemu-timer.h"
++#include "qemu-queue.h"
++#include "monitor.h"
++#include "sysemu.h"
++
++#include "qxl.h"
++
++#undef SPICE_RING_PROD_ITEM
++#define SPICE_RING_PROD_ITEM(r, ret) { \
++ typeof(r) start = r; \
++ typeof(r) end = r + 1; \
++ uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
++ typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
++ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
++ abort(); \
++ } \
++ ret = &m_item->el; \
++ }
++
++#undef SPICE_RING_CONS_ITEM
++#define SPICE_RING_CONS_ITEM(r, ret) { \
++ typeof(r) start = r; \
++ typeof(r) end = r + 1; \
++ uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
++ typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
++ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
++ abort(); \
++ } \
++ ret = &m_item->el; \
++ }
++
++#undef ALIGN
++#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
++
++#define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9"
++
++#define QXL_MODE(_x, _y, _b, _o) \
++ { .x_res = _x, \
++ .y_res = _y, \
++ .bits = _b, \
++ .stride = (_x) * (_b) / 8, \
++ .x_mili = PIXEL_SIZE * (_x), \
++ .y_mili = PIXEL_SIZE * (_y), \
++ .orientation = _o, \
++ }
++
++#define QXL_MODE_16_32(x_res, y_res, orientation) \
++ QXL_MODE(x_res, y_res, 16, orientation), \
++ QXL_MODE(x_res, y_res, 32, orientation)
++
++#define QXL_MODE_EX(x_res, y_res) \
++ QXL_MODE_16_32(x_res, y_res, 0), \
++ QXL_MODE_16_32(y_res, x_res, 1), \
++ QXL_MODE_16_32(x_res, y_res, 2), \
++ QXL_MODE_16_32(y_res, x_res, 3)
++
++static QXLMode qxl_modes[] = {
++ QXL_MODE_EX(640, 480),
++ QXL_MODE_EX(800, 480),
++ QXL_MODE_EX(800, 600),
++ QXL_MODE_EX(832, 624),
++ QXL_MODE_EX(1024, 768),
++ QXL_MODE_EX(1152, 864),
++ QXL_MODE_EX(1152, 870),
++ QXL_MODE_EX(1280, 720),
++ QXL_MODE_EX(1280, 768),
++ QXL_MODE_EX(1280, 800),
++ QXL_MODE_EX(1280, 960),
++ QXL_MODE_EX(1280, 1024),
++ QXL_MODE_EX(1360, 768),
++ QXL_MODE_EX(1366, 768),
++ QXL_MODE_EX(1400, 1050),
++ QXL_MODE_EX(1440, 900),
++ QXL_MODE_EX(1600, 900),
++ QXL_MODE_EX(1600, 1200),
++ QXL_MODE_EX(1680, 1050),
++ QXL_MODE_EX(1920, 1080),
++#ifdef QXL_HIRES_MODES
++ QXL_MODE_EX(1920, 1200),
++ QXL_MODE_EX(1920, 1440),
++ QXL_MODE_EX(2048, 1536),
++ QXL_MODE_EX(2560, 1600),
++ QXL_MODE_EX(2560, 2048),
++ QXL_MODE_EX(2800, 2100),
++ QXL_MODE_EX(3200, 2400),
++#endif
++};
++
++static int device_id = 0;
++static PCIQXLDevice *qxl0;
++
++static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
++static void qxl_destroy_primary(PCIQXLDevice *d);
++static void qxl_reset_memslots(PCIQXLDevice *d);
++static void qxl_reset_surfaces(PCIQXLDevice *d);
++static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
++
++static inline uint32_t msb_mask(uint32_t val)
++{
++ uint32_t mask;
++
++ do {
++ mask = ~(val - 1) & val;
++ val &= ~mask;
++ } while (mask < val);
++
++ return mask;
++}
++
++static ram_addr_t qxl_rom_size(void)
++{
++ uint32_t rom_size = sizeof(QXLRom) + sizeof(QXLModes) + sizeof(qxl_modes);
++ rom_size = MAX(rom_size, TARGET_PAGE_SIZE);
++ rom_size = msb_mask(rom_size * 2 - 1);
++ return rom_size;
++}
++
++static void init_qxl_rom(PCIQXLDevice *d)
++{
++ QXLRom *rom = qemu_get_ram_ptr(d->rom_offset);
++ QXLModes *modes = (QXLModes *)(rom + 1);
++ uint32_t ram_header_size;
++ uint32_t surface0_area_size;
++ uint32_t num_pages;
++ uint32_t fb, maxfb = 0;
++ int i;
++
++ memset(rom, 0, d->rom_size);
++
++ rom->magic = cpu_to_le32(QXL_ROM_MAGIC);
++ rom->id = cpu_to_le32(d->id);
++ rom->modes_offset = cpu_to_le32(sizeof(QXLRom));
++
++ rom->slot_gen_bits = MEMSLOT_GENERATION_BITS;
++ rom->slot_id_bits = MEMSLOT_SLOT_BITS;
++ rom->slots_start = 1;
++ rom->slots_end = NUM_MEMSLOTS - 1;
++ rom->n_surfaces = cpu_to_le32(NUM_SURFACES);
++
++ modes->n_modes = cpu_to_le32(ARRAY_SIZE(qxl_modes));
++ for (i = 0; i < modes->n_modes; i++) {
++ fb = qxl_modes[i].y_res * qxl_modes[i].stride;
++ if (maxfb < fb)
++ maxfb = fb;
++ modes->modes[i].id = cpu_to_le32(i);
++ modes->modes[i].x_res = cpu_to_le32(qxl_modes[i].x_res);
++ modes->modes[i].y_res = cpu_to_le32(qxl_modes[i].y_res);
++ modes->modes[i].bits = cpu_to_le32(qxl_modes[i].bits);
++ modes->modes[i].stride = cpu_to_le32(qxl_modes[i].stride);
++ modes->modes[i].x_mili = cpu_to_le32(qxl_modes[i].x_mili);
++ modes->modes[i].y_mili = cpu_to_le32(qxl_modes[i].y_mili);
++ modes->modes[i].orientation = cpu_to_le32(qxl_modes[i].orientation);
++ }
++ if (maxfb < VGA_RAM_SIZE && d->id == 0)
++ maxfb = VGA_RAM_SIZE;
++
++ ram_header_size = ALIGN(sizeof(QXLRam), 4096);
++ surface0_area_size = ALIGN(maxfb, 4096);
++ num_pages = d->vga.vram_size;
++ num_pages -= ram_header_size;
++ num_pages -= surface0_area_size;
++ num_pages = num_pages / TARGET_PAGE_SIZE;
++
++ rom->draw_area_offset = cpu_to_le32(0);
++ rom->surface0_area_size = cpu_to_le32(surface0_area_size);
++ rom->pages_offset = cpu_to_le32(surface0_area_size);
++ rom->num_pages = cpu_to_le32(num_pages);
++ rom->ram_header_offset = cpu_to_le32(d->vga.vram_size - ram_header_size);
++
++ d->shadow_rom = *rom;
++ d->rom = rom;
++ d->modes = modes;
++}
++
++static void init_qxl_ram(PCIQXLDevice *d)
++{
++ uint8_t *buf;
++ uint64_t *item;
++
++ buf = d->vga.vram_ptr;
++ d->ram = (QXLRam *)(buf + le32_to_cpu(d->shadow_rom.ram_header_offset));
++ d->ram->magic = cpu_to_le32(QXL_RAM_MAGIC);
++ d->ram->int_pending = cpu_to_le32(0);
++ d->ram->int_mask = cpu_to_le32(0);
++ SPICE_RING_INIT(&d->ram->cmd_ring);
++ SPICE_RING_INIT(&d->ram->cursor_ring);
++ SPICE_RING_INIT(&d->ram->release_ring);
++ SPICE_RING_PROD_ITEM(&d->ram->release_ring, item);
++ *item = 0;
++ qxl_ring_set_dirty(d);
++}
++
++static void qxl_set_dirty(ram_addr_t addr, ram_addr_t end)
++{
++ while (addr < end) {
++ cpu_physical_memory_set_dirty(addr);
++ addr += TARGET_PAGE_SIZE;
++ }
++}
++
++static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
++{
++ ram_addr_t addr = qxl->rom_offset;
++ qxl_set_dirty(addr, addr + qxl->rom_size);
++}
++
++static void qxl_ram_set_dirty(PCIQXLDevice *qxl, void *ptr)
++{
++ ram_addr_t addr = qxl->vga.vram_offset;
++ void *base = qxl->vga.vram_ptr;
++ intptr_t offset;
++
++ offset = ptr - base;
++ offset &= ~(TARGET_PAGE_SIZE-1);
++ assert(offset < qxl->vga.vram_size);
++ qxl_set_dirty(addr + offset, addr + offset + TARGET_PAGE_SIZE);
++}
++
++static void qxl_ring_set_dirty(PCIQXLDevice *qxl)
++{
++ ram_addr_t addr = qxl->vga.vram_offset + qxl->shadow_rom.ram_header_offset;
++ ram_addr_t end = qxl->vga.vram_offset + qxl->vga.vram_size;
++ qxl_set_dirty(addr, end);
++}
++
++/*
++ * keep track of some command state, for savevm/loadvm.
++ */
++static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
++{
++ switch (le32_to_cpu(ext->cmd.type)) {
++ case QXL_CMD_SURFACE:
++ {
++ QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
++ uint32_t id = le32_to_cpu(cmd->surface_id);
++ PANIC_ON(id >= NUM_SURFACES);
++ if (cmd->type == QXL_SURFACE_CMD_CREATE) {
++ qxl->guest_surfaces.cmds[id] = ext->cmd.data;
++ qxl->guest_surfaces.count++;
++ if (qxl->guest_surfaces.max < qxl->guest_surfaces.count)
++ qxl->guest_surfaces.max = qxl->guest_surfaces.count;
++ }
++ if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
++ qxl->guest_surfaces.cmds[id] = 0;
++ qxl->guest_surfaces.count--;
++ }
++ break;
++ }
++ case QXL_CMD_CURSOR:
++ {
++ QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
++ if (cmd->type == QXL_CURSOR_SET) {
++ qxl->guest_cursor = ext->cmd.data;
++ }
++ break;
++ }
++ }
++}
++
++/* spice display interface callbacks */
++
++static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++
++ dprintf(qxl, 1, "%s:\n", __FUNCTION__);
++ qxl->ssd.worker = qxl_worker;
++}
++
++static void interface_set_compression_level(QXLInstance *sin, int level)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++
++ dprintf(qxl, 1, "%s: %d\n", __FUNCTION__, level);
++ qxl->shadow_rom.compression_level = cpu_to_le32(level);
++ qxl->rom->compression_level = cpu_to_le32(level);
++ qxl_rom_set_dirty(qxl);
++}
++
++static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++
++ qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
++ qxl->rom->mm_clock = cpu_to_le32(mm_time);
++ qxl_rom_set_dirty(qxl);
++}
++
++static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++
++ dprintf(qxl, 1, "%s:\n", __FUNCTION__);
++ info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
++ info->memslot_id_bits = MEMSLOT_SLOT_BITS;
++ info->num_memslots = NUM_MEMSLOTS;
++ info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
++ info->internal_groupslot_id = 0;
++ info->qxl_ram_size = le32_to_cpu(qxl->shadow_rom.num_pages) << TARGET_PAGE_BITS;
++ info->n_surfaces = NUM_SURFACES;
++}
++
++static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++ SimpleSpiceUpdate *update;
++ QXLCommandRing *ring;
++ QXLCommand *cmd;
++ int notify;
++
++ switch (qxl->mode) {
++ case QXL_MODE_VGA:
++ dprintf(qxl, 2, "%s: vga\n", __FUNCTION__);
++ update = qemu_spice_create_update(&qxl->ssd);
++ if (update == NULL) {
++ return false;
++ }
++ *ext = update->ext;
++ qxl_log_command(qxl, "vga", ext);
++ return true;
++ case QXL_MODE_COMPAT:
++ case QXL_MODE_NATIVE:
++ case QXL_MODE_UNDEFINED:
++ dprintf(qxl, 2, "%s: %s\n", __FUNCTION__,
++ qxl->cmdflags ? "compat" : "native");
++ ring = &qxl->ram->cmd_ring;
++ if (SPICE_RING_IS_EMPTY(ring)) {
++ return false;
++ }
++ SPICE_RING_CONS_ITEM(ring, cmd);
++ ext->cmd = *cmd;
++ ext->group_id = MEMSLOT_GROUP_GUEST;
++ ext->flags = qxl->cmdflags;
++ SPICE_RING_POP(ring, notify);
++ qxl_ring_set_dirty(qxl);
++ if (notify) {
++ qxl_send_events(qxl, QXL_INTERRUPT_DISPLAY);
++ }
++ qxl->guest_primary.commands++;
++ qxl_track_command(qxl, ext);
++ qxl_log_command(qxl, "cmd", ext);
++ return true;
++ default:
++ return false;
++ }
++}
++
++static int interface_req_cmd_notification(QXLInstance *sin)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++ int wait = 1;
++
++ switch (qxl->mode) {
++ case QXL_MODE_COMPAT:
++ case QXL_MODE_NATIVE:
++ case QXL_MODE_UNDEFINED:
++ SPICE_RING_CONS_WAIT(&qxl->ram->cmd_ring, wait);
++ qxl_ring_set_dirty(qxl);
++ break;
++ default:
++ /* nothing */
++ break;
++ }
++ return wait;
++}
++
++static inline void qxl_push_free_res(PCIQXLDevice *d)
++{
++ QXLReleaseRing *ring = &d->ram->release_ring;
++ uint64_t *item;
++
++#define QXL_FREE_BUNCH_SIZE 32
++
++ if (SPICE_RING_IS_EMPTY(ring) || (d->num_free_res >= QXL_FREE_BUNCH_SIZE &&
++ ring->prod - ring->cons + 2 != ring->num_items)) {
++ int notify;
++
++ SPICE_RING_PUSH(ring, notify);
++ if (notify) {
++ qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
++ }
++ SPICE_RING_PROD_ITEM(ring, item);
++ *item = 0;
++ d->num_free_res = 0;
++ d->last_release = NULL;
++ qxl_ring_set_dirty(d);
++ }
++}
++
++static void interface_release_resource(QXLInstance *sin,
++ struct QXLReleaseInfoExt ext)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++ QXLReleaseRing *ring;
++ uint64_t *item, id;
++
++ if (ext.group_id == MEMSLOT_GROUP_HOST) {
++ /* host group -> vga mode update request */
++ qemu_spice_destroy_update(&qxl->ssd, (void*)ext.info->id);
++ return;
++ }
++
++ /*
++ * ext->info points into guest-visible memory
++ * pci bar 0, $command.release_info
++ */
++ ring = &qxl->ram->release_ring;
++ SPICE_RING_PROD_ITEM(ring, item);
++ if (*item == 0) {
++ /* stick head into the ring */
++ id = ext.info->id;
++ ext.info->next = 0;
++ qxl_ram_set_dirty(qxl, &ext.info->next);
++ *item = id;
++ qxl_ring_set_dirty(qxl);
++ } else {
++ /* append item to the list */
++ qxl->last_release->next = ext.info->id;
++ qxl_ram_set_dirty(qxl, &qxl->last_release->next);
++ ext.info->next = 0;
++ qxl_ram_set_dirty(qxl, &ext.info->next);
++ }
++ qxl->last_release = ext.info;
++ qxl->num_free_res++;
++ qxl_push_free_res(qxl);
++}
++
++static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++ QXLCursorRing *ring;
++ QXLCommand *cmd;
++ int notify;
++
++ switch (qxl->mode) {
++ case QXL_MODE_COMPAT:
++ case QXL_MODE_NATIVE:
++ case QXL_MODE_UNDEFINED:
++ ring = &qxl->ram->cursor_ring;
++ if (SPICE_RING_IS_EMPTY(ring)) {
++ return false;
++ }
++ SPICE_RING_CONS_ITEM(ring, cmd);
++ ext->cmd = *cmd;
++ ext->group_id = MEMSLOT_GROUP_GUEST;
++ ext->flags = qxl->cmdflags;
++ SPICE_RING_POP(ring, notify);
++ qxl_ring_set_dirty(qxl);
++ if (notify) {
++ qxl_send_events(qxl, QXL_INTERRUPT_CURSOR);
++ }
++ qxl->guest_primary.commands++;
++ qxl_track_command(qxl, ext);
++ qxl_log_command(qxl, "csr", ext);
++ if (qxl->id == 0) {
++ qxl_render_cursor(qxl, ext);
++ }
++ return true;
++ default:
++ return false;
++ }
++}
++
++static int interface_req_cursor_notification(QXLInstance *sin)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++ int wait = 1;
++
++ switch (qxl->mode) {
++ case QXL_MODE_COMPAT:
++ case QXL_MODE_NATIVE:
++ case QXL_MODE_UNDEFINED:
++ SPICE_RING_CONS_WAIT(&qxl->ram->cursor_ring, wait);
++ qxl_ring_set_dirty(qxl);
++ break;
++ default:
++ /* nothing */
++ break;
++ }
++ return wait;
++}
++
++static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
++{
++ fprintf(stderr, "%s: abort()\n", __FUNCTION__);
++ abort();
++}
++
++static int interface_flush_resources(QXLInstance *sin)
++{
++ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
++ int ret;
++
++ ret = qxl->num_free_res;
++ if (ret) {
++ qxl_push_free_res(qxl);
++ }
++ return ret;
++}
++
++static const QXLInterface qxl_interface = {
++ .base.type = SPICE_INTERFACE_QXL,
++ .base.description = "qxl gpu",
++ .base.major_version = SPICE_INTERFACE_QXL_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_QXL_MINOR,
++
++ .attache_worker = interface_attach_worker,
++ .set_compression_level = interface_set_compression_level,
++ .set_mm_time = interface_set_mm_time,
++
++ .get_init_info = interface_get_init_info,
++ .get_command = interface_get_command,
++ .req_cmd_notification = interface_req_cmd_notification,
++ .release_resource = interface_release_resource,
++ .get_cursor_command = interface_get_cursor_command,
++ .req_cursor_notification = interface_req_cursor_notification,
++ .notify_update = interface_notify_update,
++ .flush_resources = interface_flush_resources,
++};
++
++static void qxl_enter_vga_mode(PCIQXLDevice *d)
++{
++ if (d->mode == QXL_MODE_VGA) {
++ return;
++ }
++ dprintf(d, 1, "%s\n", __FUNCTION__);
++ qemu_spice_create_host_primary(&d->ssd);
++ d->mode = QXL_MODE_VGA;
++ memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
++}
++
++static void qxl_exit_vga_mode(PCIQXLDevice *d)
++{
++ if (d->mode != QXL_MODE_VGA) {
++ return;
++ }
++ dprintf(d, 1, "%s\n", __FUNCTION__);
++ qxl_destroy_primary(d);
++}
++
++static void qxl_set_irq(PCIQXLDevice *d)
++{
++ uint32_t pending = le32_to_cpu(d->ram->int_pending);
++ uint32_t mask = le32_to_cpu(d->ram->int_mask);
++ int level = !!(pending & mask);
++ qemu_set_irq(d->pci.irq[0], level);
++ qxl_ring_set_dirty(d);
++}
++
++static void qxl_write_config(PCIDevice *d, uint32_t address,
++ uint32_t val, int len)
++{
++ PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, d);
++ VGACommonState *vga = &qxl->vga;
++
++ if (qxl->id == 0) {
++ vga_dirty_log_stop(vga);
++ }
++ pci_default_write_config(d, address, val, len);
++ if (qxl->id == 0) {
++ if (vga->map_addr && qxl->pci.io_regions[0].addr == -1)
++ vga->map_addr = 0;
++ vga_dirty_log_start(vga);
++ }
++}
++
++static void qxl_check_state(PCIQXLDevice *d)
++{
++ QXLRam *ram = d->ram;
++
++ assert(SPICE_RING_IS_EMPTY(&ram->cmd_ring));
++ assert(SPICE_RING_IS_EMPTY(&ram->cursor_ring));
++}
++
++static void qxl_reset_state(PCIQXLDevice *d)
++{
++ QXLRam *ram = d->ram;
++ QXLRom *rom = d->rom;
++
++ assert(SPICE_RING_IS_EMPTY(&ram->cmd_ring));
++ assert(SPICE_RING_IS_EMPTY(&ram->cursor_ring));
++ d->shadow_rom.update_id = cpu_to_le32(0);
++ *rom = d->shadow_rom;
++ qxl_rom_set_dirty(d);
++ init_qxl_ram(d);
++ d->num_free_res = 0;
++ d->last_release = NULL;
++ memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty));
++}
++
++static void qxl_soft_reset(PCIQXLDevice *d)
++{
++ dprintf(d, 1, "%s:\n", __FUNCTION__);
++ qxl_check_state(d);
++
++ if (d->id == 0) {
++ qxl_enter_vga_mode(d);
++ } else {
++ d->mode = QXL_MODE_UNDEFINED;
++ }
++}
++
++static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
++{
++ dprintf(d, 1, "%s: start%s\n", __FUNCTION__,
++ loadvm ? " (loadvm)" : "");
++
++ d->ssd.worker->reset_cursor(d->ssd.worker);
++ d->ssd.worker->reset_image_cache(d->ssd.worker);
++ qxl_reset_surfaces(d);
++ qxl_reset_memslots(d);
++
++ /* pre loadvm reset must not touch QXLRam. This lives in
++ * device memory, is migrated together with RAM and thus
++ * already loaded at this point */
++ if (!loadvm) {
++ qxl_reset_state(d);
++ }
++ qemu_spice_create_host_memslot(&d->ssd);
++ qxl_soft_reset(d);
++
++ dprintf(d, 1, "%s: done\n", __FUNCTION__);
++}
++
++static void qxl_reset_handler(DeviceState *dev)
++{
++ PCIQXLDevice *d = DO_UPCAST(PCIQXLDevice, pci.qdev, dev);
++ qxl_hard_reset(d, 0);
++}
++
++static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
++{
++ VGACommonState *vga = opaque;
++ PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
++
++ if (qxl->mode != QXL_MODE_VGA) {
++ dprintf(qxl, 1, "%s\n", __FUNCTION__);
++ qxl_destroy_primary(qxl);
++ qxl_soft_reset(qxl);
++ }
++ vga_ioport_write(opaque, addr, val);
++}
++
++static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta)
++{
++ static const int regions[] = {
++ QXL_RAM_RANGE_INDEX,
++ QXL_VRAM_RANGE_INDEX,
++ };
++ uint64_t guest_start;
++ uint64_t guest_end;
++ int pci_region;
++ pcibus_t pci_start;
++ pcibus_t pci_end;
++ intptr_t virt_start;
++ QXLDevMemSlot memslot;
++ int i;
++
++ guest_start = le64_to_cpu(d->guest_slots[slot_id].slot.mem_start);
++ guest_end = le64_to_cpu(d->guest_slots[slot_id].slot.mem_end);
++
++ dprintf(d, 1, "%s: slot %d: guest phys 0x%" PRIx64 " - 0x%" PRIx64 "\n",
++ __FUNCTION__, slot_id,
++ guest_start, guest_end);
++
++ PANIC_ON(slot_id >= NUM_MEMSLOTS);
++ PANIC_ON(guest_start > guest_end);
++
++ for (i = 0; i < ARRAY_SIZE(regions); i++) {
++ pci_region = regions[i];
++ pci_start = d->pci.io_regions[pci_region].addr;
++ pci_end = pci_start + d->pci.io_regions[pci_region].size;
++ /* mapped? */
++ if (pci_start == -1) {
++ continue;
++ }
++ /* start address in range ? */
++ if (guest_start < pci_start || guest_start > pci_end) {
++ continue;
++ }
++ /* end address in range ? */
++ if (guest_end > pci_end) {
++ continue;
++ }
++ /* passed */
++ break;
++ }
++ PANIC_ON(i == ARRAY_SIZE(regions)); /* finished loop without match */
++
++ switch (pci_region) {
++ case QXL_RAM_RANGE_INDEX:
++ virt_start = (intptr_t)qemu_get_ram_ptr(d->vga.vram_offset);
++ break;
++ case QXL_VRAM_RANGE_INDEX:
++ virt_start = (intptr_t)qemu_get_ram_ptr(d->vram_offset);
++ break;
++ default:
++ /* should not happen */
++ abort();
++ }
++
++ memslot.slot_id = slot_id;
++ memslot.slot_group_id = MEMSLOT_GROUP_GUEST; /* guest group */
++ memslot.virt_start = virt_start + (guest_start - pci_start);
++ memslot.virt_end = virt_start + (guest_end - pci_start);
++ memslot.addr_delta = memslot.virt_start - delta;
++ memslot.generation = d->rom->slot_generation = 0; // FIXME d->generation++;
++ qxl_rom_set_dirty(d);
++
++ dprintf(d, 1, "%s: slot %d: host virt 0x%" PRIx64 " - 0x%" PRIx64 "\n",
++ __FUNCTION__, memslot.slot_id,
++ memslot.virt_start, memslot.virt_end);
++
++ d->ssd.worker->add_memslot(d->ssd.worker, &memslot);
++ d->guest_slots[slot_id].ptr = (void*)memslot.virt_start;
++ d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start;
++ d->guest_slots[slot_id].delta = delta;
++ d->guest_slots[slot_id].active = 1;
++}
++
++static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id)
++{
++ dprintf(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id);
++ d->ssd.worker->del_memslot(d->ssd.worker, MEMSLOT_GROUP_HOST, slot_id);
++ d->guest_slots[slot_id].active = 0;
++}
++
++static void qxl_reset_memslots(PCIQXLDevice *d)
++{
++ dprintf(d, 1, "%s:\n", __FUNCTION__);
++ d->ssd.worker->reset_memslots(d->ssd.worker);
++ memset(&d->guest_slots, 0, sizeof(d->guest_slots));
++}
++
++static void qxl_reset_surfaces(PCIQXLDevice *d)
++{
++ dprintf(d, 1, "%s:\n", __FUNCTION__);
++ d->mode = QXL_MODE_UNDEFINED;
++ d->ssd.worker->destroy_surfaces(d->ssd.worker);
++ memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
++}
++
++void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
++{
++ uint64_t phys = le64_to_cpu(pqxl);
++ uint32_t slot = (phys >> (64 - 8)) & 0xff;
++ uint64_t offset = phys & 0xffffffffffff;
++
++ switch (group_id) {
++ case MEMSLOT_GROUP_HOST:
++ return (void*)offset;
++ case MEMSLOT_GROUP_GUEST:
++ PANIC_ON(slot > NUM_MEMSLOTS);
++ PANIC_ON(!qxl->guest_slots[slot].active);
++ PANIC_ON(offset < qxl->guest_slots[slot].delta);
++ offset -= qxl->guest_slots[slot].delta;
++ PANIC_ON(offset > qxl->guest_slots[slot].size)
++ return qxl->guest_slots[slot].ptr + offset;
++ default:
++ PANIC_ON(1);
++ }
++}
++
++static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm)
++{
++ QXLDevSurfaceCreate surface;
++ QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
++
++ assert(qxl->mode != QXL_MODE_NATIVE);
++ qxl_exit_vga_mode(qxl);
++
++ dprintf(qxl, 1, "%s: %dx%d\n", __FUNCTION__,
++ le32_to_cpu(sc->width), le32_to_cpu(sc->height));
++
++ surface.format = le32_to_cpu(sc->format);
++ surface.height = le32_to_cpu(sc->height);
++ surface.mem = le64_to_cpu(sc->mem);
++ surface.position = le32_to_cpu(sc->position);
++ surface.stride = le32_to_cpu(sc->stride);
++ surface.width = le32_to_cpu(sc->width);
++ surface.type = le32_to_cpu(sc->type);
++ surface.flags = le32_to_cpu(sc->flags);
++
++ surface.mouse_mode = true;
++ surface.group_id = MEMSLOT_GROUP_GUEST;
++ if (loadvm) {
++ surface.flags |= QXL_SURF_FLAG_KEEP_DATA;
++ }
++
++ qxl->mode = QXL_MODE_NATIVE;
++ qxl->cmdflags = 0;
++ qxl->ssd.worker->create_primary_surface(qxl->ssd.worker, 0, &surface);
++
++ /* for local rendering */
++ qxl_render_resize(qxl);
++}
++
++static void qxl_destroy_primary(PCIQXLDevice *d)
++{
++ if (d->mode == QXL_MODE_UNDEFINED) {
++ return;
++ }
++
++ dprintf(d, 1, "%s\n", __FUNCTION__);
++
++ d->mode = QXL_MODE_UNDEFINED;
++ d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
++}
++
++static void qxl_set_mode(PCIQXLDevice *d, int modenr)
++{
++ pcibus_t start = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
++ pcibus_t end = d->pci.io_regions[QXL_RAM_RANGE_INDEX].size + start;
++ QXLMode *mode = d->modes->modes + modenr;
++ uint64_t devmem = d->pci.io_regions[QXL_RAM_RANGE_INDEX].addr;
++ QXLMemSlot slot = {
++ .mem_start = start,
++ .mem_end = end
++ };
++ QXLSurfaceCreate surface = {
++ .width = mode->x_res,
++ .height = mode->y_res,
++ .stride = -mode->x_res * 4,
++ .format = SPICE_SURFACE_FMT_32_xRGB,
++ .mouse_mode = true,
++ .mem = devmem,
++ };
++
++ dprintf(d, 1, "%s: mode %d [ %d x %d @ %d bpp devmem 0x%lx ]\n", __FUNCTION__,
++ modenr, mode->x_res, mode->y_res, mode->bits, devmem);
++ qxl_hard_reset(d, 0);
++
++ d->guest_slots[0].slot = slot;
++ qxl_add_memslot(d, 0, devmem);
++
++ d->guest_primary.surface = surface;
++ qxl_create_guest_primary(d, 0);
++
++ d->mode = QXL_MODE_COMPAT;
++ d->cmdflags = QXL_COMMAND_FLAG_COMPAT;
++ d->shadow_rom.mode = cpu_to_le32(modenr);
++ d->rom->mode = cpu_to_le32(modenr);
++ qxl_rom_set_dirty(d);
++}
++
++static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
++{
++ PCIQXLDevice *d = opaque;
++ uint32_t io_port = addr - d->io_base;
++
++ switch (io_port) {
++ case QXL_IO_RESET:
++ case QXL_IO_SET_MODE:
++ case QXL_IO_MEMSLOT_ADD:
++ case QXL_IO_MEMSLOT_DEL:
++ case QXL_IO_CREATE_PRIMARY:
++ break;
++ default:
++ if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
++ break;
++ dprintf(d, 1, "%s: unexpected port 0x%x in vga mode\n", __FUNCTION__, io_port);
++ return;
++ }
++
++ switch (io_port) {
++ case QXL_IO_UPDATE_AREA:
++ {
++ QXLRect update = d->ram->update_area;
++ d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
++ &update, NULL, 0, 0);
++ break;
++ }
++ case QXL_IO_NOTIFY_CMD:
++ d->ssd.worker->wakeup(d->ssd.worker);
++ break;
++ case QXL_IO_NOTIFY_CURSOR:
++ d->ssd.worker->wakeup(d->ssd.worker);
++ break;
++ case QXL_IO_UPDATE_IRQ:
++ qxl_set_irq(d);
++ break;
++ case QXL_IO_NOTIFY_OOM:
++ if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
++ break;
++ }
++ pthread_yield();
++ if (!SPICE_RING_IS_EMPTY(&d->ram->release_ring)) {
++ break;
++ }
++ d->ssd.worker->oom(d->ssd.worker);
++ break;
++ case QXL_IO_SET_MODE:
++ dprintf(d, 1, "QXL_SET_MODE %d\n", val);
++ qxl_set_mode(d, val);
++ break;
++ case QXL_IO_LOG:
++ dprintf(d, 1, "log %s", d->ram->log_buf);
++ break;
++ case QXL_IO_RESET:
++ dprintf(d, 1, "QXL_IO_RESET\n");
++ qxl_hard_reset(d, 0);
++ break;
++ case QXL_IO_MEMSLOT_ADD:
++ PANIC_ON(val >= NUM_MEMSLOTS);
++ PANIC_ON(d->guest_slots[val].active);
++ d->guest_slots[val].slot = d->ram->mem_slot;
++ qxl_add_memslot(d, val, 0);
++ break;
++ case QXL_IO_MEMSLOT_DEL:
++ qxl_del_memslot(d, val);
++ break;
++ case QXL_IO_CREATE_PRIMARY:
++ PANIC_ON(val != 0);
++ dprintf(d, 1, "QXL_IO_CREATE_PRIMARY\n");
++ d->guest_primary.surface = d->ram->create_surface;
++ qxl_create_guest_primary(d, 0);
++ break;
++ case QXL_IO_DESTROY_PRIMARY:
++ PANIC_ON(val != 0);
++ dprintf(d, 1, "QXL_IO_DESTROY_PRIMARY\n");
++ qxl_destroy_primary(d);
++ break;
++ case QXL_IO_DESTROY_SURFACE_WAIT:
++ d->ssd.worker->destroy_surface_wait(d->ssd.worker, val);
++ break;
++ case QXL_IO_DESTROY_ALL_SURFACES:
++ d->ssd.worker->destroy_surfaces(d->ssd.worker);
++ break;
++ default:
++ fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
++ abort();
++ }
++}
++
++static uint32_t ioport_read(void *opaque, uint32_t addr)
++{
++ PCIQXLDevice *d = opaque;
++
++ dprintf(d, 1, "%s: unexpected\n", __FUNCTION__);
++ return 0xff;
++}
++
++static void qxl_map(PCIDevice *pci, int region_num,
++ pcibus_t addr, pcibus_t size, int type)
++{
++ static const char *names[] = {
++ [ QXL_IO_RANGE_INDEX ] = "ioports",
++ [ QXL_RAM_RANGE_INDEX ] = "devram",
++ [ QXL_ROM_RANGE_INDEX ] = "rom",
++ [ QXL_VRAM_RANGE_INDEX ] = "vram",
++ };
++ PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, pci);
++
++ dprintf(qxl, 1, "%s: bar %d [%s] addr 0x%lx size 0x%lx\n", __FUNCTION__,
++ region_num, names[region_num], addr, size);
++
++ switch (region_num) {
++ case QXL_IO_RANGE_INDEX:
++ register_ioport_write(addr, size, 1, ioport_write, pci);
++ register_ioport_read(addr, size, 1, ioport_read, pci);
++ qxl->io_base = addr;
++ break;
++ case QXL_RAM_RANGE_INDEX:
++ cpu_register_physical_memory(addr, size, qxl->vga.vram_offset | IO_MEM_RAM);
++ qxl->vga.map_addr = addr;
++ qxl->vga.map_end = addr + size;
++ if (qxl->id == 0) {
++ vga_dirty_log_start(&qxl->vga);
++ }
++ break;
++ case QXL_ROM_RANGE_INDEX:
++ cpu_register_physical_memory(addr, size, qxl->rom_offset | IO_MEM_ROM);
++ break;
++ case QXL_VRAM_RANGE_INDEX:
++ cpu_register_physical_memory(addr, size, qxl->vram_offset | IO_MEM_RAM);
++ break;
++ }
++}
++
++static void pipe_read(void *opaque)
++{
++ PCIQXLDevice *d = opaque;
++ char dummy;
++ int len;
++
++ do {
++ len = read(d->pipe[0], &dummy, sizeof(dummy));
++ } while (len == sizeof(dummy));
++ qxl_set_irq(d);
++}
++
++static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
++{
++ uint32_t old_pending;
++ uint32_t le_events = cpu_to_le32(events);
++
++ assert(d->ssd.running);
++ old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events);
++ if ((old_pending & le_events) == le_events) {
++ return;
++ }
++ if (pthread_self() == d->main) {
++ qxl_set_irq(d);
++ } else {
++ if (write(d->pipe[1], d, 1) != 1) {
++ dprintf(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
++ }
++ }
++}
++
++static void init_pipe_signaling(PCIQXLDevice *d)
++{
++ if (pipe(d->pipe) < 0) {
++ dprintf(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
++ return;
++ }
++#ifdef CONFIG_IOTHREAD
++ fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
++#else
++ fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
++#endif
++ fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
++ fcntl(d->pipe[0], F_SETOWN, getpid());
++
++ d->main = pthread_self();
++ qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
++}
++
++/* graphics console */
++
++static void qxl_hw_update(void *opaque)
++{
++ PCIQXLDevice *qxl = opaque;
++ VGACommonState *vga = &qxl->vga;
++
++ switch (qxl->mode) {
++ case QXL_MODE_VGA:
++ vga->update(vga);
++ break;
++ case QXL_MODE_NATIVE:
++ qxl_render_update(qxl);
++ break;
++ default:
++ break;
++ }
++}
++
++static void qxl_hw_invalidate(void *opaque)
++{
++ PCIQXLDevice *qxl = opaque;
++ VGACommonState *vga = &qxl->vga;
++
++ vga->invalidate(vga);
++}
++
++static void qxl_hw_screen_dump(void *opaque, const char *filename)
++{
++ PCIQXLDevice *qxl = opaque;
++ VGACommonState *vga = &qxl->vga;
++
++ if (qxl->mode == QXL_MODE_VGA) {
++ vga->screen_dump(vga, filename);
++ return;
++ }
++}
++
++static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
++{
++ PCIQXLDevice *qxl = opaque;
++ VGACommonState *vga = &qxl->vga;
++
++ if (qxl->mode == QXL_MODE_VGA) {
++ vga->text_update(vga, chardata);
++ return;
++ }
++}
++
++static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
++{
++ PCIQXLDevice *qxl = opaque;
++ qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
++
++ if (!running && qxl->mode == QXL_MODE_NATIVE) {
++ /* dirty all vram (which holds surfaces) to make sure it is saved */
++ /* FIXME #1: should go out during "live" stage */
++ /* FIXME #2: we only need to save the areas which are actually used */
++ ram_addr_t addr = qxl->vram_offset;
++ qxl_set_dirty(addr, addr + qxl->vram_size);
++ }
++}
++
++/* display change listener */
++
++static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
++{
++ if (qxl0->mode == QXL_MODE_VGA) {
++ qemu_spice_display_update(&qxl0->ssd, x, y, w, h);
++ }
++}
++
++static void display_resize(struct DisplayState *ds)
++{
++ if (qxl0->mode == QXL_MODE_VGA) {
++ qemu_spice_display_resize(&qxl0->ssd);
++ }
++}
++
++static void display_refresh(struct DisplayState *ds)
++{
++ if (qxl0->mode == QXL_MODE_VGA) {
++ qemu_spice_display_refresh(&qxl0->ssd);
++ }
++}
++
++static DisplayChangeListener display_listener = {
++ .dpy_update = display_update,
++ .dpy_resize = display_resize,
++ .dpy_refresh = display_refresh,
++};
++
++static int qxl_init(PCIDevice *dev)
++{
++ PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
++ VGACommonState *vga = &qxl->vga;
++ uint8_t* config = qxl->pci.config;
++ ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
++ uint32_t pci_device_id;
++ uint32_t pci_device_rev;
++
++ if (device_id == 0 && dev->qdev.hotplugged) {
++ device_id++;
++ }
++
++ qxl->id = device_id;
++ qxl->mode = QXL_MODE_UNDEFINED;
++ qxl->generation = 1;
++ qxl->num_memslots = NUM_MEMSLOTS;
++ qxl->num_surfaces = NUM_SURFACES;
++
++ switch (qxl->revision) {
++ case 1: /* spice 0.4 -- qxl-1 */
++ pci_device_id = QXL_DEVICE_ID_STABLE;
++ pci_device_rev = QXL_REVISION_STABLE_V04;
++ break;
++ case 2: /* spice 0.6 -- qxl-2 */
++ pci_device_id = QXL_DEVICE_ID_STABLE;
++ pci_device_rev = QXL_REVISION_STABLE_V06;
++ break;
++ default: /* experimental */
++ pci_device_id = QXL_DEVICE_ID_DEVEL;
++ pci_device_rev = 1;
++ break;
++ }
++
++ if (!qxl->id) {
++ if (ram_size < 32 * 1024 * 1024)
++ ram_size = 32 * 1024 * 1024;
++ vga_common_init(vga, ram_size);
++ vga_init(vga);
++ register_ioport_write(0x3c0, 16, 1, qxl_vga_ioport_write, vga);
++ register_ioport_write(0x3b4, 2, 1, qxl_vga_ioport_write, vga);
++ register_ioport_write(0x3d4, 2, 1, qxl_vga_ioport_write, vga);
++ register_ioport_write(0x3ba, 1, 1, qxl_vga_ioport_write, vga);
++ register_ioport_write(0x3da, 1, 1, qxl_vga_ioport_write, vga);
++
++ vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
++ qxl_hw_screen_dump, qxl_hw_text_update, qxl);
++ qxl->ssd.ds = vga->ds;
++ qxl->ssd.bufsize = (16 * 1024 * 1024);
++ qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize);
++ pthread_mutex_init(&qxl->ssd.lock, NULL);
++
++ qxl0 = qxl;
++ register_displaychangelistener(vga->ds, &display_listener);
++
++ if (qxl->pci.romfile == NULL) {
++ if (pci_device_id == 0x01ff) {
++ qxl->pci.romfile = qemu_strdup("vgabios-qxldev.bin");
++ } else {
++ qxl->pci.romfile = qemu_strdup("vgabios-qxl.bin");
++ }
++ }
++ pci_config_set_class(config, PCI_CLASS_DISPLAY_VGA);
++ } else {
++ if (ram_size < 16 * 1024 * 1024)
++ ram_size = 16 * 1024 * 1024;
++ qxl->vga.vram_size = ram_size;
++ qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vgavram",
++ qxl->vga.vram_size);
++ qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
++
++ pci_config_set_class(config, PCI_CLASS_DISPLAY_OTHER);
++ }
++
++ pci_config_set_vendor_id(config, REDHAT_PCI_VENDOR_ID);
++ pci_config_set_device_id(config, pci_device_id);
++ pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
++ pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
++
++ qxl->rom_size = qxl_rom_size();
++ qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vrom", qxl->rom_size);
++ init_qxl_rom(qxl);
++ init_qxl_ram(qxl);
++
++ if (qxl->vram_size < 16 * 1024 * 1024)
++ qxl->vram_size = 16 * 1024 * 1024;
++ qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
++ qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size);
++
++ pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
++ msb_mask(QXL_IO_RANGE_SIZE * 2 - 1),
++ PCI_BASE_ADDRESS_SPACE_IO, qxl_map);
++
++ pci_register_bar(&qxl->pci, QXL_ROM_RANGE_INDEX,
++ qxl->rom_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
++ qxl_map);
++
++ pci_register_bar(&qxl->pci, QXL_RAM_RANGE_INDEX,
++ qxl->vga.vram_size, PCI_BASE_ADDRESS_SPACE_MEMORY,
++ qxl_map);
++
++ pci_register_bar(&qxl->pci, QXL_VRAM_RANGE_INDEX, qxl->vram_size,
++ PCI_BASE_ADDRESS_SPACE_MEMORY, qxl_map);
++
++ qxl->ssd.qxl.base.sif = &qxl_interface.base;
++ qxl->ssd.qxl.id = qxl->id;
++ spice_server_add_interface(spice_server, &qxl->ssd.qxl.base);
++ qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
++
++ init_pipe_signaling(qxl);
++ qxl_reset_state(qxl);
++
++ device_id++;
++ return 0;
++}
++
++static void qxl_pre_save(void *opaque)
++{
++ PCIQXLDevice* d = opaque;
++ uint8_t *ram_start = d->vga.vram_ptr;
++
++ dprintf(d, 1, "%s:\n", __FUNCTION__);
++ if (d->last_release == NULL) {
++ d->last_release_offset = 0;
++ } else {
++ d->last_release_offset = (uint8_t *)d->last_release - ram_start;
++ }
++ assert(d->last_release_offset < d->vga.vram_size);
++}
++
++static int qxl_pre_load(void *opaque)
++{
++ PCIQXLDevice* d = opaque;
++
++ dprintf(d, 1, "%s: start\n", __FUNCTION__);
++ qxl_hard_reset(d, 1);
++ qxl_exit_vga_mode(d);
++ dprintf(d, 1, "%s: done\n", __FUNCTION__);
++ return 0;
++}
++
++static int qxl_post_load(void *opaque, int version)
++{
++ PCIQXLDevice* d = opaque;
++ uint8_t *ram_start = d->vga.vram_ptr;
++ QXLCommandExt *cmds;
++ int in, out, i, newmode;
++
++ dprintf(d, 1, "%s: start\n", __FUNCTION__);
++ newmode = d->mode;
++ d->mode = QXL_MODE_UNDEFINED;
++ switch (newmode) {
++ case QXL_MODE_UNDEFINED:
++ break;
++ case QXL_MODE_VGA:
++ qxl_enter_vga_mode(d);
++ break;
++ case QXL_MODE_NATIVE:
++ for (i = 0; i < NUM_MEMSLOTS; i++) {
++ if (!d->guest_slots[i].active)
++ continue;
++ qxl_add_memslot(d, i, 0);
++ }
++ qxl_create_guest_primary(d, 1);
++
++ /* replay surface-create and cursor-set commands */
++ cmds = qemu_mallocz(sizeof(QXLCommandExt) * (NUM_SURFACES + 1));
++ for (in = 0, out = 0; in < NUM_SURFACES; in++) {
++ if (d->guest_surfaces.cmds[in] == 0)
++ continue;
++ cmds[out].cmd.data = d->guest_surfaces.cmds[in];
++ cmds[out].cmd.type = QXL_CMD_SURFACE;
++ cmds[out].group_id = MEMSLOT_GROUP_GUEST;
++ out++;
++ }
++ cmds[out].cmd.data = d->guest_cursor;
++ cmds[out].cmd.type = QXL_CMD_CURSOR;
++ cmds[out].group_id = MEMSLOT_GROUP_GUEST;
++ out++;
++ d->ssd.worker->loadvm_commands(d->ssd.worker, cmds, out);
++ qemu_free(cmds);
++
++ break;
++ case QXL_MODE_COMPAT:
++ qxl_set_mode(d, d->shadow_rom.mode);
++ break;
++ }
++ dprintf(d, 1, "%s: done\n", __FUNCTION__);
++
++ assert(d->last_release_offset < d->vga.vram_size);
++ if (d->last_release_offset == 0) {
++ d->last_release = NULL;
++ } else {
++ d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset);
++ }
++
++ /* spice 0.4 compatibility -- accept but ignore */
++ free(d->worker_data);
++ d->worker_data = NULL;
++ d->worker_data_size = 0;
++
++ return 0;
++}
++
++#define QXL_SAVE_VERSION 20
++
++static bool qxl_test_worker_data(void *opaque, int version_id)
++{
++ PCIQXLDevice* d = opaque;
++
++ if (d->revision != 1) {
++ return false;
++ }
++ if (!d->worker_data_size) {
++ return false;
++ }
++ if (!d->worker_data) {
++ d->worker_data = qemu_malloc(d->worker_data_size);
++ }
++ return true;
++}
++
++static bool qxl_test_spice04(void *opaque, int version_id)
++{
++ PCIQXLDevice* d = opaque;
++ return d->revision == 1;
++}
++
++static bool qxl_test_spice06(void *opaque)
++{
++ PCIQXLDevice* d = opaque;
++ return d->revision > 1;
++}
++
++static VMStateDescription qxl_memslot = {
++ .name = "qxl-memslot",
++ .version_id = QXL_SAVE_VERSION,
++ .minimum_version_id = QXL_SAVE_VERSION,
++ .fields = (VMStateField[]) {
++ VMSTATE_UINT64(slot.mem_start, struct guest_slots),
++ VMSTATE_UINT64(slot.mem_end, struct guest_slots),
++ VMSTATE_UINT32(active, struct guest_slots),
++ VMSTATE_END_OF_LIST()
++ }
++};
++
++static VMStateDescription qxl_surface = {
++ .name = "qxl-surface",
++ .version_id = QXL_SAVE_VERSION,
++ .minimum_version_id = QXL_SAVE_VERSION,
++ .fields = (VMStateField[]) {
++ VMSTATE_UINT32(width, QXLSurfaceCreate),
++ VMSTATE_UINT32(height, QXLSurfaceCreate),
++ VMSTATE_INT32(stride, QXLSurfaceCreate),
++ VMSTATE_UINT32(format, QXLSurfaceCreate),
++ VMSTATE_UINT32(position, QXLSurfaceCreate),
++ VMSTATE_UINT32(mouse_mode, QXLSurfaceCreate),
++ VMSTATE_UINT32(flags, QXLSurfaceCreate),
++ VMSTATE_UINT32(type, QXLSurfaceCreate),
++ VMSTATE_UINT64(mem, QXLSurfaceCreate),
++ VMSTATE_END_OF_LIST()
++ }
++};
++
++static VMStateDescription qxl_vmstate_spice06 = {
++ .name = "qxl/spice06",
++ .version_id = QXL_SAVE_VERSION,
++ .minimum_version_id = QXL_SAVE_VERSION,
++ .fields = (VMStateField []) {
++ VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
++ VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
++ qxl_memslot, struct guest_slots),
++ VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
++ qxl_surface, QXLSurfaceCreate),
++ VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
++ VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
++ vmstate_info_uint64, uint64_t),
++ VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
++ VMSTATE_END_OF_LIST()
++ },
++};
++
++static VMStateDescription qxl_vmstate = {
++ .name = "qxl",
++ .version_id = QXL_SAVE_VERSION,
++ .minimum_version_id = QXL_SAVE_VERSION,
++ .pre_save = qxl_pre_save,
++ .pre_load = qxl_pre_load,
++ .post_load = qxl_post_load,
++ .fields = (VMStateField []) {
++ VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
++ VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
++ VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
++ VMSTATE_UINT32(num_free_res, PCIQXLDevice),
++ VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
++ VMSTATE_UINT32(mode, PCIQXLDevice),
++ VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
++
++ /* spice 0.4 sends/expects them */
++ VMSTATE_VBUFFER_UINT32(vga.vram_ptr, PCIQXLDevice, 0, qxl_test_spice04, 0,
++ vga.vram_size),
++ VMSTATE_UINT32_TEST(worker_data_size, PCIQXLDevice, qxl_test_spice04),
++ VMSTATE_VBUFFER_UINT32(worker_data, PCIQXLDevice, 0, qxl_test_worker_data, 0,
++ worker_data_size),
++
++ VMSTATE_END_OF_LIST()
++ },
++ .subsections = (VMStateSubsection[]) {
++ {
++ /* additional spice 0.6 state */
++ .vmsd = &qxl_vmstate_spice06,
++ .needed = qxl_test_spice06,
++ },{
++ /* end of list */
++ },
++ },
++};
++
++static PCIDeviceInfo qxl_info = {
++ .qdev.name = "qxl",
++ .qdev.desc = "Spice QXL GPU",
++ .qdev.size = sizeof(PCIQXLDevice),
++ .qdev.reset = qxl_reset_handler,
++ .qdev.vmsd = &qxl_vmstate,
++ .init = qxl_init,
++ .config_write = qxl_write_config,
++ .qdev.props = (Property[]) {
++ DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
++ DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
++ DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
++ DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
++ DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
++ DEFINE_PROP_END_OF_LIST(),
++ }
++};
++
++static void qxl_register(void)
++{
++ pci_qdev_register(&qxl_info);
++}
++
++device_init(qxl_register);
+diff -urN qemu-kvm-0.13.0.orig/hw/qxl.h qemu-kvm-0.13.0/hw/qxl.h
+--- qemu-kvm-0.13.0.orig/hw/qxl.h 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/hw/qxl.h 2011-02-09 11:08:02.854000327 +0200
+@@ -0,0 +1,108 @@
++#include "console.h"
++#include "hw.h"
++#include "pci.h"
++#include "vga_int.h"
++
++#include "qemu-spice.h"
++#include "spice-display.h"
++
++enum qxl_mode {
++ QXL_MODE_UNDEFINED,
++ QXL_MODE_VGA,
++ QXL_MODE_COMPAT, /* spice 0.4.x */
++ QXL_MODE_NATIVE,
++};
++
++typedef struct PCIQXLDevice {
++ PCIDevice pci;
++ SimpleSpiceDisplay ssd;
++ int id;
++ uint32_t debug;
++ uint32_t cmdlog;
++ enum qxl_mode mode;
++ uint32_t cmdflags;
++ int generation;
++ uint32_t revision;
++
++ int32_t num_memslots;
++ int32_t num_surfaces;
++
++ struct guest_slots {
++ QXLMemSlot slot;
++ void *ptr;
++ uint64_t size;
++ uint64_t delta;
++ uint32_t active;
++ } guest_slots[NUM_MEMSLOTS];
++
++ struct guest_primary {
++ QXLSurfaceCreate surface;
++ uint32_t commands;
++ uint32_t resized;
++ int32_t stride;
++ uint32_t bits_pp;
++ uint32_t bytes_pp;
++ uint8_t *data, *flipped;
++ } guest_primary;
++
++ struct surfaces {
++ QXLPHYSICAL cmds[NUM_SURFACES];
++ uint32_t count;
++ uint32_t max;
++ } guest_surfaces;
++ QXLPHYSICAL guest_cursor;
++
++ /* thread signaling */
++ pthread_t main;
++ int pipe[2];
++
++ /* ram pci bar */
++ QXLRam *ram;
++ VGACommonState vga;
++ uint32_t num_free_res;
++ QXLReleaseInfo *last_release;
++ uint32_t last_release_offset;
++
++ /* rom pci bar */
++ QXLRom shadow_rom;
++ QXLRom *rom;
++ QXLModes *modes;
++ uint32_t rom_size;
++ uint64_t rom_offset;
++
++ /* vram pci bar */
++ uint32_t vram_size;
++ uint64_t vram_offset;
++
++ /* io bar */
++ uint32_t io_base;
++
++ /* spice 0.4 loadvm compatibility */
++ void *worker_data;
++ uint32_t worker_data_size;
++} PCIQXLDevice;
++
++#define PANIC_ON(x) if ((x)) { \
++ printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \
++ exit(-1); \
++}
++
++#define dprintf(_qxl, _level, _fmt, ...) \
++ do { \
++ if (_qxl->debug >= _level) { \
++ fprintf(stderr, "qxl-%d: ", _qxl->id); \
++ fprintf(stderr, _fmt, ## __VA_ARGS__); \
++ } \
++ } while (0)
++
++/* qxl.c */
++void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
++
++/* qxl-logger.c */
++void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
++void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
++
++/* qxl-render.c */
++void qxl_render_resize(PCIQXLDevice *qxl);
++void qxl_render_update(PCIQXLDevice *qxl);
++void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
+diff -urN qemu-kvm-0.13.0.orig/hw/qxl-logger.c qemu-kvm-0.13.0/hw/qxl-logger.c
+--- qemu-kvm-0.13.0.orig/hw/qxl-logger.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/hw/qxl-logger.c 2011-02-09 11:08:02.766000327 +0200
+@@ -0,0 +1,179 @@
++/*
++ * qxl command logging -- for debug purposes
++ */
++
++#include <stdio.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <string.h>
++
++#include "qxl.h"
++
++static const char *qxl_type[] = {
++ [ QXL_CMD_NOP ] = "nop",
++ [ QXL_CMD_DRAW ] = "draw",
++ [ QXL_CMD_UPDATE ] = "update",
++ [ QXL_CMD_CURSOR ] = "cursor",
++ [ QXL_CMD_MESSAGE ] = "message",
++ [ QXL_CMD_SURFACE ] = "surface",
++};
++
++static const char *qxl_draw_type[] = {
++ [ QXL_DRAW_NOP ] = "nop",
++ [ QXL_DRAW_FILL ] = "fill",
++ [ QXL_DRAW_OPAQUE ] = "opaque",
++ [ QXL_DRAW_COPY ] = "copy",
++ [ QXL_COPY_BITS ] = "copy-bits",
++ [ QXL_DRAW_BLEND ] = "blend",
++ [ QXL_DRAW_BLACKNESS ] = "blackness",
++ [ QXL_DRAW_WHITENESS ] = "whitemess",
++ [ QXL_DRAW_INVERS ] = "invers",
++ [ QXL_DRAW_ROP3 ] = "rop3",
++ [ QXL_DRAW_STROKE ] = "stroke",
++ [ QXL_DRAW_TEXT ] = "text",
++ [ QXL_DRAW_TRANSPARENT ] = "transparent",
++ [ QXL_DRAW_ALPHA_BLEND ] = "alpha-blend",
++};
++
++static const char *qxl_draw_effect[] = {
++ [ QXL_EFFECT_BLEND ] = "blend",
++ [ QXL_EFFECT_OPAQUE ] = "opaque",
++ [ QXL_EFFECT_REVERT_ON_DUP ] = "revert-on-dup",
++ [ QXL_EFFECT_BLACKNESS_ON_DUP ] = "blackness-on-dup",
++ [ QXL_EFFECT_WHITENESS_ON_DUP ] = "whiteness-on-dup",
++ [ QXL_EFFECT_NOP_ON_DUP ] = "nop-on-dup",
++ [ QXL_EFFECT_NOP ] = "nop",
++ [ QXL_EFFECT_OPAQUE_BRUSH ] = "opaque-brush",
++};
++
++static const char *qxl_surface_cmd[] = {
++ [ QXL_SURFACE_CMD_CREATE ] = "create",
++ [ QXL_SURFACE_CMD_DESTROY ] = "destroy",
++};
++
++static const char *spice_surface_fmt[] = {
++ [ SPICE_SURFACE_FMT_INVALID ] = "invalid",
++ [ SPICE_SURFACE_FMT_1_A ] = "alpha/1",
++ [ SPICE_SURFACE_FMT_8_A ] = "alpha/8",
++ [ SPICE_SURFACE_FMT_16_555 ] = "555/16",
++ [ SPICE_SURFACE_FMT_16_565 ] = "565/16",
++ [ SPICE_SURFACE_FMT_32_xRGB ] = "xRGB/32",
++ [ SPICE_SURFACE_FMT_32_ARGB ] = "ARGB/32",
++};
++
++static const char *qxl_cursor_cmd[] = {
++ [ QXL_CURSOR_SET ] = "set",
++ [ QXL_CURSOR_MOVE ] = "move",
++ [ QXL_CURSOR_HIDE ] = "hide",
++ [ QXL_CURSOR_TRAIL ] = "trail",
++};
++
++static const char *spice_cursor_type[] = {
++ [ SPICE_CURSOR_TYPE_ALPHA ] = "alpha",
++ [ SPICE_CURSOR_TYPE_MONO ] = "mono",
++ [ SPICE_CURSOR_TYPE_COLOR4 ] = "color4",
++ [ SPICE_CURSOR_TYPE_COLOR8 ] = "color8",
++ [ SPICE_CURSOR_TYPE_COLOR16 ] = "color16",
++ [ SPICE_CURSOR_TYPE_COLOR24 ] = "color24",
++ [ SPICE_CURSOR_TYPE_COLOR32 ] = "color32",
++};
++
++static const char *qxl_v2n(const char *n[], size_t l, int v)
++{
++ if (v >= l || !n[v])
++ return "???";
++ return n[v];
++}
++#define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
++
++static void qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw)
++{
++ fprintf(stderr, ": surface_id %d type %s effect %s",
++ draw->surface_id,
++ qxl_name(qxl_draw_type, draw->type),
++ qxl_name(qxl_draw_effect, draw->effect));
++}
++
++static void qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw)
++{
++ fprintf(stderr, ": type %s effect %s",
++ qxl_name(qxl_draw_type, draw->type),
++ qxl_name(qxl_draw_effect, draw->effect));
++}
++
++static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd)
++{
++ fprintf(stderr, ": %s id %d",
++ qxl_name(qxl_surface_cmd, cmd->type),
++ cmd->surface_id);
++ if (cmd->type == QXL_SURFACE_CMD_CREATE) {
++ fprintf(stderr, " size %dx%d stride %d format %s (count %d, max %d)",
++ cmd->u.surface_create.width,
++ cmd->u.surface_create.height,
++ cmd->u.surface_create.stride,
++ qxl_name(spice_surface_fmt, cmd->u.surface_create.format),
++ qxl->guest_surfaces.count, qxl->guest_surfaces.max);
++ }
++ if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
++ fprintf(stderr, " (count %d)", qxl->guest_surfaces.count);
++ }
++}
++
++void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id)
++{
++ QXLCursor *cursor;
++
++ fprintf(stderr, ": %s",
++ qxl_name(qxl_cursor_cmd, cmd->type));
++ switch (cmd->type) {
++ case QXL_CURSOR_SET:
++ fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64,
++ cmd->u.set.position.x,
++ cmd->u.set.position.y,
++ cmd->u.set.visible ? "yes" : "no",
++ cmd->u.set.shape);
++ cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id);
++ fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d"
++ " unique 0x%" PRIx64 " data-size %d",
++ qxl_name(spice_cursor_type, cursor->header.type),
++ cursor->header.width, cursor->header.height,
++ cursor->header.hot_spot_x, cursor->header.hot_spot_y,
++ cursor->header.unique, cursor->data_size);
++ break;
++ case QXL_CURSOR_MOVE:
++ fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y);
++ break;
++ }
++}
++
++void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
++{
++ bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT;
++ void *data;
++
++ if (!qxl->cmdlog) {
++ return;
++ }
++ fprintf(stderr, "qxl-%d/%s:", qxl->id, ring);
++ fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
++ qxl_name(qxl_type, ext->cmd.type),
++ compat ? "(compat)" : "");
++
++ data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
++ switch (ext->cmd.type) {
++ case QXL_CMD_DRAW:
++ if (!compat) {
++ qxl_log_cmd_draw(qxl, data);
++ } else {
++ qxl_log_cmd_draw_compat(qxl, data);
++ }
++ break;
++ case QXL_CMD_SURFACE:
++ qxl_log_cmd_surface(qxl, data);
++ break;
++ case QXL_CMD_CURSOR:
++ qxl_log_cmd_cursor(qxl, data, ext->group_id);
++ break;
++ }
++ fprintf(stderr, "\n");
++}
+diff -urN qemu-kvm-0.13.0.orig/hw/qxl-render.c qemu-kvm-0.13.0/hw/qxl-render.c
+--- qemu-kvm-0.13.0.orig/hw/qxl-render.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/hw/qxl-render.c 2011-02-09 11:08:02.766000327 +0200
+@@ -0,0 +1,207 @@
++/*
++ * qxl local rendering (aka display on sdl/vnc)
++ */
++#include <stdio.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <string.h>
++
++#include "qxl.h"
++
++static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
++{
++ uint8_t *src = qxl->guest_primary.data;
++ uint8_t *dst = qxl->guest_primary.flipped;
++ int len, i;
++
++ src += (qxl->guest_primary.surface.height - rect->top - 1) *
++ qxl->guest_primary.stride;
++ dst += rect->top * qxl->guest_primary.stride;
++ src += rect->left * qxl->guest_primary.bytes_pp;
++ dst += rect->left * qxl->guest_primary.bytes_pp;
++ len = (rect->right - rect->left) * qxl->guest_primary.bytes_pp;
++
++ for (i = rect->top; i < rect->bottom; i++) {
++ memcpy(dst, src, len);
++ dst += qxl->guest_primary.stride;
++ src -= qxl->guest_primary.stride;
++ }
++}
++
++void qxl_render_resize(PCIQXLDevice *qxl)
++{
++ QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
++
++ qxl->guest_primary.stride = sc->stride;
++ qxl->guest_primary.resized++;
++ switch (sc->format) {
++ case SPICE_SURFACE_FMT_16_555:
++ qxl->guest_primary.bytes_pp = 2;
++ qxl->guest_primary.bits_pp = 15;
++ break;
++ case SPICE_SURFACE_FMT_16_565:
++ qxl->guest_primary.bytes_pp = 2;
++ qxl->guest_primary.bits_pp = 16;
++ break;
++ case SPICE_SURFACE_FMT_32_xRGB:
++ case SPICE_SURFACE_FMT_32_ARGB:
++ qxl->guest_primary.bytes_pp = 4;
++ qxl->guest_primary.bits_pp = 32;
++ break;
++ default:
++ fprintf(stderr, "%s: unhandled format: %x\n", __FUNCTION__,
++ qxl->guest_primary.surface.format);
++ qxl->guest_primary.bytes_pp = 4;
++ qxl->guest_primary.bits_pp = 32;
++ break;
++ }
++}
++
++void qxl_render_update(PCIQXLDevice *qxl)
++{
++ VGACommonState *vga = &qxl->vga;
++ QXLRect dirty[32], update;
++ void *ptr;
++ int i;
++
++ if (qxl->guest_primary.resized) {
++ qxl->guest_primary.resized = 0;
++
++ if (qxl->guest_primary.flipped) {
++ qemu_free(qxl->guest_primary.flipped);
++ qxl->guest_primary.flipped = NULL;
++ }
++ qemu_free_displaysurface(vga->ds);
++
++ qxl->guest_primary.data = qemu_get_ram_ptr(qxl->vga.vram_offset);
++ if (qxl->guest_primary.stride < 0) {
++ /* spice surface is upside down -> need extra buffer to flip */
++ qxl->guest_primary.stride = -qxl->guest_primary.stride;
++ qxl->guest_primary.flipped = qemu_malloc(qxl->guest_primary.surface.width *
++ qxl->guest_primary.stride);
++ ptr = qxl->guest_primary.flipped;
++ } else {
++ ptr = qxl->guest_primary.data;
++ }
++ fprintf(stderr, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n",
++ __FUNCTION__,
++ qxl->guest_primary.surface.width,
++ qxl->guest_primary.surface.height,
++ qxl->guest_primary.stride,
++ qxl->guest_primary.bytes_pp,
++ qxl->guest_primary.bits_pp,
++ qxl->guest_primary.flipped ? "yes" : "no");
++ vga->ds->surface =
++ qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
++ qxl->guest_primary.surface.height,
++ qxl->guest_primary.bits_pp,
++ qxl->guest_primary.stride,
++ ptr);
++ dpy_resize(vga->ds);
++ }
++
++ if (!qxl->guest_primary.commands)
++ return;
++ qxl->guest_primary.commands = 0;
++
++ update.left = 0;
++ update.right = qxl->guest_primary.surface.width;
++ update.top = 0;
++ update.bottom = qxl->guest_primary.surface.height;
++
++ memset(dirty, 0, sizeof(dirty));
++ qxl->ssd.worker->update_area(qxl->ssd.worker, 0, &update,
++ dirty, ARRAY_SIZE(dirty), 1);
++
++ for (i = 0; i < ARRAY_SIZE(dirty); i++) {
++ if (qemu_spice_rect_is_empty(dirty+i))
++ break;
++ if (qxl->guest_primary.flipped) {
++ qxl_flip(qxl, dirty+i);
++ }
++ dpy_update(vga->ds,
++ dirty[i].left, dirty[i].top,
++ dirty[i].right - dirty[i].left,
++ dirty[i].bottom - dirty[i].top);
++ }
++}
++
++static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
++{
++ QEMUCursor *c;
++ uint8_t *image, *mask;
++ int size;
++
++ c = cursor_alloc(cursor->header.width, cursor->header.height);
++ c->hot_x = cursor->header.hot_spot_x;
++ c->hot_y = cursor->header.hot_spot_y;
++ switch (cursor->header.type) {
++ case SPICE_CURSOR_TYPE_ALPHA:
++ size = cursor->header.width * cursor->header.height * sizeof(uint32_t);
++ memcpy(c->data, cursor->chunk.data, size);
++ if (qxl->debug > 1)
++ cursor_print_ascii_art(c, "qxl/alpha");
++ break;
++ case SPICE_CURSOR_TYPE_MONO:
++ mask = cursor->chunk.data;
++ image = mask + cursor_get_mono_bpl(c) * c->width;
++ cursor_set_mono(c, 0xffffff, 0x000000, image, 1, mask);
++ if (qxl->debug > 1)
++ cursor_print_ascii_art(c, "qxl/mono");
++ break;
++ default:
++ fprintf(stderr, "%s: not implemented: type %d\n",
++ __FUNCTION__, cursor->header.type);
++ goto fail;
++ }
++ return c;
++
++fail:
++ cursor_put(c);
++ return NULL;
++}
++
++
++void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
++{
++ QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
++ QXLCursor *cursor;
++ QEMUCursor *c;
++ int x = -1, y = -1;
++
++ if (!qxl->ssd.ds->mouse_set ||
++ !qxl->ssd.ds->cursor_define)
++ return;
++
++#if 1
++ if (cmd->type != QXL_CURSOR_MOVE) {
++ fprintf(stderr, "%s", __FUNCTION__);
++ qxl_log_cmd_cursor(qxl, cmd, ext->group_id);
++ fprintf(stderr, "\n");
++ }
++#endif
++ switch (cmd->type) {
++ case QXL_CURSOR_SET:
++ x = cmd->u.set.position.x;
++ y = cmd->u.set.position.y;
++ cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id);
++ if (cursor->chunk.data_size != cursor->data_size) {
++ fprintf(stderr, "%s: multiple chunks\n", __FUNCTION__);
++ return;
++ }
++ c = qxl_cursor(qxl, cursor);
++ if (c == NULL) {
++ c = cursor_builtin_left_ptr();
++ }
++ qxl->ssd.ds->cursor_define(c);
++ cursor_put(c);
++ break;
++ case QXL_CURSOR_MOVE:
++ x = cmd->u.position.x;
++ y = cmd->u.position.y;
++ break;
++ }
++ if (x != -1 && y != -1) {
++ qxl->ssd.ds->mouse_set(x, y, 1);
++ }
++}
+diff -urN qemu-kvm-0.13.0.orig/hw/spice-vmc.c qemu-kvm-0.13.0/hw/spice-vmc.c
+--- qemu-kvm-0.13.0.orig/hw/spice-vmc.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/hw/spice-vmc.c 2011-02-09 11:08:02.891000327 +0200
+@@ -0,0 +1,262 @@
++/*
++
++ Spice Virtual Machine Channel (VMC).
++
++ A virtio-serial port used for spice to guest communication, over
++ which spice client and a daemon in the guest operating system
++ communicate.
++
++ Replaces the old vdi_port PCI device.
++
++*/
++
++#include <stdio.h>
++#include <stdbool.h>
++#include <spice.h>
++#include <spice-experimental.h>
++
++#include "virtio-serial.h"
++#include "qemu-spice.h"
++
++#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
++#define VMC_DEVICE_NAME "spicevmc"
++
++/* windows guest driver bug workaround */
++#define VMC_MAX_HOST_WRITE 2048
++
++#define dprintf(_svc, _level, _fmt, ...) \
++ do { \
++ static unsigned __dprintf_counter = 0; \
++ if (_svc->debug >= _level) { \
++ fprintf(stderr, "svc: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
++ } \
++ } while (0)
++
++typedef struct SpiceVirtualChannel {
++ VirtIOSerialPort port;
++ VMChangeStateEntry *vmstate;
++ SpiceCharDeviceInstance sin;
++ char *subtype;
++ bool active;
++ uint8_t *buffer;
++ uint8_t *datapos;
++ ssize_t bufsize, datalen;
++ uint32_t debug;
++} SpiceVirtualChannel;
++
++static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
++{
++ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
++ ssize_t out = 0;
++ ssize_t last_out;
++ uint8_t* p = (uint8_t*)buf;
++
++ while (len > 0) {
++ last_out = virtio_serial_write(&svc->port, p,
++ MIN(len, VMC_MAX_HOST_WRITE));
++ if (last_out > 0) {
++ out += last_out;
++ len -= last_out;
++ p += last_out;
++ } else {
++ break;
++ }
++ }
++
++ dprintf(svc, 3, "%s: %lu/%zd\n", __func__, out, len + out);
++ return out;
++}
++
++static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
++{
++ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
++ int bytes = MIN(len, svc->datalen);
++
++ dprintf(svc, 2, "%s: %p %d/%d/%zd\n", __func__, svc->datapos, len, bytes, svc->datalen);
++ if (bytes > 0) {
++ memcpy(buf, svc->datapos, bytes);
++ svc->datapos += bytes;
++ svc->datalen -= bytes;
++ assert(svc->datalen >= 0);
++ if (svc->datalen == 0) {
++ svc->datapos = 0;
++ virtio_serial_throttle_port(&svc->port, false);
++ // ^^^ !!! may call vmc_have_data, so don't touch svc after it!
++ }
++ }
++ return bytes;
++}
++
++static SpiceCharDeviceInterface vmc_interface = {
++ .base.type = SPICE_INTERFACE_CHAR_DEVICE,
++ .base.description = "spice virtual channel char device",
++ .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
++ .write = vmc_write,
++ .read = vmc_read,
++};
++
++static void vmc_register_interface(SpiceVirtualChannel *svc)
++{
++ if (svc->active) {
++ return;
++ }
++ dprintf(svc, 1, "%s\n", __func__);
++ svc->sin.base.sif = &vmc_interface.base;
++ spice_server_add_interface(spice_server, &svc->sin.base);
++ svc->active = true;
++}
++
++static void vmc_unregister_interface(SpiceVirtualChannel *svc)
++{
++ if (!svc->active) {
++ return;
++ }
++ dprintf(svc, 1, "%s\n", __func__);
++ spice_server_remove_interface(&svc->sin.base);
++ svc->active = false;
++}
++
++
++static void vmc_change_state_handler(void *opaque, int running, int reason)
++{
++ SpiceVirtualChannel *svc = opaque;
++
++ if (running && svc->active) {
++ spice_server_char_device_wakeup(&svc->sin);
++ }
++}
++
++/*
++ * virtio-serial callbacks
++ */
++
++static void vmc_guest_open(VirtIOSerialPort *port)
++{
++ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
++
++ dprintf(svc, 1, "%s\n", __func__);
++ vmc_register_interface(svc);
++}
++
++static void vmc_guest_close(VirtIOSerialPort *port)
++{
++ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
++
++ dprintf(svc, 1, "%s\n", __func__);
++ vmc_unregister_interface(svc);
++}
++
++static void vmc_guest_ready(VirtIOSerialPort *port)
++{
++ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
++
++ dprintf(svc, 1, "%s\n", __func__);
++ if (svc->active) {
++ spice_server_char_device_wakeup(&svc->sin);
++ }
++}
++
++static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
++{
++ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
++
++ dprintf(svc, 2, "%s: %zd\n", __func__, len);
++ assert(svc->datalen == 0);
++ if (svc->bufsize < len) {
++ svc->bufsize = len;
++ svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
++ }
++ memcpy(svc->buffer, buf, len);
++ svc->datapos = svc->buffer;
++ svc->datalen = len;
++ virtio_serial_throttle_port(&svc->port, true);
++ spice_server_char_device_wakeup(&svc->sin);
++}
++
++static void vmc_print_optional_subtypes(void)
++{
++ const char** psubtype = spice_server_char_device_recognized_subtypes();
++ int i;
++
++ fprintf(stderr, "supported subtypes: ");
++ for(i=0; *psubtype != NULL; ++psubtype, ++i) {
++ if (i == 0) {
++ fprintf(stderr, *psubtype);
++ } else {
++ fprintf(stderr, ", %s", *psubtype);
++ }
++ }
++ fprintf(stderr, "\n");
++}
++
++static int vmc_initfn(VirtIOSerialDevice *dev)
++{
++ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
++ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
++ const char** psubtype = spice_server_char_device_recognized_subtypes();
++ const char *subtype = NULL;
++
++ if (!using_spice) {
++ return -1;
++ }
++
++ dprintf(svc, 1, "%s\n", __func__);
++
++ if (svc->subtype == NULL) {
++ svc->subtype = strdup("vdagent");
++ }
++
++ for(;*psubtype != NULL; ++psubtype) {
++ if (strcmp(svc->subtype, *psubtype) == 0) {
++ subtype = *psubtype;
++ break;
++ }
++ }
++ if (subtype == NULL) {
++ fprintf(stderr, "spice-vmc: unsupported subtype\n");
++ vmc_print_optional_subtypes();
++ return -1;
++ }
++ port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
++ svc->vmstate = qemu_add_vm_change_state_handler
++ (vmc_change_state_handler, svc);
++ svc->sin.subtype = svc->subtype;
++ virtio_serial_open(port);
++ return 0;
++}
++
++static int vmc_exitfn(VirtIOSerialDevice *dev)
++{
++ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
++ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
++
++ dprintf(svc, 1, "%s\n", __func__);
++ vmc_unregister_interface(svc);
++ qemu_del_vm_change_state_handler(svc->vmstate);
++ virtio_serial_close(port);
++ return 0;
++}
++
++static VirtIOSerialPortInfo vmc_info = {
++ .qdev.name = VMC_DEVICE_NAME,
++ .qdev.size = sizeof(SpiceVirtualChannel),
++ .init = vmc_initfn,
++ .exit = vmc_exitfn,
++ .guest_open = vmc_guest_open,
++ .guest_close = vmc_guest_close,
++ .guest_ready = vmc_guest_ready,
++ .have_data = vmc_have_data,
++ .qdev.props = (Property[]) {
++ DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
++ DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
++ DEFINE_PROP_STRING("subtype", SpiceVirtualChannel, subtype),
++ DEFINE_PROP_END_OF_LIST(),
++ }
++};
++
++static void vmc_register(void)
++{
++ virtio_serial_port_qdev_register(&vmc_info);
++}
++device_init(vmc_register)
+diff -urN qemu-kvm-0.13.0.orig/hw/vga_int.h qemu-kvm-0.13.0/hw/vga_int.h
+--- qemu-kvm-0.13.0.orig/hw/vga_int.h 2011-02-09 11:01:45.856000328 +0200
++++ qemu-kvm-0.13.0/hw/vga_int.h 2011-02-09 11:08:02.771000327 +0200
+@@ -106,7 +106,7 @@
+ typedef struct VGACommonState {
+ uint8_t *vram_ptr;
+ ram_addr_t vram_offset;
+- unsigned int vram_size;
++ uint32_t vram_size;
+ uint32_t lfb_addr;
+ uint32_t lfb_end;
+ uint32_t map_addr;
+diff -urN qemu-kvm-0.13.0.orig/hw/vga-pci.c qemu-kvm-0.13.0/hw/vga-pci.c
+--- qemu-kvm-0.13.0.orig/hw/vga-pci.c 2011-02-09 11:01:45.855000328 +0200
++++ qemu-kvm-0.13.0/hw/vga-pci.c 2011-02-09 11:08:02.753000327 +0200
+@@ -81,6 +81,10 @@
+ VGACommonState *s = &d->vga;
+ uint8_t *pci_conf = d->dev.config;
+
++ if (dev->qdev.hotplugged) {
++ return -1;
++ }
++
+ // vga + console init
+ vga_common_init(s, VGA_RAM_SIZE);
+ vga_init(s);
+@@ -105,11 +109,10 @@
+ bios_total_size <<= 1;
+ pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
+ PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
++ } else {
++ if (dev->romfile == NULL)
++ dev->romfile = qemu_strdup("vgabios-stdvga.bin");
+ }
+-
+- vga_init_vbe(s);
+- /* ROM BIOS */
+- rom_add_vga(VGABIOS_FILENAME);
+ return 0;
+ }
+
+diff -urN qemu-kvm-0.13.0.orig/hw/virtio-pci.c qemu-kvm-0.13.0/hw/virtio-pci.c
+--- qemu-kvm-0.13.0.orig/hw/virtio-pci.c 2011-02-09 11:01:45.879000328 +0200
++++ qemu-kvm-0.13.0/hw/virtio-pci.c 2011-02-09 11:08:02.910000327 +0200
+@@ -427,11 +427,10 @@
+ }
+ }
+
+-static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
+- void *opaque, int masked)
++static int virtio_pci_mask_vq(PCIDevice *dev, unsigned vector,
++ VirtQueue *vq, int masked)
+ {
+ #ifdef CONFIG_KVM
+- VirtQueue *vq = opaque;
+ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
+ int r = kvm_set_irqfd(dev->msix_irq_entries[vector].gsi,
+ event_notifier_get_fd(notifier),
+@@ -452,6 +451,34 @@
+ #endif
+ }
+
++static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
++ int masked)
++{
++ VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
++ VirtIODevice *vdev = proxy->vdev;
++ int r, n;
++
++ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
++ if (!virtio_queue_get_num(vdev, n)) {
++ break;
++ }
++ if (virtio_queue_vector(vdev, n) != vector) {
++ continue;
++ }
++ r = virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), masked);
++ if (r < 0) {
++ goto undo;
++ }
++ }
++ return 0;
++undo:
++ while (--n >= 0) {
++ virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), !masked);
++ }
++ return r;
++}
++
++
+ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
+ {
+ VirtIOPCIProxy *proxy = opaque;
+@@ -465,11 +492,7 @@
+ }
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
+ virtio_pci_guest_notifier_read, NULL, vq);
+- msix_set_mask_notifier(&proxy->pci_dev,
+- virtio_queue_vector(proxy->vdev, n), vq);
+ } else {
+- msix_unset_mask_notifier(&proxy->pci_dev,
+- virtio_queue_vector(proxy->vdev, n));
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
+ NULL, NULL, NULL);
+ /* Test and clear notifier before closing it,
+@@ -487,6 +510,13 @@
+ VirtIODevice *vdev = proxy->vdev;
+ int r, n;
+
++ /* Must unset mask notifier while guest notifier
++ * is still assigned */
++ if (!assign) {
++ r = msix_unset_mask_notifier(&proxy->pci_dev);
++ assert(r >= 0);
++ }
++
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ break;
+@@ -498,6 +528,16 @@
+ }
+ }
+
++ /* Must set mask notifier after guest notifier
++ * has been assigned */
++ if (assign) {
++ r = msix_set_mask_notifier(&proxy->pci_dev,
++ virtio_pci_mask_notifier);
++ if (r < 0) {
++ goto assign_error;
++ }
++ }
++
+ return 0;
+
+ assign_error:
+@@ -583,8 +623,6 @@
+
+ proxy->pci_dev.config_write = virtio_write_config;
+
+- proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
+-
+ size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
+ if (size & (size-1))
+ size = 1 << qemu_fls(size);
+diff -urN qemu-kvm-0.13.0.orig/hw/vmmouse.c qemu-kvm-0.13.0/hw/vmmouse.c
+--- qemu-kvm-0.13.0.orig/hw/vmmouse.c 2011-02-09 11:01:45.879000328 +0200
++++ qemu-kvm-0.13.0/hw/vmmouse.c 2011-02-09 11:08:02.904000327 +0200
+@@ -100,16 +100,29 @@
+ i8042_isa_mouse_fake_event(s->ps2_mouse);
+ }
+
+-static void vmmouse_update_handler(VMMouseState *s)
++static void vmmouse_remove_handler(VMMouseState *s)
+ {
+ if (s->entry) {
+ qemu_remove_mouse_event_handler(s->entry);
+ s->entry = NULL;
+ }
+- if (s->status == 0)
++}
++
++static void vmmouse_update_handler(VMMouseState *s, int absolute)
++{
++ if (s->status != 0) {
++ return;
++ }
++ if (s->absolute != absolute) {
++ s->absolute = absolute;
++ vmmouse_remove_handler(s);
++ }
++ if (s->entry == NULL) {
+ s->entry = qemu_add_mouse_event_handler(vmmouse_mouse_event,
+ s, s->absolute,
+ "vmmouse");
++ qemu_activate_mouse_event_handler(s->entry);
++ }
+ }
+
+ static void vmmouse_read_id(VMMouseState *s)
+@@ -121,28 +134,25 @@
+
+ s->queue[s->nb_queue++] = VMMOUSE_VERSION;
+ s->status = 0;
+- vmmouse_update_handler(s);
+ }
+
+ static void vmmouse_request_relative(VMMouseState *s)
+ {
+ DPRINTF("vmmouse_request_relative()\n");
+- s->absolute = 0;
+- vmmouse_update_handler(s);
++ vmmouse_update_handler(s, 0);
+ }
+
+ static void vmmouse_request_absolute(VMMouseState *s)
+ {
+ DPRINTF("vmmouse_request_absolute()\n");
+- s->absolute = 1;
+- vmmouse_update_handler(s);
++ vmmouse_update_handler(s, 1);
+ }
+
+ static void vmmouse_disable(VMMouseState *s)
+ {
+ DPRINTF("vmmouse_disable()\n");
+ s->status = 0xffff;
+- vmmouse_update_handler(s);
++ vmmouse_remove_handler(s);
+ }
+
+ static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
+@@ -154,7 +164,7 @@
+ if (size == 0 || size > 6 || size > s->nb_queue) {
+ printf("vmmouse: driver requested too much data %d\n", size);
+ s->status = 0xffff;
+- vmmouse_update_handler(s);
++ vmmouse_remove_handler(s);
+ return;
+ }
+
+@@ -239,7 +249,8 @@
+ {
+ VMMouseState *s = opaque;
+
+- vmmouse_update_handler(s);
++ vmmouse_remove_handler(s);
++ vmmouse_update_handler(s, s->absolute);
+ return 0;
+ }
+
+diff -urN qemu-kvm-0.13.0.orig/hw/vmware_vga.c qemu-kvm-0.13.0/hw/vmware_vga.c
+--- qemu-kvm-0.13.0.orig/hw/vmware_vga.c 2011-02-09 11:01:45.878000328 +0200
++++ qemu-kvm-0.13.0/hw/vmware_vga.c 2011-02-09 11:08:02.754000327 +0200
+@@ -114,14 +114,12 @@
+ # define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
+ # define SVGA_IO_MUL 1
+ # define SVGA_FIFO_SIZE 0x10000
+-# define SVGA_MEM_BASE 0xe0000000
+ # define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2
+ #else
+ # define SVGA_ID SVGA_ID_1
+ # define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
+ # define SVGA_IO_MUL 4
+ # define SVGA_FIFO_SIZE 0x10000
+-# define SVGA_MEM_BASE 0xe0000000
+ # define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA
+ #endif
+
+@@ -1171,10 +1169,6 @@
+ vga_init(&s->vga);
+ vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
+
+- vga_init_vbe(&s->vga);
+-
+- rom_add_vga(VGABIOS_FILENAME);
+-
+ vmsvga_reset(s);
+ }
+
+@@ -1238,6 +1232,10 @@
+ struct pci_vmsvga_state_s *s =
+ DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
+
++ if (dev->qdev.hotplugged) {
++ return -1;
++ }
++
+ pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
+ pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
+ pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);
+@@ -1272,6 +1270,7 @@
+ .qdev.size = sizeof(struct pci_vmsvga_state_s),
+ .qdev.vmsd = &vmstate_vmware_vga,
+ .init = pci_vmsvga_initfn,
++ .romfile = "vgabios-vmware.bin",
+ };
+
+ static void vmsvga_register(void)
+diff -urN qemu-kvm-0.13.0.orig/Makefile qemu-kvm-0.13.0/Makefile
+--- qemu-kvm-0.13.0.orig/Makefile 2011-02-09 11:01:45.899000328 +0200
++++ qemu-kvm-0.13.0/Makefile 2011-02-09 11:08:02.739000327 +0200
+@@ -154,8 +154,9 @@
+ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
+
+ ifdef INSTALL_BLOBS
+-BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
+-video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
++BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
++vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-qxldev.bin \
++ppc_rom.bin video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
+ gpxe-eepro100-80861209.rom \
+ gpxe-eepro100-80861229.rom \
+ pxe-e1000.bin \
+diff -urN qemu-kvm-0.13.0.orig/Makefile.objs qemu-kvm-0.13.0/Makefile.objs
+--- qemu-kvm-0.13.0.orig/Makefile.objs 2011-02-09 11:01:45.720000328 +0200
++++ qemu-kvm-0.13.0/Makefile.objs 2011-02-09 11:08:02.778000327 +0200
+@@ -84,13 +84,17 @@
+ common-obj-y += msmouse.o ps2.o
+ common-obj-y += qdev.o qdev-properties.o
+ common-obj-y += block-migration.o
++common-obj-y += pflib.o
+
+ common-obj-$(CONFIG_BRLAPI) += baum.o
+ common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
+
++common-obj-$(CONFIG_SPICE) += spice.o spice-input.o spice-display.o
++
+ audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
+ audio-obj-$(CONFIG_SDL) += sdlaudio.o
+ audio-obj-$(CONFIG_OSS) += ossaudio.o
++audio-obj-$(CONFIG_SPICE) += spiceaudio.o
+ audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o
+ audio-obj-$(CONFIG_ALSA) += alsaaudio.o
+ audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o
+diff -urN qemu-kvm-0.13.0.orig/Makefile.target qemu-kvm-0.13.0/Makefile.target
+--- qemu-kvm-0.13.0.orig/Makefile.target 2011-02-09 11:01:45.776000327 +0200
++++ qemu-kvm-0.13.0/Makefile.target 2011-02-09 11:08:02.889000327 +0200
+@@ -219,6 +219,8 @@
+ obj-i386-y += pc_piix.o
+ obj-i386-y += testdev.o
+ obj-i386-y += acpi.o acpi_piix4.o
++obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
++obj-i386-$(CONFIG_SPICE) += spice-vmc.o
+
+ obj-i386-y += pcspk.o i8254.o
+ obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
+diff -urN qemu-kvm-0.13.0.orig/Makefile.target.orig qemu-kvm-0.13.0/Makefile.target.orig
+--- qemu-kvm-0.13.0.orig/Makefile.target.orig 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/Makefile.target.orig 2011-02-09 11:08:02.884000327 +0200
+@@ -0,0 +1,373 @@
++# -*- Mode: makefile -*-
++
++GENERATED_HEADERS = config-target.h
++CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
++
++include ../config-host.mak
++include config-devices.mak
++include config-target.mak
++include $(SRC_PATH)/rules.mak
++ifneq ($(HWDIR),)
++include $(HWDIR)/config.mak
++endif
++
++TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
++$(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw)
++QEMU_CFLAGS+= -I.. -I$(TARGET_PATH) -DNEED_CPU_H
++
++include $(SRC_PATH)/Makefile.objs
++
++ifdef CONFIG_USER_ONLY
++# user emulator name
++QEMU_PROG=qemu-$(TARGET_ARCH2)
++else
++# system emulator name
++ifeq ($(TARGET_ARCH), i386)
++QEMU_PROG=qemu$(EXESUF)
++else
++QEMU_PROG=qemu-system-$(TARGET_ARCH2)$(EXESUF)
++endif
++endif
++
++PROGS=$(QEMU_PROG)
++
++LIBS+=-lm
++
++kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
++
++CFLAGS += $(KVM_CFLAGS)
++
++config-target.h: config-target.h-timestamp
++config-target.h-timestamp: config-target.mak
++
++all: $(PROGS)
++
++# Dummy command so that make thinks it has done something
++ @true
++
++#########################################################
++# cpu emulator library
++libobj-y = exec.o cpu-exec.o
++libobj-$(CONFIG_NO_CPU_EMULATION) += fake-exec.o
++libobj-$(CONFIG_CPU_EMULATION) += translate-all.o translate.o
++libobj-$(CONFIG_CPU_EMULATION) += tcg/tcg.o
++libobj-$(CONFIG_SOFTFLOAT) += fpu/softfloat.o
++libobj-$(CONFIG_NOSOFTFLOAT) += fpu/softfloat-native.o
++libobj-y += op_helper.o helper.o
++ifeq ($(TARGET_BASE_ARCH), i386)
++libobj-y += cpuid.o
++endif
++libobj-$(CONFIG_NEED_MMU) += mmu.o
++
++libobj-$(CONFIG_KVM) += kvm-tpr-opt.o
++libobj-$(CONFIG_KVM) += qemu-kvm-helper.o
++
++libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
++
++libobj-y += disas.o
++
++$(libobj-y): $(GENERATED_HEADERS)
++
++# libqemu
++
++translate.o: translate.c cpu.h
++
++translate-all.o: translate-all.c cpu.h
++
++tcg/tcg.o: cpu.h
++
++# HELPER_CFLAGS is used for all the code compiled with static register
++# variables
++op_helper.o cpu-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
++
++# Note: this is a workaround. The real fix is to avoid compiling
++# cpu_signal_handler() in cpu-exec.c.
++signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
++
++qemu-kvm-helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
++
++#########################################################
++# Linux user emulator target
++
++ifdef CONFIG_LINUX_USER
++
++$(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
++
++QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
++obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
++ elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
++ qemu-malloc.o
++
++obj-$(TARGET_HAS_BFLT) += flatload.o
++
++obj-$(TARGET_I386) += vm86.o
++
++obj-i386-y += ioport-user.o
++
++nwfpe-obj-y = fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o
++nwfpe-obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o
++obj-arm-y += $(addprefix nwfpe/, $(nwfpe-obj-y))
++obj-arm-y += arm-semi.o
++
++obj-m68k-y += m68k-sim.o m68k-semi.o
++
++$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
++
++obj-y += $(addprefix ../libuser/, $(user-obj-y))
++obj-y += $(addprefix ../libdis-user/, $(libdis-y))
++obj-y += $(libobj-y)
++
++endif #CONFIG_LINUX_USER
++
++#########################################################
++# Darwin user emulator target
++
++ifdef CONFIG_DARWIN_USER
++
++$(call set-vpath, $(SRC_PATH)/darwin-user)
++
++QEMU_CFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
++
++# Leave some space for the regular program loading zone
++LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
++
++LIBS+=-lmx
++
++obj-y = main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \
++ gdbstub.o
++
++obj-i386-y += ioport-user.o
++
++$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
++
++obj-y += $(addprefix ../libuser/, $(user-obj-y))
++obj-y += $(addprefix ../libdis-user/, $(libdis-y))
++obj-y += $(libobj-y)
++
++endif #CONFIG_DARWIN_USER
++
++#########################################################
++# BSD user emulator target
++
++ifdef CONFIG_BSD_USER
++
++$(call set-vpath, $(SRC_PATH)/bsd-user)
++
++QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
++
++obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
++ gdbstub.o uaccess.o
++
++obj-i386-y += ioport-user.o
++
++$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
++
++obj-y += $(addprefix ../libuser/, $(user-obj-y))
++obj-y += $(addprefix ../libdis-user/, $(libdis-y))
++obj-y += $(libobj-y)
++
++endif #CONFIG_BSD_USER
++
++#########################################################
++# System emulator target
++ifdef CONFIG_SOFTMMU
++
++obj-y = arch_init.o cpus.o monitor.o pci.o machine.o gdbstub.o vl.o balloon.o
++# virtio has to be here due to weird dependency between PCI and virtio-net.
++# need to fix this properly
++obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
++obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
++obj-y += vhost_net.o
++obj-$(CONFIG_VHOST_NET) += vhost.o
++obj-$(CONFIG_VIRTFS) += virtio-9p.o
++obj-y += rwhandler.o
++obj-$(CONFIG_KVM) += kvm.o kvm-all.o
++obj-$(CONFIG_NO_KVM) += kvm-stub.o
++
++# MSI-X depends on kvm for interrupt injection,
++# so moved it from Makefile.objs to Makefile.target for now
++obj-y += msix.o
++
++LIBS+=-lz
++
++QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
++QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
++QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
++QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
++
++# xen backend driver support
++obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
++
++# USB layer
++obj-$(CONFIG_USB_OHCI) += usb-ohci.o
++
++# PCI network cards
++obj-y += rtl8139.o
++obj-y += e1000.o
++
++# Inter-VM PCI shared memory
++obj-$(CONFIG_KVM) += ivshmem.o
++
++# Hardware support
++obj-i386-y += vga.o
++obj-i386-y += mc146818rtc.o i8259.o pc.o
++obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
++obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
++obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
++obj-i386-y += extboot.o
++obj-i386-y += debugcon.o multiboot.o
++obj-i386-y += pc_piix.o
++obj-i386-y += testdev.o
++obj-i386-y += acpi.o acpi_piix4.o
++obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
++
++obj-i386-y += pcspk.o i8254.o
++obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
++obj-i386-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
++
++# Hardware support
++obj-ia64-y += ide.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
++obj-ia64-y += fdc.o mc146818rtc.o serial.o i8259.o ipf.o
++obj-ia64-y += cirrus_vga.o parallel.o acpi.o piix_pci.o
++obj-ia64-y += usb-uhci.o
++obj-ia64-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
++
++# shared objects
++obj-ppc-y = ppc.o
++obj-ppc-y += vga.o
++# PREP target
++obj-ppc-y += i8259.o mc146818rtc.o
++obj-ppc-y += ppc_prep.o
++# OldWorld PowerMac
++obj-ppc-y += ppc_oldworld.o
++# NewWorld PowerMac
++obj-ppc-y += ppc_newworld.o
++# PowerPC 4xx boards
++obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
++obj-ppc-y += ppc440.o ppc440_bamboo.o
++# PowerPC E500 boards
++obj-ppc-y += ppce500_mpc8544ds.o
++obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
++obj-ppc-$(CONFIG_FDT) += device_tree.o
++
++obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
++obj-mips-y += pcspk.o i8254.o
++obj-mips-y += acpi.o acpi_piix4.o
++obj-mips-y += mips_addr.o mips_timer.o mips_int.o
++obj-mips-y += vga.o i8259.o
++obj-mips-y += g364fb.o jazz_led.o
++obj-mips-y += gt64xxx.o mc146818rtc.o
++obj-mips-y += cirrus_vga.o
++obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
++
++obj-microblaze-y = petalogix_s3adsp1800_mmu.o
++
++obj-microblaze-y += microblaze_pic_cpu.o
++obj-microblaze-y += xilinx_intc.o
++obj-microblaze-y += xilinx_timer.o
++obj-microblaze-y += xilinx_uartlite.o
++obj-microblaze-y += xilinx_ethlite.o
++
++obj-microblaze-$(CONFIG_FDT) += device_tree.o
++
++# Boards
++obj-cris-y = cris_pic_cpu.o
++obj-cris-y += cris-boot.o
++obj-cris-y += etraxfs.o axis_dev88.o
++obj-cris-y += axis_dev88.o
++
++# IO blocks
++obj-cris-y += etraxfs_dma.o
++obj-cris-y += etraxfs_pic.o
++obj-cris-y += etraxfs_eth.o
++obj-cris-y += etraxfs_timer.o
++obj-cris-y += etraxfs_ser.o
++
++ifeq ($(TARGET_ARCH), sparc64)
++obj-sparc-y = sun4u.o apb_pci.o
++obj-sparc-y += vga.o
++obj-sparc-y += mc146818rtc.o
++obj-sparc-y += cirrus_vga.o
++else
++obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
++obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
++obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
++endif
++
++obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
++obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
++obj-arm-y += versatile_pci.o
++obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
++obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
++obj-arm-y += pl061.o
++obj-arm-y += arm-semi.o
++obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
++obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
++obj-arm-y += gumstix.o
++obj-arm-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
++obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
++ omap_gpio.o omap_intc.o omap_uart.o
++obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
++ omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
++obj-arm-y += omap_sx1.o palm.o tsc210x.o
++obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
++obj-arm-y += mst_fpga.o mainstone.o
++obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
++obj-arm-y += framebuffer.o
++obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
++obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
++obj-arm-y += syborg_virtio.o
++
++obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
++obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
++obj-sh4-y += ide/mmio.o
++
++obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
++obj-m68k-y += m68k-semi.o dummy_m68k.o
++
++obj-s390x-y = s390-virtio-bus.o s390-virtio.o
++
++obj-alpha-y = alpha_palcode.o
++
++ifeq ($(TARGET_ARCH), ia64)
++firmware.o: firmware.c
++ $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
++endif
++
++main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
++
++monitor.o: qemu-monitor.h
++
++$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
++
++obj-y += $(addprefix ../, $(common-obj-y))
++obj-y += $(addprefix ../libdis/, $(libdis-y))
++obj-y += $(libobj-y)
++obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
++
++endif # CONFIG_SOFTMMU
++
++obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
++
++$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
++ $(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y))
++
++
++gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh
++ $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
++
++qemu-monitor.h: $(SRC_PATH)/qemu-monitor.hx
++ $(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
++
++clean:
++ rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
++ rm -f *.d */*.d tcg/*.o ide/*.o
++ rm -f qemu-monitor.h gdbstub-xml.c
++
++install: all
++ifneq ($(PROGS),)
++ $(INSTALL) -m 755 $(STRIP_OPT) $(PROGS) "$(DESTDIR)$(bindir)"
++endif
++
++# Include automatically generated dependency files
++-include $(wildcard *.d */*.d)
+diff -urN qemu-kvm-0.13.0.orig/osdep.c qemu-kvm-0.13.0/osdep.c
+--- qemu-kvm-0.13.0.orig/osdep.c 2011-02-09 11:01:45.737000327 +0200
++++ qemu-kvm-0.13.0/osdep.c 2011-02-09 11:08:02.796000327 +0200
+@@ -100,7 +100,12 @@
+ #if defined(_POSIX_C_SOURCE) && !defined(__sun__)
+ int ret;
+ void *ptr;
++#if 0
+ ret = posix_memalign(&ptr, alignment, size);
++#else
++ ptr = memalign(alignment, size);
++ ret = (ptr == NULL) ? -1 : 0;
++#endif
+ if (ret != 0) {
+ fprintf(stderr, "Failed to allocate %zu B: %s\n",
+ size, strerror(ret));
+diff -urN qemu-kvm-0.13.0.orig/pflib.c qemu-kvm-0.13.0/pflib.c
+--- qemu-kvm-0.13.0.orig/pflib.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/pflib.c 2011-02-09 11:08:02.693000327 +0200
+@@ -0,0 +1,213 @@
++/*
++ * PixelFormat conversion library.
++ *
++ * Author: Gerd Hoffmann <kraxel@redhat.com>
++ *
++ * This work is licensed under the terms of the GNU GPL, version 2. See
++ * the COPYING file in the top-level directory.
++ *
++ */
++#include "qemu-common.h"
++#include "console.h"
++#include "pflib.h"
++
++typedef struct QemuPixel QemuPixel;
++
++typedef void (*pf_convert)(QemuPfConv *conv,
++ void *dst, void *src, uint32_t cnt);
++typedef void (*pf_convert_from)(PixelFormat *pf,
++ QemuPixel *dst, void *src, uint32_t cnt);
++typedef void (*pf_convert_to)(PixelFormat *pf,
++ void *dst, QemuPixel *src, uint32_t cnt);
++
++struct QemuPfConv {
++ pf_convert convert;
++ PixelFormat src;
++ PixelFormat dst;
++
++ /* for copy_generic() */
++ pf_convert_from conv_from;
++ pf_convert_to conv_to;
++ QemuPixel *conv_buf;
++ uint32_t conv_cnt;
++};
++
++struct QemuPixel {
++ uint8_t red;
++ uint8_t green;
++ uint8_t blue;
++ uint8_t alpha;
++};
++
++/* ----------------------------------------------------------------------- */
++/* PixelFormat -> QemuPixel conversions */
++
++static void conv_16_to_pixel(PixelFormat *pf,
++ QemuPixel *dst, void *src, uint32_t cnt)
++{
++ uint16_t *src16 = src;
++
++ while (cnt > 0) {
++ dst->red = ((*src16 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
++ dst->green = ((*src16 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
++ dst->blue = ((*src16 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
++ dst->alpha = ((*src16 & pf->amask) >> pf->ashift) << (8 - pf->abits);
++ dst++, src16++, cnt--;
++ }
++}
++
++/* assumes pf->{r,g,b,a}bits == 8 */
++static void conv_32_to_pixel_fast(PixelFormat *pf,
++ QemuPixel *dst, void *src, uint32_t cnt)
++{
++ uint32_t *src32 = src;
++
++ while (cnt > 0) {
++ dst->red = (*src32 & pf->rmask) >> pf->rshift;
++ dst->green = (*src32 & pf->gmask) >> pf->gshift;
++ dst->blue = (*src32 & pf->bmask) >> pf->bshift;
++ dst->alpha = (*src32 & pf->amask) >> pf->ashift;
++ dst++, src32++, cnt--;
++ }
++}
++
++static void conv_32_to_pixel_generic(PixelFormat *pf,
++ QemuPixel *dst, void *src, uint32_t cnt)
++{
++ uint32_t *src32 = src;
++
++ while (cnt > 0) {
++ if (pf->rbits < 8) {
++ dst->red = ((*src32 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
++ } else {
++ dst->red = ((*src32 & pf->rmask) >> pf->rshift) >> (pf->rbits - 8);
++ }
++ if (pf->gbits < 8) {
++ dst->green = ((*src32 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
++ } else {
++ dst->green = ((*src32 & pf->gmask) >> pf->gshift) >> (pf->gbits - 8);
++ }
++ if (pf->bbits < 8) {
++ dst->blue = ((*src32 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
++ } else {
++ dst->blue = ((*src32 & pf->bmask) >> pf->bshift) >> (pf->bbits - 8);
++ }
++ if (pf->abits < 8) {
++ dst->alpha = ((*src32 & pf->amask) >> pf->ashift) << (8 - pf->abits);
++ } else {
++ dst->alpha = ((*src32 & pf->amask) >> pf->ashift) >> (pf->abits - 8);
++ }
++ dst++, src32++, cnt--;
++ }
++}
++
++/* ----------------------------------------------------------------------- */
++/* QemuPixel -> PixelFormat conversions */
++
++static void conv_pixel_to_16(PixelFormat *pf,
++ void *dst, QemuPixel *src, uint32_t cnt)
++{
++ uint16_t *dst16 = dst;
++
++ while (cnt > 0) {
++ *dst16 = ((uint16_t)src->red >> (8 - pf->rbits)) << pf->rshift;
++ *dst16 |= ((uint16_t)src->green >> (8 - pf->gbits)) << pf->gshift;
++ *dst16 |= ((uint16_t)src->blue >> (8 - pf->bbits)) << pf->bshift;
++ *dst16 |= ((uint16_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
++ dst16++, src++, cnt--;
++ }
++}
++
++static void conv_pixel_to_32(PixelFormat *pf,
++ void *dst, QemuPixel *src, uint32_t cnt)
++{
++ uint32_t *dst32 = dst;
++
++ while (cnt > 0) {
++ *dst32 = ((uint32_t)src->red >> (8 - pf->rbits)) << pf->rshift;
++ *dst32 |= ((uint32_t)src->green >> (8 - pf->gbits)) << pf->gshift;
++ *dst32 |= ((uint32_t)src->blue >> (8 - pf->bbits)) << pf->bshift;
++ *dst32 |= ((uint32_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
++ dst32++, src++, cnt--;
++ }
++}
++
++/* ----------------------------------------------------------------------- */
++/* PixelFormat -> PixelFormat conversions */
++
++static void convert_copy(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
++{
++ uint32_t bytes = cnt * conv->src.bytes_per_pixel;
++ memcpy(dst, src, bytes);
++}
++
++static void convert_generic(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
++{
++ if (conv->conv_cnt < cnt) {
++ conv->conv_cnt = cnt;
++ conv->conv_buf = qemu_realloc(conv->conv_buf, sizeof(QemuPixel) * conv->conv_cnt);
++ }
++ conv->conv_from(&conv->src, conv->conv_buf, src, cnt);
++ conv->conv_to(&conv->dst, dst, conv->conv_buf, cnt);
++}
++
++/* ----------------------------------------------------------------------- */
++/* public interface */
++
++QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src)
++{
++ QemuPfConv *conv = qemu_mallocz(sizeof(QemuPfConv));
++
++ conv->src = *src;
++ conv->dst = *dst;
++
++ if (memcmp(&conv->src, &conv->dst, sizeof(PixelFormat)) == 0) {
++ /* formats identical, can simply copy */
++ conv->convert = convert_copy;
++ } else {
++ /* generic two-step conversion: src -> QemuPixel -> dst */
++ switch (conv->src.bytes_per_pixel) {
++ case 2:
++ conv->conv_from = conv_16_to_pixel;
++ break;
++ case 4:
++ if (conv->src.rbits == 8 && conv->src.gbits == 8 && conv->src.bbits == 8) {
++ conv->conv_from = conv_32_to_pixel_fast;
++ } else {
++ conv->conv_from = conv_32_to_pixel_generic;
++ }
++ break;
++ default:
++ goto err;
++ }
++ switch (conv->dst.bytes_per_pixel) {
++ case 2:
++ conv->conv_to = conv_pixel_to_16;
++ break;
++ case 4:
++ conv->conv_to = conv_pixel_to_32;
++ break;
++ default:
++ goto err;
++ }
++ conv->convert = convert_generic;
++ }
++ return conv;
++
++err:
++ qemu_free(conv);
++ return NULL;
++}
++
++void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
++{
++ conv->convert(conv, dst, src, cnt);
++}
++
++void qemu_pf_conv_put(QemuPfConv *conv)
++{
++ if (conv) {
++ qemu_free(conv->conv_buf);
++ qemu_free(conv);
++ }
++}
+diff -urN qemu-kvm-0.13.0.orig/pflib.h qemu-kvm-0.13.0/pflib.h
+--- qemu-kvm-0.13.0.orig/pflib.h 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/pflib.h 2011-02-09 11:08:02.693000327 +0200
+@@ -0,0 +1,6 @@
++/* public */
++typedef struct QemuPfConv QemuPfConv;
++
++QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src);
++void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt);
++void qemu_pf_conv_put(QemuPfConv *conv);
+diff -urN qemu-kvm-0.13.0.orig/qemu-config.c qemu-kvm-0.13.0/qemu-config.c
+--- qemu-kvm-0.13.0.orig/qemu-config.c 2011-02-09 11:01:45.719000328 +0200
++++ qemu-kvm-0.13.0/qemu-config.c 2011-02-09 11:08:02.832000327 +0200
+@@ -346,6 +346,56 @@
+ },
+ };
+
++#ifdef CONFIG_SPICE
++QemuOptsList qemu_spice_opts = {
++ .name = "spice",
++ .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
++ .desc = {
++ {
++ .name = "port",
++ .type = QEMU_OPT_NUMBER,
++ },{
++ .name = "tls-port",
++ .type = QEMU_OPT_NUMBER,
++ },{
++ .name = "password",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "disable-ticketing",
++ .type = QEMU_OPT_BOOL,
++ },{
++ .name = "x509-dir",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "x509-key-file",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "x509-key-password",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "x509-cert-file",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "x509-cacert-file",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "x509-dh-key-file",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "tls-ciphers",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "jpeg",
++ .type = QEMU_OPT_STRING,
++ },{
++ .name = "zlib-glz",
++ .type = QEMU_OPT_STRING,
++ },
++ { /* end if list */ }
++ },
++};
++#endif
++
+ static QemuOptsList *vm_config_groups[] = {
+ &qemu_drive_opts,
+ &qemu_chardev_opts,
+@@ -356,6 +406,9 @@
+ &qemu_global_opts,
+ &qemu_mon_opts,
+ &qemu_cpudef_opts,
++#ifdef CONFIG_SPICE
++ &qemu_spice_opts,
++#endif
+ NULL,
+ };
+
+diff -urN qemu-kvm-0.13.0.orig/qemu-config.h qemu-kvm-0.13.0/qemu-config.h
+--- qemu-kvm-0.13.0.orig/qemu-config.h 2011-02-09 11:01:45.735000327 +0200
++++ qemu-kvm-0.13.0/qemu-config.h 2011-02-09 11:08:02.709000327 +0200
+@@ -14,6 +14,7 @@
+ extern QemuOptsList qemu_global_opts;
+ extern QemuOptsList qemu_mon_opts;
+ extern QemuOptsList qemu_cpudef_opts;
++extern QemuOptsList qemu_spice_opts;
+
+ QemuOptsList *qemu_find_opts(const char *group);
+ int qemu_set_option(const char *str);
+diff -urN qemu-kvm-0.13.0.orig/qemu-monitor.hx.orig qemu-kvm-0.13.0/qemu-monitor.hx.orig
+--- qemu-kvm-0.13.0.orig/qemu-monitor.hx.orig 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/qemu-monitor.hx.orig 2011-02-09 11:08:02.803000327 +0200
+@@ -0,0 +1,2560 @@
++HXCOMM Use DEFHEADING() to define headings in both help text and texi
++HXCOMM Text between STEXI and ETEXI are copied to texi version and
++HXCOMM discarded from C version
++HXCOMM Text between SQMP and EQMP is copied to the QMP documention file and
++HXCOMM does not show up in the other formats.
++HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
++HXCOMM monitor commands
++HXCOMM HXCOMM can be used for comments, discarded from both texi and C
++
++SQMP
++ QMP Supported Commands
++ ----------------------
++
++This document describes all commands currently supported by QMP.
++
++Most of the time their usage is exactly the same as in the user Monitor, this
++means that any other document which also describe commands (the manpage,
++QEMU's manual, etc) can and should be consulted.
++
++QMP has two types of commands: regular and query commands. Regular commands
++usually change the Virtual Machine's state someway, while query commands just
++return information. The sections below are divided accordingly.
++
++It's important to observe that all communication examples are formatted in
++a reader-friendly way, so that they're easier to understand. However, in real
++protocol usage, they're emitted as a single line.
++
++Also, the following notation is used to denote data flow:
++
++-> data issued by the Client
++<- Server data response
++
++Please, refer to the QMP specification (QMP/qmp-spec.txt) for detailed
++information on the Server command and response formats.
++
++NOTE: This document is temporary and will be replaced soon.
++
++1. Stability Considerations
++===========================
++
++The current QMP command set (described in this file) may be useful for a
++number of use cases, however it's limited and several commands have bad
++defined semantics, specially with regard to command completion.
++
++These problems are going to be solved incrementally in the next QEMU releases
++and we're going to establish a deprecation policy for badly defined commands.
++
++If you're planning to adopt QMP, please observe the following:
++
++ 1. The deprecation policy will take efect and be documented soon, please
++ check the documentation of each used command as soon as a new release of
++ QEMU is available
++
++ 2. DO NOT rely on anything which is not explicit documented
++
++ 3. Errors, in special, are not documented. Applications should NOT check
++ for specific errors classes or data (it's strongly recommended to only
++ check for the "error" key)
++
++2. Regular Commands
++===================
++
++Server's responses in the examples below are always a success response, please
++refer to the QMP specification for more details on error responses.
++
++EQMP
++
++STEXI
++@table @option
++ETEXI
++
++ {
++ .name = "help|?",
++ .args_type = "name:s?",
++ .params = "[cmd]",
++ .help = "show the help",
++ .mhandler.cmd = do_help_cmd,
++ },
++
++STEXI
++@item help or ? [@var{cmd}]
++@findex help
++Show the help for all commands or just for command @var{cmd}.
++ETEXI
++
++ {
++ .name = "commit",
++ .args_type = "device:B",
++ .params = "device|all",
++ .help = "commit changes to the disk images (if -snapshot is used) or backing files",
++ .mhandler.cmd = do_commit,
++ },
++
++STEXI
++@item commit
++@findex commit
++Commit changes to the disk images (if -snapshot is used) or backing files.
++ETEXI
++
++ {
++ .name = "q|quit",
++ .args_type = "",
++ .params = "",
++ .help = "quit the emulator",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_quit,
++ },
++
++STEXI
++@item q or quit
++@findex quit
++Quit the emulator.
++ETEXI
++SQMP
++quit
++----
++
++Quit the emulator.
++
++Arguments: None.
++
++Example:
++
++-> { "execute": "quit" }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "eject",
++ .args_type = "force:-f,device:B",
++ .params = "[-f] device",
++ .help = "eject a removable medium (use -f to force it)",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_eject,
++ },
++
++STEXI
++@item eject [-f] @var{device}
++@findex eject
++Eject a removable medium (use -f to force it).
++ETEXI
++SQMP
++eject
++-----
++
++Eject a removable medium.
++
++Arguments:
++
++- force: force ejection (json-bool, optional)
++- device: device name (json-string)
++
++Example:
++
++-> { "execute": "eject", "arguments": { "device": "ide1-cd0" } }
++<- { "return": {} }
++
++Note: The "force" argument defaults to false.
++
++EQMP
++
++ {
++ .name = "change",
++ .args_type = "device:B,target:F,arg:s?",
++ .params = "device filename [format]",
++ .help = "change a removable medium, optional format",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_change,
++ },
++
++STEXI
++@item change @var{device} @var{setting}
++@findex change
++
++Change the configuration of a device.
++
++@table @option
++@item change @var{diskdevice} @var{filename} [@var{format}]
++Change the medium for a removable disk device to point to @var{filename}. eg
++
++@example
++(qemu) change ide1-cd0 /path/to/some.iso
++@end example
++
++@var{format} is optional.
++
++@item change vnc @var{display},@var{options}
++Change the configuration of the VNC server. The valid syntax for @var{display}
++and @var{options} are described at @ref{sec_invocation}. eg
++
++@example
++(qemu) change vnc localhost:1
++@end example
++
++@item change vnc password [@var{password}]
++
++Change the password associated with the VNC server. If the new password is not
++supplied, the monitor will prompt for it to be entered. VNC passwords are only
++significant up to 8 letters. eg
++
++@example
++(qemu) change vnc password
++Password: ********
++@end example
++
++@end table
++ETEXI
++SQMP
++change
++------
++
++Change a removable medium or VNC configuration.
++
++Arguments:
++
++- "device": device name (json-string)
++- "target": filename or item (json-string)
++- "arg": additional argument (json-string, optional)
++
++Examples:
++
++1. Change a removable medium
++
++-> { "execute": "change",
++ "arguments": { "device": "ide1-cd0",
++ "target": "/srv/images/Fedora-12-x86_64-DVD.iso" } }
++<- { "return": {} }
++
++2. Change VNC password
++
++-> { "execute": "change",
++ "arguments": { "device": "vnc", "target": "password",
++ "arg": "foobar1" } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "screendump",
++ .args_type = "filename:F",
++ .params = "filename",
++ .help = "save screen into PPM image 'filename'",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_screen_dump,
++ },
++
++STEXI
++@item screendump @var{filename}
++@findex screendump
++Save screen into PPM image @var{filename}.
++ETEXI
++SQMP
++screendump
++----------
++
++Save screen into PPM image.
++
++Arguments:
++
++- "filename": file path (json-string)
++
++Example:
++
++-> { "execute": "screendump", "arguments": { "filename": "/tmp/image" } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "logfile",
++ .args_type = "filename:F",
++ .params = "filename",
++ .help = "output logs to 'filename'",
++ .mhandler.cmd = do_logfile,
++ },
++
++STEXI
++@item logfile @var{filename}
++@findex logfile
++Output logs to @var{filename}.
++ETEXI
++
++ {
++ .name = "log",
++ .args_type = "items:s",
++ .params = "item1[,...]",
++ .help = "activate logging of the specified items to '/tmp/qemu.log'",
++ .mhandler.cmd = do_log,
++ },
++
++STEXI
++@item log @var{item1}[,...]
++@findex log
++Activate logging of the specified items to @file{/tmp/qemu.log}.
++ETEXI
++
++ {
++ .name = "savevm",
++ .args_type = "name:s?",
++ .params = "[tag|id]",
++ .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
++ .mhandler.cmd = do_savevm,
++ },
++
++STEXI
++@item savevm [@var{tag}|@var{id}]
++@findex savevm
++Create a snapshot of the whole virtual machine. If @var{tag} is
++provided, it is used as human readable identifier. If there is already
++a snapshot with the same tag or ID, it is replaced. More info at
++@ref{vm_snapshots}.
++ETEXI
++
++ {
++ .name = "loadvm",
++ .args_type = "name:s",
++ .params = "tag|id",
++ .help = "restore a VM snapshot from its tag or id",
++ .mhandler.cmd = do_loadvm,
++ },
++
++STEXI
++@item loadvm @var{tag}|@var{id}
++@findex loadvm
++Set the whole virtual machine to the snapshot identified by the tag
++@var{tag} or the unique snapshot ID @var{id}.
++ETEXI
++
++ {
++ .name = "delvm",
++ .args_type = "name:s",
++ .params = "tag|id",
++ .help = "delete a VM snapshot from its tag or id",
++ .mhandler.cmd = do_delvm,
++ },
++
++STEXI
++@item delvm @var{tag}|@var{id}
++@findex delvm
++Delete the snapshot identified by @var{tag} or @var{id}.
++ETEXI
++
++ {
++ .name = "singlestep",
++ .args_type = "option:s?",
++ .params = "[on|off]",
++ .help = "run emulation in singlestep mode or switch to normal mode",
++ .mhandler.cmd = do_singlestep,
++ },
++
++STEXI
++@item singlestep [off]
++@findex singlestep
++Run the emulation in single step mode.
++If called with option off, the emulation returns to normal mode.
++ETEXI
++
++ {
++ .name = "stop",
++ .args_type = "",
++ .params = "",
++ .help = "stop emulation",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_stop,
++ },
++
++STEXI
++@item stop
++@findex stop
++Stop emulation.
++ETEXI
++SQMP
++stop
++----
++
++Stop the emulator.
++
++Arguments: None.
++
++Example:
++
++-> { "execute": "stop" }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "c|cont",
++ .args_type = "",
++ .params = "",
++ .help = "resume emulation",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_cont,
++ },
++
++STEXI
++@item c or cont
++@findex cont
++Resume emulation.
++ETEXI
++SQMP
++cont
++----
++
++Resume emulation.
++
++Arguments: None.
++
++Example:
++
++-> { "execute": "cont" }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "gdbserver",
++ .args_type = "device:s?",
++ .params = "[device]",
++ .help = "start gdbserver on given device (default 'tcp::1234'), stop with 'none'",
++ .mhandler.cmd = do_gdbserver,
++ },
++
++STEXI
++@item gdbserver [@var{port}]
++@findex gdbserver
++Start gdbserver session (default @var{port}=1234)
++ETEXI
++
++ {
++ .name = "x",
++ .args_type = "fmt:/,addr:l",
++ .params = "/fmt addr",
++ .help = "virtual memory dump starting at 'addr'",
++ .mhandler.cmd = do_memory_dump,
++ },
++
++STEXI
++@item x/fmt @var{addr}
++@findex x
++Virtual memory dump starting at @var{addr}.
++ETEXI
++
++ {
++ .name = "xp",
++ .args_type = "fmt:/,addr:l",
++ .params = "/fmt addr",
++ .help = "physical memory dump starting at 'addr'",
++ .mhandler.cmd = do_physical_memory_dump,
++ },
++
++STEXI
++@item xp /@var{fmt} @var{addr}
++@findex xp
++Physical memory dump starting at @var{addr}.
++
++@var{fmt} is a format which tells the command how to format the
++data. Its syntax is: @option{/@{count@}@{format@}@{size@}}
++
++@table @var
++@item count
++is the number of items to be dumped.
++
++@item format
++can be x (hex), d (signed decimal), u (unsigned decimal), o (octal),
++c (char) or i (asm instruction).
++
++@item size
++can be b (8 bits), h (16 bits), w (32 bits) or g (64 bits). On x86,
++@code{h} or @code{w} can be specified with the @code{i} format to
++respectively select 16 or 32 bit code instruction size.
++
++@end table
++
++Examples:
++@itemize
++@item
++Dump 10 instructions at the current instruction pointer:
++@example
++(qemu) x/10i $eip
++0x90107063: ret
++0x90107064: sti
++0x90107065: lea 0x0(%esi,1),%esi
++0x90107069: lea 0x0(%edi,1),%edi
++0x90107070: ret
++0x90107071: jmp 0x90107080
++0x90107073: nop
++0x90107074: nop
++0x90107075: nop
++0x90107076: nop
++@end example
++
++@item
++Dump 80 16 bit values at the start of the video memory.
++@smallexample
++(qemu) xp/80hx 0xb8000
++0x000b8000: 0x0b50 0x0b6c 0x0b65 0x0b78 0x0b38 0x0b36 0x0b2f 0x0b42
++0x000b8010: 0x0b6f 0x0b63 0x0b68 0x0b73 0x0b20 0x0b56 0x0b47 0x0b41
++0x000b8020: 0x0b42 0x0b69 0x0b6f 0x0b73 0x0b20 0x0b63 0x0b75 0x0b72
++0x000b8030: 0x0b72 0x0b65 0x0b6e 0x0b74 0x0b2d 0x0b63 0x0b76 0x0b73
++0x000b8040: 0x0b20 0x0b30 0x0b35 0x0b20 0x0b4e 0x0b6f 0x0b76 0x0b20
++0x000b8050: 0x0b32 0x0b30 0x0b30 0x0b33 0x0720 0x0720 0x0720 0x0720
++0x000b8060: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
++0x000b8070: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
++0x000b8080: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
++0x000b8090: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
++@end smallexample
++@end itemize
++ETEXI
++
++ {
++ .name = "p|print",
++ .args_type = "fmt:/,val:l",
++ .params = "/fmt expr",
++ .help = "print expression value (use $reg for CPU register access)",
++ .mhandler.cmd = do_print,
++ },
++
++STEXI
++@item p or print/@var{fmt} @var{expr}
++@findex print
++
++Print expression value. Only the @var{format} part of @var{fmt} is
++used.
++ETEXI
++
++ {
++ .name = "i",
++ .args_type = "fmt:/,addr:i,index:i.",
++ .params = "/fmt addr",
++ .help = "I/O port read",
++ .mhandler.cmd = do_ioport_read,
++ },
++
++STEXI
++Read I/O port.
++ETEXI
++
++ {
++ .name = "o",
++ .args_type = "fmt:/,addr:i,val:i",
++ .params = "/fmt addr value",
++ .help = "I/O port write",
++ .mhandler.cmd = do_ioport_write,
++ },
++
++STEXI
++Write to I/O port.
++ETEXI
++
++ {
++ .name = "sendkey",
++ .args_type = "string:s,hold_time:i?",
++ .params = "keys [hold_ms]",
++ .help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
++ .mhandler.cmd = do_sendkey,
++ },
++
++STEXI
++@item sendkey @var{keys}
++@findex sendkey
++
++Send @var{keys} to the emulator. @var{keys} could be the name of the
++key or @code{#} followed by the raw value in either decimal or hexadecimal
++format. Use @code{-} to press several keys simultaneously. Example:
++@example
++sendkey ctrl-alt-f1
++@end example
++
++This command is useful to send keys that your graphical user interface
++intercepts at low level, such as @code{ctrl-alt-f1} in X Window.
++ETEXI
++
++ {
++ .name = "system_reset",
++ .args_type = "",
++ .params = "",
++ .help = "reset the system",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_system_reset,
++ },
++
++STEXI
++@item system_reset
++@findex system_reset
++
++Reset the system.
++ETEXI
++SQMP
++system_reset
++------------
++
++Reset the system.
++
++Arguments: None.
++
++Example:
++
++-> { "execute": "system_reset" }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "system_powerdown",
++ .args_type = "",
++ .params = "",
++ .help = "send system power down event",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_system_powerdown,
++ },
++
++STEXI
++@item system_powerdown
++@findex system_powerdown
++
++Power down the system (if supported).
++ETEXI
++SQMP
++system_powerdown
++----------------
++
++Send system power down event.
++
++Arguments: None.
++
++Example:
++
++-> { "execute": "system_powerdown" }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "sum",
++ .args_type = "start:i,size:i",
++ .params = "addr size",
++ .help = "compute the checksum of a memory region",
++ .mhandler.cmd = do_sum,
++ },
++
++STEXI
++@item sum @var{addr} @var{size}
++@findex sum
++
++Compute the checksum of a memory region.
++ETEXI
++
++ {
++ .name = "usb_add",
++ .args_type = "devname:s",
++ .params = "device",
++ .help = "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')",
++ .mhandler.cmd = do_usb_add,
++ },
++
++STEXI
++@item usb_add @var{devname}
++@findex usb_add
++
++Add the USB device @var{devname}. For details of available devices see
++@ref{usb_devices}
++ETEXI
++
++ {
++ .name = "usb_del",
++ .args_type = "devname:s",
++ .params = "device",
++ .help = "remove USB device 'bus.addr'",
++ .mhandler.cmd = do_usb_del,
++ },
++
++STEXI
++@item usb_del @var{devname}
++@findex usb_del
++
++Remove the USB device @var{devname} from the QEMU virtual USB
++hub. @var{devname} has the syntax @code{bus.addr}. Use the monitor
++command @code{info usb} to see the devices you can remove.
++ETEXI
++
++ {
++ .name = "device_add",
++ .args_type = "device:O",
++ .params = "driver[,prop=value][,...]",
++ .help = "add device, like -device on the command line",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_device_add,
++ },
++
++STEXI
++@item device_add @var{config}
++@findex device_add
++
++Add device.
++ETEXI
++SQMP
++device_add
++----------
++
++Add a device.
++
++Arguments:
++
++- "driver": the name of the new device's driver (json-string)
++- "bus": the device's parent bus (device tree path, json-string, optional)
++- "id": the device's ID, must be unique (json-string)
++- device properties
++
++Example:
++
++-> { "execute": "device_add", "arguments": { "driver": "e1000", "id": "net1" } }
++<- { "return": {} }
++
++Notes:
++
++(1) For detailed information about this command, please refer to the
++ 'docs/qdev-device-use.txt' file.
++
++(2) It's possible to list device properties by running QEMU with the
++ "-device DEVICE,\?" command-line argument, where DEVICE is the device's name
++
++EQMP
++
++ {
++ .name = "device_del",
++ .args_type = "id:s",
++ .params = "device",
++ .help = "remove device",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_device_del,
++ },
++
++STEXI
++@item device_del @var{id}
++@findex device_del
++
++Remove device @var{id}.
++ETEXI
++SQMP
++device_del
++----------
++
++Remove a device.
++
++Arguments:
++
++- "id": the device's ID (json-string)
++
++Example:
++
++-> { "execute": "device_del", "arguments": { "id": "net1" } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "cpu",
++ .args_type = "index:i",
++ .params = "index",
++ .help = "set the default CPU",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_cpu_set,
++ },
++
++STEXI
++@item cpu @var{index}
++@findex cpu
++Set the default CPU.
++ETEXI
++SQMP
++cpu
++---
++
++Set the default CPU.
++
++Arguments:
++
++- "index": the CPU's index (json-int)
++
++Example:
++
++-> { "execute": "cpu", "arguments": { "index": 0 } }
++<- { "return": {} }
++
++Note: CPUs' indexes are obtained with the 'query-cpus' command.
++
++EQMP
++
++ {
++ .name = "mouse_move",
++ .args_type = "dx_str:s,dy_str:s,dz_str:s?",
++ .params = "dx dy [dz]",
++ .help = "send mouse move events",
++ .mhandler.cmd = do_mouse_move,
++ },
++
++STEXI
++@item mouse_move @var{dx} @var{dy} [@var{dz}]
++@findex mouse_move
++Move the active mouse to the specified coordinates @var{dx} @var{dy}
++with optional scroll axis @var{dz}.
++ETEXI
++
++ {
++ .name = "mouse_button",
++ .args_type = "button_state:i",
++ .params = "state",
++ .help = "change mouse button state (1=L, 2=M, 4=R)",
++ .mhandler.cmd = do_mouse_button,
++ },
++
++STEXI
++@item mouse_button @var{val}
++@findex mouse_button
++Change the active mouse button state @var{val} (1=L, 2=M, 4=R).
++ETEXI
++
++ {
++ .name = "mouse_set",
++ .args_type = "index:i",
++ .params = "index",
++ .help = "set which mouse device receives events",
++ .mhandler.cmd = do_mouse_set,
++ },
++
++STEXI
++@item mouse_set @var{index}
++@findex mouse_set
++Set which mouse device receives events at given @var{index}, index
++can be obtained with
++@example
++info mice
++@end example
++ETEXI
++
++#ifdef HAS_AUDIO
++ {
++ .name = "wavcapture",
++ .args_type = "path:F,freq:i?,bits:i?,nchannels:i?",
++ .params = "path [frequency [bits [channels]]]",
++ .help = "capture audio to a wave file (default frequency=44100 bits=16 channels=2)",
++ .mhandler.cmd = do_wav_capture,
++ },
++#endif
++STEXI
++@item wavcapture @var{filename} [@var{frequency} [@var{bits} [@var{channels}]]]
++@findex wavcapture
++Capture audio into @var{filename}. Using sample rate @var{frequency}
++bits per sample @var{bits} and number of channels @var{channels}.
++
++Defaults:
++@itemize @minus
++@item Sample rate = 44100 Hz - CD quality
++@item Bits = 16
++@item Number of channels = 2 - Stereo
++@end itemize
++ETEXI
++
++#ifdef HAS_AUDIO
++ {
++ .name = "stopcapture",
++ .args_type = "n:i",
++ .params = "capture index",
++ .help = "stop capture",
++ .mhandler.cmd = do_stop_capture,
++ },
++#endif
++STEXI
++@item stopcapture @var{index}
++@findex stopcapture
++Stop capture with a given @var{index}, index can be obtained with
++@example
++info capture
++@end example
++ETEXI
++
++ {
++ .name = "memsave",
++ .args_type = "val:l,size:i,filename:s",
++ .params = "addr size file",
++ .help = "save to disk virtual memory dump starting at 'addr' of size 'size'",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_memory_save,
++ },
++
++STEXI
++@item memsave @var{addr} @var{size} @var{file}
++@findex memsave
++save to disk virtual memory dump starting at @var{addr} of size @var{size}.
++ETEXI
++SQMP
++memsave
++-------
++
++Save to disk virtual memory dump starting at 'val' of size 'size'.
++
++Arguments:
++
++- "val": the starting address (json-int)
++- "size": the memory size, in bytes (json-int)
++- "filename": file path (json-string)
++
++Example:
++
++-> { "execute": "memsave",
++ "arguments": { "val": 10,
++ "size": 100,
++ "filename": "/tmp/virtual-mem-dump" } }
++<- { "return": {} }
++
++Note: Depends on the current CPU.
++
++EQMP
++
++ {
++ .name = "pmemsave",
++ .args_type = "val:l,size:i,filename:s",
++ .params = "addr size file",
++ .help = "save to disk physical memory dump starting at 'addr' of size 'size'",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_physical_memory_save,
++ },
++
++STEXI
++@item pmemsave @var{addr} @var{size} @var{file}
++@findex pmemsave
++save to disk physical memory dump starting at @var{addr} of size @var{size}.
++ETEXI
++SQMP
++pmemsave
++--------
++
++Save to disk physical memory dump starting at 'val' of size 'size'.
++
++Arguments:
++
++- "val": the starting address (json-int)
++- "size": the memory size, in bytes (json-int)
++- "filename": file path (json-string)
++
++Example:
++
++-> { "execute": "pmemsave",
++ "arguments": { "val": 10,
++ "size": 100,
++ "filename": "/tmp/physical-mem-dump" } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "boot_set",
++ .args_type = "bootdevice:s",
++ .params = "bootdevice",
++ .help = "define new values for the boot device list",
++ .mhandler.cmd = do_boot_set,
++ },
++
++STEXI
++@item boot_set @var{bootdevicelist}
++@findex boot_set
++
++Define new values for the boot device list. Those values will override
++the values specified on the command line through the @code{-boot} option.
++
++The values that can be specified here depend on the machine type, but are
++the same that can be specified in the @code{-boot} command line option.
++ETEXI
++
++#if defined(TARGET_I386)
++ {
++ .name = "nmi",
++ .args_type = "cpu_index:i",
++ .params = "cpu",
++ .help = "inject an NMI on the given CPU",
++ .mhandler.cmd = do_inject_nmi,
++ },
++#endif
++STEXI
++@item nmi @var{cpu}
++@findex nmi
++Inject an NMI on the given CPU (x86 only).
++ETEXI
++
++ {
++ .name = "migrate",
++ .args_type = "detach:-d,blk:-b,inc:-i,uri:s",
++ .params = "[-d] [-b] [-i] uri",
++ .help = "migrate to URI (using -d to not wait for completion)"
++ "\n\t\t\t -b for migration without shared storage with"
++ " full copy of disk\n\t\t\t -i for migration without "
++ "shared storage with incremental copy of disk "
++ "(base image shared between src and destination)",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_migrate,
++ },
++
++
++STEXI
++@item migrate [-d] [-b] [-i] @var{uri}
++@findex migrate
++Migrate to @var{uri} (using -d to not wait for completion).
++ -b for migration with full copy of disk
++ -i for migration with incremental copy of disk (base image is shared)
++ETEXI
++SQMP
++migrate
++-------
++
++Migrate to URI.
++
++Arguments:
++
++- "blk": block migration, full disk copy (json-bool, optional)
++- "inc": incremental disk copy (json-bool, optional)
++- "uri": Destination URI (json-string)
++
++Example:
++
++-> { "execute": "migrate", "arguments": { "uri": "tcp:0:4446" } }
++<- { "return": {} }
++
++Notes:
++
++(1) The 'query-migrate' command should be used to check migration's progress
++ and final result (this information is provided by the 'status' member)
++(2) All boolean arguments default to false
++(3) The user Monitor's "detach" argument is invalid in QMP and should not
++ be used
++
++EQMP
++
++ {
++ .name = "migrate_cancel",
++ .args_type = "",
++ .params = "",
++ .help = "cancel the current VM migration",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_migrate_cancel,
++ },
++
++STEXI
++@item migrate_cancel
++@findex migrate_cancel
++Cancel the current VM migration.
++ETEXI
++SQMP
++migrate_cancel
++--------------
++
++Cancel the current migration.
++
++Arguments: None.
++
++Example:
++
++-> { "execute": "migrate_cancel" }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "migrate_set_speed",
++ .args_type = "value:f",
++ .params = "value",
++ .help = "set maximum speed (in bytes) for migrations",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_migrate_set_speed,
++ },
++
++STEXI
++@item migrate_set_speed @var{value}
++@findex migrate_set_speed
++Set maximum speed to @var{value} (in bytes) for migrations.
++ETEXI
++SQMP
++migrate_set_speed
++-----------------
++
++Set maximum speed for migrations.
++
++Arguments:
++
++- "value": maximum speed, in bytes per second (json-number)
++
++Example:
++
++-> { "execute": "migrate_set_speed", "arguments": { "value": 1024 } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "migrate_set_downtime",
++ .args_type = "value:T",
++ .params = "value",
++ .help = "set maximum tolerated downtime (in seconds) for migrations",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_migrate_set_downtime,
++ },
++
++STEXI
++@item migrate_set_downtime @var{second}
++@findex migrate_set_downtime
++Set maximum tolerated downtime (in seconds) for migration.
++ETEXI
++SQMP
++migrate_set_downtime
++--------------------
++
++Set maximum tolerated downtime (in seconds) for migrations.
++
++Arguments:
++
++- "value": maximum downtime (json-number)
++
++Example:
++
++-> { "execute": "migrate_set_downtime", "arguments": { "value": 0.1 } }
++<- { "return": {} }
++
++EQMP
++
++#if defined(TARGET_I386)
++ {
++ .name = "drive_add",
++ .args_type = "pci_addr:s,opts:s",
++ .params = "[[<domain>:]<bus>:]<slot>\n"
++ "[file=file][,if=type][,bus=n]\n"
++ "[,unit=m][,media=d][index=i]\n"
++ "[,cyls=c,heads=h,secs=s[,trans=t]]\n"
++ "[snapshot=on|off][,cache=on|off]",
++ .help = "add drive to PCI storage controller",
++ .mhandler.cmd = drive_hot_add,
++ },
++#endif
++
++STEXI
++@item drive_add
++@findex drive_add
++Add drive to PCI storage controller.
++ETEXI
++
++#if defined(TARGET_I386)
++ {
++ .name = "pci_add",
++ .args_type = "pci_addr:s,type:s,opts:s?",
++ .params = "auto|[[<domain>:]<bus>:]<slot> nic|storage|host [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]... [host=02:00.0[,name=string][,dma=none]",
++ .help = "hot-add PCI device",
++ .mhandler.cmd = pci_device_hot_add,
++ },
++#endif
++
++STEXI
++@item pci_add
++@findex pci_add
++Hot-add PCI device.
++ETEXI
++
++#if defined(TARGET_I386)
++ {
++ .name = "pci_del",
++ .args_type = "pci_addr:s",
++ .params = "[[<domain>:]<bus>:]<slot>",
++ .help = "hot remove PCI device",
++ .mhandler.cmd = do_pci_device_hot_remove,
++ },
++#endif
++
++STEXI
++@item pci_del
++@findex pci_del
++Hot remove PCI device.
++ETEXI
++
++ {
++ .name = "host_net_add",
++ .args_type = "device:s,opts:s?",
++ .params = "tap|user|socket|vde|dump [options]",
++ .help = "add host VLAN client",
++ .mhandler.cmd = net_host_device_add,
++ },
++
++STEXI
++@item host_net_add
++@findex host_net_add
++Add host VLAN client.
++ETEXI
++
++ {
++ .name = "host_net_remove",
++ .args_type = "vlan_id:i,device:s",
++ .params = "vlan_id name",
++ .help = "remove host VLAN client",
++ .mhandler.cmd = net_host_device_remove,
++ },
++
++STEXI
++@item host_net_remove
++@findex host_net_remove
++Remove host VLAN client.
++ETEXI
++
++ {
++ .name = "netdev_add",
++ .args_type = "netdev:O",
++ .params = "[user|tap|socket],id=str[,prop=value][,...]",
++ .help = "add host network device",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_netdev_add,
++ },
++
++STEXI
++@item netdev_add
++@findex netdev_add
++Add host network device.
++ETEXI
++SQMP
++netdev_add
++----------
++
++Add host network device.
++
++Arguments:
++
++- "type": the device type, "tap", "user", ... (json-string)
++- "id": the device's ID, must be unique (json-string)
++- device options
++
++Example:
++
++-> { "execute": "netdev_add", "arguments": { "type": "user", "id": "netdev1" } }
++<- { "return": {} }
++
++Note: The supported device options are the same ones supported by the '-net'
++ command-line argument, which are listed in the '-help' output or QEMU's
++ manual
++
++EQMP
++
++ {
++ .name = "netdev_del",
++ .args_type = "id:s",
++ .params = "id",
++ .help = "remove host network device",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_netdev_del,
++ },
++
++STEXI
++@item netdev_del
++@findex netdev_del
++Remove host network device.
++ETEXI
++SQMP
++netdev_del
++----------
++
++Remove host network device.
++
++Arguments:
++
++- "id": the device's ID, must be unique (json-string)
++
++Example:
++
++-> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
++<- { "return": {} }
++
++EQMP
++
++#ifdef CONFIG_SLIRP
++ {
++ .name = "hostfwd_add",
++ .args_type = "arg1:s,arg2:s?,arg3:s?",
++ .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
++ .help = "redirect TCP or UDP connections from host to guest (requires -net user)",
++ .mhandler.cmd = net_slirp_hostfwd_add,
++ },
++#endif
++STEXI
++@item hostfwd_add
++@findex hostfwd_add
++Redirect TCP or UDP connections from host to guest (requires -net user).
++ETEXI
++
++#ifdef CONFIG_SLIRP
++ {
++ .name = "hostfwd_remove",
++ .args_type = "arg1:s,arg2:s?,arg3:s?",
++ .params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
++ .help = "remove host-to-guest TCP or UDP redirection",
++ .mhandler.cmd = net_slirp_hostfwd_remove,
++ },
++
++#endif
++STEXI
++@item hostfwd_remove
++@findex hostfwd_remove
++Remove host-to-guest TCP or UDP redirection.
++ETEXI
++
++ {
++ .name = "balloon",
++ .args_type = "value:M",
++ .params = "target",
++ .help = "request VM to change its memory allocation (in MB)",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_async = do_balloon,
++ .flags = MONITOR_CMD_ASYNC,
++ },
++
++STEXI
++@item balloon @var{value}
++@findex balloon
++Request VM to change its memory allocation to @var{value} (in MB).
++ETEXI
++SQMP
++balloon
++-------
++
++Request VM to change its memory allocation (in bytes).
++
++Arguments:
++
++- "value": New memory allocation (json-int)
++
++Example:
++
++-> { "execute": "balloon", "arguments": { "value": 536870912 } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "set_link",
++ .args_type = "name:s,up:b",
++ .params = "name on|off",
++ .help = "change the link status of a network adapter",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_set_link,
++ },
++
++STEXI
++@item set_link @var{name} [on|off]
++@findex set_link
++Switch link @var{name} on (i.e. up) or off (i.e. down).
++ETEXI
++SQMP
++set_link
++--------
++
++Change the link status of a network adapter.
++
++Arguments:
++
++- "name": network device name (json-string)
++- "up": status is up (json-bool)
++
++Example:
++
++-> { "execute": "set_link", "arguments": { "name": "e1000.0", "up": false } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "watchdog_action",
++ .args_type = "action:s",
++ .params = "[reset|shutdown|poweroff|pause|debug|none]",
++ .help = "change watchdog action",
++ .mhandler.cmd = do_watchdog_action,
++ },
++
++STEXI
++@item watchdog_action
++@findex watchdog_action
++Change watchdog action.
++ETEXI
++
++ {
++ .name = "acl_show",
++ .args_type = "aclname:s",
++ .params = "aclname",
++ .help = "list rules in the access control list",
++ .mhandler.cmd = do_acl_show,
++ },
++
++STEXI
++@item acl_show @var{aclname}
++@findex acl_show
++List all the matching rules in the access control list, and the default
++policy. There are currently two named access control lists,
++@var{vnc.x509dname} and @var{vnc.username} matching on the x509 client
++certificate distinguished name, and SASL username respectively.
++ETEXI
++
++ {
++ .name = "acl_policy",
++ .args_type = "aclname:s,policy:s",
++ .params = "aclname allow|deny",
++ .help = "set default access control list policy",
++ .mhandler.cmd = do_acl_policy,
++ },
++
++STEXI
++@item acl_policy @var{aclname} @code{allow|deny}
++@findex acl_policy
++Set the default access control list policy, used in the event that
++none of the explicit rules match. The default policy at startup is
++always @code{deny}.
++ETEXI
++
++ {
++ .name = "acl_add",
++ .args_type = "aclname:s,match:s,policy:s,index:i?",
++ .params = "aclname match allow|deny [index]",
++ .help = "add a match rule to the access control list",
++ .mhandler.cmd = do_acl_add,
++ },
++
++STEXI
++@item acl_add @var{aclname} @var{match} @code{allow|deny} [@var{index}]
++@findex acl_add
++Add a match rule to the access control list, allowing or denying access.
++The match will normally be an exact username or x509 distinguished name,
++but can optionally include wildcard globs. eg @code{*@@EXAMPLE.COM} to
++allow all users in the @code{EXAMPLE.COM} kerberos realm. The match will
++normally be appended to the end of the ACL, but can be inserted
++earlier in the list if the optional @var{index} parameter is supplied.
++ETEXI
++
++ {
++ .name = "acl_remove",
++ .args_type = "aclname:s,match:s",
++ .params = "aclname match",
++ .help = "remove a match rule from the access control list",
++ .mhandler.cmd = do_acl_remove,
++ },
++
++STEXI
++@item acl_remove @var{aclname} @var{match}
++@findex acl_remove
++Remove the specified match rule from the access control list.
++ETEXI
++
++ {
++ .name = "acl_reset",
++ .args_type = "aclname:s",
++ .params = "aclname",
++ .help = "reset the access control list",
++ .mhandler.cmd = do_acl_reset,
++ },
++
++STEXI
++@item acl_reset @var{aclname}
++@findex acl_reset
++Remove all matches from the access control list, and set the default
++policy back to @code{deny}.
++ETEXI
++
++#if defined(TARGET_I386)
++
++ {
++ .name = "mce",
++ .args_type = "cpu_index:i,bank:i,status:l,mcg_status:l,addr:l,misc:l",
++ .params = "cpu bank status mcgstatus addr misc",
++ .help = "inject a MCE on the given CPU",
++ .mhandler.cmd = do_inject_mce,
++ },
++
++#endif
++STEXI
++@item mce @var{cpu} @var{bank} @var{status} @var{mcgstatus} @var{addr} @var{misc}
++@findex mce (x86)
++Inject an MCE on the given CPU (x86 only).
++ETEXI
++
++ {
++ .name = "getfd",
++ .args_type = "fdname:s",
++ .params = "getfd name",
++ .help = "receive a file descriptor via SCM rights and assign it a name",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_getfd,
++ },
++
++STEXI
++@item getfd @var{fdname}
++@findex getfd
++If a file descriptor is passed alongside this command using the SCM_RIGHTS
++mechanism on unix sockets, it is stored using the name @var{fdname} for
++later use by other monitor commands.
++ETEXI
++SQMP
++getfd
++-----
++
++Receive a file descriptor via SCM rights and assign it a name.
++
++Arguments:
++
++- "fdname": file descriptor name (json-string)
++
++Example:
++
++-> { "execute": "getfd", "arguments": { "fdname": "fd1" } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "closefd",
++ .args_type = "fdname:s",
++ .params = "closefd name",
++ .help = "close a file descriptor previously passed via SCM rights",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_closefd,
++ },
++
++STEXI
++@item closefd @var{fdname}
++@findex closefd
++Close the file descriptor previously assigned to @var{fdname} using the
++@code{getfd} command. This is only needed if the file descriptor was never
++used by another monitor command.
++ETEXI
++SQMP
++closefd
++-------
++
++Close a file descriptor previously passed via SCM rights.
++
++Arguments:
++
++- "fdname": file descriptor name (json-string)
++
++Example:
++
++-> { "execute": "closefd", "arguments": { "fdname": "fd1" } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "block_passwd",
++ .args_type = "device:B,password:s",
++ .params = "block_passwd device password",
++ .help = "set the password of encrypted block devices",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_block_set_passwd,
++ },
++
++STEXI
++@item block_passwd @var{device} @var{password}
++@findex block_passwd
++Set the encrypted device @var{device} password to @var{password}
++ETEXI
++SQMP
++block_passwd
++------------
++
++Set the password of encrypted block devices.
++
++Arguments:
++
++- "device": device name (json-string)
++- "password": password (json-string)
++
++Example:
++
++-> { "execute": "block_passwd", "arguments": { "device": "ide0-hd0",
++ "password": "12345" } }
++<- { "return": {} }
++
++EQMP
++
++ {
++ .name = "cpu_set",
++ .args_type = "cpu:i,state:s",
++ .params = "cpu [online|offline]",
++ .help = "change cpu state",
++ .mhandler.cmd = do_cpu_set_nr,
++ },
++
++STEXI
++@item cpu_set @var{cpu} [online|offline]
++Set CPU @var{cpu} online or offline.
++ETEXI
++
++ {
++ .name = "qmp_capabilities",
++ .args_type = "",
++ .params = "",
++ .help = "enable QMP capabilities",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_qmp_capabilities,
++ },
++
++STEXI
++@item qmp_capabilities
++@findex qmp_capabilities
++Enable the specified QMP capabilities
++ETEXI
++SQMP
++qmp_capabilities
++----------------
++
++Enable QMP capabilities.
++
++Arguments: None.
++
++Example:
++
++-> { "execute": "qmp_capabilities" }
++<- { "return": {} }
++
++Note: This command must be issued before issuing any other command.
++
++EQMP
++
++
++HXCOMM Keep the 'info' command at the end!
++HXCOMM This is required for the QMP documentation layout.
++
++SQMP
++
++3. Query Commands
++=================
++
++EQMP
++
++ {
++ .name = "info",
++ .args_type = "item:s?",
++ .params = "[subcommand]",
++ .help = "show various information about the system state",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = do_info,
++ },
++
++STEXI
++@item info @var{subcommand}
++@findex info
++Show various information about the system state.
++
++@table @option
++@item info version
++show the version of QEMU
++ETEXI
++SQMP
++query-version
++-------------
++
++Show QEMU version.
++
++Return a json-object with the following information:
++
++- "qemu": A json-object containing three integer values:
++ - "major": QEMU's major version (json-int)
++ - "minor": QEMU's minor version (json-int)
++ - "micro": QEMU's micro version (json-int)
++- "package": package's version (json-string)
++
++Example:
++
++-> { "execute": "query-version" }
++<- {
++ "return":{
++ "qemu":{
++ "major":0,
++ "minor":11,
++ "micro":5
++ },
++ "package":""
++ }
++ }
++
++EQMP
++
++STEXI
++@item info commands
++list QMP available commands
++ETEXI
++SQMP
++query-commands
++--------------
++
++List QMP available commands.
++
++Each command is represented by a json-object, the returned value is a json-array
++of all commands.
++
++Each json-object contain:
++
++- "name": command's name (json-string)
++
++Example:
++
++-> { "execute": "query-commands" }
++<- {
++ "return":[
++ {
++ "name":"query-balloon"
++ },
++ {
++ "name":"system_powerdown"
++ }
++ ]
++ }
++
++Note: This example has been shortened as the real response is too long.
++
++EQMP
++
++STEXI
++@item info network
++show the various VLANs and the associated devices
++ETEXI
++
++STEXI
++@item info chardev
++show the character devices
++ETEXI
++SQMP
++query-chardev
++-------------
++
++Each device is represented by a json-object. The returned value is a json-array
++of all devices.
++
++Each json-object contain the following:
++
++- "label": device's label (json-string)
++- "filename": device's file (json-string)
++
++Example:
++
++-> { "execute": "query-chardev" }
++<- {
++ "return":[
++ {
++ "label":"monitor",
++ "filename":"stdio"
++ },
++ {
++ "label":"serial0",
++ "filename":"vc"
++ }
++ ]
++ }
++
++EQMP
++
++STEXI
++@item info block
++show the block devices
++ETEXI
++SQMP
++query-block
++-----------
++
++Show the block devices.
++
++Each block device information is stored in a json-object and the returned value
++is a json-array of all devices.
++
++Each json-object contain the following:
++
++- "device": device name (json-string)
++- "type": device type (json-string)
++ - Possible values: "hd", "cdrom", "floppy", "unknown"
++- "removable": true if the device is removable, false otherwise (json-bool)
++- "locked": true if the device is locked, false otherwise (json-bool)
++- "inserted": only present if the device is inserted, it is a json-object
++ containing the following:
++ - "file": device file name (json-string)
++ - "ro": true if read-only, false otherwise (json-bool)
++ - "drv": driver format name (json-string)
++ - Possible values: "blkdebug", "bochs", "cloop", "cow", "dmg",
++ "file", "file", "ftp", "ftps", "host_cdrom",
++ "host_device", "host_floppy", "http", "https",
++ "nbd", "parallels", "qcow", "qcow2", "raw",
++ "tftp", "vdi", "vmdk", "vpc", "vvfat"
++ - "backing_file": backing file name (json-string, optional)
++ - "encrypted": true if encrypted, false otherwise (json-bool)
++
++Example:
++
++-> { "execute": "query-block" }
++<- {
++ "return":[
++ {
++ "device":"ide0-hd0",
++ "locked":false,
++ "removable":false,
++ "inserted":{
++ "ro":false,
++ "drv":"qcow2",
++ "encrypted":false,
++ "file":"disks/test.img"
++ },
++ "type":"hd"
++ },
++ {
++ "device":"ide1-cd0",
++ "locked":false,
++ "removable":true,
++ "type":"cdrom"
++ },
++ {
++ "device":"floppy0",
++ "locked":false,
++ "removable":true,
++ "type": "floppy"
++ },
++ {
++ "device":"sd0",
++ "locked":false,
++ "removable":true,
++ "type":"floppy"
++ }
++ ]
++ }
++
++EQMP
++
++STEXI
++@item info blockstats
++show block device statistics
++ETEXI
++SQMP
++query-blockstats
++----------------
++
++Show block device statistics.
++
++Each device statistic information is stored in a json-object and the returned
++value is a json-array of all devices.
++
++Each json-object contain the following:
++
++- "device": device name (json-string)
++- "stats": A json-object with the statistics information, it contains:
++ - "rd_bytes": bytes read (json-int)
++ - "wr_bytes": bytes written (json-int)
++ - "rd_operations": read operations (json-int)
++ - "wr_operations": write operations (json-int)
++ - "wr_highest_offset": Highest offset of a sector written since the
++ BlockDriverState has been opened (json-int)
++- "parent": Contains recursively the statistics of the underlying
++ protocol (e.g. the host file for a qcow2 image). If there is
++ no underlying protocol, this field is omitted
++ (json-object, optional)
++
++Example:
++
++-> { "execute": "query-blockstats" }
++<- {
++ "return":[
++ {
++ "device":"ide0-hd0",
++ "parent":{
++ "stats":{
++ "wr_highest_offset":3686448128,
++ "wr_bytes":9786368,
++ "wr_operations":751,
++ "rd_bytes":122567168,
++ "rd_operations":36772
++ }
++ },
++ "stats":{
++ "wr_highest_offset":2821110784,
++ "wr_bytes":9786368,
++ "wr_operations":692,
++ "rd_bytes":122739200,
++ "rd_operations":36604
++ }
++ },
++ {
++ "device":"ide1-cd0",
++ "stats":{
++ "wr_highest_offset":0,
++ "wr_bytes":0,
++ "wr_operations":0,
++ "rd_bytes":0,
++ "rd_operations":0
++ }
++ },
++ {
++ "device":"floppy0",
++ "stats":{
++ "wr_highest_offset":0,
++ "wr_bytes":0,
++ "wr_operations":0,
++ "rd_bytes":0,
++ "rd_operations":0
++ }
++ },
++ {
++ "device":"sd0",
++ "stats":{
++ "wr_highest_offset":0,
++ "wr_bytes":0,
++ "wr_operations":0,
++ "rd_bytes":0,
++ "rd_operations":0
++ }
++ }
++ ]
++ }
++
++EQMP
++
++STEXI
++@item info registers
++show the cpu registers
++@item info cpus
++show infos for each CPU
++ETEXI
++SQMP
++query-cpus
++----------
++
++Show CPU information.
++
++Return a json-array. Each CPU is represented by a json-object, which contains:
++
++- "CPU": CPU index (json-int)
++- "current": true if this is the current CPU, false otherwise (json-bool)
++- "halted": true if the cpu is halted, false otherwise (json-bool)
++- Current program counter. The key's name depends on the architecture:
++ "pc": i386/x86_64 (json-int)
++ "nip": PPC (json-int)
++ "pc" and "npc": sparc (json-int)
++ "PC": mips (json-int)
++
++Example:
++
++-> { "execute": "query-cpus" }
++<- {
++ "return":[
++ {
++ "CPU":0,
++ "current":true,
++ "halted":false,
++ "pc":3227107138
++ },
++ {
++ "CPU":1,
++ "current":false,
++ "halted":true,
++ "pc":7108165
++ }
++ ]
++ }
++
++EQMP
++
++STEXI
++@item info history
++show the command line history
++@item info irq
++show the interrupts statistics (if available)
++@item info pic
++show i8259 (PIC) state
++ETEXI
++
++STEXI
++@item info pci
++show emulated PCI device info
++ETEXI
++SQMP
++query-pci
++---------
++
++PCI buses and devices information.
++
++The returned value is a json-array of all buses. Each bus is represented by
++a json-object, which has a key with a json-array of all PCI devices attached
++to it. Each device is represented by a json-object.
++
++The bus json-object contains the following:
++
++- "bus": bus number (json-int)
++- "devices": a json-array of json-objects, each json-object represents a
++ PCI device
++
++The PCI device json-object contains the following:
++
++- "bus": identical to the parent's bus number (json-int)
++- "slot": slot number (json-int)
++- "function": function number (json-int)
++- "class_info": a json-object containing:
++ - "desc": device class description (json-string, optional)
++ - "class": device class number (json-int)
++- "id": a json-object containing:
++ - "device": device ID (json-int)
++ - "vendor": vendor ID (json-int)
++- "irq": device's IRQ if assigned (json-int, optional)
++- "qdev_id": qdev id string (json-string)
++- "pci_bridge": It's a json-object, only present if this device is a
++ PCI bridge, contains:
++ - "bus": bus number (json-int)
++ - "secondary": secondary bus number (json-int)
++ - "subordinate": subordinate bus number (json-int)
++ - "io_range": I/O memory range information, a json-object with the
++ following members:
++ - "base": base address, in bytes (json-int)
++ - "limit": limit address, in bytes (json-int)
++ - "memory_range": memory range information, a json-object with the
++ following members:
++ - "base": base address, in bytes (json-int)
++ - "limit": limit address, in bytes (json-int)
++ - "prefetchable_range": Prefetchable memory range information, a
++ json-object with the following members:
++ - "base": base address, in bytes (json-int)
++ - "limit": limit address, in bytes (json-int)
++ - "devices": a json-array of PCI devices if there's any attached, each
++ each element is represented by a json-object, which contains
++ the same members of the 'PCI device json-object' described
++ above (optional)
++- "regions": a json-array of json-objects, each json-object represents a
++ memory region of this device
++
++The memory range json-object contains the following:
++
++- "base": base memory address (json-int)
++- "limit": limit value (json-int)
++
++The region json-object can be an I/O region or a memory region, an I/O region
++json-object contains the following:
++
++- "type": "io" (json-string, fixed)
++- "bar": BAR number (json-int)
++- "address": memory address (json-int)
++- "size": memory size (json-int)
++
++A memory region json-object contains the following:
++
++- "type": "memory" (json-string, fixed)
++- "bar": BAR number (json-int)
++- "address": memory address (json-int)
++- "size": memory size (json-int)
++- "mem_type_64": true or false (json-bool)
++- "prefetch": true or false (json-bool)
++
++Example:
++
++-> { "execute": "query-pci" }
++<- {
++ "return":[
++ {
++ "bus":0,
++ "devices":[
++ {
++ "bus":0,
++ "qdev_id":"",
++ "slot":0,
++ "class_info":{
++ "class":1536,
++ "desc":"Host bridge"
++ },
++ "id":{
++ "device":32902,
++ "vendor":4663
++ },
++ "function":0,
++ "regions":[
++
++ ]
++ },
++ {
++ "bus":0,
++ "qdev_id":"",
++ "slot":1,
++ "class_info":{
++ "class":1537,
++ "desc":"ISA bridge"
++ },
++ "id":{
++ "device":32902,
++ "vendor":28672
++ },
++ "function":0,
++ "regions":[
++
++ ]
++ },
++ {
++ "bus":0,
++ "qdev_id":"",
++ "slot":1,
++ "class_info":{
++ "class":257,
++ "desc":"IDE controller"
++ },
++ "id":{
++ "device":32902,
++ "vendor":28688
++ },
++ "function":1,
++ "regions":[
++ {
++ "bar":4,
++ "size":16,
++ "address":49152,
++ "type":"io"
++ }
++ ]
++ },
++ {
++ "bus":0,
++ "qdev_id":"",
++ "slot":2,
++ "class_info":{
++ "class":768,
++ "desc":"VGA controller"
++ },
++ "id":{
++ "device":4115,
++ "vendor":184
++ },
++ "function":0,
++ "regions":[
++ {
++ "prefetch":true,
++ "mem_type_64":false,
++ "bar":0,
++ "size":33554432,
++ "address":4026531840,
++ "type":"memory"
++ },
++ {
++ "prefetch":false,
++ "mem_type_64":false,
++ "bar":1,
++ "size":4096,
++ "address":4060086272,
++ "type":"memory"
++ },
++ {
++ "prefetch":false,
++ "mem_type_64":false,
++ "bar":6,
++ "size":65536,
++ "address":-1,
++ "type":"memory"
++ }
++ ]
++ },
++ {
++ "bus":0,
++ "qdev_id":"",
++ "irq":11,
++ "slot":4,
++ "class_info":{
++ "class":1280,
++ "desc":"RAM controller"
++ },
++ "id":{
++ "device":6900,
++ "vendor":4098
++ },
++ "function":0,
++ "regions":[
++ {
++ "bar":0,
++ "size":32,
++ "address":49280,
++ "type":"io"
++ }
++ ]
++ }
++ ]
++ }
++ ]
++ }
++
++Note: This example has been shortened as the real response is too long.
++
++EQMP
++
++STEXI
++@item info tlb
++show virtual to physical memory mappings (i386 only)
++@item info mem
++show the active virtual memory mappings (i386 only)
++ETEXI
++
++STEXI
++@item info jit
++show dynamic compiler info
++@item info kvm
++show KVM information
++@item info numa
++show NUMA information
++ETEXI
++
++STEXI
++@item info kvm
++show KVM information
++ETEXI
++SQMP
++query-kvm
++---------
++
++Show KVM information.
++
++Return a json-object with the following information:
++
++- "enabled": true if KVM support is enabled, false otherwise (json-bool)
++- "present": true if QEMU has KVM support, false otherwise (json-bool)
++
++Example:
++
++-> { "execute": "query-kvm" }
++<- { "return": { "enabled": true, "present": true } }
++
++EQMP
++
++STEXI
++@item info usb
++show USB devices plugged on the virtual USB hub
++@item info usbhost
++show all USB host devices
++@item info profile
++show profiling information
++@item info capture
++show information about active capturing
++@item info snapshots
++show list of VM snapshots
++ETEXI
++
++STEXI
++@item info status
++show the current VM status (running|paused)
++ETEXI
++SQMP
++query-status
++------------
++
++Return a json-object with the following information:
++
++- "running": true if the VM is running, or false if it is paused (json-bool)
++- "singlestep": true if the VM is in single step mode,
++ false otherwise (json-bool)
++
++Example:
++
++-> { "execute": "query-status" }
++<- { "return": { "running": true, "singlestep": false } }
++
++EQMP
++
++STEXI
++@item info pcmcia
++show guest PCMCIA status
++ETEXI
++
++STEXI
++@item info mice
++show which guest mouse is receiving events
++ETEXI
++SQMP
++query-mice
++----------
++
++Show VM mice information.
++
++Each mouse is represented by a json-object, the returned value is a json-array
++of all mice.
++
++The mouse json-object contains the following:
++
++- "name": mouse's name (json-string)
++- "index": mouse's index (json-int)
++- "current": true if this mouse is receiving events, false otherwise (json-bool)
++- "absolute": true if the mouse generates absolute input events (json-bool)
++
++Example:
++
++-> { "execute": "query-mice" }
++<- {
++ "return":[
++ {
++ "name":"QEMU Microsoft Mouse",
++ "index":0,
++ "current":false,
++ "absolute":false
++ },
++ {
++ "name":"QEMU PS/2 Mouse",
++ "index":1,
++ "current":true,
++ "absolute":true
++ }
++ ]
++ }
++
++EQMP
++
++STEXI
++@item info vnc
++show the vnc server status
++ETEXI
++SQMP
++query-vnc
++---------
++
++Show VNC server information.
++
++Return a json-object with server information. Connected clients are returned
++as a json-array of json-objects.
++
++The main json-object contains the following:
++
++- "enabled": true or false (json-bool)
++- "host": server's IP address (json-string)
++- "family": address family (json-string)
++ - Possible values: "ipv4", "ipv6", "unix", "unknown"
++- "service": server's port number (json-string)
++- "auth": authentication method (json-string)
++ - Possible values: "invalid", "none", "ra2", "ra2ne", "sasl", "tight",
++ "tls", "ultra", "unknown", "vencrypt", "vencrypt",
++ "vencrypt+plain", "vencrypt+tls+none",
++ "vencrypt+tls+plain", "vencrypt+tls+sasl",
++ "vencrypt+tls+vnc", "vencrypt+x509+none",
++ "vencrypt+x509+plain", "vencrypt+x509+sasl",
++ "vencrypt+x509+vnc", "vnc"
++- "clients": a json-array of all connected clients
++
++Clients are described by a json-object, each one contain the following:
++
++- "host": client's IP address (json-string)
++- "family": address family (json-string)
++ - Possible values: "ipv4", "ipv6", "unix", "unknown"
++- "service": client's port number (json-string)
++- "x509_dname": TLS dname (json-string, optional)
++- "sasl_username": SASL username (json-string, optional)
++
++Example:
++
++-> { "execute": "query-vnc" }
++<- {
++ "return":{
++ "enabled":true,
++ "host":"0.0.0.0",
++ "service":"50402",
++ "auth":"vnc",
++ "family":"ipv4",
++ "clients":[
++ {
++ "host":"127.0.0.1",
++ "service":"50401",
++ "family":"ipv4"
++ }
++ ]
++ }
++ }
++
++EQMP
++
++STEXI
++@item info name
++show the current VM name
++ETEXI
++SQMP
++query-name
++----------
++
++Show VM name.
++
++Return a json-object with the following information:
++
++- "name": VM's name (json-string, optional)
++
++Example:
++
++-> { "execute": "query-name" }
++<- { "return": { "name": "qemu-name" } }
++
++EQMP
++
++STEXI
++@item info uuid
++show the current VM UUID
++ETEXI
++SQMP
++query-uuid
++----------
++
++Show VM UUID.
++
++Return a json-object with the following information:
++
++- "UUID": Universally Unique Identifier (json-string)
++
++Example:
++
++-> { "execute": "query-uuid" }
++<- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } }
++
++EQMP
++
++STEXI
++@item info cpustats
++show CPU statistics
++@item info usernet
++show user network stack connection states
++ETEXI
++
++STEXI
++@item info migrate
++show migration status
++ETEXI
++SQMP
++query-migrate
++-------------
++
++Migration status.
++
++Return a json-object. If migration is active there will be another json-object
++with RAM migration status and if block migration is active another one with
++block migration status.
++
++The main json-object contains the following:
++
++- "status": migration status (json-string)
++ - Possible values: "active", "completed", "failed", "cancelled"
++- "ram": only present if "status" is "active", it is a json-object with the
++ following RAM information (in bytes):
++ - "transferred": amount transferred (json-int)
++ - "remaining": amount remaining (json-int)
++ - "total": total (json-int)
++- "disk": only present if "status" is "active" and it is a block migration,
++ it is a json-object with the following disk information (in bytes):
++ - "transferred": amount transferred (json-int)
++ - "remaining": amount remaining (json-int)
++ - "total": total (json-int)
++
++Examples:
++
++1. Before the first migration
++
++-> { "execute": "query-migrate" }
++<- { "return": {} }
++
++2. Migration is done and has succeeded
++
++-> { "execute": "query-migrate" }
++<- { "return": { "status": "completed" } }
++
++3. Migration is done and has failed
++
++-> { "execute": "query-migrate" }
++<- { "return": { "status": "failed" } }
++
++4. Migration is being performed and is not a block migration:
++
++-> { "execute": "query-migrate" }
++<- {
++ "return":{
++ "status":"active",
++ "ram":{
++ "transferred":123,
++ "remaining":123,
++ "total":246
++ }
++ }
++ }
++
++5. Migration is being performed and is a block migration:
++
++-> { "execute": "query-migrate" }
++<- {
++ "return":{
++ "status":"active",
++ "ram":{
++ "total":1057024,
++ "remaining":1053304,
++ "transferred":3720
++ },
++ "disk":{
++ "total":20971520,
++ "remaining":20880384,
++ "transferred":91136
++ }
++ }
++ }
++
++EQMP
++
++STEXI
++@item info balloon
++show balloon information
++ETEXI
++SQMP
++query-balloon
++-------------
++
++Show balloon information.
++
++Make an asynchronous request for balloon info. When the request completes a
++json-object will be returned containing the following data:
++
++- "actual": current balloon value in bytes (json-int)
++- "mem_swapped_in": Amount of memory swapped in bytes (json-int, optional)
++- "mem_swapped_out": Amount of memory swapped out in bytes (json-int, optional)
++- "major_page_faults": Number of major faults (json-int, optional)
++- "minor_page_faults": Number of minor faults (json-int, optional)
++- "free_mem": Total amount of free and unused memory in
++ bytes (json-int, optional)
++- "total_mem": Total amount of available memory in bytes (json-int, optional)
++
++Example:
++
++-> { "execute": "query-balloon" }
++<- {
++ "return":{
++ "actual":1073741824,
++ "mem_swapped_in":0,
++ "mem_swapped_out":0,
++ "major_page_faults":142,
++ "minor_page_faults":239245,
++ "free_mem":1014185984,
++ "total_mem":1044668416
++ }
++ }
++
++EQMP
++
++STEXI
++@item info qtree
++show device tree
++@item info qdm
++show qdev device model list
++@item info roms
++show roms
++@end table
++ETEXI
++
++HXCOMM DO NOT add new commands after 'info', move your addition before it!
++
++#if defined(CONFIG_SPICE)
++ {
++ .name = "spice_migrate_info",
++ .args_type = "hostname:s,port:i?,tls-port:i?,cert-subject:s?",
++ .params = "hostname port tls-port cert-subject",
++ .help = "send migration info to spice client",
++ .user_print = monitor_user_noop,
++ .mhandler.cmd_new = mon_spice_migrate,
++ },
++#endif
++
++STEXI
++@end table
++ETEXI
+diff -urN qemu-kvm-0.13.0.orig/qemu-options.hx qemu-kvm-0.13.0/qemu-options.hx
+--- qemu-kvm-0.13.0.orig/qemu-options.hx 2011-02-09 11:01:45.887000328 +0200
++++ qemu-kvm-0.13.0/qemu-options.hx 2011-02-09 11:08:02.915000327 +0200
+@@ -676,6 +676,14 @@
+ Enable SDL.
+ ETEXI
+
++#ifdef CONFIG_SPICE
++DEF("spice", HAS_ARG, QEMU_OPTION_spice,
++ "-spice <args> use spice\n", QEMU_ARCH_ALL)
++STEXI
++Use Spice.
++ETEXI
++#endif
++
+ DEF("portrait", 0, QEMU_OPTION_portrait,
+ "-portrait rotate graphical output 90 deg left (only PXA LCD)\n",
+ QEMU_ARCH_ALL)
+@@ -686,7 +694,7 @@
+ ETEXI
+
+ DEF("vga", HAS_ARG, QEMU_OPTION_vga,
+- "-vga [std|cirrus|vmware|xenfb|none]\n"
++ "-vga [std|cirrus|vmware|xenfb|qxl|none]\n"
+ " select video card type\n", QEMU_ARCH_ALL)
+ STEXI
+ @item -vga @var{type}
+diff -urN qemu-kvm-0.13.0.orig/qemu-spice.h qemu-kvm-0.13.0/qemu-spice.h
+--- qemu-kvm-0.13.0.orig/qemu-spice.h 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/qemu-spice.h 2011-02-09 11:08:02.873000327 +0200
+@@ -0,0 +1,25 @@
++#ifndef QEMU_SPICE_H
++#define QEMU_SPICE_H
++
++#ifdef CONFIG_SPICE
++
++#include <spice.h>
++
++#include "qemu-option.h"
++#include "qemu-config.h"
++
++extern SpiceServer *spice_server;
++extern int using_spice;
++
++void qemu_spice_init(void);
++void qemu_spice_input_init(void);
++void qemu_spice_audio_init(void);
++void qemu_spice_display_init(DisplayState *ds);
++
++#else /* CONFIG_SPICE */
++
++#define using_spice 0
++
++#endif /* CONFIG_SPICE */
++
++#endif /* QEMU_SPICE_H */
+diff -urN qemu-kvm-0.13.0.orig/spice.c qemu-kvm-0.13.0/spice.c
+--- qemu-kvm-0.13.0.orig/spice.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/spice.c 2011-02-09 11:08:02.874000327 +0200
+@@ -0,0 +1,245 @@
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++
++#include <spice.h>
++#include <spice-experimental.h>
++
++#include "qemu-common.h"
++#include "qemu-spice.h"
++#include "qemu-timer.h"
++#include "qemu-queue.h"
++#include "qemu-x509.h"
++#include "monitor.h"
++
++/* core bits */
++
++SpiceServer *spice_server;
++int using_spice = 0;
++
++struct SpiceTimer {
++ QEMUTimer *timer;
++ QTAILQ_ENTRY(SpiceTimer) next;
++};
++static QTAILQ_HEAD(, SpiceTimer) timers = QTAILQ_HEAD_INITIALIZER(timers);
++
++static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque)
++{
++ SpiceTimer *timer;
++
++ timer = qemu_mallocz(sizeof(*timer));
++ timer->timer = qemu_new_timer(rt_clock, func, opaque);
++ QTAILQ_INSERT_TAIL(&timers, timer, next);
++ return timer;
++}
++
++static void timer_start(SpiceTimer *timer, uint32_t ms)
++{
++ qemu_mod_timer(timer->timer, qemu_get_clock(rt_clock) + ms);
++}
++
++static void timer_cancel(SpiceTimer *timer)
++{
++ qemu_del_timer(timer->timer);
++}
++
++static void timer_remove(SpiceTimer *timer)
++{
++ qemu_del_timer(timer->timer);
++ qemu_free_timer(timer->timer);
++ QTAILQ_REMOVE(&timers, timer, next);
++ free(timer);
++}
++
++struct SpiceWatch {
++ int fd;
++ int event_mask;
++ SpiceWatchFunc func;
++ void *opaque;
++ QTAILQ_ENTRY(SpiceWatch) next;
++};
++static QTAILQ_HEAD(, SpiceWatch) watches = QTAILQ_HEAD_INITIALIZER(watches);
++
++static void watch_read(void *opaque)
++{
++ SpiceWatch *watch = opaque;
++ watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
++}
++
++static void watch_write(void *opaque)
++{
++ SpiceWatch *watch = opaque;
++ watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
++}
++
++static void watch_update_mask(SpiceWatch *watch, int event_mask)
++{
++ IOHandler *on_read = NULL;
++ IOHandler *on_write = NULL;
++
++ watch->event_mask = event_mask;
++ if (watch->event_mask & SPICE_WATCH_EVENT_READ)
++ on_read = watch_read;
++ if (watch->event_mask & SPICE_WATCH_EVENT_WRITE)
++ on_read = watch_write;
++ qemu_set_fd_handler(watch->fd, on_read, on_write, watch);
++}
++
++static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
++{
++ SpiceWatch *watch;
++
++ watch = qemu_mallocz(sizeof(*watch));
++ watch->fd = fd;
++ watch->func = func;
++ watch->opaque = opaque;
++ QTAILQ_INSERT_TAIL(&watches, watch, next);
++
++ watch_update_mask(watch, event_mask);
++ return watch;
++}
++
++static void watch_remove(SpiceWatch *watch)
++{
++ watch_update_mask(watch, 0);
++ QTAILQ_REMOVE(&watches, watch, next);
++ qemu_free(watch);
++}
++
++static SpiceCoreInterface core_interface = {
++ .base.type = SPICE_INTERFACE_CORE,
++ .base.description = "qemu core services",
++ .base.major_version = SPICE_INTERFACE_CORE_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_CORE_MINOR,
++
++ .timer_add = timer_add,
++ .timer_start = timer_start,
++ .timer_cancel = timer_cancel,
++ .timer_remove = timer_remove,
++
++ .watch_add = watch_add,
++ .watch_update_mask = watch_update_mask,
++ .watch_remove = watch_remove,
++};
++
++/* functions for the rest of qemu */
++
++#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
++static inline spice_wan_compression_t get_wan_compression_value(const char *str)
++{
++ if (!strcmp(str, "wan")) {
++ return SPICE_WAN_COMPRESSION_AUTO;
++ }
++
++ if (!strcmp(str, "never")) {
++ return SPICE_WAN_COMPRESSION_NEVER;
++ }
++
++ if (!strcmp(str, "always")) {
++ return SPICE_WAN_COMPRESSION_ALWAYS;
++ }
++
++ return SPICE_WAN_COMPRESSION_INVALID;
++}
++#endif
++
++void qemu_spice_init(void)
++{
++ QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
++ const char *password, *str, *x509_dir,
++ *x509_key_password = NULL,
++ *x509_dh_file = NULL,
++ *tls_ciphers = NULL;
++ char *x509_key_file = NULL,
++ *x509_cert_file = NULL,
++ *x509_cacert_file = NULL;
++ int port, tls_port, len;
++
++ if (!opts)
++ return;
++ port = qemu_opt_get_number(opts, "port", 0);
++ tls_port = qemu_opt_get_number(opts, "tls-port", 0);
++ if (!port && !tls_port)
++ return;
++ password = qemu_opt_get(opts, "password");
++
++ if (tls_port) {
++ x509_dir = qemu_opt_get(opts, "x509-dir");
++ if (NULL == x509_dir)
++ x509_dir = ".";
++ len = strlen(x509_dir) + 32;
++
++ str = qemu_opt_get(opts, "x509-key-file");
++ if (str) {
++ x509_key_file = qemu_strdup(str);
++ } else {
++ x509_key_file = qemu_malloc(len);
++ snprintf(x509_key_file, len, "%s/%s", x509_dir, X509_SERVER_KEY_FILE);
++ }
++
++ str = qemu_opt_get(opts, "x509-cert-file");
++ if (str) {
++ x509_cert_file = qemu_strdup(str);
++ } else {
++ x509_cert_file = qemu_malloc(len);
++ snprintf(x509_cert_file, len, "%s/%s", x509_dir, X509_SERVER_CERT_FILE);
++ }
++
++ str = qemu_opt_get(opts, "x509-cacert-file");
++ if (str) {
++ x509_cacert_file = qemu_strdup(str);
++ } else {
++ x509_cacert_file = qemu_malloc(len);
++ snprintf(x509_cacert_file, len, "%s/%s", x509_dir, X509_CA_CERT_FILE);
++ }
++
++ x509_key_password = qemu_opt_get(opts, "x509-key-password");
++ x509_dh_file = qemu_opt_get(opts, "x509-dh-file");
++ tls_ciphers = qemu_opt_get(opts, "tls-ciphers");
++ }
++
++ spice_server = spice_server_new();
++ if (port) {
++ spice_server_set_port(spice_server, port);
++ }
++ if (tls_port) {
++ spice_server_set_tls(spice_server, tls_port,
++ x509_cacert_file,
++ x509_cert_file,
++ x509_key_file,
++ x509_key_password,
++ x509_dh_file,
++ tls_ciphers);
++ }
++ if (password)
++ spice_server_set_ticket(spice_server, password, 0, 0, 0);
++ if (qemu_opt_get_bool(opts, "disable-ticketing", 0))
++ spice_server_set_noauth(spice_server);
++
++ /* TODO: make configurable via cmdline */
++ spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
++
++#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
++ const char *jpeg, *zlib_glz;
++ jpeg = qemu_opt_get(opts, "jpeg");
++ zlib_glz = qemu_opt_get(opts, "zlib-glz");
++
++ if (jpeg) {
++ spice_server_set_jpeg_compression(spice_server, get_wan_compression_value(jpeg));
++ }
++
++ if (zlib_glz) {
++ spice_server_set_zlib_glz_compression(spice_server, get_wan_compression_value(zlib_glz));
++ }
++#endif
++
++ spice_server_init(spice_server, &core_interface);
++ using_spice = 1;
++
++ qemu_spice_input_init();
++ qemu_spice_audio_init();
++
++ qemu_free(x509_key_file);
++ qemu_free(x509_cert_file);
++ qemu_free(x509_cacert_file);
++}
+diff -urN qemu-kvm-0.13.0.orig/spice-display.c qemu-kvm-0.13.0/spice-display.c
+--- qemu-kvm-0.13.0.orig/spice-display.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/spice-display.c 2011-02-09 11:08:02.816000327 +0200
+@@ -0,0 +1,390 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <string.h>
++#include <pthread.h>
++
++#include "qemu-common.h"
++#include "qemu-spice.h"
++#include "qemu-timer.h"
++#include "qemu-queue.h"
++#include "monitor.h"
++#include "console.h"
++#include "sysemu.h"
++
++#include "spice-display.h"
++
++static int debug = 0;
++
++int qemu_spice_rect_is_empty(const QXLRect* r)
++{
++ return r->top == r->bottom || r->left == r->right;
++}
++
++void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
++{
++ if (qemu_spice_rect_is_empty(r)) {
++ return;
++ }
++
++ if (qemu_spice_rect_is_empty(dest)) {
++ *dest = *r;
++ return;
++ }
++
++ dest->top = MIN(dest->top, r->top);
++ dest->left = MIN(dest->left, r->left);
++ dest->bottom = MAX(dest->bottom, r->bottom);
++ dest->right = MAX(dest->right, r->right);
++}
++
++SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
++{
++ SimpleSpiceUpdate *update;
++ QXLDrawable *drawable;
++ QXLImage *image;
++ QXLCommand *cmd;
++ uint8_t *src, *dst;
++ int by, bw, bh;
++
++ if (qemu_spice_rect_is_empty(&ssd->dirty)) {
++ return NULL;
++ };
++
++ pthread_mutex_lock(&ssd->lock);
++ if (debug > 1)
++ fprintf(stderr, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__,
++ ssd->dirty.left, ssd->dirty.right,
++ ssd->dirty.top, ssd->dirty.bottom);
++
++ update = qemu_mallocz(sizeof(*update));
++ drawable = &update->drawable;
++ image = &update->image;
++ cmd = &update->ext.cmd;
++
++ bw = ssd->dirty.right - ssd->dirty.left;
++ bh = ssd->dirty.bottom - ssd->dirty.top;
++ update->bitmap = qemu_malloc(bw * bh * 4);
++
++ drawable->bbox = ssd->dirty;
++ drawable->clip.type = SPICE_CLIP_TYPE_NONE;
++ drawable->effect = QXL_EFFECT_OPAQUE;
++ drawable->release_info.id = (intptr_t)update;
++ drawable->type = QXL_DRAW_COPY;
++
++ drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
++ drawable->u.copy.src_bitmap = (intptr_t)image;
++ drawable->u.copy.src_area.right = bw;
++ drawable->u.copy.src_area.bottom = bh;
++
++ QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ssd->unique++);
++ image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
++ image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
++ image->bitmap.stride = bw * 4;
++ image->descriptor.width = image->bitmap.x = bw;
++ image->descriptor.height = image->bitmap.y = bh;
++ image->bitmap.data = (intptr_t)(update->bitmap);
++ image->bitmap.palette = 0;
++ image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
++
++ if (ssd->conv == NULL) {
++ PixelFormat dst = qemu_default_pixelformat(32);
++ ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf);
++ assert(ssd->conv);
++ }
++
++ src = ds_get_data(ssd->ds) +
++ ssd->dirty.top * ds_get_linesize(ssd->ds) +
++ ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds);
++ dst = update->bitmap;
++ for (by = 0; by < bh; by++) {
++ qemu_pf_conv_run(ssd->conv, dst, src, bw);
++ src += ds_get_linesize(ssd->ds);
++ dst += image->bitmap.stride;
++ }
++
++ cmd->type = QXL_CMD_DRAW;
++ cmd->data = (intptr_t)drawable;
++
++ memset(&ssd->dirty, 0, sizeof(ssd->dirty));
++ pthread_mutex_unlock(&ssd->lock);
++ return update;
++}
++
++void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update)
++{
++ qemu_free(update->bitmap);
++ qemu_free(update);
++}
++
++void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
++{
++ QXLDevMemSlot memslot;
++
++ if (debug)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++
++ memset(&memslot, 0, sizeof(memslot));
++ memslot.slot_group_id = MEMSLOT_GROUP_HOST;
++ memslot.virt_end = ~0;
++ ssd->worker->add_memslot(ssd->worker, &memslot);
++}
++
++void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
++{
++ QXLDevSurfaceCreate surface;
++
++ if (debug)
++ fprintf(stderr, "%s: %dx%d\n", __FUNCTION__,
++ ds_get_width(ssd->ds), ds_get_height(ssd->ds));
++
++ surface.format = SPICE_SURFACE_FMT_32_xRGB;
++ surface.width = ds_get_width(ssd->ds);
++ surface.height = ds_get_height(ssd->ds);
++ surface.stride = -surface.width * 4;
++ surface.mouse_mode = true;
++ surface.flags = 0;
++ surface.type = 0;
++ surface.mem = (intptr_t)ssd->buf;
++ surface.group_id = MEMSLOT_GROUP_HOST;
++ ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
++}
++
++void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
++{
++ if (debug)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++
++ ssd->worker->destroy_primary_surface(ssd->worker, 0);
++}
++
++void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
++{
++ SimpleSpiceDisplay *ssd = opaque;
++
++ if (running) {
++ ssd->worker->start(ssd->worker);
++ } else {
++ ssd->worker->stop(ssd->worker);
++ }
++ ssd->running = running;
++}
++
++/* display listener callbacks */
++
++void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
++ int x, int y, int w, int h)
++{
++ QXLRect update_area;
++
++ if (debug > 1)
++ fprintf(stderr, "%s: x %d y %d w %d h %d\n", __FUNCTION__, x, y, w, h);
++ update_area.left = x,
++ update_area.right = x + w;
++ update_area.top = y;
++ update_area.bottom = y + h;
++
++ pthread_mutex_lock(&ssd->lock);
++ if (qemu_spice_rect_is_empty(&ssd->dirty)) {
++ ssd->notify++;
++ }
++ qemu_spice_rect_union(&ssd->dirty, &update_area);
++ pthread_mutex_unlock(&ssd->lock);
++}
++
++void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
++{
++ if (debug)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++
++ pthread_mutex_lock(&ssd->lock);
++ memset(&ssd->dirty, 0, sizeof(ssd->dirty));
++ pthread_mutex_unlock(&ssd->lock);
++
++ qemu_spice_destroy_host_primary(ssd);
++ qemu_spice_create_host_primary(ssd);
++ qemu_pf_conv_put(ssd->conv);
++ ssd->conv = NULL;
++
++ pthread_mutex_lock(&ssd->lock);
++ ssd->dirty.left = 0;
++ ssd->dirty.right = ds_get_width(ssd->ds);
++ ssd->dirty.top = 0;
++ ssd->dirty.bottom = ds_get_height(ssd->ds);
++ ssd->notify++;
++ pthread_mutex_unlock(&ssd->lock);
++}
++
++void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
++{
++ if (debug > 2)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ vga_hw_update();
++ if (ssd->notify) {
++ ssd->notify = 0;
++ ssd->worker->wakeup(ssd->worker);
++ if (debug > 1)
++ fprintf(stderr, "%s: notify\n", __FUNCTION__);
++ }
++}
++
++/* spice display interface callbacks */
++
++static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
++{
++ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
++
++ if (debug)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ ssd->worker = qxl_worker;
++}
++
++static void interface_set_compression_level(QXLInstance *sin, int level)
++{
++ if (debug)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ /* nothing to do */
++}
++
++static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
++{
++ if (debug > 2)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ /* nothing to do */
++}
++
++static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
++{
++ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
++
++ info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
++ info->memslot_id_bits = MEMSLOT_SLOT_BITS;
++ info->num_memslots = NUM_MEMSLOTS;
++ info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
++ info->internal_groupslot_id = 0;
++ info->qxl_ram_size = ssd->bufsize;
++ info->n_surfaces = NUM_SURFACES;
++}
++
++static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
++{
++ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
++ SimpleSpiceUpdate *update;
++
++ if (debug > 2)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ update = qemu_spice_create_update(ssd);
++ if (update == NULL) {
++ return false;
++ }
++ *ext = update->ext;
++ return true;
++}
++
++static int interface_req_cmd_notification(QXLInstance *sin)
++{
++ if (debug)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ return 1;
++}
++
++static void interface_release_resource(QXLInstance *sin,
++ struct QXLReleaseInfoExt ext)
++{
++ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
++ uintptr_t id;
++
++ if (debug > 1)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ id = ext.info->id;
++ qemu_spice_destroy_update(ssd, (void*)id);
++}
++
++static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
++{
++ if (debug > 2)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ return false;
++}
++
++static int interface_req_cursor_notification(QXLInstance *sin)
++{
++ if (debug)
++ fprintf(stderr, "%s:\n", __FUNCTION__);
++ return 1;
++}
++
++static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
++{
++ fprintf(stderr, "%s: abort()\n", __FUNCTION__);
++ abort();
++}
++
++static int interface_flush_resources(QXLInstance *sin)
++{
++ fprintf(stderr, "%s: abort()\n", __FUNCTION__);
++ abort();
++ return 0;
++}
++
++static const QXLInterface dpy_interface = {
++ .base.type = SPICE_INTERFACE_QXL,
++ .base.description = "qemu simple display",
++ .base.major_version = SPICE_INTERFACE_QXL_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_QXL_MINOR,
++
++ .attache_worker = interface_attach_worker,
++ .set_compression_level = interface_set_compression_level,
++ .set_mm_time = interface_set_mm_time,
++
++ .get_init_info = interface_get_init_info,
++ .get_command = interface_get_command,
++ .req_cmd_notification = interface_req_cmd_notification,
++ .release_resource = interface_release_resource,
++ .get_cursor_command = interface_get_cursor_command,
++ .req_cursor_notification = interface_req_cursor_notification,
++ .notify_update = interface_notify_update,
++ .flush_resources = interface_flush_resources,
++};
++
++static SimpleSpiceDisplay sdpy;
++
++static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
++{
++ qemu_spice_display_update(&sdpy, x, y, w, h);
++}
++
++static void display_resize(struct DisplayState *ds)
++{
++ qemu_spice_display_resize(&sdpy);
++}
++
++static void display_refresh(struct DisplayState *ds)
++{
++ qemu_spice_display_refresh(&sdpy);
++}
++
++static DisplayChangeListener display_listener = {
++ .dpy_update = display_update,
++ .dpy_resize = display_resize,
++ .dpy_refresh = display_refresh,
++};
++
++void qemu_spice_display_init(DisplayState *ds)
++{
++ assert(sdpy.ds == NULL);
++ sdpy.ds = ds;
++ sdpy.bufsize = (16 * 1024 * 1024);
++ sdpy.buf = qemu_malloc(sdpy.bufsize);
++ pthread_mutex_init(&sdpy.lock, NULL);
++ register_displaychangelistener(ds, &display_listener);
++
++ sdpy.qxl.base.sif = &dpy_interface.base;
++ spice_server_add_interface(spice_server, &sdpy.qxl.base);
++ assert(sdpy.worker);
++
++ qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy);
++ qemu_spice_create_host_memslot(&sdpy);
++ qemu_spice_create_host_primary(&sdpy);
++}
+diff -urN qemu-kvm-0.13.0.orig/spice-display.h qemu-kvm-0.13.0/spice-display.h
+--- qemu-kvm-0.13.0.orig/spice-display.h 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/spice-display.h 2011-02-09 11:08:02.809000327 +0200
+@@ -0,0 +1,52 @@
++#include <spice/ipc_ring.h>
++#include <spice/enums.h>
++#include <spice/qxl_dev.h>
++
++#include "pflib.h"
++
++#define NUM_MEMSLOTS 8
++#define MEMSLOT_GENERATION_BITS 8
++#define MEMSLOT_SLOT_BITS 8
++
++#define MEMSLOT_GROUP_HOST 0
++#define MEMSLOT_GROUP_GUEST 1
++#define NUM_MEMSLOTS_GROUPS 2
++
++#define NUM_SURFACES 1024
++
++typedef struct SimpleSpiceDisplay {
++ DisplayState *ds;
++ void *buf;
++ int bufsize;
++ QXLWorker *worker;
++ QXLInstance qxl;
++ uint32_t unique;
++ QemuPfConv *conv;
++
++ pthread_mutex_t lock;
++ QXLRect dirty;
++ int notify;
++ int running;
++} SimpleSpiceDisplay;
++
++typedef struct SimpleSpiceUpdate {
++ QXLDrawable drawable;
++ QXLImage image;
++ QXLCommandExt ext;
++ uint8_t *bitmap;
++} SimpleSpiceUpdate;
++
++int qemu_spice_rect_is_empty(const QXLRect* r);
++void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r);
++
++SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *sdpy);
++void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update);
++void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd);
++void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
++void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
++void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason);
++
++void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
++ int x, int y, int w, int h);
++void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
++void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
+diff -urN qemu-kvm-0.13.0.orig/spice-input.c qemu-kvm-0.13.0/spice-input.c
+--- qemu-kvm-0.13.0.orig/spice-input.c 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/spice-input.c 2011-02-09 11:08:02.735000327 +0200
+@@ -0,0 +1,173 @@
++#include <stdlib.h>
++#include <stdio.h>
++#include <stdbool.h>
++#include <string.h>
++
++#include <spice.h>
++
++#include "qemu-common.h"
++#include "qemu-spice.h"
++#include "console.h"
++
++/* keyboard bits */
++
++typedef struct QemuSpiceKbd {
++ SpiceKbdInstance sin;
++ int ledstate;
++} QemuSpiceKbd;
++
++static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag);
++static uint8_t kbd_get_leds(SpiceKbdInstance *sin);
++static void kbd_leds(void *opaque, int l);
++
++static const SpiceKbdInterface kbd_interface = {
++ .base.type = SPICE_INTERFACE_KEYBOARD,
++ .base.description = "qemu keyboard",
++ .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR,
++ .push_scan_freg = kbd_push_key,
++ .get_leds = kbd_get_leds,
++};
++
++static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
++{
++ kbd_put_keycode(frag);
++}
++
++static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
++{
++ QemuSpiceKbd *kbd = container_of(sin, QemuSpiceKbd, sin);
++ return kbd->ledstate;
++}
++
++static void kbd_leds(void *opaque, int ledstate)
++{
++ QemuSpiceKbd *kbd = opaque;
++ kbd->ledstate = ledstate;
++ spice_server_kbd_leds(&kbd->sin, ledstate);
++}
++
++/* mouse bits */
++
++typedef struct QemuSpicePointer {
++ SpiceMouseInstance mouse;
++ SpiceTabletInstance tablet;
++ int width, height, x, y;
++ Notifier mouse_mode;
++ bool absolute;
++} QemuSpicePointer;
++
++static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz,
++ uint32_t buttons_state)
++{
++ kbd_mouse_event(dx, dy, dz, buttons_state);
++}
++
++static void mouse_buttons(SpiceMouseInstance *sin, uint32_t buttons_state)
++{
++ kbd_mouse_event(0, 0, 0, buttons_state);
++}
++
++static const SpiceMouseInterface mouse_interface = {
++ .base.type = SPICE_INTERFACE_MOUSE,
++ .base.description = "mouse",
++ .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR,
++ .motion = mouse_motion,
++ .buttons = mouse_buttons,
++};
++
++static void tablet_set_logical_size(SpiceTabletInstance* sin, int width, int height)
++{
++ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
++
++ fprintf(stderr, "%s: %dx%d\n", __FUNCTION__, width, height);
++ if (height < 16)
++ height = 16;
++ if (width < 16)
++ width = 16;
++ pointer->width = width;
++ pointer->height = height;
++}
++
++static void tablet_position(SpiceTabletInstance* sin, int x, int y,
++ uint32_t buttons_state)
++{
++ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
++
++ pointer->x = x * 0x7FFF / (pointer->width - 1);
++ pointer->y = y * 0x7FFF / (pointer->height - 1);
++ kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
++}
++
++
++static void tablet_wheel(SpiceTabletInstance* sin, int wheel,
++ uint32_t buttons_state)
++{
++ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
++
++ kbd_mouse_event(pointer->x, pointer->y, wheel, buttons_state);
++}
++
++static void tablet_buttons(SpiceTabletInstance *sin,
++ uint32_t buttons_state)
++{
++ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
++
++ kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
++}
++
++static const SpiceTabletInterface tablet_interface = {
++ .base.type = SPICE_INTERFACE_TABLET,
++ .base.description = "tablet",
++ .base.major_version = SPICE_INTERFACE_TABLET_MAJOR,
++ .base.minor_version = SPICE_INTERFACE_TABLET_MINOR,
++ .set_logical_size = tablet_set_logical_size,
++ .position = tablet_position,
++ .wheel = tablet_wheel,
++ .buttons = tablet_buttons,
++};
++
++static void mouse_mode_notifier(Notifier *notifier)
++{
++ QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode);
++ bool is_absolute = kbd_mouse_is_absolute();
++ bool has_absolute = kbd_mouse_has_absolute();
++
++ fprintf(stderr, "%s: absolute pointer: %s%s\n", __FUNCTION__,
++ has_absolute ? "present" : "not available",
++ is_absolute ? "+active" : "");
++
++ if (pointer->absolute == is_absolute)
++ return;
++
++ if (is_absolute) {
++ fprintf(stderr, "%s: using absolute pointer (client mode)\n", __FUNCTION__);
++ spice_server_add_interface(spice_server, &pointer->tablet.base);
++ } else {
++ fprintf(stderr, "%s: using relative pointer (server mode)\n", __FUNCTION__);
++ spice_server_remove_interface(&pointer->tablet.base);
++ }
++ pointer->absolute = is_absolute;
++}
++
++void qemu_spice_input_init(void)
++{
++ QemuSpiceKbd *kbd;
++ QemuSpicePointer *pointer;
++
++ kbd = qemu_mallocz(sizeof(*kbd));
++ kbd->sin.base.sif = &kbd_interface.base;
++ spice_server_add_interface(spice_server, &kbd->sin.base);
++ qemu_add_led_event_handler(kbd_leds, kbd);
++
++ pointer = qemu_mallocz(sizeof(*pointer));
++ pointer->mouse.base.sif = &mouse_interface.base;
++ pointer->tablet.base.sif = &tablet_interface.base;
++ spice_server_add_interface(spice_server, &pointer->mouse.base);
++
++ pointer->absolute = false;
++ pointer->mouse_mode.notify = mouse_mode_notifier;
++ qemu_add_mouse_mode_change_notifier(&pointer->mouse_mode);
++ mouse_mode_notifier(&pointer->mouse_mode);
++}
+diff -urN qemu-kvm-0.13.0.orig/sysemu.h qemu-kvm-0.13.0/sysemu.h
+--- qemu-kvm-0.13.0.orig/sysemu.h 2011-02-09 11:01:45.776000327 +0200
++++ qemu-kvm-0.13.0/sysemu.h 2011-02-09 11:08:02.771000327 +0200
+@@ -104,7 +104,7 @@
+ extern int bios_size;
+
+ typedef enum {
+- VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
++ VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL,
+ } VGAInterfaceType;
+
+ extern int vga_interface_type;
+@@ -112,6 +112,7 @@
+ #define std_vga_enabled (vga_interface_type == VGA_STD)
+ #define xenfb_enabled (vga_interface_type == VGA_XENFB)
+ #define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
++#define qxl_enabled (vga_interface_type == VGA_QXL)
+
+ extern int graphic_width;
+ extern int graphic_height;
+diff -urN qemu-kvm-0.13.0.orig/sysemu.h.orig qemu-kvm-0.13.0/sysemu.h.orig
+--- qemu-kvm-0.13.0.orig/sysemu.h.orig 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/sysemu.h.orig 2011-02-09 11:07:32.579000328 +0200
+@@ -0,0 +1,197 @@
++#ifndef SYSEMU_H
++#define SYSEMU_H
++/* Misc. things related to the system emulator. */
++
++#include "qemu-common.h"
++#include "qemu-option.h"
++#include "qemu-queue.h"
++#include "qemu-timer.h"
++#include "notify.h"
++
++#ifdef _WIN32
++#include <windows.h>
++#include "qemu-os-win32.h"
++#endif
++
++#ifdef CONFIG_POSIX
++#include "qemu-os-posix.h"
++#endif
++
++/* vl.c */
++extern const char *bios_name;
++
++#define QEMU_FILE_TYPE_BIOS 0
++#define QEMU_FILE_TYPE_KEYMAP 1
++char *qemu_find_file(int type, const char *name);
++
++extern int vm_running;
++extern const char *qemu_name;
++extern uint8_t qemu_uuid[];
++int qemu_uuid_parse(const char *str, uint8_t *uuid);
++#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
++
++typedef struct vm_change_state_entry VMChangeStateEntry;
++typedef void VMChangeStateHandler(void *opaque, int running, int reason);
++
++VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
++ void *opaque);
++void qemu_del_vm_change_state_handler(VMChangeStateEntry *e);
++
++void vm_start(void);
++void vm_stop(int reason);
++
++uint64_t ram_bytes_remaining(void);
++uint64_t ram_bytes_transferred(void);
++uint64_t ram_bytes_total(void);
++
++int64_t cpu_get_ticks(void);
++void cpu_enable_ticks(void);
++void cpu_disable_ticks(void);
++
++void qemu_system_reset_request(void);
++void qemu_system_shutdown_request(void);
++void qemu_system_powerdown_request(void);
++int qemu_no_shutdown(void);
++int qemu_shutdown_requested(void);
++int qemu_reset_requested(void);
++int qemu_powerdown_requested(void);
++extern qemu_irq qemu_system_powerdown;
++void qemu_system_reset(void);
++
++void qemu_add_exit_notifier(Notifier *notify);
++void qemu_remove_exit_notifier(Notifier *notify);
++
++void do_savevm(Monitor *mon, const QDict *qdict);
++int load_vmstate(const char *name);
++void do_delvm(Monitor *mon, const QDict *qdict);
++void do_info_snapshots(Monitor *mon);
++
++void cpu_synchronize_all_states(void);
++void cpu_synchronize_all_post_reset(void);
++void cpu_synchronize_all_post_init(void);
++
++void qemu_announce_self(void);
++
++void main_loop_wait(int nonblocking);
++
++int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
++ int shared);
++int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
++int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
++void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
++int qemu_loadvm_state(QEMUFile *f);
++
++/* SLIRP */
++void do_info_slirp(Monitor *mon);
++
++/* OS specific functions */
++void os_setup_early_signal_handling(void);
++char *os_find_datadir(const char *argv0);
++void os_parse_cmd_args(int index, const char *optarg);
++void os_pidfile_error(void);
++
++typedef enum DisplayType
++{
++ DT_DEFAULT,
++ DT_CURSES,
++ DT_SDL,
++ DT_VNC,
++ DT_NOGRAPHIC,
++} DisplayType;
++
++extern int autostart;
++extern int incoming_expected;
++extern int bios_size;
++
++typedef enum {
++ VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
++} VGAInterfaceType;
++
++extern int vga_interface_type;
++#define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS)
++#define std_vga_enabled (vga_interface_type == VGA_STD)
++#define xenfb_enabled (vga_interface_type == VGA_XENFB)
++#define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
++
++extern int graphic_width;
++extern int graphic_height;
++extern int graphic_depth;
++extern uint8_t irq0override;
++extern DisplayType display_type;
++extern const char *keyboard_layout;
++extern int win2k_install_hack;
++extern int rtc_td_hack;
++extern int alt_grab;
++extern int ctrl_grab;
++extern int usb_enabled;
++extern int smp_cpus;
++extern int max_cpus;
++extern int cursor_hide;
++extern int graphic_rotate;
++extern int no_quit;
++extern int no_shutdown;
++extern int semihosting_enabled;
++extern int old_param;
++extern int boot_menu;
++extern QEMUClock *rtc_clock;
++extern long hpagesize;
++
++#define MAX_NODES 64
++extern int nb_numa_nodes;
++extern uint64_t node_mem[MAX_NODES];
++extern uint64_t node_cpumask[MAX_NODES];
++
++#define MAX_OPTION_ROMS 16
++extern const char *option_rom[MAX_OPTION_ROMS];
++extern int nb_option_roms;
++
++#define MAX_PROM_ENVS 128
++extern const char *prom_envs[MAX_PROM_ENVS];
++extern unsigned int nb_prom_envs;
++
++/* acpi */
++void qemu_system_cpu_hot_add(int cpu, int state);
++
++/* pci-hotplug */
++void pci_device_hot_add(Monitor *mon, const QDict *qdict);
++void drive_hot_add(Monitor *mon, const QDict *qdict);
++void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
++
++/* serial ports */
++
++#define MAX_SERIAL_PORTS 4
++
++extern CharDriverState *serial_hds[MAX_SERIAL_PORTS];
++
++/* parallel ports */
++
++#define MAX_PARALLEL_PORTS 3
++
++extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
++
++#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
++
++#ifdef HAS_AUDIO
++struct soundhw {
++ const char *name;
++ const char *descr;
++ int enabled;
++ int isa;
++ union {
++ int (*init_isa) (qemu_irq *pic);
++ int (*init_pci) (PCIBus *bus);
++ } init;
++};
++
++extern struct soundhw soundhw[];
++#endif
++
++void do_usb_add(Monitor *mon, const QDict *qdict);
++void do_usb_del(Monitor *mon, const QDict *qdict);
++void usb_info(Monitor *mon);
++
++void rtc_change_mon_event(struct tm *tm);
++
++void register_devices(void);
++
++#endif
+diff -urN qemu-kvm-0.13.0.orig/vl.c qemu-kvm-0.13.0/vl.c
+--- qemu-kvm-0.13.0.orig/vl.c 2011-02-09 11:01:45.746000327 +0200
++++ qemu-kvm-0.13.0/vl.c 2011-02-09 11:08:02.773000327 +0200
+@@ -162,6 +162,8 @@
+ #include "cpus.h"
+ #include "arch_init.h"
+
++#include "qemu-spice.h"
++
+ //#define DEBUG_NET
+ //#define DEBUG_SLIRP
+
+@@ -1458,6 +1460,8 @@
+ vga_interface_type = VGA_VMWARE;
+ } else if (strstart(p, "xenfb", &opts)) {
+ vga_interface_type = VGA_XENFB;
++ } else if (strstart(p, "qxl", &opts)) {
++ vga_interface_type = VGA_QXL;
+ } else if (!strstart(p, "none", &opts)) {
+ invalid_vga:
+ fprintf(stderr, "Unknown vga type: %s\n", p);
+@@ -2679,6 +2683,15 @@
+ }
+ break;
+ }
++#ifdef CONFIG_SPICE
++ case QEMU_OPTION_spice:
++ opts = qemu_opts_parse(&qemu_spice_opts, optarg, 0);
++ if (!opts) {
++ fprintf(stderr, "parse error: %s\n", optarg);
++ exit(1);
++ }
++ break;
++#endif
+ case QEMU_OPTION_writeconfig:
+ {
+ FILE *fp;
+@@ -2953,6 +2966,10 @@
+ }
+ qemu_add_globals();
+
++#ifdef CONFIG_SPICE
++ qemu_spice_init();
++#endif
++
+ machine->init(ram_size, boot_devices,
+ kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
+
+@@ -2980,7 +2997,7 @@
+ /* just use the first displaystate for the moment */
+ ds = get_displaystate();
+
+- if (display_type == DT_DEFAULT) {
++ if (display_type == DT_DEFAULT && !using_spice) {
+ #if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
+ display_type = DT_SDL;
+ #else
+@@ -3020,6 +3037,11 @@
+ default:
+ break;
+ }
++#ifdef CONFIG_SPICE
++ if (using_spice && !qxl_enabled) {
++ qemu_spice_display_init(ds);
++ }
++#endif
+ dpy_resize(ds);
+
+ dcl = ds->listeners;
+diff -urN qemu-kvm-0.13.0.orig/vl.c.orig qemu-kvm-0.13.0/vl.c.orig
+--- qemu-kvm-0.13.0.orig/vl.c.orig 1970-01-01 02:00:00.000000000 +0200
++++ qemu-kvm-0.13.0/vl.c.orig 2011-02-09 11:08:02.730000327 +0200
+@@ -0,0 +1,3100 @@
++/*
++ * QEMU System Emulator
++ *
++ * Copyright (c) 2003-2008 Fabrice Bellard
++ *
++ * 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 <unistd.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <time.h>
++#include <errno.h>
++#include <sys/time.h>
++#include <zlib.h>
++
++/* Needed early for CONFIG_BSD etc. */
++#include "config-host.h"
++
++#ifndef _WIN32
++#include <libgen.h>
++#include <sys/times.h>
++#include <sys/wait.h>
++#include <termios.h>
++#include <sys/mman.h>
++#include <sys/ioctl.h>
++#include <sys/resource.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <net/if.h>
++#include <arpa/inet.h>
++#include <dirent.h>
++#include <netdb.h>
++#include <sys/select.h>
++#ifdef CONFIG_BSD
++#include <sys/stat.h>
++#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
++#include <libutil.h>
++#include <sys/sysctl.h>
++#else
++#include <util.h>
++#endif
++#else
++#ifdef __linux__
++#include <pty.h>
++#include <malloc.h>
++
++#include <linux/ppdev.h>
++#include <linux/parport.h>
++#endif
++#ifdef __sun__
++#include <sys/stat.h>
++#include <sys/ethernet.h>
++#include <sys/sockio.h>
++#include <netinet/arp.h>
++#include <netinet/in_systm.h>
++#include <netinet/ip.h>
++#include <netinet/ip_icmp.h> // must come after ip.h
++#include <netinet/udp.h>
++#include <netinet/tcp.h>
++#include <net/if.h>
++#include <syslog.h>
++#include <stropts.h>
++/* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
++ discussion about Solaris header problems */
++extern int madvise(caddr_t, size_t, int);
++#endif
++#endif
++#endif
++
++#if defined(__OpenBSD__)
++#include <util.h>
++#endif
++
++#if defined(CONFIG_VDE)
++#include <libvdeplug.h>
++#endif
++
++#ifdef _WIN32
++#include <windows.h>
++#endif
++
++#ifdef CONFIG_SDL
++#if defined(__APPLE__) || defined(main)
++#include <SDL.h>
++int qemu_main(int argc, char **argv, char **envp);
++int main(int argc, char **argv)
++{
++ return qemu_main(argc, argv, NULL);
++}
++#undef main
++#define main qemu_main
++#endif
++#endif /* CONFIG_SDL */
++
++#ifdef CONFIG_COCOA
++#undef main
++#define main qemu_main
++#endif /* CONFIG_COCOA */
++
++#include "hw/hw.h"
++#include "hw/boards.h"
++#include "hw/usb.h"
++#include "hw/pcmcia.h"
++#include "hw/pc.h"
++#include "hw/isa.h"
++#include "hw/baum.h"
++#include "hw/bt.h"
++#include "hw/watchdog.h"
++#include "hw/smbios.h"
++#include "hw/xen.h"
++#include "hw/qdev.h"
++#include "hw/loader.h"
++#include "bt-host.h"
++#include "net.h"
++#include "net/slirp.h"
++#include "monitor.h"
++#include "console.h"
++#include "sysemu.h"
++#include "gdbstub.h"
++#include "qemu-timer.h"
++#include "qemu-char.h"
++#include "cache-utils.h"
++#include "block.h"
++#include "blockdev.h"
++#include "block-migration.h"
++#include "dma.h"
++#include "audio/audio.h"
++#include "migration.h"
++#include "kvm.h"
++#include "qemu-option.h"
++#include "qemu-config.h"
++#include "qemu-objects.h"
++#include "qemu-options.h"
++#include "hw/device-assignment.h"
++#ifdef CONFIG_VIRTFS
++#include "fsdev/qemu-fsdev.h"
++#endif
++
++#include "disas.h"
++
++#include "qemu_socket.h"
++
++#include "slirp/libslirp.h"
++
++#include "qemu-queue.h"
++#include "cpus.h"
++#include "arch_init.h"
++
++#include "qemu-spice.h"
++
++//#define DEBUG_NET
++//#define DEBUG_SLIRP
++
++#define DEFAULT_RAM_SIZE 128
++
++#define MAX_VIRTIO_CONSOLES 1
++
++static const char *data_dir;
++const char *bios_name = NULL;
++enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
++DisplayType display_type = DT_DEFAULT;
++const char* keyboard_layout = NULL;
++ram_addr_t ram_size;
++const char *mem_path = NULL;
++#ifdef MAP_POPULATE
++int mem_prealloc = 0; /* force preallocation of physical target memory */
++#endif
++int nb_nics;
++NICInfo nd_table[MAX_NICS];
++int vm_running;
++int autostart;
++int incoming_expected; /* Started with -incoming and waiting for incoming */
++static int rtc_utc = 1;
++static int rtc_date_offset = -1; /* -1 means no change */
++QEMUClock *rtc_clock;
++int vga_interface_type = VGA_NONE;
++static int full_screen = 0;
++#ifdef CONFIG_SDL
++static int no_frame = 0;
++#endif
++int no_quit = 0;
++CharDriverState *serial_hds[MAX_SERIAL_PORTS];
++CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
++CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
++int win2k_install_hack = 0;
++int rtc_td_hack = 0;
++int usb_enabled = 0;
++int singlestep = 0;
++const char *assigned_devices[MAX_DEV_ASSIGN_CMDLINE];
++int assigned_devices_index;
++int smp_cpus = 1;
++int max_cpus = 0;
++int smp_cores = 1;
++int smp_threads = 1;
++const char *vnc_display;
++int acpi_enabled = 1;
++int no_hpet = 0;
++int fd_bootchk = 1;
++int no_reboot = 0;
++int no_shutdown = 0;
++int cursor_hide = 1;
++int graphic_rotate = 0;
++uint8_t irq0override = 1;
++const char *watchdog;
++const char *option_rom[MAX_OPTION_ROMS];
++int nb_option_roms;
++int semihosting_enabled = 0;
++int time_drift_fix = 0;
++unsigned int kvm_shadow_memory = 0;
++int old_param = 0;
++const char *qemu_name;
++int alt_grab = 0;
++int ctrl_grab = 0;
++unsigned int nb_prom_envs = 0;
++const char *prom_envs[MAX_PROM_ENVS];
++const char *nvram = NULL;
++int boot_menu;
++
++int nb_numa_nodes;
++uint64_t node_mem[MAX_NODES];
++uint64_t node_cpumask[MAX_NODES];
++
++static QEMUTimer *nographic_timer;
++
++uint8_t qemu_uuid[16];
++
++static QEMUBootSetHandler *boot_set_handler;
++static void *boot_set_opaque;
++
++static NotifierList exit_notifiers =
++ NOTIFIER_LIST_INITIALIZER(exit_notifiers);
++
++int kvm_allowed = 1;
++uint32_t xen_domid;
++enum xen_mode xen_mode = XEN_EMULATE;
++
++static int default_serial = 1;
++static int default_parallel = 1;
++static int default_virtcon = 1;
++static int default_monitor = 1;
++static int default_vga = 1;
++static int default_floppy = 1;
++static int default_cdrom = 1;
++static int default_sdcard = 1;
++
++static struct {
++ const char *driver;
++ int *flag;
++} default_list[] = {
++ { .driver = "isa-serial", .flag = &default_serial },
++ { .driver = "isa-parallel", .flag = &default_parallel },
++ { .driver = "isa-fdc", .flag = &default_floppy },
++ { .driver = "ide-drive", .flag = &default_cdrom },
++ { .driver = "virtio-serial-pci", .flag = &default_virtcon },
++ { .driver = "virtio-serial-s390", .flag = &default_virtcon },
++ { .driver = "virtio-serial", .flag = &default_virtcon },
++ { .driver = "VGA", .flag = &default_vga },
++ { .driver = "cirrus-vga", .flag = &default_vga },
++ { .driver = "vmware-svga", .flag = &default_vga },
++};
++
++static int default_driver_check(QemuOpts *opts, void *opaque)
++{
++ const char *driver = qemu_opt_get(opts, "driver");
++ int i;
++
++ if (!driver)
++ return 0;
++ for (i = 0; i < ARRAY_SIZE(default_list); i++) {
++ if (strcmp(default_list[i].driver, driver) != 0)
++ continue;
++ *(default_list[i].flag) = 0;
++ }
++ return 0;
++}
++
++/***********************************************************/
++/* real time host monotonic timer */
++
++/* compute with 96 bit intermediate result: (a*b)/c */
++uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
++{
++ union {
++ uint64_t ll;
++ struct {
++#ifdef HOST_WORDS_BIGENDIAN
++ uint32_t high, low;
++#else
++ uint32_t low, high;
++#endif
++ } l;
++ } u, res;
++ uint64_t rl, rh;
++
++ u.ll = a;
++ rl = (uint64_t)u.l.low * (uint64_t)b;
++ rh = (uint64_t)u.l.high * (uint64_t)b;
++ rh += (rl >> 32);
++ res.l.high = rh / c;
++ res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
++ return res.ll;
++}
++
++/***********************************************************/
++/* host time/date access */
++void qemu_get_timedate(struct tm *tm, int offset)
++{
++ time_t ti;
++ struct tm *ret;
++
++ time(&ti);
++ ti += offset;
++ if (rtc_date_offset == -1) {
++ if (rtc_utc)
++ ret = gmtime(&ti);
++ else
++ ret = localtime(&ti);
++ } else {
++ ti -= rtc_date_offset;
++ ret = gmtime(&ti);
++ }
++
++ memcpy(tm, ret, sizeof(struct tm));
++}
++
++int qemu_timedate_diff(struct tm *tm)
++{
++ time_t seconds;
++
++ if (rtc_date_offset == -1)
++ if (rtc_utc)
++ seconds = mktimegm(tm);
++ else
++ seconds = mktime(tm);
++ else
++ seconds = mktimegm(tm) + rtc_date_offset;
++
++ return seconds - time(NULL);
++}
++
++void rtc_change_mon_event(struct tm *tm)
++{
++ QObject *data;
++
++ data = qobject_from_jsonf("{ 'offset': %d }", qemu_timedate_diff(tm));
++ monitor_protocol_event(QEVENT_RTC_CHANGE, data);
++ qobject_decref(data);
++}
++
++static void configure_rtc_date_offset(const char *startdate, int legacy)
++{
++ time_t rtc_start_date;
++ struct tm tm;
++
++ if (!strcmp(startdate, "now") && legacy) {
++ rtc_date_offset = -1;
++ } else {
++ if (sscanf(startdate, "%d-%d-%dT%d:%d:%d",
++ &tm.tm_year,
++ &tm.tm_mon,
++ &tm.tm_mday,
++ &tm.tm_hour,
++ &tm.tm_min,
++ &tm.tm_sec) == 6) {
++ /* OK */
++ } else if (sscanf(startdate, "%d-%d-%d",
++ &tm.tm_year,
++ &tm.tm_mon,
++ &tm.tm_mday) == 3) {
++ tm.tm_hour = 0;
++ tm.tm_min = 0;
++ tm.tm_sec = 0;
++ } else {
++ goto date_fail;
++ }
++ tm.tm_year -= 1900;
++ tm.tm_mon--;
++ rtc_start_date = mktimegm(&tm);
++ if (rtc_start_date == -1) {
++ date_fail:
++ fprintf(stderr, "Invalid date format. Valid formats are:\n"
++ "'2006-06-17T16:01:21' or '2006-06-17'\n");
++ exit(1);
++ }
++ rtc_date_offset = time(NULL) - rtc_start_date;
++ }
++}
++
++static void configure_rtc(QemuOpts *opts)
++{
++ const char *value;
++
++ value = qemu_opt_get(opts, "base");
++ if (value) {
++ if (!strcmp(value, "utc")) {
++ rtc_utc = 1;
++ } else if (!strcmp(value, "localtime")) {
++ rtc_utc = 0;
++ } else {
++ configure_rtc_date_offset(value, 0);
++ }
++ }
++ value = qemu_opt_get(opts, "clock");
++ if (value) {
++ if (!strcmp(value, "host")) {
++ rtc_clock = host_clock;
++ } else if (!strcmp(value, "vm")) {
++ rtc_clock = vm_clock;
++ } else {
++ fprintf(stderr, "qemu: invalid option value '%s'\n", value);
++ exit(1);
++ }
++ }
++ value = qemu_opt_get(opts, "driftfix");
++ if (value) {
++ if (!strcmp(value, "slew")) {
++ rtc_td_hack = 1;
++ } else if (!strcmp(value, "none")) {
++ rtc_td_hack = 0;
++ } else {
++ fprintf(stderr, "qemu: invalid option value '%s'\n", value);
++ exit(1);
++ }
++ }
++}
++
++/***********************************************************/
++/* Bluetooth support */
++static int nb_hcis;
++static int cur_hci;
++static struct HCIInfo *hci_table[MAX_NICS];
++
++static struct bt_vlan_s {
++ struct bt_scatternet_s net;
++ int id;
++ struct bt_vlan_s *next;
++} *first_bt_vlan;
++
++/* find or alloc a new bluetooth "VLAN" */
++static struct bt_scatternet_s *qemu_find_bt_vlan(int id)
++{
++ struct bt_vlan_s **pvlan, *vlan;
++ for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
++ if (vlan->id == id)
++ return &vlan->net;
++ }
++ vlan = qemu_mallocz(sizeof(struct bt_vlan_s));
++ vlan->id = id;
++ pvlan = &first_bt_vlan;
++ while (*pvlan != NULL)
++ pvlan = &(*pvlan)->next;
++ *pvlan = vlan;
++ return &vlan->net;
++}
++
++static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
++{
++}
++
++static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
++{
++ return -ENOTSUP;
++}
++
++static struct HCIInfo null_hci = {
++ .cmd_send = null_hci_send,
++ .sco_send = null_hci_send,
++ .acl_send = null_hci_send,
++ .bdaddr_set = null_hci_addr_set,
++};
++
++struct HCIInfo *qemu_next_hci(void)
++{
++ if (cur_hci == nb_hcis)
++ return &null_hci;
++
++ return hci_table[cur_hci++];
++}
++
++static struct HCIInfo *hci_init(const char *str)
++{
++ char *endp;
++ struct bt_scatternet_s *vlan = 0;
++
++ if (!strcmp(str, "null"))
++ /* null */
++ return &null_hci;
++ else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':'))
++ /* host[:hciN] */
++ return bt_host_hci(str[4] ? str + 5 : "hci0");
++ else if (!strncmp(str, "hci", 3)) {
++ /* hci[,vlan=n] */
++ if (str[3]) {
++ if (!strncmp(str + 3, ",vlan=", 6)) {
++ vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0));
++ if (*endp)
++ vlan = 0;
++ }
++ } else
++ vlan = qemu_find_bt_vlan(0);
++ if (vlan)
++ return bt_new_hci(vlan);
++ }
++
++ fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str);
++
++ return 0;
++}
++
++static int bt_hci_parse(const char *str)
++{
++ struct HCIInfo *hci;
++ bdaddr_t bdaddr;
++
++ if (nb_hcis >= MAX_NICS) {
++ fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS);
++ return -1;
++ }
++
++ hci = hci_init(str);
++ if (!hci)
++ return -1;
++
++ bdaddr.b[0] = 0x52;
++ bdaddr.b[1] = 0x54;
++ bdaddr.b[2] = 0x00;
++ bdaddr.b[3] = 0x12;
++ bdaddr.b[4] = 0x34;
++ bdaddr.b[5] = 0x56 + nb_hcis;
++ hci->bdaddr_set(hci, bdaddr.b);
++
++ hci_table[nb_hcis++] = hci;
++
++ return 0;
++}
++
++static void bt_vhci_add(int vlan_id)
++{
++ struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id);
++
++ if (!vlan->slave)
++ fprintf(stderr, "qemu: warning: adding a VHCI to "
++ "an empty scatternet %i\n", vlan_id);
++
++ bt_vhci_init(bt_new_hci(vlan));
++}
++
++static struct bt_device_s *bt_device_add(const char *opt)
++{
++ struct bt_scatternet_s *vlan;
++ int vlan_id = 0;
++ char *endp = strstr(opt, ",vlan=");
++ int len = (endp ? endp - opt : strlen(opt)) + 1;
++ char devname[10];
++
++ pstrcpy(devname, MIN(sizeof(devname), len), opt);
++
++ if (endp) {
++ vlan_id = strtol(endp + 6, &endp, 0);
++ if (*endp) {
++ fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n");
++ return 0;
++ }
++ }
++
++ vlan = qemu_find_bt_vlan(vlan_id);
++
++ if (!vlan->slave)
++ fprintf(stderr, "qemu: warning: adding a slave device to "
++ "an empty scatternet %i\n", vlan_id);
++
++ if (!strcmp(devname, "keyboard"))
++ return bt_keyboard_init(vlan);
++
++ fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname);
++ return 0;
++}
++
++static int bt_parse(const char *opt)
++{
++ const char *endp, *p;
++ int vlan;
++
++ if (strstart(opt, "hci", &endp)) {
++ if (!*endp || *endp == ',') {
++ if (*endp)
++ if (!strstart(endp, ",vlan=", 0))
++ opt = endp + 1;
++
++ return bt_hci_parse(opt);
++ }
++ } else if (strstart(opt, "vhci", &endp)) {
++ if (!*endp || *endp == ',') {
++ if (*endp) {
++ if (strstart(endp, ",vlan=", &p)) {
++ vlan = strtol(p, (char **) &endp, 0);
++ if (*endp) {
++ fprintf(stderr, "qemu: bad scatternet '%s'\n", p);
++ return 1;
++ }
++ } else {
++ fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1);
++ return 1;
++ }
++ } else
++ vlan = 0;
++
++ bt_vhci_add(vlan);
++ return 0;
++ }
++ } else if (strstart(opt, "device:", &endp))
++ return !bt_device_add(endp);
++
++ fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt);
++ return 1;
++}
++
++/***********************************************************/
++/* QEMU Block devices */
++
++#define HD_ALIAS "index=%d,media=disk"
++#define CDROM_ALIAS "index=2,media=cdrom"
++#define FD_ALIAS "index=%d,if=floppy"
++#define PFLASH_ALIAS "if=pflash"
++#define MTD_ALIAS "if=mtd"
++#define SD_ALIAS "index=0,if=sd"
++
++static int drive_init_func(QemuOpts *opts, void *opaque)
++{
++ int *use_scsi = opaque;
++ int fatal_error = 0;
++
++ if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
++ if (fatal_error)
++ return 1;
++ }
++ return 0;
++}
++
++static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
++{
++ if (NULL == qemu_opt_get(opts, "snapshot")) {
++ qemu_opt_set(opts, "snapshot", "on");
++ }
++ return 0;
++}
++
++void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
++{
++ boot_set_handler = func;
++ boot_set_opaque = opaque;
++}
++
++int qemu_boot_set(const char *boot_devices)
++{
++ if (!boot_set_handler) {
++ return -EINVAL;
++ }
++ return boot_set_handler(boot_set_opaque, boot_devices);
++}
++
++static void validate_bootdevices(char *devices)
++{
++ /* We just do some generic consistency checks */
++ const char *p;
++ int bitmap = 0;
++
++ for (p = devices; *p != '\0'; p++) {
++ /* Allowed boot devices are:
++ * a-b: floppy disk drives
++ * c-f: IDE disk drives
++ * g-m: machine implementation dependant drives
++ * n-p: network devices
++ * It's up to each machine implementation to check if the given boot
++ * devices match the actual hardware implementation and firmware
++ * features.
++ */
++ if (*p < 'a' || *p > 'p') {
++ fprintf(stderr, "Invalid boot device '%c'\n", *p);
++ exit(1);
++ }
++ if (bitmap & (1 << (*p - 'a'))) {
++ fprintf(stderr, "Boot device '%c' was given twice\n", *p);
++ exit(1);
++ }
++ bitmap |= 1 << (*p - 'a');
++ }
++}
++
++static void restore_boot_devices(void *opaque)
++{
++ char *standard_boot_devices = opaque;
++ static int first = 1;
++
++ /* Restore boot order and remove ourselves after the first boot */
++ if (first) {
++ first = 0;
++ return;
++ }
++
++ qemu_boot_set(standard_boot_devices);
++
++ qemu_unregister_reset(restore_boot_devices, standard_boot_devices);
++ qemu_free(standard_boot_devices);
++}
++
++static void numa_add(const char *optarg)
++{
++ char option[128];
++ char *endptr;
++ unsigned long long value, endvalue;
++ int nodenr;
++
++ optarg = get_opt_name(option, 128, optarg, ',') + 1;
++ if (!strcmp(option, "node")) {
++ if (get_param_value(option, 128, "nodeid", optarg) == 0) {
++ nodenr = nb_numa_nodes;
++ } else {
++ nodenr = strtoull(option, NULL, 10);
++ }
++
++ if (get_param_value(option, 128, "mem", optarg) == 0) {
++ node_mem[nodenr] = 0;
++ } else {
++ value = strtoull(option, &endptr, 0);
++ switch (*endptr) {
++ case 0: case 'M': case 'm':
++ value <<= 20;
++ break;
++ case 'G': case 'g':
++ value <<= 30;
++ break;
++ }
++ node_mem[nodenr] = value;
++ }
++ if (get_param_value(option, 128, "cpus", optarg) == 0) {
++ node_cpumask[nodenr] = 0;
++ } else {
++ value = strtoull(option, &endptr, 10);
++ if (value >= 64) {
++ value = 63;
++ fprintf(stderr, "only 64 CPUs in NUMA mode supported.\n");
++ } else {
++ if (*endptr == '-') {
++ endvalue = strtoull(endptr+1, &endptr, 10);
++ if (endvalue >= 63) {
++ endvalue = 62;
++ fprintf(stderr,
++ "only 63 CPUs in NUMA mode supported.\n");
++ }
++ value = (2ULL << endvalue) - (1ULL << value);
++ } else {
++ value = 1ULL << value;
++ }
++ }
++ node_cpumask[nodenr] = value;
++ }
++ nb_numa_nodes++;
++ }
++ return;
++}
++
++static void smp_parse(const char *optarg)
++{
++ int smp, sockets = 0, threads = 0, cores = 0;
++ char *endptr;
++ char option[128];
++
++ smp = strtoul(optarg, &endptr, 10);
++ if (endptr != optarg) {
++ if (*endptr == ',') {
++ endptr++;
++ }
++ }
++ if (get_param_value(option, 128, "sockets", endptr) != 0)
++ sockets = strtoull(option, NULL, 10);
++ if (get_param_value(option, 128, "cores", endptr) != 0)
++ cores = strtoull(option, NULL, 10);
++ if (get_param_value(option, 128, "threads", endptr) != 0)
++ threads = strtoull(option, NULL, 10);
++ if (get_param_value(option, 128, "maxcpus", endptr) != 0)
++ max_cpus = strtoull(option, NULL, 10);
++
++ /* compute missing values, prefer sockets over cores over threads */
++ if (smp == 0 || sockets == 0) {
++ sockets = sockets > 0 ? sockets : 1;
++ cores = cores > 0 ? cores : 1;
++ threads = threads > 0 ? threads : 1;
++ if (smp == 0) {
++ smp = cores * threads * sockets;
++ }
++ } else {
++ if (cores == 0) {
++ threads = threads > 0 ? threads : 1;
++ cores = smp / (sockets * threads);
++ } else {
++ if (sockets) {
++ threads = smp / (cores * sockets);
++ }
++ }
++ }
++ smp_cpus = smp;
++ smp_cores = cores > 0 ? cores : 1;
++ smp_threads = threads > 0 ? threads : 1;
++ if (max_cpus == 0)
++ max_cpus = smp_cpus;
++}
++
++/***********************************************************/
++/* USB devices */
++
++static int usb_device_add(const char *devname)
++{
++ const char *p;
++ USBDevice *dev = NULL;
++
++ if (!usb_enabled)
++ return -1;
++
++ /* drivers with .usbdevice_name entry in USBDeviceInfo */
++ dev = usbdevice_create(devname);
++ if (dev)
++ goto done;
++
++ /* the other ones */
++ if (strstart(devname, "host:", &p)) {
++ dev = usb_host_device_open(p);
++ } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
++ dev = usb_bt_init(devname[2] ? hci_init(p) :
++ bt_new_hci(qemu_find_bt_vlan(0)));
++ } else {
++ return -1;
++ }
++ if (!dev)
++ return -1;
++
++done:
++ return 0;
++}
++
++static int usb_device_del(const char *devname)
++{
++ int bus_num, addr;
++ const char *p;
++
++ if (strstart(devname, "host:", &p))
++ return usb_host_device_close(p);
++
++ if (!usb_enabled)
++ return -1;
++
++ p = strchr(devname, '.');
++ if (!p)
++ return -1;
++ bus_num = strtoul(devname, NULL, 0);
++ addr = strtoul(p + 1, NULL, 0);
++
++ return usb_device_delete_addr(bus_num, addr);
++}
++
++static int usb_parse(const char *cmdline)
++{
++ int r;
++ r = usb_device_add(cmdline);
++ if (r < 0) {
++ fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
++ }
++ return r;
++}
++
++void do_usb_add(Monitor *mon, const QDict *qdict)
++{
++ const char *devname = qdict_get_str(qdict, "devname");
++ if (usb_device_add(devname) < 0) {
++ error_report("could not add USB device '%s'", devname);
++ }
++}
++
++void do_usb_del(Monitor *mon, const QDict *qdict)
++{
++ const char *devname = qdict_get_str(qdict, "devname");
++ if (usb_device_del(devname) < 0) {
++ error_report("could not delete USB device '%s'", devname);
++ }
++}
++
++/***********************************************************/
++/* PCMCIA/Cardbus */
++
++static struct pcmcia_socket_entry_s {
++ PCMCIASocket *socket;
++ struct pcmcia_socket_entry_s *next;
++} *pcmcia_sockets = 0;
++
++void pcmcia_socket_register(PCMCIASocket *socket)
++{
++ struct pcmcia_socket_entry_s *entry;
++
++ entry = qemu_malloc(sizeof(struct pcmcia_socket_entry_s));
++ entry->socket = socket;
++ entry->next = pcmcia_sockets;
++ pcmcia_sockets = entry;
++}
++
++void pcmcia_socket_unregister(PCMCIASocket *socket)
++{
++ struct pcmcia_socket_entry_s *entry, **ptr;
++
++ ptr = &pcmcia_sockets;
++ for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr)
++ if (entry->socket == socket) {
++ *ptr = entry->next;
++ qemu_free(entry);
++ }
++}
++
++void pcmcia_info(Monitor *mon)
++{
++ struct pcmcia_socket_entry_s *iter;
++
++ if (!pcmcia_sockets)
++ monitor_printf(mon, "No PCMCIA sockets\n");
++
++ for (iter = pcmcia_sockets; iter; iter = iter->next)
++ monitor_printf(mon, "%s: %s\n", iter->socket->slot_string,
++ iter->socket->attached ? iter->socket->card_string :
++ "Empty");
++}
++
++/***********************************************************/
++/* I/O handling */
++
++typedef struct IOHandlerRecord {
++ int fd;
++ IOCanReadHandler *fd_read_poll;
++ IOHandler *fd_read;
++ IOHandler *fd_write;
++ int deleted;
++ void *opaque;
++ /* temporary data */
++ struct pollfd *ufd;
++ QLIST_ENTRY(IOHandlerRecord) next;
++} IOHandlerRecord;
++
++static QLIST_HEAD(, IOHandlerRecord) io_handlers =
++ QLIST_HEAD_INITIALIZER(io_handlers);
++
++
++/* XXX: fd_read_poll should be suppressed, but an API change is
++ necessary in the character devices to suppress fd_can_read(). */
++int qemu_set_fd_handler2(int fd,
++ IOCanReadHandler *fd_read_poll,
++ IOHandler *fd_read,
++ IOHandler *fd_write,
++ void *opaque)
++{
++ IOHandlerRecord *ioh;
++
++ if (!fd_read && !fd_write) {
++ QLIST_FOREACH(ioh, &io_handlers, next) {
++ if (ioh->fd == fd) {
++ ioh->deleted = 1;
++ break;
++ }
++ }
++ } else {
++ QLIST_FOREACH(ioh, &io_handlers, next) {
++ if (ioh->fd == fd)
++ goto found;
++ }
++ ioh = qemu_mallocz(sizeof(IOHandlerRecord));
++ QLIST_INSERT_HEAD(&io_handlers, ioh, next);
++ found:
++ ioh->fd = fd;
++ ioh->fd_read_poll = fd_read_poll;
++ ioh->fd_read = fd_read;
++ ioh->fd_write = fd_write;
++ ioh->opaque = opaque;
++ ioh->deleted = 0;
++ }
++ qemu_notify_event();
++ return 0;
++}
++
++int qemu_set_fd_handler(int fd,
++ IOHandler *fd_read,
++ IOHandler *fd_write,
++ void *opaque)
++{
++ return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
++}
++
++/***********************************************************/
++/* machine registration */
++
++static QEMUMachine *first_machine = NULL;
++QEMUMachine *current_machine = NULL;
++
++int qemu_register_machine(QEMUMachine *m)
++{
++ QEMUMachine **pm;
++ pm = &first_machine;
++ while (*pm != NULL)
++ pm = &(*pm)->next;
++ m->next = NULL;
++ *pm = m;
++ return 0;
++}
++
++static QEMUMachine *find_machine(const char *name)
++{
++ QEMUMachine *m;
++
++ for(m = first_machine; m != NULL; m = m->next) {
++ if (!strcmp(m->name, name))
++ return m;
++ if (m->alias && !strcmp(m->alias, name))
++ return m;
++ }
++ return NULL;
++}
++
++static QEMUMachine *find_default_machine(void)
++{
++ QEMUMachine *m;
++
++ for(m = first_machine; m != NULL; m = m->next) {
++ if (m->is_default) {
++ return m;
++ }
++ }
++ return NULL;
++}
++
++/***********************************************************/
++/* main execution loop */
++
++static void gui_update(void *opaque)
++{
++ uint64_t interval = GUI_REFRESH_INTERVAL;
++ DisplayState *ds = opaque;
++ DisplayChangeListener *dcl = ds->listeners;
++
++ qemu_flush_coalesced_mmio_buffer();
++ dpy_refresh(ds);
++
++ while (dcl != NULL) {
++ if (dcl->gui_timer_interval &&
++ dcl->gui_timer_interval < interval)
++ interval = dcl->gui_timer_interval;
++ dcl = dcl->next;
++ }
++ qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock));
++}
++
++static void nographic_update(void *opaque)
++{
++ uint64_t interval = GUI_REFRESH_INTERVAL;
++
++ qemu_flush_coalesced_mmio_buffer();
++ qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
++}
++
++struct vm_change_state_entry {
++ VMChangeStateHandler *cb;
++ void *opaque;
++ QLIST_ENTRY (vm_change_state_entry) entries;
++};
++
++static QLIST_HEAD(vm_change_state_head, vm_change_state_entry) vm_change_state_head;
++
++VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
++ void *opaque)
++{
++ VMChangeStateEntry *e;
++
++ e = qemu_mallocz(sizeof (*e));
++
++ e->cb = cb;
++ e->opaque = opaque;
++ QLIST_INSERT_HEAD(&vm_change_state_head, e, entries);
++ return e;
++}
++
++void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
++{
++ QLIST_REMOVE (e, entries);
++ qemu_free (e);
++}
++
++void vm_state_notify(int running, int reason)
++{
++ VMChangeStateEntry *e;
++
++ for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
++ e->cb(e->opaque, running, reason);
++ }
++}
++
++void vm_start(void)
++{
++ if (!vm_running) {
++ cpu_enable_ticks();
++ vm_running = 1;
++ vm_state_notify(1, 0);
++ resume_all_vcpus();
++ monitor_protocol_event(QEVENT_RESUME, NULL);
++ }
++}
++
++/* reset/shutdown handler */
++
++typedef struct QEMUResetEntry {
++ QTAILQ_ENTRY(QEMUResetEntry) entry;
++ QEMUResetHandler *func;
++ void *opaque;
++} QEMUResetEntry;
++
++static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
++ QTAILQ_HEAD_INITIALIZER(reset_handlers);
++static int reset_requested;
++static int shutdown_requested;
++static int powerdown_requested;
++int debug_requested;
++int vmstop_requested;
++
++int qemu_no_shutdown(void)
++{
++ int r = no_shutdown;
++ no_shutdown = 0;
++ return r;
++}
++
++int qemu_shutdown_requested(void)
++{
++ int r = shutdown_requested;
++ shutdown_requested = 0;
++ return r;
++}
++
++int qemu_reset_requested(void)
++{
++ int r = reset_requested;
++ reset_requested = 0;
++ return r;
++}
++
++int qemu_powerdown_requested(void)
++{
++ int r = powerdown_requested;
++ powerdown_requested = 0;
++ return r;
++}
++
++static int qemu_debug_requested(void)
++{
++ int r = debug_requested;
++ debug_requested = 0;
++ return r;
++}
++
++static int qemu_vmstop_requested(void)
++{
++ int r = vmstop_requested;
++ vmstop_requested = 0;
++ return r;
++}
++
++void qemu_register_reset(QEMUResetHandler *func, void *opaque)
++{
++ QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry));
++
++ re->func = func;
++ re->opaque = opaque;
++ QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
++}
++
++void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
++{
++ QEMUResetEntry *re;
++
++ QTAILQ_FOREACH(re, &reset_handlers, entry) {
++ if (re->func == func && re->opaque == opaque) {
++ QTAILQ_REMOVE(&reset_handlers, re, entry);
++ qemu_free(re);
++ return;
++ }
++ }
++}
++
++void qemu_system_reset(void)
++{
++ QEMUResetEntry *re, *nre;
++
++ /* reset all devices */
++ QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
++ re->func(re->opaque);
++ }
++ monitor_protocol_event(QEVENT_RESET, NULL);
++ cpu_synchronize_all_post_reset();
++}
++
++void qemu_system_reset_request(void)
++{
++ if (no_reboot) {
++ shutdown_requested = 1;
++ } else {
++ reset_requested = 1;
++ }
++ if (cpu_single_env) {
++ cpu_single_env->stopped = 1;
++ cpu_exit(cpu_single_env);
++ }
++ qemu_notify_event();
++}
++
++void qemu_system_shutdown_request(void)
++{
++ shutdown_requested = 1;
++ qemu_notify_event();
++}
++
++void qemu_system_powerdown_request(void)
++{
++ powerdown_requested = 1;
++ qemu_notify_event();
++}
++
++void main_loop_wait(int nonblocking)
++{
++ IOHandlerRecord *ioh;
++ fd_set rfds, wfds, xfds;
++ int ret, nfds;
++ struct timeval tv;
++ int timeout;
++
++ if (nonblocking)
++ timeout = 0;
++ else {
++ timeout = qemu_calculate_timeout();
++ qemu_bh_update_timeout(&timeout);
++ }
++
++ os_host_main_loop_wait(&timeout);
++
++ /* poll any events */
++ /* XXX: separate device handlers from system ones */
++ nfds = -1;
++ FD_ZERO(&rfds);
++ FD_ZERO(&wfds);
++ FD_ZERO(&xfds);
++ QLIST_FOREACH(ioh, &io_handlers, next) {
++ if (ioh->deleted)
++ continue;
++ if (ioh->fd_read &&
++ (!ioh->fd_read_poll ||
++ ioh->fd_read_poll(ioh->opaque) != 0)) {
++ FD_SET(ioh->fd, &rfds);
++ if (ioh->fd > nfds)
++ nfds = ioh->fd;
++ }
++ if (ioh->fd_write) {
++ FD_SET(ioh->fd, &wfds);
++ if (ioh->fd > nfds)
++ nfds = ioh->fd;
++ }
++ }
++
++ tv.tv_sec = timeout / 1000;
++ tv.tv_usec = (timeout % 1000) * 1000;
++
++ slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
++
++ qemu_mutex_unlock_iothread();
++ ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
++ qemu_mutex_lock_iothread();
++ if (ret > 0) {
++ IOHandlerRecord *pioh;
++
++ QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
++ if (ioh->deleted) {
++ QLIST_REMOVE(ioh, next);
++ qemu_free(ioh);
++ continue;
++ }
++ if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
++ ioh->fd_read(ioh->opaque);
++ if (!(ioh->fd_read_poll && ioh->fd_read_poll(ioh->opaque)))
++ FD_CLR(ioh->fd, &rfds);
++ }
++ if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
++ ioh->fd_write(ioh->opaque);
++ }
++ }
++ }
++
++ slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
++
++ qemu_run_all_timers();
++
++ /* Check bottom-halves last in case any of the earlier events triggered
++ them. */
++ qemu_bh_poll();
++
++}
++
++static int vm_can_run(void)
++{
++ if (powerdown_requested)
++ return 0;
++ if (reset_requested)
++ return 0;
++ if (shutdown_requested)
++ return 0;
++ if (debug_requested)
++ return 0;
++ return 1;
++}
++
++qemu_irq qemu_system_powerdown;
++
++static void main_loop(void)
++{
++ int r;
++
++ if (kvm_enabled()) {
++ kvm_main_loop();
++ cpu_disable_ticks();
++ return;
++ }
++
++ qemu_main_loop_start();
++
++ for (;;) {
++ do {
++ bool nonblocking = false;
++#ifdef CONFIG_PROFILER
++ int64_t ti;
++#endif
++#ifndef CONFIG_IOTHREAD
++ nonblocking = cpu_exec_all();
++#endif
++#ifdef CONFIG_PROFILER
++ ti = profile_getclock();
++#endif
++ main_loop_wait(nonblocking);
++#ifdef CONFIG_PROFILER
++ dev_time += profile_getclock() - ti;
++#endif
++ } while (vm_can_run());
++
++ if ((r = qemu_debug_requested())) {
++ vm_stop(r);
++ }
++ if (qemu_shutdown_requested()) {
++ monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
++ if (no_shutdown) {
++ vm_stop(0);
++ no_shutdown = 0;
++ } else
++ break;
++ }
++ if (qemu_reset_requested()) {
++ pause_all_vcpus();
++ qemu_system_reset();
++ resume_all_vcpus();
++ }
++ if (qemu_powerdown_requested()) {
++ monitor_protocol_event(QEVENT_POWERDOWN, NULL);
++ qemu_irq_raise(qemu_system_powerdown);
++ }
++ if ((r = qemu_vmstop_requested())) {
++ vm_stop(r);
++ }
++ }
++ bdrv_close_all();
++ pause_all_vcpus();
++}
++
++static void version(void)
++{
++ printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
++}
++
++static void help(int exitcode)
++{
++ const char *options_help =
++#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
++ opt_help
++#define DEFHEADING(text) stringify(text) "\n"
++#include "qemu-options.def"
++#undef DEF
++#undef DEFHEADING
++#undef GEN_DOCS
++ ;
++ version();
++ printf("usage: %s [options] [disk_image]\n"
++ "\n"
++ "'disk_image' is a raw hard disk image for IDE hard disk 0\n"
++ "\n"
++ "%s\n"
++ "During emulation, the following keys are useful:\n"
++ "ctrl-alt-f toggle full screen\n"
++ "ctrl-alt-n switch to virtual console 'n'\n"
++ "ctrl-alt toggle mouse and keyboard grab\n"
++ "\n"
++ "When using -nographic, press 'ctrl-a h' to get some help.\n",
++ "qemu",
++ options_help);
++ exit(exitcode);
++}
++
++#define HAS_ARG 0x0001
++
++typedef struct QEMUOption {
++ const char *name;
++ int flags;
++ int index;
++ uint32_t arch_mask;
++} QEMUOption;
++
++static const QEMUOption qemu_options[] = {
++ { "h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL },
++#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
++ { option, opt_arg, opt_enum, arch_mask },
++#define DEFHEADING(text)
++#include "qemu-options.def"
++#undef DEF
++#undef DEFHEADING
++#undef GEN_DOCS
++ { NULL },
++};
++static void select_vgahw (const char *p)
++{
++ const char *opts;
++
++ default_vga = 0;
++ vga_interface_type = VGA_NONE;
++ if (strstart(p, "std", &opts)) {
++ vga_interface_type = VGA_STD;
++ } else if (strstart(p, "cirrus", &opts)) {
++ vga_interface_type = VGA_CIRRUS;
++ } else if (strstart(p, "vmware", &opts)) {
++ vga_interface_type = VGA_VMWARE;
++ } else if (strstart(p, "xenfb", &opts)) {
++ vga_interface_type = VGA_XENFB;
++ } else if (!strstart(p, "none", &opts)) {
++ invalid_vga:
++ fprintf(stderr, "Unknown vga type: %s\n", p);
++ exit(1);
++ }
++ while (*opts) {
++ const char *nextopt;
++
++ if (strstart(opts, ",retrace=", &nextopt)) {
++ opts = nextopt;
++ if (strstart(opts, "dumb", &nextopt))
++ vga_retrace_method = VGA_RETRACE_DUMB;
++ else if (strstart(opts, "precise", &nextopt))
++ vga_retrace_method = VGA_RETRACE_PRECISE;
++ else goto invalid_vga;
++ } else goto invalid_vga;
++ opts = nextopt;
++ }
++}
++
++static int balloon_parse(const char *arg)
++{
++ QemuOpts *opts;
++
++ if (strcmp(arg, "none") == 0) {
++ return 0;
++ }
++
++ if (!strncmp(arg, "virtio", 6)) {
++ if (arg[6] == ',') {
++ /* have params -> parse them */
++ opts = qemu_opts_parse(&qemu_device_opts, arg+7, 0);
++ if (!opts)
++ return -1;
++ } else {
++ /* create empty opts */
++ opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
++ }
++ qemu_opt_set(opts, "driver", "virtio-balloon-pci");
++ return 0;
++ }
++
++ return -1;
++}
++
++char *qemu_find_file(int type, const char *name)
++{
++ int len;
++ const char *subdir;
++ char *buf;
++
++ /* If name contains path separators then try it as a straight path. */
++ if ((strchr(name, '/') || strchr(name, '\\'))
++ && access(name, R_OK) == 0) {
++ return qemu_strdup(name);
++ }
++ switch (type) {
++ case QEMU_FILE_TYPE_BIOS:
++ subdir = "";
++ break;
++ case QEMU_FILE_TYPE_KEYMAP:
++ subdir = "keymaps/";
++ break;
++ default:
++ abort();
++ }
++ len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2;
++ buf = qemu_mallocz(len);
++ snprintf(buf, len, "%s/%s%s", data_dir, subdir, name);
++ if (access(buf, R_OK)) {
++ qemu_free(buf);
++ return NULL;
++ }
++ return buf;
++}
++
++static int device_help_func(QemuOpts *opts, void *opaque)
++{
++ return qdev_device_help(opts);
++}
++
++static int device_init_func(QemuOpts *opts, void *opaque)
++{
++ DeviceState *dev;
++
++ dev = qdev_device_add(opts);
++ if (!dev)
++ return -1;
++ return 0;
++}
++
++static int chardev_init_func(QemuOpts *opts, void *opaque)
++{
++ CharDriverState *chr;
++
++ chr = qemu_chr_open_opts(opts, NULL);
++ if (!chr)
++ return -1;
++ return 0;
++}
++
++#ifdef CONFIG_VIRTFS
++static int fsdev_init_func(QemuOpts *opts, void *opaque)
++{
++ int ret;
++ ret = qemu_fsdev_add(opts);
++
++ return ret;
++}
++#endif
++
++static int mon_init_func(QemuOpts *opts, void *opaque)
++{
++ CharDriverState *chr;
++ const char *chardev;
++ const char *mode;
++ int flags;
++
++ mode = qemu_opt_get(opts, "mode");
++ if (mode == NULL) {
++ mode = "readline";
++ }
++ if (strcmp(mode, "readline") == 0) {
++ flags = MONITOR_USE_READLINE;
++ } else if (strcmp(mode, "control") == 0) {
++ flags = MONITOR_USE_CONTROL;
++ } else {
++ fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
++ exit(1);
++ }
++
++ if (qemu_opt_get_bool(opts, "default", 0))
++ flags |= MONITOR_IS_DEFAULT;
++
++ chardev = qemu_opt_get(opts, "chardev");
++ chr = qemu_chr_find(chardev);
++ if (chr == NULL) {
++ fprintf(stderr, "chardev \"%s\" not found\n", chardev);
++ exit(1);
++ }
++
++ monitor_init(chr, flags);
++ return 0;
++}
++
++static void monitor_parse(const char *optarg, const char *mode)
++{
++ static int monitor_device_index = 0;
++ QemuOpts *opts;
++ const char *p;
++ char label[32];
++ int def = 0;
++
++ if (strstart(optarg, "chardev:", &p)) {
++ snprintf(label, sizeof(label), "%s", p);
++ } else {
++ snprintf(label, sizeof(label), "compat_monitor%d",
++ monitor_device_index);
++ if (monitor_device_index == 0) {
++ def = 1;
++ }
++ opts = qemu_chr_parse_compat(label, optarg);
++ if (!opts) {
++ fprintf(stderr, "parse error: %s\n", optarg);
++ exit(1);
++ }
++ }
++
++ opts = qemu_opts_create(&qemu_mon_opts, label, 1);
++ if (!opts) {
++ fprintf(stderr, "duplicate chardev: %s\n", label);
++ exit(1);
++ }
++ qemu_opt_set(opts, "mode", mode);
++ qemu_opt_set(opts, "chardev", label);
++ if (def)
++ qemu_opt_set(opts, "default", "on");
++ monitor_device_index++;
++}
++
++struct device_config {
++ enum {
++ DEV_USB, /* -usbdevice */
++ DEV_BT, /* -bt */
++ DEV_SERIAL, /* -serial */
++ DEV_PARALLEL, /* -parallel */
++ DEV_VIRTCON, /* -virtioconsole */
++ DEV_DEBUGCON, /* -debugcon */
++ } type;
++ const char *cmdline;
++ QTAILQ_ENTRY(device_config) next;
++};
++QTAILQ_HEAD(, device_config) device_configs = QTAILQ_HEAD_INITIALIZER(device_configs);
++
++static void add_device_config(int type, const char *cmdline)
++{
++ struct device_config *conf;
++
++ conf = qemu_mallocz(sizeof(*conf));
++ conf->type = type;
++ conf->cmdline = cmdline;
++ QTAILQ_INSERT_TAIL(&device_configs, conf, next);
++}
++
++static int foreach_device_config(int type, int (*func)(const char *cmdline))
++{
++ struct device_config *conf;
++ int rc;
++
++ QTAILQ_FOREACH(conf, &device_configs, next) {
++ if (conf->type != type)
++ continue;
++ rc = func(conf->cmdline);
++ if (0 != rc)
++ return rc;
++ }
++ return 0;
++}
++
++static int serial_parse(const char *devname)
++{
++ static int index = 0;
++ char label[32];
++
++ if (strcmp(devname, "none") == 0)
++ return 0;
++ if (index == MAX_SERIAL_PORTS) {
++ fprintf(stderr, "qemu: too many serial ports\n");
++ exit(1);
++ }
++ snprintf(label, sizeof(label), "serial%d", index);
++ serial_hds[index] = qemu_chr_open(label, devname, NULL);
++ if (!serial_hds[index]) {
++ fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
++ devname, strerror(errno));
++ return -1;
++ }
++ index++;
++ return 0;
++}
++
++static int parallel_parse(const char *devname)
++{
++ static int index = 0;
++ char label[32];
++
++ if (strcmp(devname, "none") == 0)
++ return 0;
++ if (index == MAX_PARALLEL_PORTS) {
++ fprintf(stderr, "qemu: too many parallel ports\n");
++ exit(1);
++ }
++ snprintf(label, sizeof(label), "parallel%d", index);
++ parallel_hds[index] = qemu_chr_open(label, devname, NULL);
++ if (!parallel_hds[index]) {
++ fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
++ devname, strerror(errno));
++ return -1;
++ }
++ index++;
++ return 0;
++}
++
++static int virtcon_parse(const char *devname)
++{
++ static int index = 0;
++ char label[32];
++ QemuOpts *bus_opts, *dev_opts;
++
++ if (strcmp(devname, "none") == 0)
++ return 0;
++ if (index == MAX_VIRTIO_CONSOLES) {
++ fprintf(stderr, "qemu: too many virtio consoles\n");
++ exit(1);
++ }
++
++ bus_opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
++ qemu_opt_set(bus_opts, "driver", "virtio-serial");
++
++ dev_opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
++ qemu_opt_set(dev_opts, "driver", "virtconsole");
++
++ snprintf(label, sizeof(label), "virtcon%d", index);
++ virtcon_hds[index] = qemu_chr_open(label, devname, NULL);
++ if (!virtcon_hds[index]) {
++ fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
++ devname, strerror(errno));
++ return -1;
++ }
++ qemu_opt_set(dev_opts, "chardev", label);
++
++ index++;
++ return 0;
++}
++
++static int debugcon_parse(const char *devname)
++{
++ QemuOpts *opts;
++
++ if (!qemu_chr_open("debugcon", devname, NULL)) {
++ exit(1);
++ }
++ opts = qemu_opts_create(&qemu_device_opts, "debugcon", 1);
++ if (!opts) {
++ fprintf(stderr, "qemu: already have a debugcon device\n");
++ exit(1);
++ }
++ qemu_opt_set(opts, "driver", "isa-debugcon");
++ qemu_opt_set(opts, "chardev", "debugcon");
++ return 0;
++}
++
++void qemu_add_exit_notifier(Notifier *notify)
++{
++ notifier_list_add(&exit_notifiers, notify);
++}
++
++void qemu_remove_exit_notifier(Notifier *notify)
++{
++ notifier_list_remove(&exit_notifiers, notify);
++}
++
++static void qemu_run_exit_notifiers(void)
++{
++ notifier_list_notify(&exit_notifiers);
++}
++
++static const QEMUOption *lookup_opt(int argc, char **argv,
++ const char **poptarg, int *poptind)
++{
++ const QEMUOption *popt;
++ int optind = *poptind;
++ char *r = argv[optind];
++ const char *optarg;
++
++ loc_set_cmdline(argv, optind, 1);
++ optind++;
++ /* Treat --foo the same as -foo. */
++ if (r[1] == '-')
++ r++;
++ popt = qemu_options;
++ for(;;) {
++ if (!popt->name) {
++ error_report("invalid option");
++ exit(1);
++ }
++ if (!strcmp(popt->name, r + 1))
++ break;
++ popt++;
++ }
++ if (popt->flags & HAS_ARG) {
++ if (optind >= argc) {
++ error_report("requires an argument");
++ exit(1);
++ }
++ optarg = argv[optind++];
++ loc_set_cmdline(argv, optind - 2, 2);
++ } else {
++ optarg = NULL;
++ }
++
++ *poptarg = optarg;
++ *poptind = optind;
++
++ return popt;
++}
++
++int main(int argc, char **argv, char **envp)
++{
++ const char *gdbstub_dev = NULL;
++ int i;
++ int snapshot, linux_boot;
++ const char *icount_option = NULL;
++ const char *initrd_filename;
++ const char *kernel_filename, *kernel_cmdline;
++ char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */
++ DisplayState *ds;
++ DisplayChangeListener *dcl;
++ int cyls, heads, secs, translation;
++ QemuOpts *hda_opts = NULL, *opts;
++ int optind;
++ const char *optarg;
++ const char *loadvm = NULL;
++ QEMUMachine *machine;
++ const char *cpu_model;
++ int tb_size;
++ const char *pid_file = NULL;
++ const char *incoming = NULL;
++ int show_vnc_port = 0;
++ int defconfig = 1;
++
++ atexit(qemu_run_exit_notifiers);
++ error_set_progname(argv[0]);
++
++ init_clocks();
++
++ qemu_cache_utils_init(envp);
++
++ QLIST_INIT (&vm_change_state_head);
++ os_setup_early_signal_handling();
++
++ module_call_init(MODULE_INIT_MACHINE);
++ machine = find_default_machine();
++ cpu_model = NULL;
++ initrd_filename = NULL;
++ ram_size = 0;
++ snapshot = 0;
++ kernel_filename = NULL;
++ kernel_cmdline = "";
++ cyls = heads = secs = 0;
++ translation = BIOS_ATA_TRANSLATION_AUTO;
++
++ for (i = 0; i < MAX_NODES; i++) {
++ node_mem[i] = 0;
++ node_cpumask[i] = 0;
++ }
++
++ assigned_devices_index = 0;
++
++ nb_numa_nodes = 0;
++ nb_nics = 0;
++
++ tb_size = 0;
++ autostart= 1;
++
++ /* first pass of option parsing */
++ optind = 1;
++ while (optind < argc) {
++ if (argv[optind][0] != '-') {
++ /* disk image */
++ optind++;
++ continue;
++ } else {
++ const QEMUOption *popt;
++
++ popt = lookup_opt(argc, argv, &optarg, &optind);
++ switch (popt->index) {
++ case QEMU_OPTION_nodefconfig:
++ defconfig=0;
++ break;
++ }
++ }
++ }
++
++ if (defconfig) {
++ int ret;
++
++ ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
++ if (ret < 0 && ret != -ENOENT) {
++ exit(1);
++ }
++
++ ret = qemu_read_config_file(arch_config_name);
++ if (ret < 0 && ret != -ENOENT) {
++ exit(1);
++ }
++ }
++ cpudef_init();
++
++ /* second pass of option parsing */
++ optind = 1;
++ for(;;) {
++ if (optind >= argc)
++ break;
++ if (argv[optind][0] != '-') {
++ hda_opts = drive_add(argv[optind++], HD_ALIAS, 0);
++ } else {
++ const QEMUOption *popt;
++
++ popt = lookup_opt(argc, argv, &optarg, &optind);
++ if (!(popt->arch_mask & arch_type)) {
++ printf("Option %s not supported for this target\n", popt->name);
++ exit(1);
++ }
++ switch(popt->index) {
++ case QEMU_OPTION_M:
++ machine = find_machine(optarg);
++ if (!machine) {
++ QEMUMachine *m;
++ printf("Supported machines are:\n");
++ for(m = first_machine; m != NULL; m = m->next) {
++ if (m->alias)
++ printf("%-10s %s (alias of %s)\n",
++ m->alias, m->desc, m->name);
++ printf("%-10s %s%s\n",
++ m->name, m->desc,
++ m->is_default ? " (default)" : "");
++ }
++ exit(*optarg != '?');
++ }
++ break;
++ case QEMU_OPTION_cpu:
++ /* hw initialization will check this */
++ if (*optarg == '?') {
++ list_cpus(stdout, &fprintf, optarg);
++ exit(0);
++ } else {
++ cpu_model = optarg;
++ }
++ break;
++ case QEMU_OPTION_initrd:
++ initrd_filename = optarg;
++ break;
++ case QEMU_OPTION_hda:
++ if (cyls == 0)
++ hda_opts = drive_add(optarg, HD_ALIAS, 0);
++ else
++ hda_opts = drive_add(optarg, HD_ALIAS
++ ",cyls=%d,heads=%d,secs=%d%s",
++ 0, cyls, heads, secs,
++ translation == BIOS_ATA_TRANSLATION_LBA ?
++ ",trans=lba" :
++ translation == BIOS_ATA_TRANSLATION_NONE ?
++ ",trans=none" : "");
++ break;
++ case QEMU_OPTION_hdb:
++ case QEMU_OPTION_hdc:
++ case QEMU_OPTION_hdd:
++ drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
++ break;
++ case QEMU_OPTION_drive:
++ drive_add(NULL, "%s", optarg);
++ break;
++ case QEMU_OPTION_set:
++ if (qemu_set_option(optarg) != 0)
++ exit(1);
++ break;
++ case QEMU_OPTION_global:
++ if (qemu_global_option(optarg) != 0)
++ exit(1);
++ break;
++ case QEMU_OPTION_mtdblock:
++ drive_add(optarg, MTD_ALIAS);
++ break;
++ case QEMU_OPTION_sd:
++ drive_add(optarg, SD_ALIAS);
++ break;
++ case QEMU_OPTION_pflash:
++ drive_add(optarg, PFLASH_ALIAS);
++ break;
++ case QEMU_OPTION_snapshot:
++ snapshot = 1;
++ break;
++ case QEMU_OPTION_hdachs:
++ {
++ const char *p;
++ p = optarg;
++ cyls = strtol(p, (char **)&p, 0);
++ if (cyls < 1 || cyls > 16383)
++ goto chs_fail;
++ if (*p != ',')
++ goto chs_fail;
++ p++;
++ heads = strtol(p, (char **)&p, 0);
++ if (heads < 1 || heads > 16)
++ goto chs_fail;
++ if (*p != ',')
++ goto chs_fail;
++ p++;
++ secs = strtol(p, (char **)&p, 0);
++ if (secs < 1 || secs > 63)
++ goto chs_fail;
++ if (*p == ',') {
++ p++;
++ if (!strcmp(p, "none"))
++ translation = BIOS_ATA_TRANSLATION_NONE;
++ else if (!strcmp(p, "lba"))
++ translation = BIOS_ATA_TRANSLATION_LBA;
++ else if (!strcmp(p, "auto"))
++ translation = BIOS_ATA_TRANSLATION_AUTO;
++ else
++ goto chs_fail;
++ } else if (*p != '\0') {
++ chs_fail:
++ fprintf(stderr, "qemu: invalid physical CHS format\n");
++ exit(1);
++ }
++ if (hda_opts != NULL) {
++ char num[16];
++ snprintf(num, sizeof(num), "%d", cyls);
++ qemu_opt_set(hda_opts, "cyls", num);
++ snprintf(num, sizeof(num), "%d", heads);
++ qemu_opt_set(hda_opts, "heads", num);
++ snprintf(num, sizeof(num), "%d", secs);
++ qemu_opt_set(hda_opts, "secs", num);
++ if (translation == BIOS_ATA_TRANSLATION_LBA)
++ qemu_opt_set(hda_opts, "trans", "lba");
++ if (translation == BIOS_ATA_TRANSLATION_NONE)
++ qemu_opt_set(hda_opts, "trans", "none");
++ }
++ }
++ break;
++ case QEMU_OPTION_numa:
++ if (nb_numa_nodes >= MAX_NODES) {
++ fprintf(stderr, "qemu: too many NUMA nodes\n");
++ exit(1);
++ }
++ numa_add(optarg);
++ break;
++ case QEMU_OPTION_nographic:
++ display_type = DT_NOGRAPHIC;
++ break;
++#ifdef CONFIG_CURSES
++ case QEMU_OPTION_curses:
++ display_type = DT_CURSES;
++ break;
++#endif
++ case QEMU_OPTION_portrait:
++ graphic_rotate = 1;
++ break;
++ case QEMU_OPTION_kernel:
++ kernel_filename = optarg;
++ break;
++ case QEMU_OPTION_append:
++ kernel_cmdline = optarg;
++ break;
++ case QEMU_OPTION_cdrom:
++ drive_add(optarg, CDROM_ALIAS);
++ break;
++ case QEMU_OPTION_boot:
++ {
++ static const char * const params[] = {
++ "order", "once", "menu", NULL
++ };
++ char buf[sizeof(boot_devices)];
++ char *standard_boot_devices;
++ int legacy = 0;
++
++ if (!strchr(optarg, '=')) {
++ legacy = 1;
++ pstrcpy(buf, sizeof(buf), optarg);
++ } else if (check_params(buf, sizeof(buf), params, optarg) < 0) {
++ fprintf(stderr,
++ "qemu: unknown boot parameter '%s' in '%s'\n",
++ buf, optarg);
++ exit(1);
++ }
++
++ if (legacy ||
++ get_param_value(buf, sizeof(buf), "order", optarg)) {
++ validate_bootdevices(buf);
++ pstrcpy(boot_devices, sizeof(boot_devices), buf);
++ }
++ if (!legacy) {
++ if (get_param_value(buf, sizeof(buf),
++ "once", optarg)) {
++ validate_bootdevices(buf);
++ standard_boot_devices = qemu_strdup(boot_devices);
++ pstrcpy(boot_devices, sizeof(boot_devices), buf);
++ qemu_register_reset(restore_boot_devices,
++ standard_boot_devices);
++ }
++ if (get_param_value(buf, sizeof(buf),
++ "menu", optarg)) {
++ if (!strcmp(buf, "on")) {
++ boot_menu = 1;
++ } else if (!strcmp(buf, "off")) {
++ boot_menu = 0;
++ } else {
++ fprintf(stderr,
++ "qemu: invalid option value '%s'\n",
++ buf);
++ exit(1);
++ }
++ }
++ }
++ }
++ break;
++ case QEMU_OPTION_fda:
++ case QEMU_OPTION_fdb:
++ drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
++ break;
++ case QEMU_OPTION_no_fd_bootchk:
++ fd_bootchk = 0;
++ break;
++ case QEMU_OPTION_netdev:
++ if (net_client_parse(&qemu_netdev_opts, optarg) == -1) {
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_net:
++ if (net_client_parse(&qemu_net_opts, optarg) == -1) {
++ exit(1);
++ }
++ break;
++#ifdef CONFIG_SLIRP
++ case QEMU_OPTION_tftp:
++ legacy_tftp_prefix = optarg;
++ break;
++ case QEMU_OPTION_bootp:
++ legacy_bootp_filename = optarg;
++ break;
++ case QEMU_OPTION_redir:
++ if (net_slirp_redir(optarg) < 0)
++ exit(1);
++ break;
++#endif
++ case QEMU_OPTION_bt:
++ add_device_config(DEV_BT, optarg);
++ break;
++ case QEMU_OPTION_audio_help:
++ if (!(audio_available())) {
++ printf("Option %s not supported for this target\n", popt->name);
++ exit(1);
++ }
++ AUD_help ();
++ exit (0);
++ break;
++ case QEMU_OPTION_soundhw:
++ if (!(audio_available())) {
++ printf("Option %s not supported for this target\n", popt->name);
++ exit(1);
++ }
++ select_soundhw (optarg);
++ break;
++ case QEMU_OPTION_h:
++ help(0);
++ break;
++ case QEMU_OPTION_version:
++ version();
++ exit(0);
++ break;
++ case QEMU_OPTION_m: {
++ uint64_t value;
++ char *ptr;
++
++ value = strtoul(optarg, &ptr, 10);
++ switch (*ptr) {
++ case 0: case 'M': case 'm':
++ value <<= 20;
++ break;
++ case 'G': case 'g':
++ value <<= 30;
++ break;
++ default:
++ fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
++ exit(1);
++ }
++
++ /* On 32-bit hosts, QEMU is limited by virtual address space */
++ if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
++ fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
++ exit(1);
++ }
++ if (value != (uint64_t)(ram_addr_t)value) {
++ fprintf(stderr, "qemu: ram size too large\n");
++ exit(1);
++ }
++ ram_size = value;
++ break;
++ }
++ case QEMU_OPTION_mempath:
++ mem_path = optarg;
++ break;
++#ifdef MAP_POPULATE
++ case QEMU_OPTION_mem_prealloc:
++ mem_prealloc = 1;
++ break;
++#endif
++ case QEMU_OPTION_d:
++ set_cpu_log(optarg);
++ break;
++ case QEMU_OPTION_s:
++ gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
++ break;
++ case QEMU_OPTION_gdb:
++ gdbstub_dev = optarg;
++ break;
++ case QEMU_OPTION_L:
++ data_dir = optarg;
++ break;
++ case QEMU_OPTION_bios:
++ bios_name = optarg;
++ break;
++ case QEMU_OPTION_singlestep:
++ singlestep = 1;
++ break;
++ case QEMU_OPTION_S:
++ autostart = 0;
++ break;
++ case QEMU_OPTION_k:
++ keyboard_layout = optarg;
++ break;
++ case QEMU_OPTION_localtime:
++ rtc_utc = 0;
++ break;
++ case QEMU_OPTION_vga:
++ select_vgahw (optarg);
++ break;
++ case QEMU_OPTION_g:
++ {
++ const char *p;
++ int w, h, depth;
++ p = optarg;
++ w = strtol(p, (char **)&p, 10);
++ if (w <= 0) {
++ graphic_error:
++ fprintf(stderr, "qemu: invalid resolution or depth\n");
++ exit(1);
++ }
++ if (*p != 'x')
++ goto graphic_error;
++ p++;
++ h = strtol(p, (char **)&p, 10);
++ if (h <= 0)
++ goto graphic_error;
++ if (*p == 'x') {
++ p++;
++ depth = strtol(p, (char **)&p, 10);
++ if (depth != 8 && depth != 15 && depth != 16 &&
++ depth != 24 && depth != 32)
++ goto graphic_error;
++ } else if (*p == '\0') {
++ depth = graphic_depth;
++ } else {
++ goto graphic_error;
++ }
++
++ graphic_width = w;
++ graphic_height = h;
++ graphic_depth = depth;
++ }
++ break;
++ case QEMU_OPTION_echr:
++ {
++ char *r;
++ term_escape_char = strtol(optarg, &r, 0);
++ if (r == optarg)
++ printf("Bad argument to echr\n");
++ break;
++ }
++ case QEMU_OPTION_monitor:
++ monitor_parse(optarg, "readline");
++ default_monitor = 0;
++ break;
++ case QEMU_OPTION_qmp:
++ monitor_parse(optarg, "control");
++ default_monitor = 0;
++ break;
++ case QEMU_OPTION_mon:
++ opts = qemu_opts_parse(&qemu_mon_opts, optarg, 1);
++ if (!opts) {
++ exit(1);
++ }
++ default_monitor = 0;
++ break;
++ case QEMU_OPTION_chardev:
++ opts = qemu_opts_parse(&qemu_chardev_opts, optarg, 1);
++ if (!opts) {
++ exit(1);
++ }
++ break;
++#ifdef CONFIG_VIRTFS
++ case QEMU_OPTION_fsdev:
++ opts = qemu_opts_parse(&qemu_fsdev_opts, optarg, 1);
++ if (!opts) {
++ fprintf(stderr, "parse error: %s\n", optarg);
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_virtfs: {
++ char *arg_fsdev = NULL;
++ char *arg_9p = NULL;
++ int len = 0;
++
++ opts = qemu_opts_parse(&qemu_virtfs_opts, optarg, 1);
++ if (!opts) {
++ fprintf(stderr, "parse error: %s\n", optarg);
++ exit(1);
++ }
++
++ if (qemu_opt_get(opts, "fstype") == NULL ||
++ qemu_opt_get(opts, "mount_tag") == NULL ||
++ qemu_opt_get(opts, "path") == NULL ||
++ qemu_opt_get(opts, "security_model") == NULL) {
++ fprintf(stderr, "Usage: -virtfs fstype,path=/share_path/,"
++ "security_model=[mapped|passthrough],"
++ "mnt_tag=tag.\n");
++ exit(1);
++ }
++
++ len = strlen(",id=,path=,security_model=");
++ len += strlen(qemu_opt_get(opts, "fstype"));
++ len += strlen(qemu_opt_get(opts, "mount_tag"));
++ len += strlen(qemu_opt_get(opts, "path"));
++ len += strlen(qemu_opt_get(opts, "security_model"));
++ arg_fsdev = qemu_malloc((len + 1) * sizeof(*arg_fsdev));
++
++ if (!arg_fsdev) {
++ fprintf(stderr, "No memory to parse -fsdev for %s\n",
++ optarg);
++ exit(1);
++ }
++
++ sprintf(arg_fsdev, "%s,id=%s,path=%s,security_model=%s",
++ qemu_opt_get(opts, "fstype"),
++ qemu_opt_get(opts, "mount_tag"),
++ qemu_opt_get(opts, "path"),
++ qemu_opt_get(opts, "security_model"));
++
++ len = strlen("virtio-9p-pci,fsdev=,mount_tag=");
++ len += 2*strlen(qemu_opt_get(opts, "mount_tag"));
++ arg_9p = qemu_malloc((len + 1) * sizeof(*arg_9p));
++
++ if (!arg_9p) {
++ fprintf(stderr, "No memory to parse -device for %s\n",
++ optarg);
++ exit(1);
++ }
++
++ sprintf(arg_9p, "virtio-9p-pci,fsdev=%s,mount_tag=%s",
++ qemu_opt_get(opts, "mount_tag"),
++ qemu_opt_get(opts, "mount_tag"));
++
++ if (!qemu_opts_parse(&qemu_fsdev_opts, arg_fsdev, 1)) {
++ fprintf(stderr, "parse error [fsdev]: %s\n", optarg);
++ exit(1);
++ }
++
++ if (!qemu_opts_parse(&qemu_device_opts, arg_9p, 1)) {
++ fprintf(stderr, "parse error [device]: %s\n", optarg);
++ exit(1);
++ }
++
++ qemu_free(arg_fsdev);
++ qemu_free(arg_9p);
++ break;
++ }
++#endif
++ case QEMU_OPTION_serial:
++ add_device_config(DEV_SERIAL, optarg);
++ default_serial = 0;
++ if (strncmp(optarg, "mon:", 4) == 0) {
++ default_monitor = 0;
++ }
++ break;
++ case QEMU_OPTION_watchdog:
++ if (watchdog) {
++ fprintf(stderr,
++ "qemu: only one watchdog option may be given\n");
++ return 1;
++ }
++ watchdog = optarg;
++ break;
++ case QEMU_OPTION_watchdog_action:
++ if (select_watchdog_action(optarg) == -1) {
++ fprintf(stderr, "Unknown -watchdog-action parameter\n");
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_virtiocon:
++ add_device_config(DEV_VIRTCON, optarg);
++ default_virtcon = 0;
++ if (strncmp(optarg, "mon:", 4) == 0) {
++ default_monitor = 0;
++ }
++ break;
++ case QEMU_OPTION_parallel:
++ add_device_config(DEV_PARALLEL, optarg);
++ default_parallel = 0;
++ if (strncmp(optarg, "mon:", 4) == 0) {
++ default_monitor = 0;
++ }
++ break;
++ case QEMU_OPTION_debugcon:
++ add_device_config(DEV_DEBUGCON, optarg);
++ break;
++ case QEMU_OPTION_loadvm:
++ loadvm = optarg;
++ break;
++ case QEMU_OPTION_full_screen:
++ full_screen = 1;
++ break;
++#ifdef CONFIG_SDL
++ case QEMU_OPTION_no_frame:
++ no_frame = 1;
++ break;
++ case QEMU_OPTION_alt_grab:
++ alt_grab = 1;
++ break;
++ case QEMU_OPTION_ctrl_grab:
++ ctrl_grab = 1;
++ break;
++ case QEMU_OPTION_no_quit:
++ no_quit = 1;
++ break;
++ case QEMU_OPTION_sdl:
++ display_type = DT_SDL;
++ break;
++#endif
++ case QEMU_OPTION_pidfile:
++ pid_file = optarg;
++ break;
++ case QEMU_OPTION_win2k_hack:
++ win2k_install_hack = 1;
++ break;
++ case QEMU_OPTION_rtc_td_hack:
++ rtc_td_hack = 1;
++ break;
++ case QEMU_OPTION_acpitable:
++ do_acpitable_option(optarg);
++ break;
++ case QEMU_OPTION_smbios:
++ do_smbios_option(optarg);
++ break;
++#ifdef KVM_UPSTREAM
++ case QEMU_OPTION_enable_kvm:
++ kvm_allowed = 1;
++#endif
++ break;
++ case QEMU_OPTION_no_kvm:
++ kvm_allowed = 0;
++#ifdef CONFIG_NO_CPU_EMULATION
++ fprintf(stderr, "cpu emulation not configured\n");
++ exit(1);
++#endif
++ break;
++#ifdef CONFIG_KVM
++ case QEMU_OPTION_no_kvm_irqchip: {
++ kvm_irqchip = 0;
++ kvm_pit = 0;
++ break;
++ }
++ case QEMU_OPTION_no_kvm_pit: {
++ kvm_pit = 0;
++ break;
++ }
++ case QEMU_OPTION_no_kvm_pit_reinjection: {
++ kvm_pit_reinject = 0;
++ break;
++ }
++ case QEMU_OPTION_enable_nesting: {
++ kvm_nested = 1;
++ break;
++ }
++#endif
++#if defined(TARGET_I386) || defined(TARGET_X86_64) || defined(TARGET_IA64) || defined(__linux__)
++ case QEMU_OPTION_pcidevice:
++ if (assigned_devices_index >= MAX_DEV_ASSIGN_CMDLINE) {
++ fprintf(stderr, "Too many assigned devices\n");
++ exit(1);
++ }
++ assigned_devices[assigned_devices_index] = optarg;
++ assigned_devices_index++;
++ break;
++#endif
++ case QEMU_OPTION_usb:
++ usb_enabled = 1;
++ break;
++ case QEMU_OPTION_usbdevice:
++ usb_enabled = 1;
++ add_device_config(DEV_USB, optarg);
++ break;
++ case QEMU_OPTION_device:
++ if (!qemu_opts_parse(&qemu_device_opts, optarg, 1)) {
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_smp:
++ smp_parse(optarg);
++ if (smp_cpus < 1) {
++ fprintf(stderr, "Invalid number of CPUs\n");
++ exit(1);
++ }
++ if (max_cpus < smp_cpus) {
++ fprintf(stderr, "maxcpus must be equal to or greater than "
++ "smp\n");
++ exit(1);
++ }
++ if (max_cpus > 255) {
++ fprintf(stderr, "Unsupported number of maxcpus\n");
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_vnc:
++ display_type = DT_VNC;
++ vnc_display = optarg;
++ break;
++ case QEMU_OPTION_no_acpi:
++ acpi_enabled = 0;
++ break;
++ case QEMU_OPTION_no_hpet:
++ no_hpet = 1;
++ break;
++ case QEMU_OPTION_balloon:
++ if (balloon_parse(optarg) < 0) {
++ fprintf(stderr, "Unknown -balloon argument %s\n", optarg);
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_no_reboot:
++ no_reboot = 1;
++ break;
++ case QEMU_OPTION_no_shutdown:
++ no_shutdown = 1;
++ break;
++ case QEMU_OPTION_show_cursor:
++ cursor_hide = 0;
++ break;
++ case QEMU_OPTION_uuid:
++ if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
++ fprintf(stderr, "Fail to parse UUID string."
++ " Wrong format.\n");
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_option_rom:
++ if (nb_option_roms >= MAX_OPTION_ROMS) {
++ fprintf(stderr, "Too many option ROMs\n");
++ exit(1);
++ }
++ option_rom[nb_option_roms] = optarg;
++ nb_option_roms++;
++ break;
++ case QEMU_OPTION_semihosting:
++ semihosting_enabled = 1;
++ break;
++ case QEMU_OPTION_tdf:
++ time_drift_fix = 1;
++ break;
++ case QEMU_OPTION_kvm_shadow_memory:
++ kvm_shadow_memory = (int64_t)atoi(optarg) * 1024 * 1024 / 4096;
++ break;
++ case QEMU_OPTION_name:
++ qemu_name = qemu_strdup(optarg);
++ {
++ char *p = strchr(qemu_name, ',');
++ if (p != NULL) {
++ *p++ = 0;
++ if (strncmp(p, "process=", 8)) {
++ fprintf(stderr, "Unknown subargument %s to -name", p);
++ exit(1);
++ }
++ p += 8;
++ os_set_proc_name(p);
++ }
++ }
++ break;
++ case QEMU_OPTION_prom_env:
++ if (nb_prom_envs >= MAX_PROM_ENVS) {
++ fprintf(stderr, "Too many prom variables\n");
++ exit(1);
++ }
++ prom_envs[nb_prom_envs] = optarg;
++ nb_prom_envs++;
++ break;
++ case QEMU_OPTION_old_param:
++ old_param = 1;
++ break;
++ case QEMU_OPTION_clock:
++ configure_alarms(optarg);
++ break;
++ case QEMU_OPTION_startdate:
++ configure_rtc_date_offset(optarg, 1);
++ break;
++ case QEMU_OPTION_rtc:
++ opts = qemu_opts_parse(&qemu_rtc_opts, optarg, 0);
++ if (!opts) {
++ exit(1);
++ }
++ configure_rtc(opts);
++ break;
++ case QEMU_OPTION_tb_size:
++ tb_size = strtol(optarg, NULL, 0);
++ if (tb_size < 0)
++ tb_size = 0;
++ break;
++ case QEMU_OPTION_icount:
++ icount_option = optarg;
++ break;
++ case QEMU_OPTION_incoming:
++ incoming = optarg;
++ incoming_expected = true;
++ break;
++ case QEMU_OPTION_nodefaults:
++ default_serial = 0;
++ default_parallel = 0;
++ default_virtcon = 0;
++ default_monitor = 0;
++ default_vga = 0;
++ default_net = 0;
++ default_floppy = 0;
++ default_cdrom = 0;
++ default_sdcard = 0;
++ break;
++#ifndef _WIN32
++ case QEMU_OPTION_nvram:
++ nvram = optarg;
++ break;
++#endif
++ case QEMU_OPTION_xen_domid:
++ if (!(xen_available())) {
++ printf("Option %s not supported for this target\n", popt->name);
++ exit(1);
++ }
++ xen_domid = atoi(optarg);
++ break;
++ case QEMU_OPTION_xen_create:
++ if (!(xen_available())) {
++ printf("Option %s not supported for this target\n", popt->name);
++ exit(1);
++ }
++ xen_mode = XEN_CREATE;
++ break;
++ case QEMU_OPTION_xen_attach:
++ if (!(xen_available())) {
++ printf("Option %s not supported for this target\n", popt->name);
++ exit(1);
++ }
++ xen_mode = XEN_ATTACH;
++ break;
++ case QEMU_OPTION_readconfig:
++ {
++ int ret = qemu_read_config_file(optarg);
++ if (ret < 0) {
++ fprintf(stderr, "read config %s: %s\n", optarg,
++ strerror(-ret));
++ exit(1);
++ }
++ break;
++ }
++#ifdef CONFIG_SPICE
++ case QEMU_OPTION_spice:
++ opts = qemu_opts_parse(&qemu_spice_opts, optarg, 0);
++ if (!opts) {
++ fprintf(stderr, "parse error: %s\n", optarg);
++ exit(1);
++ }
++ break;
++#endif
++ case QEMU_OPTION_writeconfig:
++ {
++ FILE *fp;
++ if (strcmp(optarg, "-") == 0) {
++ fp = stdout;
++ } else {
++ fp = fopen(optarg, "w");
++ if (fp == NULL) {
++ fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
++ exit(1);
++ }
++ }
++ qemu_config_write(fp);
++ fclose(fp);
++ break;
++ }
++ default:
++ os_parse_cmd_args(popt->index, optarg);
++ }
++ }
++ }
++ loc_set_none();
++
++ /* If no data_dir is specified then try to find it relative to the
++ executable path. */
++ if (!data_dir) {
++ data_dir = os_find_datadir(argv[0]);
++ }
++ /* If all else fails use the install patch specified when building. */
++ if (!data_dir) {
++ data_dir = CONFIG_QEMU_DATADIR;
++ }
++
++ /*
++ * Default to max_cpus = smp_cpus, in case the user doesn't
++ * specify a max_cpus value.
++ */
++ if (!max_cpus)
++ max_cpus = smp_cpus;
++
++ machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */
++ if (smp_cpus > machine->max_cpus) {
++ fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus "
++ "supported by machine `%s' (%d)\n", smp_cpus, machine->name,
++ machine->max_cpus);
++ exit(1);
++ }
++
++ qemu_opts_foreach(&qemu_device_opts, default_driver_check, NULL, 0);
++ qemu_opts_foreach(&qemu_global_opts, default_driver_check, NULL, 0);
++
++ if (machine->no_serial) {
++ default_serial = 0;
++ }
++ if (machine->no_parallel) {
++ default_parallel = 0;
++ }
++ if (!machine->use_virtcon) {
++ default_virtcon = 0;
++ }
++ if (machine->no_vga) {
++ default_vga = 0;
++ }
++ if (machine->no_floppy) {
++ default_floppy = 0;
++ }
++ if (machine->no_cdrom) {
++ default_cdrom = 0;
++ }
++ if (machine->no_sdcard) {
++ default_sdcard = 0;
++ }
++
++ if (display_type == DT_NOGRAPHIC) {
++ if (default_parallel)
++ add_device_config(DEV_PARALLEL, "null");
++ if (default_serial && default_monitor) {
++ add_device_config(DEV_SERIAL, "mon:stdio");
++ } else if (default_virtcon && default_monitor) {
++ add_device_config(DEV_VIRTCON, "mon:stdio");
++ } else {
++ if (default_serial)
++ add_device_config(DEV_SERIAL, "stdio");
++ if (default_virtcon)
++ add_device_config(DEV_VIRTCON, "stdio");
++ if (default_monitor)
++ monitor_parse("stdio", "readline");
++ }
++ } else {
++ if (default_serial)
++ add_device_config(DEV_SERIAL, "vc:80Cx24C");
++ if (default_parallel)
++ add_device_config(DEV_PARALLEL, "vc:80Cx24C");
++ if (default_monitor)
++ monitor_parse("vc:80Cx24C", "readline");
++ if (default_virtcon)
++ add_device_config(DEV_VIRTCON, "vc:80Cx24C");
++ }
++ if (default_vga)
++ vga_interface_type = VGA_CIRRUS;
++
++ socket_init();
++
++ if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
++ exit(1);
++#ifdef CONFIG_VIRTFS
++ if (qemu_opts_foreach(&qemu_fsdev_opts, fsdev_init_func, NULL, 1) != 0) {
++ exit(1);
++ }
++#endif
++
++ os_daemonize();
++
++ if (pid_file && qemu_create_pidfile(pid_file) != 0) {
++ os_pidfile_error();
++ exit(1);
++ }
++
++ if (kvm_allowed) {
++ int ret = kvm_init(smp_cpus);
++ if (ret < 0) {
++#if defined(KVM_UPSTREAM) || defined(CONFIG_NO_CPU_EMULATION)
++ if (!kvm_available()) {
++ printf("KVM not supported for this target\n");
++ } else {
++ fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret));
++ }
++ exit(1);
++#endif
++#ifdef CONFIG_KVM
++ fprintf(stderr, "Could not initialize KVM, will disable KVM support\n");
++ kvm_allowed = 0;
++#endif
++ }
++ }
++
++ if (qemu_init_main_loop()) {
++ fprintf(stderr, "qemu_init_main_loop failed\n");
++ exit(1);
++ }
++ linux_boot = (kernel_filename != NULL);
++
++ if (!linux_boot && *kernel_cmdline != '\0') {
++ fprintf(stderr, "-append only allowed with -kernel option\n");
++ exit(1);
++ }
++
++ if (!linux_boot && initrd_filename != NULL) {
++ fprintf(stderr, "-initrd only allowed with -kernel option\n");
++ exit(1);
++ }
++
++ os_set_line_buffering();
++
++ if (init_timer_alarm() < 0) {
++ fprintf(stderr, "could not initialize alarm timer\n");
++ exit(1);
++ }
++ configure_icount(icount_option);
++
++ if (net_init_clients() < 0) {
++ exit(1);
++ }
++
++ /* init the bluetooth world */
++ if (foreach_device_config(DEV_BT, bt_parse))
++ exit(1);
++
++ /* init the memory */
++ if (ram_size == 0)
++ ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
++
++ /* init the dynamic translator */
++ cpu_exec_init_all(tb_size * 1024 * 1024);
++
++ bdrv_init_with_whitelist();
++
++ blk_mig_init();
++
++ if (default_cdrom) {
++ /* we always create the cdrom drive, even if no disk is there */
++ drive_add(NULL, CDROM_ALIAS);
++ }
++
++ if (default_floppy) {
++ /* we always create at least one floppy */
++ drive_add(NULL, FD_ALIAS, 0);
++ }
++
++ if (default_sdcard) {
++ /* we always create one sd slot, even if no card is in it */
++ drive_add(NULL, SD_ALIAS);
++ }
++
++ /* open the virtual block devices */
++ if (snapshot)
++ qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0);
++ if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
++ exit(1);
++
++ register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
++ ram_load, NULL);
++
++ if (nb_numa_nodes > 0) {
++ int i;
++
++ if (nb_numa_nodes > smp_cpus) {
++ nb_numa_nodes = smp_cpus;
++ }
++
++ /* If no memory size if given for any node, assume the default case
++ * and distribute the available memory equally across all nodes
++ */
++ for (i = 0; i < nb_numa_nodes; i++) {
++ if (node_mem[i] != 0)
++ break;
++ }
++ if (i == nb_numa_nodes) {
++ uint64_t usedmem = 0;
++
++ /* On Linux, the each node's border has to be 8MB aligned,
++ * the final node gets the rest.
++ */
++ for (i = 0; i < nb_numa_nodes - 1; i++) {
++ node_mem[i] = (ram_size / nb_numa_nodes) & ~((1 << 23UL) - 1);
++ usedmem += node_mem[i];
++ }
++ node_mem[i] = ram_size - usedmem;
++ }
++
++ for (i = 0; i < nb_numa_nodes; i++) {
++ if (node_cpumask[i] != 0)
++ break;
++ }
++ /* assigning the VCPUs round-robin is easier to implement, guest OSes
++ * must cope with this anyway, because there are BIOSes out there in
++ * real machines which also use this scheme.
++ */
++ if (i == nb_numa_nodes) {
++ for (i = 0; i < smp_cpus; i++) {
++ node_cpumask[i % nb_numa_nodes] |= 1 << i;
++ }
++ }
++ }
++
++ if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0) {
++ exit(1);
++ }
++
++ if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
++ exit(1);
++ if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
++ exit(1);
++ if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
++ exit(1);
++ if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
++ exit(1);
++
++ module_call_init(MODULE_INIT_DEVICE);
++
++ if (qemu_opts_foreach(&qemu_device_opts, device_help_func, NULL, 0) != 0)
++ exit(0);
++
++ if (watchdog) {
++ i = select_watchdog(watchdog);
++ if (i > 0)
++ exit (i == 1 ? 1 : 0);
++ }
++
++ if (machine->compat_props) {
++ qdev_prop_register_global_list(machine->compat_props);
++ }
++ qemu_add_globals();
++
++#ifdef CONFIG_SPICE
++ qemu_spice_init();
++#endif
++
++ machine->init(ram_size, boot_devices,
++ kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
++
++ cpu_synchronize_all_post_init();
++
++ /* must be after terminal init, SDL library changes signal handlers */
++ os_setup_signal_handling();
++
++ set_numa_modes();
++
++ current_machine = machine;
++
++ /* init USB devices */
++ if (usb_enabled) {
++ if (foreach_device_config(DEV_USB, usb_parse) < 0)
++ exit(1);
++ }
++
++ /* init generic devices */
++ if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
++ exit(1);
++
++ net_check_clients();
++
++ /* just use the first displaystate for the moment */
++ ds = get_displaystate();
++
++ if (display_type == DT_DEFAULT && !using_spice) {
++#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
++ display_type = DT_SDL;
++#else
++ display_type = DT_VNC;
++ vnc_display = "localhost:0,to=99";
++ show_vnc_port = 1;
++#endif
++ }
++
++
++ switch (display_type) {
++ case DT_NOGRAPHIC:
++ break;
++#if defined(CONFIG_CURSES)
++ case DT_CURSES:
++ curses_display_init(ds, full_screen);
++ break;
++#endif
++#if defined(CONFIG_SDL)
++ case DT_SDL:
++ sdl_display_init(ds, full_screen, no_frame);
++ break;
++#elif defined(CONFIG_COCOA)
++ case DT_SDL:
++ cocoa_display_init(ds, full_screen);
++ break;
++#endif
++ case DT_VNC:
++ vnc_display_init(ds);
++ if (vnc_display_open(ds, vnc_display) < 0)
++ exit(1);
++
++ if (show_vnc_port) {
++ printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
++ }
++ break;
++ default:
++ break;
++ }
++#ifdef CONFIG_SPICE
++ if (using_spice) {
++ qemu_spice_display_init(ds);
++ }
++#endif
++ dpy_resize(ds);
++
++ dcl = ds->listeners;
++ while (dcl != NULL) {
++ if (dcl->dpy_refresh != NULL) {
++ ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
++ qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
++ break;
++ }
++ dcl = dcl->next;
++ }
++
++ if (display_type == DT_NOGRAPHIC || display_type == DT_VNC) {
++ nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL);
++ qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
++ }
++
++ text_consoles_set_display(ds);
++
++ if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
++ fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
++ gdbstub_dev);
++ exit(1);
++ }
++
++ qdev_machine_creation_done();
++
++ if (rom_load_all() != 0) {
++ fprintf(stderr, "rom loading failed\n");
++ exit(1);
++ }
++
++ qemu_system_reset();
++ if (loadvm) {
++ if (load_vmstate(loadvm) < 0) {
++ autostart = 0;
++ }
++ }
++
++ if (incoming) {
++ int ret = qemu_start_incoming_migration(incoming);
++ if (ret < 0) {
++ fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
++ incoming, ret);
++ exit(ret);
++ }
++ } else if (autostart) {
++ vm_start();
++ }
++
++ os_setup_post();
++
++ main_loop();
++ quit_timers();
++ net_cleanup();
++
++ return 0;
++}
diff --git a/app-emulation/qemu-kvm/files/qemu-kvm-guest-hang-on-usb-add.patch b/app-emulation/qemu-kvm/files/qemu-kvm-guest-hang-on-usb-add.patch
new file mode 100644
index 0000000..3f2abef
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/qemu-kvm-guest-hang-on-usb-add.patch
@@ -0,0 +1,100 @@
+From 485b75728884a052b74d5458199ad45f0acbf190 Mon Sep 17 00:00:00 2001
+From: Timothy Jones <one.timothy.jones@gmail.com>
+Date: Mon, 28 Jun 2010 10:38:18 -0400
+Subject: [PATCH v2] Guest OS hangs on usb_add
+
+This is a small patch to sligtly "intelligentify" usb device and
+config descriptor parsing and to handle bug with certain usb
+device (URC MX-950) reporting device desriptor length as 0x18
+instead of 18 with added vendor_id/product_id check
+---
+ hw/usb.h | 5 +++++
+ usb-linux.c | 37 ++++++++++++++++++++++---------------
+ 2 files changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/hw/usb.h b/hw/usb.h
+index 00d2802..5c3528f 100644
+--- a/hw/usb.h
++++ b/hw/usb.h
+@@ -117,6 +117,11 @@
+ #define USB_DT_INTERFACE 0x04
+ #define USB_DT_ENDPOINT 0x05
+
++#define USB_DT_DEVICE_LEN 18
++#define USB_DT_CONFIG_LEN 9
++#define USB_DT_INTERFACE_LEN 9
++#define USB_DT_ENDPOINT_LEN 7
++
+ #define USB_ENDPOINT_XFER_CONTROL 0
+ #define USB_ENDPOINT_XFER_ISOC 1
+ #define USB_ENDPOINT_XFER_BULK 2
+diff --git a/usb-linux.c b/usb-linux.c
+index 88273ff..2ac6562 100644
+--- a/usb-linux.c
++++ b/usb-linux.c
+@@ -288,7 +288,7 @@ static void async_cancel(USBPacket *unused, void *opaque)
+
+ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
+ {
+- int dev_descr_len, config_descr_len;
++ int dev_descr_len, config_descr_total_len;
+ int interface, nb_interfaces;
+ int ret, i;
+
+@@ -297,32 +297,39 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
+
+ DPRINTF("husb: claiming interfaces. config %d\n", configuration);
+
+- i = 0;
+ dev_descr_len = dev->descr[0];
+- if (dev_descr_len > dev->descr_len) {
++ if (dev_descr_len == 0x18 && dev->descr[ 8] == 0x47 && dev->descr[ 9] == 0x46
++ && dev->descr[10] == 0x00 && dev->descr[11] == 0x30)
++ dev_descr_len = USB_DT_DEVICE_LEN; /* for buggy MX-950 remote reporting len in hex */
++
++ if (dev_descr_len > dev->descr_len || dev_descr_len < USB_DT_DEVICE_LEN || dev->descr[1] != USB_DT_DEVICE) {
++ fprintf(stderr, "husb: invalid device descriptor\n");
+ goto fail;
+ }
+
+- i += dev_descr_len;
+- while (i < dev->descr_len) {
++ for (i = dev_descr_len; i < dev->descr_len; ) {
+ DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
+ i, dev->descr_len,
+ dev->descr[i], dev->descr[i+1]);
+
+- if (dev->descr[i+1] != USB_DT_CONFIG) {
+- i += dev->descr[i];
+- continue;
++ if (dev->descr[i] < 2) {
++ fprintf(stderr, "husb: invalid descriptor\n");
++ goto fail;
+ }
+- config_descr_len = dev->descr[i];
++ if (dev->descr[i+1] == USB_DT_CONFIG) {
++ config_descr_total_len = dev->descr[i+2] + (dev->descr[i+3] << 8);
+
+- printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
++ printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
+
+- if (configuration < 0 || configuration == dev->descr[i + 5]) {
+- configuration = dev->descr[i + 5];
+- break;
+- }
++ if (configuration < 0 || configuration == dev->descr[i + 5]) {
++ configuration = dev->descr[i + 5];
++ break;
++ }
+
+- i += config_descr_len;
++ i += config_descr_total_len;
++ }
++ else
++ i += dev->descr[i];
+ }
+
+ if (i >= dev->descr_len) {
+--
+1.7.1
+
diff --git a/app-emulation/qemu-kvm/metadata.xml b/app-emulation/qemu-kvm/metadata.xml
new file mode 100644
index 0000000..29522f7
--- /dev/null
+++ b/app-emulation/qemu-kvm/metadata.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <herd>qemu</herd>
+ <use>
+ <flag name='aio'>Enables support for Linux's Async IO</flag>
+ <flag name='alsa'>Enable alsa output for sound emulation</flag>
+ <flag name='brltty'>Adds support for braille displays using brltty</flag>
+ <flag name='esd'>Enable esound output for sound emulation</flag>
+ <flag name='fdt'>Enables firmware device tree support</flag>
+ <flag name='jpeg'>Enable JPEG compression for the VNC console server</flag>
+ <flag name='kvm-trace'>Allows you to use KVM tracing</flag>
+ <flag name='ncurses'>Enable the ncurses-based console</flag>
+ <flag name='png'>Enable PNG compression for the VNC console server</flag>
+ <flag name='pulseaudio'>Enable pulseaudio output for sound emulation</flag>
+ <flag name='qemu-ifup'>Provides the qemu-ifup script for use with QEMU's
+ built in bridging</flag>
+ <flag name='rbd'>Enable rados block device backend support, see http://ceph.newdream.net/wiki/QEMU-RBD</flag>
+ <flag name='sdl'>Enable the SDL-based console</flag>
+ <flag name='spice'>Enable Spice protocol support via <pkg>app-emulation/spice</pkg></flag>
+ <flag name='ssl'>Enable TLS support for the VNC console server</flag>
+ <flag name='vde'>Enable VDE-based networking</flag>
+ <flag name='vhost-net'>Enable accelerated networking using vhost-net, see http://www.linux-kvm.org/page/VhostNet</flag>
+ <flag name='xen'>Enables support for Xen backends</flag>
+</use>
+</pkgmetadata>
diff --git a/app-emulation/qemu-kvm/qemu-kvm-0.13.0-r99.ebuild b/app-emulation/qemu-kvm/qemu-kvm-0.13.0-r99.ebuild
new file mode 100644
index 0000000..3455d67
--- /dev/null
+++ b/app-emulation/qemu-kvm/qemu-kvm-0.13.0-r99.ebuild
@@ -0,0 +1,261 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="2"
+
+if [[ ${PV} = *9999* ]]; then
+ EGIT_REPO_URI="git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git"
+ GIT_ECLASS="git"
+fi
+
+inherit eutils flag-o-matic ${GIT_ECLASS} linux-info toolchain-funcs
+
+if [[ ${PV} = *9999* ]]; then
+ SRC_URI=""
+ KEYWORDS=""
+else
+ SRC_URI="mirror://sourceforge/kvm/${PN}/${P}.tar.gz"
+ KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
+fi
+
+DESCRIPTION="QEMU + Kernel-based Virtual Machine userland tools"
+HOMEPAGE="http://www.linux-kvm.org"
+
+LICENSE="GPL-2"
+SLOT="0"
+# xen is disabled until the deps are fixed
+IUSE="+aio alsa bluetooth brltty curl esd fdt hardened jpeg ncurses \
+png pulseaudio qemu-ifup sasl sdl ssl static vde"
+
+COMMON_TARGETS="i386 x86_64 arm cris m68k microblaze mips mipsel ppc ppc64 sh4 sh4eb sparc sparc64"
+IUSE_SOFTMMU_TARGETS="${COMMON_TARGETS} mips64 mips64el ppcemb"
+IUSE_USER_TARGETS="${COMMON_TARGETS} alpha armeb ppc64abi32 sparc32plus"
+
+for target in ${IUSE_SOFTMMU_TARGETS}; do
+ IUSE="${IUSE} +qemu_softmmu_targets_${target}"
+done
+
+for target in ${IUSE_USER_TARGETS}; do
+ IUSE="${IUSE} +qemu_user_targets_${target}"
+done
+
+RESTRICT="test"
+
+RDEPEND="
+ !app-emulation/kqemu
+ !app-emulation/qemu
+ !app-emulation/qemu-softmmu
+ !app-emulation/qemu-user
+ !app-emulation/qemu-kvm-spice
+ sys-apps/pciutils
+ >=sys-apps/util-linux-2.16.0
+ sys-libs/zlib
+ aio? ( dev-libs/libaio )
+ alsa? ( >=media-libs/alsa-lib-1.0.13 )
+ bluetooth? ( net-wireless/bluez )
+ brltty? ( app-accessibility/brltty )
+ curl? ( net-misc/curl )
+ esd? ( media-sound/esound )
+ fdt? ( >=sys-apps/dtc-1.2.0 )
+ jpeg? ( virtual/jpeg )
+ ncurses? ( sys-libs/ncurses )
+ png? ( media-libs/libpng )
+ pulseaudio? ( media-sound/pulseaudio )
+ qemu-ifup? ( sys-apps/iproute2 net-misc/bridge-utils )
+ sasl? ( dev-libs/cyrus-sasl )
+ sdl? ( >=media-libs/libsdl-1.2.11[X] )
+ ssl? ( net-libs/gnutls )
+ vde? ( net-misc/vde )
+ amd64? ( >=app-emulation/spice-0.6.0 )
+ amd64? ( >=app-emulation/spice-protocol-0.6.0 )
+"
+
+DEPEND="${RDEPEND}
+ app-text/texi2html
+ >=sys-kernel/linux-headers-2.6.29
+ ssl? ( dev-util/pkgconfig )
+"
+
+kvm_kern_warn() {
+ eerror "Please enable KVM support in your kernel, found at:"
+ eerror
+ eerror " Virtualization"
+ eerror " Kernel-based Virtual Machine (KVM) support"
+ eerror
+}
+
+pkg_setup() {
+ use qemu_softmmu_targets_x86_64 || ewarn "You disabled default target QEMU_SOFTMMU_TARGETS=x86_64"
+
+ if kernel_is lt 2 6 25; then
+ eerror "This version of KVM requres a host kernel of 2.6.25 or higher."
+ eerror "Either upgrade your kernel"
+ else
+ if ! linux_config_exists; then
+ eerror "Unable to check your kernel for KVM support"
+ kvm_kern_warn
+ elif ! linux_chkconfig_present KVM; then
+ kvm_kern_warn
+ fi
+ fi
+
+ enewgroup kvm
+}
+
+src_prepare() {
+ # prevent docs to get automatically installed
+ sed -i '/$(DESTDIR)$(docdir)/d' Makefile || die
+ # Alter target makefiles to accept CFLAGS set via flag-o
+ sed -i 's/^\(C\|OP_C\|HELPER_C\)FLAGS=/\1FLAGS+=/' \
+ Makefile Makefile.target || die
+ # append CFLAGS while linking
+ sed -i 's/$(LDFLAGS)/$(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS)/' rules.mak || die
+
+ # remove part to make udev happy
+ sed -e 's~NAME="%k", ~~' -i kvm/scripts/65-kvm.rules || die
+
+ # ${PN}-guest-hang-on-usb-add.patch was sent by Timothy Jones
+ # to the qemu-devel ml - bug 337988
+ epatch "${FILESDIR}/qemu-0.11.0-mips64-user-fix.patch" \
+ "${FILESDIR}/${PN}-0.12.3-include-madvise-defines.patch"
+# "${FILESDIR}/${PN}-guest-hang-on-usb-add.patch"
+
+ epatch "${FILESDIR}/${PN}-0.13.0-redhat-patches.patch"
+}
+
+src_configure() {
+ local conf_opts audio_opts user_targets
+
+ for target in ${IUSE_SOFTMMU_TARGETS} ; do
+ use "qemu_softmmu_targets_${target}" && \
+ softmmu_targets="${softmmu_targets} ${target}-softmmu"
+ done
+
+ for target in ${IUSE_USER_TARGETS} ; do
+ use "qemu_user_targets_${target}" && \
+ user_targets="${user_targets} ${target}-linux-user"
+ done
+
+ if [ -z "${softmmu_targets}" ]; then
+ conf_opts="${conf_opts} --disable-system"
+ else
+ einfo "Building the following softmmu targets: ${softmmu_targets}"
+ fi
+
+ if [ ! -z "${user_targets}" ]; then
+ einfo "Building the following user targets: ${user_targets}"
+ conf_opts="${conf_opts} --enable-linux-user"
+ else
+ conf_opts="${conf_opts} --disable-linux-user"
+ fi
+
+ # Fix QA issues. QEMU needs executable heaps and we need to mark it as such
+ conf_opts="${conf_opts} --extra-ldflags=-Wl,-z,execheap"
+
+ # Add support for static builds
+ use static && conf_opts="${conf_opts} --static"
+
+ # Fix the $(prefix)/etc issue
+ conf_opts="${conf_opts} --sysconfdir=/etc"
+
+ #config options
+ conf_opts="${conf_opts} $(use_enable aio linux-aio)"
+ conf_opts="${conf_opts} $(use_enable bluetooth bluez)"
+ conf_opts="${conf_opts} $(use_enable brltty brlapi)"
+ conf_opts="${conf_opts} $(use_enable curl)"
+ conf_opts="${conf_opts} $(use_enable fdt)"
+ conf_opts="${conf_opts} $(use_enable hardened user-pie)"
+ conf_opts="${conf_opts} $(use_enable jpeg vnc-jpeg)"
+ conf_opts="${conf_opts} $(use_enable ncurses curses)"
+ conf_opts="${conf_opts} $(use_enable png vnc-png)"
+ conf_opts="${conf_opts} $(use_enable sasl vnc-sasl)"
+ conf_opts="${conf_opts} $(use_enable sdl)"
+ conf_opts="${conf_opts} $(use_enable ssl vnc-tls)"
+ conf_opts="${conf_opts} $(use_enable vde)"
+# conf_opts="${conf_opts} $(use_enable xen)"
+ conf_opts="${conf_opts} --disable-xen"
+ conf_opts="${conf_opts} --disable-darwin-user --disable-bsd-user"
+
+ # enable spice on amd64
+ use amd64 && conf_opts="${conf_opts} --enable-spice"
+
+ # audio options
+ audio_opts="oss"
+ use alsa && audio_opts="alsa ${audio_opts}"
+ use esd && audio_opts="esd ${audio_opts}"
+ use pulseaudio && audio_opts="pa ${audio_opts}"
+ use sdl && audio_opts="sdl ${audio_opts}"
+ ./configure --prefix=/usr \
+ --disable-strip \
+ --disable-werror \
+ --enable-kvm \
+ --enable-nptl \
+ --enable-uuid \
+ ${conf_opts} \
+ --audio-drv-list="${audio_opts}" \
+ --target-list="${softmmu_targets} ${user_targets}" \
+ --cc="$(tc-getCC)" \
+ --host-cc="$(tc-getBUILD_CC)" \
+ || die "configure failed"
+
+ # this is for qemu upstream's threaded support which is
+ # in development and broken
+ # the kvm project has its own support for threaded IO
+ # which is always on and works
+ # --enable-io-thread \
+}
+
+src_compile() {
+ # Restricting parallel build until we get a patch to fix this
+ emake -j1 || die
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "make install failed"
+
+ if [ ! -z "${softmmu_targets}" ]; then
+ insinto /etc/udev/rules.d/
+ doins kvm/scripts/65-kvm.rules || die
+
+ if use qemu-ifup; then
+ insinto /etc/qemu/
+ insopts -m0755
+ doins kvm/scripts/qemu-ifup || die
+ fi
+
+ if use qemu_softmmu_targets_x86_64 ; then
+ dobin "${FILESDIR}"/qemu-kvm
+ dosym /usr/bin/qemu-kvm /usr/bin/kvm
+ else
+ elog "You disabled QEMU_SOFTMMU_TARGETS=x86_64, this disables install"
+ elog "of /usr/bin/qemu-kvm and /usr/bin/kvm"
+ fi
+ fi
+
+ dodoc Changelog MAINTAINERS TODO pci-ids.txt || die
+ newdoc pc-bios/README README.pc-bios || die
+ dohtml qemu-doc.html qemu-tech.html || die
+}
+
+pkg_postinst() {
+
+ if [ ! -z "${softmmu_targets}" ]; then
+ elog "If you don't have kvm compiled into the kernel, make sure you have"
+ elog "the kernel module loaded before running kvm. The easiest way to"
+ elog "ensure that the kernel module is loaded is to load it on boot."
+ elog "For AMD CPUs the module is called 'kvm-amd'"
+ elog "For Intel CPUs the module is called 'kvm-intel'"
+ elog "Please review /etc/conf.d/modules for how to load these"
+ elog
+ elog "Make sure your user is in the 'kvm' group"
+ elog "Just run 'gpasswd -a <USER> kvm', then have <USER> re-login."
+ elog
+ elog "You will need the Universal TUN/TAP driver compiled into your"
+ elog "kernel or loaded as a module to use the virtual network device"
+ elog "if using -net tap. You will also need support for 802.1d"
+ elog "Ethernet Bridging and a configured bridge if using the provided"
+ elog "kvm-ifup script from /etc/kvm."
+ elog
+ elog "The gnutls use flag was renamed to ssl, so adjust your use flags."
+ fi
+}