* [gentoo-commits] dev/dev-zero:master commit in: app-emulation/qemu-kvm/, app-emulation/qemu-kvm/files/patches-from-fedora/, ...
@ 2011-04-29 6:26 Tiziano Müller
0 siblings, 0 replies; 2+ messages in thread
From: Tiziano Müller @ 2011-04-29 6:26 UTC (permalink / raw
To: gentoo-commits
commit: 9f68be096ca9520cd1639b5e25bf522d4e02d48d
Author: Tiziano Mueller <dev-zero <AT> gentoo <DOT> org>
AuthorDate: Fri Apr 29 06:26:23 2011 +0000
Commit: Tiziano Müller <dev-zero <AT> gentoo <DOT> org>
CommitDate: Fri Apr 29 06:26:23 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=dev/dev-zero.git;a=commit;h=9f68be09
Added qemu-kvm-0.14.0 bump including patches from Fedora.
---
app-emulation/qemu-kvm/Manifest | 24 +
.../0000-qemu-fix-non-PCI-target-build.patch | 53 ++
.../0000-qemu-vhost-fix-dirty-page-handling.patch | 31 +
.../0001-qxl-spice-display-move-pipe-to-ssd.patch | 143 +++++
...ent-get_command-in-vga-mode-without-locks.patch | 312 +++++++++
...emove-qemu_mutex_-un-lock_iothread-around.patch | 148 +++++
...ender-drop-cursor-locks-replace-with-pipe.patch | 249 ++++++++
...out-tcp-socket-close-code-in-a-separate-f.patch | 56 ++
...QemuChrHandlers-struct-to-initialise-char.patch | 673 ++++++++++++++++++++
...Add-enable-disable_write_fd_handler-funct.patch | 76 +++
...-framework-for-a-write-unblocked-callback.patch | 62 ++
...-send_all-to-handle-nonblocking-chardev-w.patch | 197 ++++++
...the-unix-tcp-backend-to-handle-nonblockin.patch | 80 +++
...har-Throttle-when-host-connection-is-down.patch | 56 ++
...ole-Enable-port-throttling-when-chardev-i.patch | 48 ++
.../0013-spice-qemu-char.c-add-throttling.patch | 133 ++++
...ce-qemu-char.c-remove-intermediate-buffer.patch | 71 ++
...ow-frontends-to-notify-backends-of-guest-.patch | 76 +++
...onsole-notify-backend-of-guest-open-close.patch | 49 ++
...ardev-listen-to-frontend-guest-open-close.patch | 49 ++
...char-Fix-flow-control-in-client-guest-dir.patch | 56 ++
.../files/qemu-0.11.0-mips64-user-fix.patch | 11 +
app-emulation/qemu-kvm/files/qemu-kvm | 2 +
app-emulation/qemu-kvm/qemu-kvm-0.14.0.ebuild | 260 ++++++++
24 files changed, 2915 insertions(+), 0 deletions(-)
diff --git a/app-emulation/qemu-kvm/Manifest b/app-emulation/qemu-kvm/Manifest
new file mode 100644
index 0000000..e81f2a3
--- /dev/null
+++ b/app-emulation/qemu-kvm/Manifest
@@ -0,0 +1,24 @@
+AUX patches-from-fedora/0000-qemu-fix-non-PCI-target-build.patch 1748 RMD160 6b74c349fa036728a38fe1ee56bf2ed567da2fb8 SHA1 08563c7e311d1c350065a6e4790e2abddc71c3d4 SHA256 9bd9e44061763aae606ee4cc19a0a54dc1c88830fe59432693be6a3a32a65328
+AUX patches-from-fedora/0000-qemu-vhost-fix-dirty-page-handling.patch 1045 RMD160 abbfe09dd7136ff2e89d0a4aee12903ac07dd38f SHA1 d544c845b2f782327babcfc8167d8fb4974db5d8 SHA256 9f78073f23657feef5e0bf017315476356d9cf6a0b953e39e54199e0a5e0c7b5
+AUX patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch 4618 RMD160 f8bee2614fd8791cf478b09cb0babbf5c113ff4b SHA1 29bbe1bd0b1d5bd54e4d22aa062ed5fe9d7b80e7 SHA256 22152847a75d9f14d4d73f5f2042d83e0de2d882c066bf7524827127230b7d2d
+AUX patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch 10176 RMD160 316ed43c95137c49c25ef0d1d8faca736850f0b2 SHA1 61663c85a06ae2aaeff12887e609fcd76cbc1b31 SHA256 c788c617ee226716657dbfd778790f6b87734235e5d9fe702099bdd6e7147edb
+AUX patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch 5073 RMD160 3ce5594c2144edaff73a929c47260674724c3bbd SHA1 17844d9a38ef837098a492a994a60c7d06aeb007 SHA256 a656f4b0faac207578edf0171676799680da4427d2e332c144350dec2699bced
+AUX patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch 7783 RMD160 4261b2ad8ee333c31fe4fe700e40b27c794b60cb SHA1 8d5b0ab3a6d2a247d3197ba65cd2d1fb8f99eba7 SHA256 bb6aeaecb66e2d0215191c64e580c1ca5bbe004accddff9f7454d222b5af74de
+AUX patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch 1733 RMD160 30e31570c31d68be3b0f9f12870c13d51a18b3aa SHA1 f80a973a826693accd331c6d3d3cdddc8f47a9b6 SHA256 e123d523c974617510c59d026fdc26ec7e502bcda6c1652797dad9ae404167db
+AUX patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch 22320 RMD160 50ba6be5ef638865a18ef0c65ff8c13800d70169 SHA1 85ea8ae83047d576e69bb45cacd2f6291d7c9d3c SHA256 69192c8b9d530c4bb21c002803812d42f8bedf6f99f86a17b2493ae58ef0aff2
+AUX patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch 1913 RMD160 3c2b3fe8087de960064e33f4c3dcda74cf1ad028 SHA1 7d4ad12e0f5e019155ab4f02186cc1db0360560b SHA256 3778a50b0065ea51a52f624a6d080d0a8c260bb9bdfb23ec7646018f228b3716
+AUX patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch 2182 RMD160 8bef66b38c3b90e011c20d7a2d23f680be2fa2fc SHA1 783ce01d2ba57f7ff94dc2e3899f2ecdbf5ba528 SHA256 01a72c82db6da782854b2cdaaf094d103b3854c7ad26328d84e97c356b150ae8
+AUX patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch 6678 RMD160 e929fb838a590ade9cde62804f2d0503c14fd734 SHA1 ce4917bb9c3b580286c31137c46c7e034463503f SHA256 5b9e50e98c39523c790e2ec75c65e6576b13580ccb01c9e22e51caa40c4a40be
+AUX patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch 2583 RMD160 dd6080a4e259410b7dd6ba6b51a0af51b6a8ca0c SHA1 73f62b43270f4b6369efd7e6015e3f6e7d0cb9a9 SHA256 61dd33665fad5bfb4df1d387cebec1e0bed6128bbf427c9f8a3c60f91c713c6c
+AUX patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch 2000 RMD160 3fa3bd27d69d90f26e30b3cc5c899cb49554639a SHA1 3d662d181d77f8e4420b6f8c5fa57687d11f3858 SHA256 c496a5bd77aa973f6368b06d8a0a67568ae53a0990cec65897b57918f6fee6e7
+AUX patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch 1650 RMD160 0e94375a02675398d1627bdbc6617661139ae0d7 SHA1 10371019b8053965e63ccd8d5472c11a05ccc3d2 SHA256 6eabb8a5f3207fd24a7c27dbbfb47168c7a4778771a84f00622c3cadc21b4674
+AUX patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch 5036 RMD160 8cf7d356f1664b32f462ad2b957194031d3e6126 SHA1 35cce42333140d5c65f54cbab5e438b0de7f7d95 SHA256 c7d863e59849c732f3fef3a425f1f32843fd2e542a94b61fae61ce36a087f0e3
+AUX patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch 2822 RMD160 5d5ab6de3e5a0e8ebea6001127d61c0f730c609f SHA1 ddd50cf6e52ca8dae01f7253417946e2f4cc4cbe SHA256 d7cb0159ac28d78a68208a99ec5dbfaf43e01bde68b90528d7cfb629c78e7247
+AUX patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch 2807 RMD160 5193a86c3400d78d1a0190f98532738fbc53aa77 SHA1 f7365f2eb85fb2cd824f5dbcd198a406354e04e5 SHA256 077b6a431156a5a7fbadabfdc7543f4096fd46a7990b56332c1b82928941f4b2
+AUX patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch 1592 RMD160 a024a9fced5e3a44580ae6ae78409e0e4b8e5265 SHA1 243028b1f28ab67b04341ea22492bd58e9dab231 SHA256 0bbc7fa3d32dae0d812baac88fb4dff7ba075221f16ed90116432562aa5be9b8
+AUX patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch 1536 RMD160 a62580485c1cecc5cd979b67cd8567947d223d2f SHA1 2df9fe95487101ed1fea739d106c8fbb3633d8f0 SHA256 86623ce9e32fee56d1f13ee51770d89043d1c6fb7a4d972e15840fab95a0b04d
+AUX patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch 1784 RMD160 25fe156aafa2070905476ccdd0e4f2946729bec8 SHA1 7ed5fa3d92ed45d2e0d95247cc5d437304419074 SHA256 68215f7f55f749aa8333d840e40c0c58e957c12c90b47eb8b0c5cad3f6249fec
+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
+EBUILD qemu-kvm-0.14.0.ebuild 8262 RMD160 cea3db6007a7ddf1f274b95b7cfc67091d99dc64 SHA1 cdfd9bd633b2f2453b613a99796b0e6dd97bad2b SHA256 52ec87addca7e8db2164dc09b02116c3335aa9eac49c2b2744dfe5b480559d88
+DIST qemu-kvm-0.14.0.tar.gz 5320696 RMD160 9b55c252390ece716295fdc6a012eaa6091f7b90 SHA1 dba0b9484084374b6191608051f40e1991c54ea0 SHA256 2f62aff3655c7b904ccd088e80927b021126d91125e9d9515ee9dda8835c0635
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-fix-non-PCI-target-build.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-fix-non-PCI-target-build.patch
new file mode 100644
index 0000000..b479efa
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-fix-non-PCI-target-build.patch
@@ -0,0 +1,53 @@
+commit 1a8364456c2f3946b4feb8fc78eaf00d974f4c03
+Author: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Wed Feb 23 09:28:53 2011 +0100
+
+ qemu-kvm: Fix non-PCI target build
+
+ Replace obsolete qemu-kvm.h with kvm.h in pci.c and build that module
+ just like upstream does. This fixes non-x86 targets which have no PCI
+ support.
+
+ Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+ Signed-off-by: Avi Kivity <avi@redhat.com>
+
+diff --git a/Makefile.objs b/Makefile.objs
+index f5702eb..3ec7121 100644
+--- a/Makefile.objs
++++ b/Makefile.objs
+@@ -170,7 +170,7 @@ hw-obj-y =
+ hw-obj-y += loader.o
+ hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
+ hw-obj-y += fw_cfg.o
+-hw-obj-$(CONFIG_PCI) += pci_bridge.o
++hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
+ hw-obj-$(CONFIG_PCI) += msix.o msi.o
+ hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
+ hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
+diff --git a/Makefile.target b/Makefile.target
+index 6e9a024..23367eb 100644
+--- a/Makefile.target
++++ b/Makefile.target
+@@ -195,7 +195,7 @@ 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
++obj-y = arch_init.o cpus.o monitor.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-$(CONFIG_NO_PCI) += pci-stub.o
+diff --git a/hw/pci.c b/hw/pci.c
+index 0c44939..1f6cebe 100644
+--- a/hw/pci.c
++++ b/hw/pci.c
+@@ -29,8 +29,8 @@
+ #include "net.h"
+ #include "sysemu.h"
+ #include "loader.h"
+-#include "qemu-kvm.h"
+ #include "hw/pc.h"
++#include "kvm.h"
+ #include "device-assignment.h"
+ #include "qemu-objects.h"
+ #include "range.h"
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-vhost-fix-dirty-page-handling.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-vhost-fix-dirty-page-handling.patch
new file mode 100644
index 0000000..e3fabb7
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-vhost-fix-dirty-page-handling.patch
@@ -0,0 +1,31 @@
+vhost was passing a physical address to cpu_physical_memory_set_dirty,
+which is wrong: we need to translate to ram address first.
+
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+
+Note: this lead to crashes during migration, so the patch
+is needed on the stable branch too.
+
+---
+ hw/vhost.c | 4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/hw/vhost.c b/hw/vhost.c
+index aaa34e4..97a1299 100644
+--- a/hw/vhost.c
++++ b/hw/vhost.c
+@@ -49,8 +49,10 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
+ log = __sync_fetch_and_and(from, 0);
+ while ((bit = sizeof(log) > sizeof(int) ?
+ ffsll(log) : ffs(log))) {
++ ram_addr_t ram_addr;
+ bit -= 1;
+- cpu_physical_memory_set_dirty(addr + bit * VHOST_LOG_PAGE);
++ ram_addr = cpu_get_physical_page_desc(addr + bit * VHOST_LOG_PAGE);
++ cpu_physical_memory_set_dirty(ram_addr);
+ log &= ~(0x1ull << bit);
+ }
+ addr += VHOST_LOG_CHUNK;
+--
+1.7.3.2.91.g446ac
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch
new file mode 100644
index 0000000..b542f54
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch
@@ -0,0 +1,143 @@
+>From fd04276a00b172e6fbba3e3c72b1d13a0f179414 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Wed, 16 Mar 2011 15:21:03 +0100
+Subject: [PATCH 1/4] qxl/spice-display: move pipe to ssd
+
+This moves the int pipe[2] and pthread_t main data from the
+PCIQXLDevice struct to the SimpleSpiceDisplay. This will let us
+reuse it in the next patch for both -spice with no -qxl usage and
+for vga mode from qxl.
+
+Also move the pipe creation function (which is effectively completely rewritten
+by this patch anyways) from hw/qxl.c to ui/spice-display.c, since
+spice-display will depend on it after the next patch and qemu can be build
+with ui/spice-display.c in combination with no hw/qxl.c.
+---
+ hw/qxl.c | 22 +++++-----------------
+ hw/qxl.h | 4 ----
+ ui/spice-display.c | 21 +++++++++++++++++++++
+ ui/spice-display.h | 8 ++++++++
+ 4 files changed, 34 insertions(+), 21 deletions(-)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index fe4212b..201698f 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -1062,7 +1062,7 @@ static void pipe_read(void *opaque)
+ int len;
+
+ do {
+- len = read(d->pipe[0], &dummy, sizeof(dummy));
++ len = read(d->ssd.pipe[0], &dummy, sizeof(dummy));
+ } while (len == sizeof(dummy));
+ qxl_set_irq(d);
+ }
+@@ -1078,10 +1078,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
+ if ((old_pending & le_events) == le_events) {
+ return;
+ }
+- if (pthread_self() == d->main) {
++ if (pthread_self() == d->ssd.main) {
++ /* running in io_thread thread */
+ qxl_set_irq(d);
+ } else {
+- if (write(d->pipe[1], d, 1) != 1) {
++ if (write(d->ssd.pipe[1], d, 1) != 1) {
+ dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
+ }
+ }
+@@ -1089,20 +1090,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
+
+ static void init_pipe_signaling(PCIQXLDevice *d)
+ {
+- if (pipe(d->pipe) < 0) {
+- dprint(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);
++ qxl_create_server_to_iothread_pipe(&d->ssd, pipe_read);
+ }
+
+ /* graphics console */
+diff --git a/hw/qxl.h b/hw/qxl.h
+index f6c450d..701245f 100644
+--- a/hw/qxl.h
++++ b/hw/qxl.h
+@@ -55,10 +55,6 @@ typedef struct PCIQXLDevice {
+ } guest_surfaces;
+ QXLPHYSICAL guest_cursor;
+
+- /* thread signaling */
+- pthread_t main;
+- int pipe[2];
+-
+ /* ram pci bar */
+ QXLRam *ram;
+ VGACommonState vga;
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index 020b423..ec6e0cb 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -394,6 +394,27 @@ static DisplayChangeListener display_listener = {
+ .dpy_refresh = display_refresh,
+ };
+
++void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
++ IOHandler *pipe_read)
++{
++ if (pipe(ssd->pipe) < 0) {
++ fprintf(stderr, "%s: pipe creation failed\n", __FUNCTION__);
++ return;
++ }
++
++#ifdef CONFIG_IOTHREAD
++ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK);
++#else
++ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
++#endif
++ fcntl(ssd->pipe[1], F_SETFL, O_NONBLOCK);
++
++ fcntl(ssd->pipe[0], F_SETOWN, getpid());
++
++ qemu_set_fd_handler(ssd->pipe[0], pipe_read, NULL, ssd);
++ ssd->main = pthread_self();
++}
++
+ void qemu_spice_display_init(DisplayState *ds)
+ {
+ assert(sdpy.ds == NULL);
+diff --git a/ui/spice-display.h b/ui/spice-display.h
+index aef0464..3e6cf7c 100644
+--- a/ui/spice-display.h
++++ b/ui/spice-display.h
+@@ -43,6 +43,11 @@ typedef struct SimpleSpiceDisplay {
+ QXLRect dirty;
+ int notify;
+ int running;
++
++ /* thread signaling - used both in qxl (in vga mode
++ * and in native mode) and without qxl */
++ pthread_t main;
++ int pipe[2]; /* to iothread */
+ } SimpleSpiceDisplay;
+
+ typedef struct SimpleSpiceUpdate {
+@@ -66,3 +71,6 @@ 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);
++/* used by both qxl and spice-display */
++void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
++ IOHandler *pipe_read);
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch
new file mode 100644
index 0000000..d221d5f
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch
@@ -0,0 +1,312 @@
+>From 97e291086fef45762e0278e85ab1d231a9902bbb Mon Sep 17 00:00:00 2001
+From: Uri Lublin <uril@redhat.com>
+Date: Wed, 16 Mar 2011 15:43:45 +0100
+Subject: [PATCH 2/4] qxl: implement get_command in vga mode without locks
+
+This patch and the next drop the requirement to lose the global qemu
+mutex during dispatcher calls. This patch enables it, the next drops
+the unlock/lock pairs around dispatcher calls.
+
+The current solution of dropping the locks is buggy:
+ * it allows multiple dispatcher calls from two vcpu threads, the
+ dispatcher doesn't handle that by design (single fd, not locked, can't
+ handle writes from two threads)
+ * it requires us to keep track of cpu_single_env, which is magic.
+
+The solution implemented in this patch and the next (the next just
+drops the locks, this patch allows that to work):
+ * the only operation that needed locking was qemu_create_simple_update,
+ * it required locking because it was called from the spice-server thread.
+ * do it in the iothread by reusing the existing pipe used for set_irq.
+
+The current flow implemented is now:
+spice-server thread:
+ qxl.c:interface_get_command (called either by polling or from wakeup)
+ if update!=NULL:
+ waiting_for_update=0
+ update=NULL
+ return update
+ else:
+ if not waiting_for_update:
+ waiting_for_update=1
+ write to pipe, which is read by iothread (main thread)
+
+iothread:
+ wakeup from select,
+ qxl.c:pipe_read
+ update=qemu_create_simple_update()
+ wakeup spice-server thread by calling d.worker->wakeup(d.worker)
+---
+ hw/qxl.c | 81 +++++++++++++++++++++++++++++++++++++++------------
+ ui/spice-display.c | 75 +++++++++++++++++++++++++++++++++++++++++++----
+ ui/spice-display.h | 16 ++++++++++
+ 3 files changed, 146 insertions(+), 26 deletions(-)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index 201698f..64580f1 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -340,7 +340,6 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
+ 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;
+@@ -348,16 +347,25 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
+ switch (qxl->mode) {
+ case QXL_MODE_VGA:
+ dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
+- update = qemu_spice_create_update(&qxl->ssd);
+- if (update == NULL) {
+- return false;
++ if (qxl_vga_mode_get_command(&qxl->ssd, ext)) {
++ qxl_log_command(qxl, "vga", ext);
++ return true;
+ }
+- *ext = update->ext;
+- qxl_log_command(qxl, "vga", ext);
+- return true;
++ return false;
+ case QXL_MODE_COMPAT:
+ case QXL_MODE_NATIVE:
+ case QXL_MODE_UNDEFINED:
++ /* flush any existing updates that we didn't send to the guest.
++ * since update != NULL it means the server didn't get it, and
++ * because we changed mode to != QXL_MODE_VGA, it won't. */
++ if (qxl->ssd.update != NULL) {
++ if (qxl->ssd.update != QXL_EMPTY_UPDATE) {
++ qemu_spice_destroy_update(&qxl->ssd, qxl->ssd.update);
++ }
++ qxl->ssd.update = NULL;
++ qxl->ssd.waiting_for_update = 0;
++ }
++ /* */
+ dprint(qxl, 2, "%s: %s\n", __FUNCTION__,
+ qxl->cmdflags ? "compat" : "native");
+ ring = &qxl->ram->cmd_ring;
+@@ -1057,17 +1065,50 @@ static void qxl_map(PCIDevice *pci, int region_num,
+
+ static void pipe_read(void *opaque)
+ {
+- PCIQXLDevice *d = opaque;
+- char dummy;
+- int len;
+-
+- do {
+- len = read(d->ssd.pipe[0], &dummy, sizeof(dummy));
+- } while (len == sizeof(dummy));
+- qxl_set_irq(d);
++ SimpleSpiceDisplay *ssd = opaque;
++ unsigned char cmd;
++ int len, set_irq = 0;
++ int create_update = 0;
++
++ while (1) {
++ cmd = 0;
++ len = read(ssd->pipe[0], &cmd, sizeof(cmd));
++ if (len < 0) {
++ if (errno == EINTR) {
++ continue;
++ }
++ if (errno == EAGAIN) {
++ break;
++ }
++ perror("qxl: pipe_read: read failed");
++ break;
++ }
++ switch (cmd) {
++ case QXL_SERVER_SET_IRQ:
++ set_irq = 1;
++ break;
++ case QXL_SERVER_CREATE_UPDATE:
++ create_update = 1;
++ break;
++ default:
++ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
++ abort();
++ }
++ }
++ /* no need to do either operation more than once */
++ if (create_update) {
++ assert(ssd->update == NULL);
++ ssd->update = qemu_spice_create_update(ssd);
++ if (ssd->update == NULL) {
++ ssd->update = QXL_EMPTY_UPDATE;
++ }
++ ssd->worker->wakeup(ssd->worker);
++ }
++ if (set_irq) {
++ qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd));
++ }
+ }
+
+-/* called from spice server thread context only */
+ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
+ {
+ uint32_t old_pending;
+@@ -1082,9 +1123,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
+ /* running in io_thread thread */
+ qxl_set_irq(d);
+ } else {
+- if (write(d->ssd.pipe[1], d, 1) != 1) {
+- dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
+- }
++ /* called from spice-server thread */
++ int ret;
++ unsigned char ack = QXL_SERVER_SET_IRQ;
++ ret = write(d->ssd.pipe[1], &ack, 1);
++ assert(ret == 1);
+ }
+ }
+
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index ec6e0cb..bdd14b8 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -294,18 +294,39 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
+ info->n_surfaces = NUM_SURFACES;
+ }
+
++/* Called from spice server thread context (via interface_get_command) */
++int qxl_vga_mode_get_command(
++ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext)
++{
++ SimpleSpiceUpdate *update;
++ unsigned char req;
++ int r;
++
++ update = ssd->update;
++ if (update != NULL) {
++ ssd->waiting_for_update = 0;
++ ssd->update = NULL;
++ if (update != QXL_EMPTY_UPDATE) {
++ *ext = update->ext;
++ return true;
++ }
++ } else {
++ if (!ssd->waiting_for_update) {
++ ssd->waiting_for_update = 1;
++ req = QXL_SERVER_CREATE_UPDATE;
++ r = write(ssd->pipe[1], &req , 1);
++ assert(r == 1);
++ }
++ }
++ return false;
++}
++
+ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
+ {
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
+- SimpleSpiceUpdate *update;
+
+ dprint(3, "%s:\n", __FUNCTION__);
+- update = qemu_spice_create_update(ssd);
+- if (update == NULL) {
+- return false;
+- }
+- *ext = update->ext;
+- return true;
++ return qxl_vga_mode_get_command(ssd, ext);
+ }
+
+ static int interface_req_cmd_notification(QXLInstance *sin)
+@@ -394,6 +415,45 @@ static DisplayChangeListener display_listener = {
+ .dpy_refresh = display_refresh,
+ };
+
++static void pipe_read(void *opaque)
++{
++ SimpleSpiceDisplay *ssd = opaque;
++ unsigned char cmd;
++ int len, create_update = 0;
++
++ while (1) {
++ cmd = 0;
++ len = read(ssd->pipe[0], &cmd, sizeof(cmd));
++ if (len < 0) {
++ if (errno == EINTR) {
++ continue;
++ }
++ if (errno == EAGAIN) {
++ break;
++ }
++ perror("qxl: pipe_read: read failed");
++ break;
++ }
++ switch (cmd) {
++ case QXL_SERVER_CREATE_UPDATE:
++ create_update = 1;
++ break;
++ default:
++ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
++ abort();
++ }
++ }
++ /* no need to do this more than once */
++ if (create_update) {
++ assert(ssd->update == NULL);
++ ssd->update = qemu_spice_create_update(ssd);
++ if (ssd->update == NULL) {
++ ssd->update = QXL_EMPTY_UPDATE;
++ }
++ ssd->worker->wakeup(ssd->worker);
++ }
++}
++
+ void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
+ IOHandler *pipe_read)
+ {
+@@ -427,6 +487,7 @@ void qemu_spice_display_init(DisplayState *ds)
+ qemu_spice_add_interface(&sdpy.qxl.base);
+ assert(sdpy.worker);
+
++ qxl_create_server_to_iothread_pipe(&sdpy, pipe_read);
+ 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 --git a/ui/spice-display.h b/ui/spice-display.h
+index 3e6cf7c..2be6a34 100644
+--- a/ui/spice-display.h
++++ b/ui/spice-display.h
+@@ -31,6 +31,15 @@
+
+ #define NUM_SURFACES 1024
+
++/* For commands/requests from server thread to iothread */
++#define QXL_EMPTY_UPDATE ((void *)-1)
++enum {
++ QXL_SERVER_SET_IRQ = 1,
++ QXL_SERVER_CREATE_UPDATE,
++};
++
++struct SimpleSpiceUpdate;
++
+ typedef struct SimpleSpiceDisplay {
+ DisplayState *ds;
+ void *buf;
+@@ -48,6 +57,10 @@ typedef struct SimpleSpiceDisplay {
+ * and in native mode) and without qxl */
+ pthread_t main;
+ int pipe[2]; /* to iothread */
++
++ /* ssd updates (one request/command at a time) */
++ struct SimpleSpiceUpdate *update;
++ int waiting_for_update;
+ } SimpleSpiceDisplay;
+
+ typedef struct SimpleSpiceUpdate {
+@@ -71,6 +84,9 @@ 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);
++/* shared with qxl.c in vga mode and ui/spice-display (no qxl mode) */
++int qxl_vga_mode_get_command(
++ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext);
+ /* used by both qxl and spice-display */
+ void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
+ IOHandler *pipe_read);
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch
new file mode 100644
index 0000000..92a148e
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch
@@ -0,0 +1,148 @@
+>From d413b3c36cbd9820c5b9492b52caa421abccf745 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Wed, 16 Mar 2011 15:46:22 +0100
+Subject: [PATCH 3/4] qxl/spice: remove qemu_mutex_{un,}lock_iothread around dispatcher
+
+with the previous patch making sure get_command no longer needs to lock,
+there is no reason to drop the qemu iothread mutex in qxl.c and in
+ui/spice-display.c
+
+The only location where the lock remains are the cursor related callbacks,
+that path is currently broken. It is only triggered if running spice and sdl,
+which is broken already before that.
+---
+ hw/qxl.c | 8 --------
+ ui/spice-display.c | 19 +++----------------
+ 2 files changed, 3 insertions(+), 24 deletions(-)
+
+diff --git a/hw/qxl.c b/hw/qxl.c
+index 64580f1..cf3c938 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -670,10 +670,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
+ dprint(d, 1, "%s: start%s\n", __FUNCTION__,
+ loadvm ? " (loadvm)" : "");
+
+- qemu_mutex_unlock_iothread();
+ d->ssd.worker->reset_cursor(d->ssd.worker);
+ d->ssd.worker->reset_image_cache(d->ssd.worker);
+- qemu_mutex_lock_iothread();
+ qxl_reset_surfaces(d);
+ qxl_reset_memslots(d);
+
+@@ -803,9 +801,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
+ {
+ dprint(d, 1, "%s:\n", __FUNCTION__);
+ d->mode = QXL_MODE_UNDEFINED;
+- qemu_mutex_unlock_iothread();
+ d->ssd.worker->destroy_surfaces(d->ssd.worker);
+- qemu_mutex_lock_iothread();
+ memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
+ }
+
+@@ -874,9 +870,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d)
+ dprint(d, 1, "%s\n", __FUNCTION__);
+
+ d->mode = QXL_MODE_UNDEFINED;
+- qemu_mutex_unlock_iothread();
+ d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
+- qemu_mutex_lock_iothread();
+ }
+
+ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
+@@ -946,10 +940,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
+ case QXL_IO_UPDATE_AREA:
+ {
+ QXLRect update = d->ram->update_area;
+- qemu_mutex_unlock_iothread();
+ d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
+ &update, NULL, 0, 0);
+- qemu_mutex_lock_iothread();
+ break;
+ }
+ case QXL_IO_NOTIFY_CMD:
+diff --git a/ui/spice-display.c b/ui/spice-display.c
+index bdd14b8..ecb22cc 100644
+--- a/ui/spice-display.c
++++ b/ui/spice-display.c
+@@ -62,13 +62,7 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
+ dest->right = MAX(dest->right, r->right);
+ }
+
+-/*
+- * Called from spice server thread context (via interface_get_command).
+- *
+- * We must aquire the global qemu mutex here to make sure the
+- * DisplayState (+DisplaySurface) we are accessing doesn't change
+- * underneath us.
+- */
++/* Called from io-thread context (via pipe_read) */
+ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+ {
+ SimpleSpiceUpdate *update;
+@@ -78,9 +72,7 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+ uint8_t *src, *dst;
+ int by, bw, bh;
+
+- qemu_mutex_lock_iothread();
+ if (qemu_spice_rect_is_empty(&ssd->dirty)) {
+- qemu_mutex_unlock_iothread();
+ return NULL;
+ };
+
+@@ -141,7 +133,6 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+ cmd->data = (intptr_t)drawable;
+
+ memset(&ssd->dirty, 0, sizeof(ssd->dirty));
+- qemu_mutex_unlock_iothread();
+ return update;
+ }
+
+@@ -169,6 +160,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
+ ssd->worker->add_memslot(ssd->worker, &memslot);
+ }
+
++/* called from iothread (main) or a vcpu-thread */
+ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
+ {
+ QXLDevSurfaceCreate surface;
+@@ -186,18 +178,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
+ surface.mem = (intptr_t)ssd->buf;
+ surface.group_id = MEMSLOT_GROUP_HOST;
+
+- qemu_mutex_unlock_iothread();
+ ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
+- qemu_mutex_lock_iothread();
+ }
+
+ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
+ {
+ dprint(1, "%s:\n", __FUNCTION__);
+
+- qemu_mutex_unlock_iothread();
+ ssd->worker->destroy_primary_surface(ssd->worker, 0);
+- qemu_mutex_lock_iothread();
+ }
+
+ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
+@@ -207,9 +195,7 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
+ if (running) {
+ ssd->worker->start(ssd->worker);
+ } else {
+- qemu_mutex_unlock_iothread();
+ ssd->worker->stop(ssd->worker);
+- qemu_mutex_lock_iothread();
+ }
+ ssd->running = running;
+ }
+@@ -233,6 +219,7 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
+ qemu_spice_rect_union(&ssd->dirty, &update_area);
+ }
+
++/* called only from iothread (main) */
+ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
+ {
+ dprint(1, "%s:\n", __FUNCTION__);
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch
new file mode 100644
index 0000000..03daba4
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch
@@ -0,0 +1,249 @@
+>From 1a33e5f2fa6de800047517a6f3251dc7191c97b5 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Wed, 16 Mar 2011 16:02:16 +0100
+Subject: [PATCH 4/4] hw/qxl-render: drop cursor locks, replace with pipe
+
+Switching locking protection of ds->cursor_set/cursor_move to moving
+every call to these functions into the iothread and using the ssd->pipe
+to transfer that, adding QXL_SERVER_CURSOR_SET, QXL_SERVER_CURSOR_MOVE.
+
+This is tested with both -vnc :0 -spice and -sdl -spice.
+---
+ hw/qxl-render.c | 25 +++++++++-----
+ hw/qxl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ hw/qxl.h | 4 ++
+ ui/spice-display.h | 13 +++++++-
+ 4 files changed, 122 insertions(+), 10 deletions(-)
+
+diff --git a/hw/qxl-render.c b/hw/qxl-render.c
+index 58965e0..6759edb 100644
+--- a/hw/qxl-render.c
++++ b/hw/qxl-render.c
+@@ -178,7 +178,6 @@ fail:
+ return NULL;
+ }
+
+-
+ /* called from spice server thread context only */
+ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
+ {
+@@ -209,18 +208,26 @@ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
+ if (c == NULL) {
+ c = cursor_builtin_left_ptr();
+ }
+- qemu_mutex_lock_iothread();
+- qxl->ssd.ds->cursor_define(c);
+- qxl->ssd.ds->mouse_set(x, y, 1);
+- qemu_mutex_unlock_iothread();
+- cursor_put(c);
++ qxl_server_request_cursor_set(qxl, c, x, y);
+ break;
+ case QXL_CURSOR_MOVE:
+ x = cmd->u.position.x;
+ y = cmd->u.position.y;
+- qemu_mutex_lock_iothread();
+- qxl->ssd.ds->mouse_set(x, y, 1);
+- qemu_mutex_unlock_iothread();
++ qxl_server_request_cursor_move(qxl, x, y);
+ break;
+ }
+ }
++
++/* called from iothread only (via qxl.c:pipe_read) */
++void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y)
++{
++ ssd->ds->cursor_define(c);
++ ssd->ds->mouse_set(x, y, 1);
++ cursor_put(c);
++}
++
++/* called from iothread only (via qxl.c:pipe_read) */
++void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y)
++{
++ ssd->ds->mouse_set(x, y, 1);
++}
+diff --git a/hw/qxl.c b/hw/qxl.c
+index cf3c938..4c27deb 100644
+--- a/hw/qxl.c
++++ b/hw/qxl.c
+@@ -117,6 +117,27 @@ static QXLMode qxl_modes[] = {
+ #endif
+ };
+
++typedef struct __attribute__ ((__packed__)) {
++ QEMUCursor *c;
++ int x;
++ int y;
++} QXLServerCursorSet;
++
++typedef struct __attribute__ ((__packed__)) {
++ int x;
++ int y;
++} QXLServerCursorMove;
++
++typedef struct __attribute__ ((__packed__)) {
++ unsigned char req;
++ QXLServerCursorMove data;
++} QXLServerCursorMoveRequest;
++
++typedef struct __attribute__ ((__packed__)) {
++ unsigned char req;
++ QXLServerCursorSet data;
++} QXLServerCursorSetRequest;
++
+ static PCIQXLDevice *qxl0;
+
+ static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
+@@ -337,6 +358,33 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
+ }
+
+ /* called from spice server thread context only */
++void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y)
++{
++ QXLServerCursorSetRequest req;
++ int r;
++
++ req.req = QXL_SERVER_CURSOR_SET;
++ req.data.c = c;
++ req.data.x = x;
++ req.data.y = y;
++ r = write(qxl->ssd.pipe[1], &req, sizeof(req));
++ assert(r == sizeof(req));
++}
++
++/* called from spice server thread context only */
++void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y)
++{
++ QXLServerCursorMoveRequest req;
++ int r;
++
++ req.req = QXL_SERVER_CURSOR_MOVE;
++ req.data.x = x;
++ req.data.y = y;
++ r = write(qxl->ssd.pipe[1], &req, sizeof(req));
++ assert(r == sizeof(req));
++}
++
++/* called from spice server thread context only */
+ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
+ {
+ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+@@ -1055,12 +1103,37 @@ static void qxl_map(PCIDevice *pci, int region_num,
+ }
+ }
+
++static void read_bytes(int fd, void *buf, int len_requested)
++{
++ int len;
++ int total_len = 0;
++
++ do {
++ len = read(fd, buf, len_requested - total_len);
++ if (len < 0) {
++ if (errno == EINTR || errno == EAGAIN) {
++ continue;
++ }
++ perror("qxl: pipe_read: read failed");
++ /* will abort once it's out of the while loop */
++ break;
++ }
++ total_len += len;
++ buf = (uint8_t *)buf + len;
++ } while (total_len < len_requested);
++ assert(total_len == len_requested);
++}
++
+ static void pipe_read(void *opaque)
+ {
+ SimpleSpiceDisplay *ssd = opaque;
+ unsigned char cmd;
+ int len, set_irq = 0;
+ int create_update = 0;
++ int cursor_set = 0;
++ int cursor_move = 0;
++ QXLServerCursorSet cursor_set_data;
++ QXLServerCursorMove cursor_move_data;
+
+ while (1) {
+ cmd = 0;
+@@ -1082,6 +1155,17 @@ static void pipe_read(void *opaque)
+ case QXL_SERVER_CREATE_UPDATE:
+ create_update = 1;
+ break;
++ case QXL_SERVER_CURSOR_SET:
++ if (cursor_set == 1) {
++ cursor_put(cursor_set_data.c);
++ }
++ cursor_set = 1;
++ read_bytes(ssd->pipe[0], &cursor_set_data, sizeof(cursor_set_data));
++ break;
++ case QXL_SERVER_CURSOR_MOVE:
++ cursor_move = 1;
++ read_bytes(ssd->pipe[0], &cursor_move_data, sizeof(cursor_move_data));
++ break;
+ default:
+ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
+ abort();
+@@ -1099,6 +1183,12 @@ static void pipe_read(void *opaque)
+ if (set_irq) {
+ qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd));
+ }
++ if (cursor_move) {
++ qxl_render_cursor_move(ssd, cursor_move_data.x, cursor_move_data.y);
++ }
++ if (cursor_set) {
++ qxl_render_cursor_set(ssd, cursor_set_data.c, cursor_set_data.x, cursor_set_data.y);
++ }
+ }
+
+ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
+diff --git a/hw/qxl.h b/hw/qxl.h
+index 701245f..f4f99ec 100644
+--- a/hw/qxl.h
++++ b/hw/qxl.h
+@@ -93,6 +93,8 @@ typedef struct PCIQXLDevice {
+
+ /* qxl.c */
+ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
++void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y);
++void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y);
+
+ /* qxl-logger.c */
+ void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
+@@ -102,3 +104,5 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
+ void qxl_render_resize(PCIQXLDevice *qxl);
+ void qxl_render_update(PCIQXLDevice *qxl);
+ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
++void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y);
++void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y);
+diff --git a/ui/spice-display.h b/ui/spice-display.h
+index 2be6a34..bbfd689 100644
+--- a/ui/spice-display.h
++++ b/ui/spice-display.h
+@@ -31,11 +31,22 @@
+
+ #define NUM_SURFACES 1024
+
+-/* For commands/requests from server thread to iothread */
++/*
++ * Commands/requests from server thread to iothread.
++ * Note that CREATE_UPDATE is used both with qxl and without it (spice-display)
++ * the others are only used with the qxl device.
++ *
++ * SET_IRQ - just the request is sent (1 byte)
++ * CREATE_UPDATE - jus the request is sent (1 byte)
++ * CURSOR_SET - send QXLServerRequestCursorSet
++ * CURSOR_MOVE - send QXLServerRequestCursorMove
++ */
+ #define QXL_EMPTY_UPDATE ((void *)-1)
+ enum {
+ QXL_SERVER_SET_IRQ = 1,
+ QXL_SERVER_CREATE_UPDATE,
++ QXL_SERVER_CURSOR_SET,
++ QXL_SERVER_CURSOR_MOVE
+ };
+
+ struct SimpleSpiceUpdate;
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
new file mode 100644
index 0000000..0ec25a0
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
@@ -0,0 +1,56 @@
+>From b248befcd93bcd713971b15147fcaa217a3d1bb7 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 21:57:47 +0100
+Subject: [PATCH 05/17] char: Split out tcp socket close code in a separate function
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c | 25 ++++++++++++++++---------
+ 1 files changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index bd4e944..4b57af9 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -1911,6 +1911,21 @@ typedef struct {
+
+ static void tcp_chr_accept(void *opaque);
+
++static void tcp_closed(void *opaque)
++{
++ CharDriverState *chr = opaque;
++ TCPCharDriver *s = chr->opaque;
++
++ s->connected = 0;
++ if (s->listen_fd >= 0) {
++ qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
++ }
++ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
++ closesocket(s->fd);
++ s->fd = -1;
++ qemu_chr_event(chr, CHR_EVENT_CLOSED);
++}
++
+ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+ TCPCharDriver *s = chr->opaque;
+@@ -2061,15 +2076,7 @@ static void tcp_chr_read(void *opaque)
+ len = s->max_size;
+ size = tcp_chr_recv(chr, (void *)buf, len);
+ if (size == 0) {
+- /* connection closed */
+- s->connected = 0;
+- if (s->listen_fd >= 0) {
+- qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
+- }
+- qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+- closesocket(s->fd);
+- s->fd = -1;
+- qemu_chr_event(chr, CHR_EVENT_CLOSED);
++ tcp_closed(chr);
+ } else if (size > 0) {
+ if (s->do_telnetopt)
+ tcp_chr_process_IAC_bytes(chr, s, buf, &size);
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
new file mode 100644
index 0000000..095e7ff
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
@@ -0,0 +1,673 @@
+>From 003cc09f8fc34e7571ebd4a89ea6aa6324a80b54 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 20:31:45 +0100
+Subject: [PATCH 06/19] char: Add a QemuChrHandlers struct to initialise chardev handlers
+
+Instead of passing each handler in the qemu_add_handlers() function,
+create a struct of handlers that can be passed to the function instead.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ gdbstub.c | 9 +++++++--
+ hw/debugcon.c | 2 +-
+ hw/escc.c | 9 +++++++--
+ hw/etraxfs_ser.c | 13 +++++++++----
+ hw/grlib_apbuart.c | 12 +++++++-----
+ hw/ivshmem.c | 28 ++++++++++++++++++++++------
+ hw/mcf_uart.c | 9 +++++++--
+ hw/pl011.c | 9 +++++++--
+ hw/pxa2xx.c | 13 +++++++++----
+ hw/serial.c | 9 +++++++--
+ hw/sh_serial.c | 12 +++++++++---
+ hw/syborg_serial.c | 9 +++++++--
+ hw/usb-serial.c | 9 +++++++--
+ hw/virtio-console.c | 9 +++++++--
+ hw/xen_console.c | 16 +++++++++++-----
+ hw/xilinx_uartlite.c | 11 +++++++++--
+ monitor.c | 18 ++++++++++++++----
+ net/slirp.c | 8 ++++++--
+ qemu-char.c | 30 +++++++++++++++++++++---------
+ qemu-char.h | 13 +++++++++----
+ 20 files changed, 183 insertions(+), 65 deletions(-)
+
+diff --git a/gdbstub.c b/gdbstub.c
+index 14e8b9b..4190ac7 100644
+--- a/gdbstub.c
++++ b/gdbstub.c
+@@ -2634,6 +2634,12 @@ static void gdb_sigterm_handler(int signal)
+ }
+ #endif
+
++static const QemuChrHandlers gdb_handlers = {
++ .fd_can_read = gdb_chr_can_receive,
++ .fd_read = gdb_chr_receive,
++ .fd_event = gdb_chr_event,
++};
++
+ int gdbserver_start(const char *device)
+ {
+ GDBState *s;
+@@ -2663,8 +2669,7 @@ int gdbserver_start(const char *device)
+ if (!chr)
+ return -1;
+
+- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
+- gdb_chr_event, NULL);
++ qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
+ }
+
+ s = gdbserver_state;
+diff --git a/hw/debugcon.c b/hw/debugcon.c
+index 5ee6821..e79a595 100644
+--- a/hw/debugcon.c
++++ b/hw/debugcon.c
+@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
+ exit(1);
+ }
+
+- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
++ qemu_chr_add_handlers(s->chr, NULL, s);
+ }
+
+ static int debugcon_isa_initfn(ISADevice *dev)
+diff --git a/hw/escc.c b/hw/escc.c
+index f6fd919..dfa329a 100644
+--- a/hw/escc.c
++++ b/hw/escc.c
+@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
+ sysbus_mmio_map(s, 0, base);
+ }
+
++static const QemuChrHandlers serial_handlers = {
++ .fd_can_read = serial_can_receive,
++ .fd_read = serial_receive1,
++ .fd_event = serial_event,
++};
++
+ static int escc_init1(SysBusDevice *dev)
+ {
+ SerialState *s = FROM_SYSBUS(SerialState, dev);
+@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev)
+ s->chn[i].chn = 1 - i;
+ s->chn[i].clock = s->frequency / 2;
+ if (s->chn[i].chr) {
+- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+- serial_receive1, serial_event, &s->chn[i]);
++ qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
+ }
+ }
+ s->chn[0].otherchn = &s->chn[1];
+diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
+index 2787ebd..406121c 100644
+--- a/hw/etraxfs_ser.c
++++ b/hw/etraxfs_ser.c
+@@ -190,6 +190,12 @@ static void serial_event(void *opaque, int event)
+
+ }
+
++static const QemuChrHandlers serial_handlers = {
++ .fd_can_read = serial_can_receive,
++ .fd_read = serial_receive,
++ .fd_event = serial_event,
++};
++
+ static int etraxfs_ser_init(SysBusDevice *dev)
+ {
+ struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
+@@ -204,10 +210,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
+ DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
+ s->chr = qdev_init_chardev(&dev->qdev);
+- if (s->chr)
+- qemu_chr_add_handlers(s->chr,
+- serial_can_receive, serial_receive,
+- serial_event, s);
++ if (s->chr) {
++ qemu_chr_add_handlers(s->chr, &serial_handlers, s);
++ }
+ return 0;
+ }
+
+diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
+index 101b150..40d6968 100644
+--- a/hw/grlib_apbuart.c
++++ b/hw/grlib_apbuart.c
+@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
+ NULL, NULL, grlib_apbuart_writel,
+ };
+
++static const QemuChrHandlers grlib_handlers = {
++ .fd_can_read = grlib_apbuart_can_receive,
++ .fd_read = grlib_apbuart_receive,
++ .fd_event = grlib_apbuart_event,
++};
++
+ static int grlib_apbuart_init(SysBusDevice *dev)
+ {
+ UART *uart = FROM_SYSBUS(typeof(*uart), dev);
+ int uart_regs = 0;
+
+- qemu_chr_add_handlers(uart->chr,
+- grlib_apbuart_can_receive,
+- grlib_apbuart_receive,
+- grlib_apbuart_event,
+- uart);
++ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
+
+ sysbus_init_irq(dev, &uart->irq);
+
+diff --git a/hw/ivshmem.c b/hw/ivshmem.c
+index 7b19a81..ef8e5ce 100644
+--- a/hw/ivshmem.c
++++ b/hw/ivshmem.c
+@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
+ msix_notify(pdev, entry->vector);
+ }
+
++static const QemuChrHandlers ivshmem_handlers = {
++ .fd_can_read = ivshmem_can_receive,
++ .fd_read = ivshmem_receive,
++ .fd_event = ivshmem_event,
++};
++
++static const QemuChrHandlers ivshmem_msi_handlers = {
++ .fd_can_read = ivshmem_can_receive,
++ .fd_read = fake_irqfd,
++ .fd_event = ivshmem_event,
++};
++
+ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
+ int vector)
+ {
+@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
+ s->eventfd_table[vector].pdev = &s->dev;
+ s->eventfd_table[vector].vector = vector;
+
+- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
+- ivshmem_event, &s->eventfd_table[vector]);
++ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
++ &s->eventfd_table[vector]);
+ } else {
+- qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
+- ivshmem_event, s);
++ qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
+ }
+
+ return chr;
+@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
+ return 0;
+ }
+
++static const QemuChrHandlers ivshmem_server_handlers = {
++ .fd_can_read = ivshmem_can_receive,
++ .fd_read = ivshmem_read,
++ .fd_event = ivshmem_event,
++};
++
+ static int pci_ivshmem_init(PCIDevice *dev)
+ {
+ IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
+@@ -754,8 +771,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
+
+ s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *));
+
+- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
+- ivshmem_event, s);
++ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
+ } else {
+ /* just map the file immediately, we're not using a server */
+ int fd;
+diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
+index db57096..9928c11 100644
+--- a/hw/mcf_uart.c
++++ b/hw/mcf_uart.c
+@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
+ mcf_uart_push_byte(s, buf[0]);
+ }
+
++static const QemuChrHandlers mcf_uart_handlers = {
++ .fd_can_read = mcf_uart_can_receive,
++ .fd_read = mcf_uart_receive,
++ .fd_event = mcf_uart_event,
++};
++
+ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
+ {
+ mcf_uart_state *s;
+@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
+ s->chr = chr;
+ s->irq = irq;
+ if (chr) {
+- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
+- mcf_uart_event, s);
++ qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
+ }
+ mcf_uart_reset(s);
+ return s;
+diff --git a/hw/pl011.c b/hw/pl011.c
+index 77f0dbf..d93c655 100644
+--- a/hw/pl011.c
++++ b/hw/pl011.c
+@@ -286,6 +286,12 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id)
+ return 0;
+ }
+
++static const QemuChrHandlers pl011_handlers = {
++ .fd_can_read = pl011_can_receive,
++ .fd_read = pl011_receive,
++ .fd_event = pl011_event,
++};
++
+ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
+ {
+ int iomemtype;
+@@ -304,8 +310,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
+ s->cr = 0x300;
+ s->flags = 0x90;
+ if (s->chr) {
+- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
+- pl011_event, s);
++ qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
+ }
+ register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
+ return 0;
+diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
+index d966846..d7ebf33 100644
+--- a/hw/pxa2xx.c
++++ b/hw/pxa2xx.c
+@@ -1995,6 +1995,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
+ return 0;
+ }
+
++static const QemuChrHandlers pxa2xx_handlers = {
++ .fd_can_read = pxa2xx_fir_is_empty,
++ .fd_read = pxa2xx_fir_rx,
++ .fd_event = pxa2xx_fir_event,
++};
++
+ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
+ qemu_irq irq, PXA2xxDMAState *dma,
+ CharDriverState *chr)
+@@ -2013,10 +2019,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
+ pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
+ cpu_register_physical_memory(base, 0x1000, iomemtype);
+
+- if (chr)
+- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
+- pxa2xx_fir_rx, pxa2xx_fir_event, s);
+-
++ if (chr) {
++ qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
++ }
+ register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+ pxa2xx_fir_load, s);
+
+diff --git a/hw/serial.c b/hw/serial.c
+index 2c4af61..65265e2 100644
+--- a/hw/serial.c
++++ b/hw/serial.c
+@@ -727,6 +727,12 @@ static void serial_reset(void *opaque)
+ qemu_irq_lower(s->irq);
+ }
+
++static const QemuChrHandlers serial_handlers = {
++ .fd_can_read = serial_can_receive1,
++ .fd_read = serial_receive1,
++ .fd_event = serial_event,
++};
++
+ static void serial_init_core(SerialState *s)
+ {
+ if (!s->chr) {
+@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s)
+
+ qemu_register_reset(serial_reset, s);
+
+- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
+- serial_event, s);
++ qemu_chr_add_handlers(s->chr, &serial_handlers, s);
+ }
+
+ /* Change the main reference oscillator frequency. */
+diff --git a/hw/sh_serial.c b/hw/sh_serial.c
+index 191f4a6..8b6460d 100644
+--- a/hw/sh_serial.c
++++ b/hw/sh_serial.c
+@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
+ &sh_serial_write,
+ };
+
++static const QemuChrHandlers sh_serial_handlers = {
++ .fd_can_read = sh_serial_can_receive1,
++ .fd_read = sh_serial_receive1,
++ .fd_event = sh_serial_event,
++};
++
+ void sh_serial_init (target_phys_addr_t base, int feat,
+ uint32_t freq, CharDriverState *chr,
+ qemu_irq eri_source,
+@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
+
+ s->chr = chr;
+
+- if (chr)
+- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
+- sh_serial_event, s);
++ if (chr) {
++ qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
++ }
+
+ s->eri = eri_source;
+ s->rxi = rxi_source;
+diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
+index 34ce076..124b636 100644
+--- a/hw/syborg_serial.c
++++ b/hw/syborg_serial.c
+@@ -315,6 +315,12 @@ static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
+ return 0;
+ }
+
++static const QemuChrHandlers syborg_serial_handlers = {
++ .fd_can_read = syborg_serial_can_receive,
++ .fd_read = syborg_serial_receive,
++ .fd_event = syborg_serial_event,
++};
++
+ static int syborg_serial_init(SysBusDevice *dev)
+ {
+ SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
+@@ -327,8 +333,7 @@ static int syborg_serial_init(SysBusDevice *dev)
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+ s->chr = qdev_init_chardev(&dev->qdev);
+ if (s->chr) {
+- qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
+- syborg_serial_receive, syborg_serial_event, s);
++ qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s);
+ }
+ if (s->fifo_size <= 0) {
+ fprintf(stderr, "syborg_serial: fifo too small\n");
+diff --git a/hw/usb-serial.c b/hw/usb-serial.c
+index 6763d52..2435d9d 100644
+--- a/hw/usb-serial.c
++++ b/hw/usb-serial.c
+@@ -475,6 +475,12 @@ static void usb_serial_event(void *opaque, int event)
+ }
+ }
+
++static const QemuChrHandlers usb_serial_handlers = {
++ .fd_can_read = usb_serial_can_read,
++ .fd_read = usb_serial_read,
++ .fd_event = usb_serial_event,
++};
++
+ static int usb_serial_initfn(USBDevice *dev)
+ {
+ USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+@@ -486,8 +492,7 @@ static int usb_serial_initfn(USBDevice *dev)
+ return -1;
+ }
+
+- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
+- usb_serial_event, s);
++ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
+ usb_serial_handle_reset(dev);
+ return 0;
+ }
+diff --git a/hw/virtio-console.c b/hw/virtio-console.c
+index 62624ec..22cf28c 100644
+--- a/hw/virtio-console.c
++++ b/hw/virtio-console.c
+@@ -57,13 +57,18 @@ static void chr_event(void *opaque, int event)
+ }
+ }
+
++static const QemuChrHandlers chr_handlers = {
++ .fd_can_read = chr_can_read,
++ .fd_read = chr_read,
++ .fd_event = chr_event,
++};
++
+ static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
+ {
+ vcon->port.info = dev->info;
+
+ if (vcon->chr) {
+- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
+- vcon);
++ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
+ vcon->port.info->have_data = flush_buf;
+ }
+ return 0;
+diff --git a/hw/xen_console.c b/hw/xen_console.c
+index d2261f4..8327e4e 100644
+--- a/hw/xen_console.c
++++ b/hw/xen_console.c
+@@ -202,6 +202,11 @@ static int con_init(struct XenDevice *xendev)
+ return 0;
+ }
+
++static const QemuChrHandlers xencons_handlers = {
++ .fd_can_read = xencons_can_receive,
++ .fd_read = xencons_receive,
++};
++
+ static int con_connect(struct XenDevice *xendev)
+ {
+ struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
+@@ -222,9 +227,9 @@ static int con_connect(struct XenDevice *xendev)
+ return -1;
+
+ xen_be_bind_evtchn(&con->xendev);
+- if (con->chr)
+- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
+- NULL, con);
++ if (con->chr) {
++ qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
++ }
+
+ xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
+ con->ring_ref,
+@@ -238,8 +243,9 @@ static void con_disconnect(struct XenDevice *xendev)
+ {
+ struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
+
+- if (con->chr)
+- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
++ if (con->chr) {
++ qemu_chr_add_handlers(con->chr, NULL, NULL);
++ }
+ xen_be_unbind_evtchn(&con->xendev);
+
+ if (con->sring) {
+diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
+index 9b94e98..1845577 100644
+--- a/hw/xilinx_uartlite.c
++++ b/hw/xilinx_uartlite.c
+@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event)
+
+ }
+
++static const QemuChrHandlers uart_handlers = {
++ .fd_can_read = uart_can_rx,
++ .fd_read = uart_rx,
++ .fd_event = uart_event,
++};
++
+ static int xilinx_uartlite_init(SysBusDevice *dev)
+ {
+ struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
+@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
+ sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
+
+ s->chr = qdev_init_chardev(&dev->qdev);
+- if (s->chr)
+- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
++ if (s->chr) {
++ qemu_chr_add_handlers(s->chr, &uart_handlers, s);
++ }
+ return 0;
+ }
+
+diff --git a/monitor.c b/monitor.c
+index 096d42b..a00a233 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -5179,6 +5179,18 @@ static void monitor_event(void *opaque, int event)
+ * End:
+ */
+
++static const QemuChrHandlers monitor_handlers = {
++ .fd_can_read = monitor_can_read,
++ .fd_read = monitor_read,
++ .fd_event = monitor_event,
++};
++
++static const QemuChrHandlers monitor_control_handlers = {
++ .fd_can_read = monitor_can_read,
++ .fd_read = monitor_control_read,
++ .fd_event = monitor_control_event,
++};
++
+ void monitor_init(CharDriverState *chr, int flags)
+ {
+ static int is_first_init = 1;
+@@ -5201,12 +5213,10 @@ void monitor_init(CharDriverState *chr, int flags)
+ if (monitor_ctrl_mode(mon)) {
+ mon->mc = qemu_mallocz(sizeof(MonitorControl));
+ /* Control mode requires special handlers */
+- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
+- monitor_control_event, mon);
++ qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
+ qemu_chr_set_echo(chr, true);
+ } else {
+- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
+- monitor_event, mon);
++ qemu_chr_add_handlers(chr, &monitor_handlers, mon);
+ }
+
+ QLIST_INSERT_HEAD(&mon_list, mon, entry);
+diff --git a/net/slirp.c b/net/slirp.c
+index b41c60a..437be46 100644
+--- a/net/slirp.c
++++ b/net/slirp.c
+@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
+ slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
+ }
+
++static const QemuChrHandlers guestfwd_handlers = {
++ .fd_can_read = guestfwd_can_read,
++ .fd_read = guestfwd_read,
++};
++
+ static int slirp_guestfwd(SlirpState *s, const char *config_str,
+ int legacy_format)
+ {
+@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
+ fwd->port = port;
+ fwd->slirp = s->slirp;
+
+- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+- NULL, fwd);
++ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
+ return 0;
+
+ fail_syntax:
+diff --git a/qemu-char.c b/qemu-char.c
+index 4b57af9..3a31d8b 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -191,15 +191,22 @@ void qemu_chr_send_event(CharDriverState *s, int event)
+ s->chr_send_event(s, event);
+ }
+
++static const QemuChrHandlers null_handlers = {
++ /* All handlers are initialised to NULL */
++};
++
+ void qemu_chr_add_handlers(CharDriverState *s,
+- IOCanReadHandler *fd_can_read,
+- IOReadHandler *fd_read,
+- IOEventHandler *fd_event,
+- void *opaque)
+-{
+- s->chr_can_read = fd_can_read;
+- s->chr_read = fd_read;
+- s->chr_event = fd_event;
++ const QemuChrHandlers *handlers, void *opaque)
++{
++ if (!s) {
++ return;
++ }
++ if (!handlers) {
++ handlers = &null_handlers;
++ }
++ s->chr_can_read = handlers->fd_can_read;
++ s->chr_read = handlers->fd_read;
++ s->chr_event = handlers->fd_event;
+ s->handler_opaque = opaque;
+ if (s->chr_update_read_handler)
+ s->chr_update_read_handler(s);
+@@ -437,6 +444,12 @@ static void mux_chr_event(void *opaque, int event)
+ mux_chr_send_event(d, i, event);
+ }
+
++static const QemuChrHandlers mux_chr_handlers = {
++ .fd_can_read = mux_chr_can_read,
++ .fd_read = mux_chr_read,
++ .fd_event = mux_chr_event,
++};
++
+ static void mux_chr_update_read_handler(CharDriverState *chr)
+ {
+ MuxDriver *d = chr->opaque;
+@@ -451,8 +464,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
+ d->chr_event[d->mux_cnt] = chr->chr_event;
+ /* Fix up the real driver with mux routines */
+ if (d->mux_cnt == 0) {
+- qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
+- mux_chr_event, chr);
++ qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
+ }
+ if (d->focus != -1) {
+ mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
+diff --git a/qemu-char.h b/qemu-char.h
+index 56d9954..7a1924c 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -1,6 +1,7 @@
+ #ifndef QEMU_CHAR_H
+ #define QEMU_CHAR_H
+
++#include <stdbool.h>
+ #include "qemu-common.h"
+ #include "qemu-queue.h"
+ #include "qemu-option.h"
+@@ -73,6 +74,13 @@ struct CharDriverState {
+ QTAILQ_ENTRY(CharDriverState) next;
+ };
+
++typedef struct QemuChrHandlers {
++ IOCanReadHandler *fd_can_read;
++ IOReadHandler *fd_read;
++ IOHandler *fd_write_unblocked;
++ IOEventHandler *fd_event;
++} QemuChrHandlers;
++
+ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
+ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
+ void (*init)(struct CharDriverState *s));
+@@ -83,10 +91,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
+ GCC_FMT_ATTR(2, 3);
+ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
+ void qemu_chr_send_event(CharDriverState *s, int event);
+-void qemu_chr_add_handlers(CharDriverState *s,
+- IOCanReadHandler *fd_can_read,
+- IOReadHandler *fd_read,
+- IOEventHandler *fd_event,
++void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
+ void *opaque);
+ int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
+ void qemu_chr_generic_open(CharDriverState *s);
+--
+1.7.4.1
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
new file mode 100644
index 0000000..336c582
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
@@ -0,0 +1,76 @@
+>From da7e6cd863ed0cffe885cd2d3639f92c82baf6e2 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 20:32:58 +0100
+Subject: [PATCH 07/17] iohandlers: Add enable/disable_write_fd_handler() functions
+
+These will be used to provide a cleaner API for the nonblocking case.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.h | 3 +++
+ vl.c | 35 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 38 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.h b/qemu-char.h
+index 7a1924c..185377c 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -116,6 +116,9 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr);
+
+ /* async I/O support */
+
++void enable_write_fd_handler(int fd, IOHandler *fd_write);
++void disable_write_fd_handler(int fd);
++
+ int qemu_set_fd_handler2(int fd,
+ IOCanReadHandler *fd_read_poll,
+ IOHandler *fd_read,
+diff --git a/vl.c b/vl.c
+index 85c36e3..95f51cb 100644
+--- a/vl.c
++++ b/vl.c
+@@ -1044,6 +1044,41 @@ typedef struct IOHandlerRecord {
+ static QLIST_HEAD(, IOHandlerRecord) io_handlers =
+ QLIST_HEAD_INITIALIZER(io_handlers);
+
++static IOHandlerRecord *find_iohandler(int fd)
++{
++ IOHandlerRecord *ioh;
++
++ QLIST_FOREACH(ioh, &io_handlers, next) {
++ if (ioh->fd == fd) {
++ return ioh;
++ }
++ }
++ return NULL;
++}
++
++void enable_write_fd_handler(int fd, IOHandler *fd_write)
++{
++ IOHandlerRecord *ioh;
++
++ ioh = find_iohandler(fd);
++ if (!ioh) {
++ return;
++ }
++
++ ioh->fd_write = fd_write;
++}
++
++void disable_write_fd_handler(int fd)
++{
++ IOHandlerRecord *ioh;
++
++ ioh = find_iohandler(fd);
++ if (!ioh) {
++ return;
++ }
++
++ ioh->fd_write = NULL;
++}
+
+ /* XXX: fd_read_poll should be suppressed, but an API change is
+ necessary in the character devices to suppress fd_can_read(). */
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch
new file mode 100644
index 0000000..ab3eb1f
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch
@@ -0,0 +1,62 @@
+>From daf37480ffe37b3e7a781ff010beb4fa89821c29 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 21:41:42 +0100
+Subject: [PATCH 08/17] char: Add framework for a 'write unblocked' callback
+
+The char layer can let users know that the driver will block on further
+input. For users interested in not blocking, they can assign a function
+pointer that will be called back when the driver becomes writable. This
+patch just adds the function pointers to the CharDriverState structure,
+future patches will enable the nonblocking and callback functionality.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c | 3 +++
+ qemu-char.h | 5 +++++
+ 2 files changed, 8 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 3a31d8b..ce76411 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -206,11 +206,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
+ }
+ s->chr_can_read = handlers->fd_can_read;
+ s->chr_read = handlers->fd_read;
++ s->chr_write_unblocked = handlers->fd_write_unblocked;
+ s->chr_event = handlers->fd_event;
+ s->handler_opaque = opaque;
+ if (s->chr_update_read_handler)
+ s->chr_update_read_handler(s);
+
++ s->write_blocked = false;
++
+ /* We're connecting to an already opened device, so let's make sure we
+ also get the open event */
+ if (s->opened) {
+diff --git a/qemu-char.h b/qemu-char.h
+index 185377c..bf06da0 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -61,6 +61,9 @@ struct CharDriverState {
+ IOEventHandler *chr_event;
+ IOCanReadHandler *chr_can_read;
+ IOReadHandler *chr_read;
++ IOHandler *chr_write_unblocked;
++ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
++ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
+ void *handler_opaque;
+ void (*chr_send_event)(struct CharDriverState *chr, int event);
+ void (*chr_close)(struct CharDriverState *chr);
+@@ -71,6 +74,8 @@ struct CharDriverState {
+ char *label;
+ char *filename;
+ int opened;
++ /* Are we in a blocked state? */
++ bool write_blocked;
+ QTAILQ_ENTRY(CharDriverState) next;
+ };
+
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
new file mode 100644
index 0000000..ccf98ad
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
@@ -0,0 +1,197 @@
+>From 8b73193a8584da4e93bccd93fe6f0b8f1a1612b3 Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:00:27 +0100
+Subject: [PATCH 09/17] char: Update send_all() to handle nonblocking chardev write requests
+
+The send_all function is modified to return to the caller in case the
+driver cannot handle any more data. It returns -EAGAIN or
+WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This
+is only done when the caller sets a callback function handler indicating
+it's not interested in blocking till the driver has written out all the
+data.
+
+Currently there's no driver or caller that supports this. Future
+commits will add such capability.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ net/socket.c | 4 +-
+ qemu-char.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ qemu_socket.h | 2 +-
+ 3 files changed, 76 insertions(+), 9 deletions(-)
+
+diff --git a/net/socket.c b/net/socket.c
+index 3182b37..5dedd78 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
+ uint32_t len;
+ len = htonl(size);
+
+- send_all(s->fd, (const uint8_t *)&len, sizeof(len));
+- return send_all(s->fd, buf, size);
++ send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len));
++ return send_all(NULL, s->fd, buf, size);
+ }
+
+ static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
+diff --git a/qemu-char.c b/qemu-char.c
+index ce76411..eed61d6 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -500,7 +500,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+
+
+ #ifdef _WIN32
+-int send_all(int fd, const void *buf, int len1)
++static int do_send(int fd, const void *buf, int len1, bool nonblock)
+ {
+ int ret, len;
+
+@@ -508,9 +508,14 @@ int send_all(int fd, const void *buf, int len1)
+ while (len > 0) {
+ ret = send(fd, buf, len, 0);
+ if (ret < 0) {
++ if (nonblock && len1 - len) {
++ return len1 - len;
++ }
+ errno = WSAGetLastError();
+ if (errno != WSAEWOULDBLOCK) {
+ return -1;
++ } else if (errno == WSAEWOULDBLOCK && nonblock) {
++ return WSAEWOULDBLOCK;
+ }
+ } else if (ret == 0) {
+ break;
+@@ -524,7 +529,7 @@ int send_all(int fd, const void *buf, int len1)
+
+ #else
+
+-int send_all(int fd, const void *_buf, int len1)
++static int do_send(int fd, const void *_buf, int len1, bool nonblock)
+ {
+ int ret, len;
+ const uint8_t *buf = _buf;
+@@ -533,8 +538,15 @@ int send_all(int fd, const void *_buf, int len1)
+ while (len > 0) {
+ ret = write(fd, buf, len);
+ if (ret < 0) {
+- if (errno != EINTR && errno != EAGAIN)
++ if (nonblock && len1 - len) {
++ return len1 - len;
++ }
++ if (errno == EAGAIN && nonblock) {
++ return -EAGAIN;
++ }
++ if (errno != EINTR && errno != EAGAIN) {
+ return -1;
++ }
+ } else if (ret == 0) {
+ break;
+ } else {
+@@ -546,6 +558,55 @@ int send_all(int fd, const void *_buf, int len1)
+ }
+ #endif /* !_WIN32 */
+
++int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
++{
++ int ret, eagain_errno;
++ bool nonblock;
++
++ if (chr && chr->write_blocked) {
++ /*
++ * We don't handle this situation: the caller should not send
++ * us data while we're blocked.
++ *
++ * We could buffer this data here but that'll only encourage
++ * bad behaviour on part of the callers.
++ *
++ * Also, the data already in fd's buffers isn't easily
++ * migratable. If we want full migration support, all the
++ * data landing here needs to be buffered and on migration,
++ * anything that's unsent needs to be transferred to the
++ * dest. machine (which again isn't a very good way of solving
++ * the problem, as the src may become writable just during
++ * migration and the reader could receive some data twice,
++ * essentially corrupting the data).
++ */
++ abort();
++ }
++
++ nonblock = false;
++ /*
++ * Ensure the char backend is able to receive and handle the
++ * 'write unblocked' event before we turn on nonblock support.
++ */
++ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
++ nonblock = true;
++ }
++ ret = do_send(fd, _buf, len1, nonblock);
++
++#ifdef _WIN32
++ eagain_errno = WSAEWOULDBLOCK;
++#else
++ eagain_errno = -EAGAIN;
++#endif
++
++ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
++ /* Update fd handler to wake up when chr becomes writable */
++ chr->chr_enable_write_fd_handler(chr);
++ chr->write_blocked = true;
++ }
++ return ret;
++}
++
+ #ifndef _WIN32
+
+ typedef struct {
+@@ -559,7 +620,7 @@ static int stdio_nb_clients = 0;
+ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+ FDCharDriver *s = chr->opaque;
+- return send_all(s->fd_out, buf, len);
++ return send_all(chr, s->fd_out, buf, len);
+ }
+
+ static int fd_chr_read_poll(void *opaque)
+@@ -875,7 +936,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ pty_chr_update_read_handler(chr);
+ return 0;
+ }
+- return send_all(s->fd, buf, len);
++ return send_all(chr, s->fd, buf, len);
+ }
+
+ static int pty_chr_read_poll(void *opaque)
+@@ -1944,8 +2005,14 @@ static void tcp_closed(void *opaque)
+ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+ TCPCharDriver *s = chr->opaque;
++
+ if (s->connected) {
+- return send_all(s->fd, buf, len);
++ int ret;
++
++ ret = send_all(chr, s->fd, buf, len);
++ if (ret == -1 && errno == EPIPE) {
++ tcp_closed(chr);
++ }
+ } else {
+ /* XXX: indicate an error ? */
+ return len;
+diff --git a/qemu_socket.h b/qemu_socket.h
+index 897a8ae..97dd24a 100644
+--- a/qemu_socket.h
++++ b/qemu_socket.h
+@@ -36,7 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
+ int qemu_socket(int domain, int type, int protocol);
+ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+ void socket_set_nonblock(int fd);
+-int send_all(int fd, const void *buf, int len1);
++int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
+
+ /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
+ int inet_listen_opts(QemuOpts *opts, int port_offset);
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
new file mode 100644
index 0000000..f08d700
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
@@ -0,0 +1,80 @@
+>From 7d8cbead9454da6dbfdc050c6828faae39621a1b Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:02:47 +0100
+Subject: [PATCH 10/17] char: Equip the unix/tcp backend to handle nonblocking writes#
+
+Now that the infrastructure is in place to return -EAGAIN to callers,
+individual char drivers can set their update_fd_handlers() function to
+set or remove an fd's write handler. This handler checks if the driver
+became writable.
+
+A generic callback routine is used for unblocking writes and letting
+users of chardevs know that a driver became writable again.
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 files changed, 34 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index eed61d6..7517f64 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -107,6 +107,19 @@
+ static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
+ QTAILQ_HEAD_INITIALIZER(chardevs);
+
++/*
++ * Generic routine that gets called when chardev becomes writable.
++ * Lets chardev user know it's OK to send more data.
++ */
++static void char_write_unblocked(void *opaque)
++{
++ CharDriverState *chr = opaque;
++
++ chr->write_blocked = false;
++ chr->chr_disable_write_fd_handler(chr);
++ chr->chr_write_unblocked(chr->handler_opaque);
++}
++
+ static void qemu_chr_event(CharDriverState *s, int event)
+ {
+ /* Keep track if the char device is open */
+@@ -2261,6 +2274,25 @@ static void tcp_chr_close(CharDriverState *chr)
+ qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ }
+
++static void tcp_enable_write_fd_handler(CharDriverState *chr)
++{
++ TCPCharDriver *s = chr->opaque;
++
++ /*
++ * This function is called only after tcp_chr_connect() is called
++ * (either in 'server' mode or client mode. So we're sure of
++ * s->fd being initialised.
++ */
++ enable_write_fd_handler(s->fd, char_write_unblocked);
++}
++
++static void tcp_disable_write_fd_handler(CharDriverState *chr)
++{
++ TCPCharDriver *s = chr->opaque;
++
++ disable_write_fd_handler(s->fd);
++}
++
+ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
+ {
+ CharDriverState *chr = NULL;
+@@ -2313,6 +2345,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
+ chr->chr_write = tcp_chr_write;
+ chr->chr_close = tcp_chr_close;
+ chr->get_msgfd = tcp_get_msgfd;
++ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
++ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
+
+ if (is_listen) {
+ s->listen_fd = fd;
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch
new file mode 100644
index 0000000..78f906a
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch
@@ -0,0 +1,56 @@
+>From 473be206466567646e3377b8eb64e25ffc2b3afe Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:05:10 +0100
+Subject: [PATCH 11/17] char: Throttle when host connection is down#
+
+When the host-side connection goes down, throttle the virtio-serial bus
+and later unthrottle when a connection gets established. This helps
+prevent any lost IO (guest->host) while the host connection was down.
+
+Bugzilla: 621484
+
+This commit actually helps the bug mentioned above as no writes will now
+get lost because of the throttling done here. With just the patches
+sent earlier for that bug, one write will end up getting lost in the
+worst case (host d/c, guest write, host connect).
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ qemu-char.c | 14 ++++++++++++++
+ 1 files changed, 14 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 7517f64..2ef972f 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -141,6 +141,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
+ {
+ CharDriverState *s = opaque;
+ qemu_chr_event(s, CHR_EVENT_OPENED);
++ if (s->write_blocked) {
++ char_write_unblocked(s);
++ }
+ qemu_bh_delete(s->bh);
+ s->bh = NULL;
+ }
+@@ -2025,6 +2028,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ ret = send_all(chr, s->fd, buf, len);
+ if (ret == -1 && errno == EPIPE) {
+ tcp_closed(chr);
++
++ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
++ /*
++ * Since we haven't written out anything, let's say
++ * we're throttled. This will prevent any output from
++ * the guest getting lost if host-side chardev goes
++ * down. Unthrottle when we re-connect.
++ */
++ chr->write_blocked = true;
++ return 0;
++ }
+ }
+ } else {
+ /* XXX: indicate an error ? */
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch
new file mode 100644
index 0000000..90f7629
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch
@@ -0,0 +1,48 @@
+>From 94e8b44e4fdfbf312e54b78ca7bbb95271cc83ae Mon Sep 17 00:00:00 2001
+From: Amit Shah <amit.shah@redhat.com>
+Date: Mon, 21 Mar 2011 22:06:41 +0100
+Subject: [PATCH 12/17] virtio-console: Enable port throttling when chardev is slow to consume data
+
+When a chardev indicates it can't accept more data, we tell the
+virtio-serial code to stop sending us any more data till we tell
+otherwise. This helps in guests continuing to run normally while the vq
+keeps getting full and eventually the guest stops queueing more data.
+As soon as the chardev indicates it can accept more data, start pushing!
+
+Signed-off-by: Amit Shah <amit.shah@redhat.com>
+---
+ hw/virtio-console.c | 11 +++++++++++
+ 1 files changed, 11 insertions(+), 0 deletions(-)
+
+diff --git a/hw/virtio-console.c b/hw/virtio-console.c
+index 22cf28c..eecbdf7 100644
+--- a/hw/virtio-console.c
++++ b/hw/virtio-console.c
+@@ -18,6 +18,16 @@ typedef struct VirtConsole {
+ CharDriverState *chr;
+ } VirtConsole;
+
++/*
++ * Callback function that's called from chardevs when backend becomes
++ * writable.
++ */
++static void chr_write_unblocked(void *opaque)
++{
++ VirtConsole *vcon = opaque;
++
++ virtio_serial_throttle_port(&vcon->port, false);
++}
+
+ /* Callback function that's called when the guest sends us data */
+ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
+@@ -61,6 +71,7 @@ static const QemuChrHandlers chr_handlers = {
+ .fd_can_read = chr_can_read,
+ .fd_read = chr_read,
+ .fd_event = chr_event,
++ .fd_write_unblocked = chr_write_unblocked,
+ };
+
+ static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch
new file mode 100644
index 0000000..34cb283
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch
@@ -0,0 +1,133 @@
+>From 06ad256d2939aea4086428dcb5e5e7d5f86eb335 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Tue, 22 Mar 2011 12:27:59 +0200
+Subject: [PATCH 13/17] spice-qemu-char.c: add throttling
+
+BZ: 672191
+
+upstream: not submitted (explained below)
+
+Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
+1. spice-server: reds.c: read_from_vdi_port
+2. qemu: spice-qemu-char.c: vmc_read
+3. chr_write_unblocked
+ (calls virtio_serial_throttle_port(port, false))
+4. qemu: virtio ...
+5. qemu: spice-qemu-char.c: spice_chr_write
+6. qemu: spice-qemu-char.c: wakeup (calls into spice-server)
+7. spice-server: ...
+8. qemu: spice-qemu-char.c: vmc_read
+
+Instead, in vmc_read if we were throttled and we are just about to return
+all the bytes we will set a timer to be triggered immediately to call
+chr_write_unblocked. Then we return after 2 above, and 3 is called from the
+timer callback. This also means we can later remove some ugly recursion protection
+from spice-server.
+
+The other tricky point in this patch is not returning the leftover chunk twice.
+When we throttle, by definition we have data that spice server didn't consume.
+It is being kept by virtio-serial, and by us. The next vmc_read callback needs
+to not return it, but just do unthrottling. Then virtio will give us the remaining
+chunk as usual in spice_chr_write, and we will pass it to spice server in the
+next vmc_read.
+
+This patch relies on Amit's series to expose throttling to chardev's, which
+was not accepted upstream, and will not be accepted upstream until the mainloop
+is reworked to use glib.
+---
+ spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++----
+ 1 files changed, 35 insertions(+), 4 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index 517f337..91467d5 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -1,4 +1,6 @@
+ #include "config-host.h"
++#include "qemu-common.h"
++#include "qemu-timer.h"
+ #include "trace.h"
+ #include "ui/qemu-spice.h"
+ #include <spice.h>
+@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
+ uint8_t *datapos;
+ ssize_t bufsize, datalen;
+ uint32_t debug;
++ QEMUTimer *unblock_timer;
+ } SpiceCharDriver;
+
+ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+@@ -51,6 +54,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+ return out;
+ }
+
++static void spice_chr_unblock(void *opaque)
++{
++ SpiceCharDriver *scd = opaque;
++
++ if (scd->chr->chr_write_unblocked == NULL) {
++ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
++ return;
++ }
++ scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
++}
++
+ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+ {
+ SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+@@ -62,9 +76,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+ scd->datapos += bytes;
+ scd->datalen -= bytes;
+ assert(scd->datalen >= 0);
+- if (scd->datalen == 0) {
+- scd->datapos = 0;
+- }
++ }
++ if (scd->datalen == 0 && scd->chr->write_blocked) {
++ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
++ scd->chr->write_blocked = false;
++ /*
++ * set a timer instead of calling scd->chr->chr_write_unblocked directly,
++ * because that will call back into spice_chr_write (see
++ * virtio-console.c:chr_write_unblocked), which is unwanted.
++ */
++ qemu_mod_timer(scd->unblock_timer, 0);
+ }
+ trace_spice_vmc_read(bytes, len);
+ return bytes;
+@@ -107,6 +128,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
+ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+ SpiceCharDriver *s = chr->opaque;
++ int read_bytes;
+
+ dprintf(s, 2, "%s: %d\n", __func__, len);
+ vmc_register_interface(s);
+@@ -119,7 +141,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ s->datapos = s->buffer;
+ s->datalen = len;
+ spice_server_char_device_wakeup(&s->sin);
+- return len;
++ read_bytes = len - s->datalen;
++ if (read_bytes != len) {
++ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
++ read_bytes, len, s->bufsize);
++ s->chr->write_blocked = true;
++ /* We'll get passed in the unconsumed data with the next call */
++ s->datalen = 0;
++ }
++ return read_bytes;
+ }
+
+ static void spice_chr_close(struct CharDriverState *chr)
+@@ -183,6 +213,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+ chr->opaque = s;
+ chr->chr_write = spice_chr_write;
+ chr->chr_close = spice_chr_close;
++ s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s);
+
+ qemu_chr_generic_open(chr);
+
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch
new file mode 100644
index 0000000..2f56ce6
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch
@@ -0,0 +1,71 @@
+>From 6ce8a141a37387a5138d0361cbe92885130010fe Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy@redhat.com>
+Date: Tue, 22 Mar 2011 12:28:00 +0200
+Subject: [PATCH 14/17] spice-qemu-char.c: remove intermediate buffer
+
+BZ: 672191
+upstream: not submitted (explained below)
+
+virtio-serial's buffer is valid when it calls us, and we don't
+access it otherwise: vmc_read is only called in response to wakeup,
+or else we set datalen=0 and throttle. Then vmc_read is called back,
+we return 0 (not accessing the buffer) and set the timer to unthrottle.
+
+Also make datalen int and not ssize_t (to fit spice_chr_write signature).
+
+This relied on the previous patch that introduces throttling, which
+can't go upstream right now as explained in that patch.
+---
+ spice-qemu-char.c | 18 ++++++------------
+ 1 files changed, 6 insertions(+), 12 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index 91467d5..ed7851e 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
+ SpiceCharDeviceInstance sin;
+ char *subtype;
+ bool active;
+- uint8_t *buffer;
+- uint8_t *datapos;
+- ssize_t bufsize, datalen;
++ const uint8_t *datapos;
++ int datalen;
+ uint32_t debug;
+ QEMUTimer *unblock_timer;
+ } SpiceCharDriver;
+@@ -70,7 +69,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+ SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+ int bytes = MIN(len, scd->datalen);
+
+- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
++ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
+ if (bytes > 0) {
+ memcpy(buf, scd->datapos, bytes);
+ scd->datapos += bytes;
+@@ -133,18 +132,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+ dprintf(s, 2, "%s: %d\n", __func__, len);
+ vmc_register_interface(s);
+ assert(s->datalen == 0);
+- if (s->bufsize < len) {
+- s->bufsize = len;
+- s->buffer = qemu_realloc(s->buffer, s->bufsize);
+- }
+- memcpy(s->buffer, buf, len);
+- s->datapos = s->buffer;
++ s->datapos = buf;
+ s->datalen = len;
+ spice_server_char_device_wakeup(&s->sin);
+ read_bytes = len - s->datalen;
+ if (read_bytes != len) {
+- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
+- read_bytes, len, s->bufsize);
++ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
++ read_bytes, len);
+ s->chr->write_blocked = true;
+ /* We'll get passed in the unconsumed data with the next call */
+ s->datalen = 0;
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch
new file mode 100644
index 0000000..bae63b8
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch
@@ -0,0 +1,76 @@
+>From c8cb28f0791ab38945c7facb5a63e445b4b6f41f Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 18 Mar 2011 15:23:21 +0100
+Subject: [PATCH 15/17] chardev: Allow frontends to notify backends of guest open / close
+
+Some frontends know when the guest has opened the "channel" and is actively
+listening to it, for example virtio-serial. This patch adds 2 new qemu-chardev
+functions which can be used by frontends to signal guest open / close, and
+allows interested backends to listen to this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ qemu-char.c | 17 +++++++++++++++++
+ qemu-char.h | 4 ++++
+ 2 files changed, 21 insertions(+), 0 deletions(-)
+
+diff --git a/qemu-char.c b/qemu-char.c
+index 2ef972f..d52eb51 100644
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -507,6 +507,9 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+ chr->chr_write = mux_chr_write;
+ chr->chr_update_read_handler = mux_chr_update_read_handler;
+ chr->chr_accept_input = mux_chr_accept_input;
++ /* Frontend guest-open / -close notification is not support with muxes */
++ chr->chr_guest_open = NULL;
++ chr->chr_guest_close = NULL;
+
+ /* Muxes are always open on creation */
+ qemu_chr_generic_open(chr);
+@@ -2712,6 +2715,20 @@ void qemu_chr_set_echo(struct CharDriverState *chr, bool echo)
+ }
+ }
+
++void qemu_chr_guest_open(struct CharDriverState *chr)
++{
++ if (chr->chr_guest_open) {
++ chr->chr_guest_open(chr);
++ }
++}
++
++void qemu_chr_guest_close(struct CharDriverState *chr)
++{
++ if (chr->chr_guest_close) {
++ chr->chr_guest_close(chr);
++ }
++}
++
+ void qemu_chr_close(CharDriverState *chr)
+ {
+ QTAILQ_REMOVE(&chardevs, chr, next);
+diff --git a/qemu-char.h b/qemu-char.h
+index bf06da0..f3b9bf4 100644
+--- a/qemu-char.h
++++ b/qemu-char.h
+@@ -69,6 +69,8 @@ struct CharDriverState {
+ void (*chr_close)(struct CharDriverState *chr);
+ void (*chr_accept_input)(struct CharDriverState *chr);
+ void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
++ void (*chr_guest_open)(struct CharDriverState *chr);
++ void (*chr_guest_close)(struct CharDriverState *chr);
+ void *opaque;
+ QEMUBH *bh;
+ char *label;
+@@ -91,6 +93,8 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
+ void (*init)(struct CharDriverState *s));
+ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
+ void qemu_chr_set_echo(struct CharDriverState *chr, bool echo);
++void qemu_chr_guest_open(struct CharDriverState *chr);
++void qemu_chr_guest_close(struct CharDriverState *chr);
+ void qemu_chr_close(CharDriverState *chr);
+ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
+ GCC_FMT_ATTR(2, 3);
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch
new file mode 100644
index 0000000..0b3e3f8
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch
@@ -0,0 +1,49 @@
+>From 3baf76e384c04f58f032632c078860d66c8c9db3 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 18 Mar 2011 15:30:45 +0100
+Subject: [PATCH 16/17] virtio-console: notify backend of guest open / close
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ hw/virtio-console.c | 18 ++++++++++++++++++
+ 1 files changed, 18 insertions(+), 0 deletions(-)
+
+diff --git a/hw/virtio-console.c b/hw/virtio-console.c
+index eecbdf7..828a1a3 100644
+--- a/hw/virtio-console.c
++++ b/hw/virtio-console.c
+@@ -37,6 +37,22 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
+ return qemu_chr_write(vcon->chr, buf, len);
+ }
+
++/* Callback function that's called when the guest opens the port */
++static void guest_open(VirtIOSerialPort *port)
++{
++ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
++
++ qemu_chr_guest_open(vcon->chr);
++}
++
++/* Callback function that's called when the guest closes the port */
++static void guest_close(VirtIOSerialPort *port)
++{
++ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
++
++ qemu_chr_guest_close(vcon->chr);
++}
++
+ /* Readiness of the guest to accept data on a port */
+ static int chr_can_read(void *opaque)
+ {
+@@ -81,6 +97,8 @@ static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
+ if (vcon->chr) {
+ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
+ vcon->port.info->have_data = flush_buf;
++ vcon->port.info->guest_open = guest_open;
++ vcon->port.info->guest_close = guest_close;
+ }
+ return 0;
+ }
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch
new file mode 100644
index 0000000..1944bbc
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch
@@ -0,0 +1,49 @@
+>From c169795bed5374f0071af201da2dd32b3c5a2417 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 18 Mar 2011 15:35:27 +0100
+Subject: [PATCH 17/17] spice-chardev: listen to frontend guest open / close
+
+Note the vmc_register_interface() in spice_chr_write is left in place
+in case someone uses spice-chardev with a frontend which does not have
+guest open / close notification.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ spice-qemu-char.c | 14 ++++++++++++++
+ 1 files changed, 14 insertions(+), 0 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index ed7851e..343146c 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -155,6 +155,18 @@ static void spice_chr_close(struct CharDriverState *chr)
+ qemu_free(s);
+ }
+
++static void spice_chr_guest_open(struct CharDriverState *chr)
++{
++ SpiceCharDriver *s = chr->opaque;
++ vmc_register_interface(s);
++}
++
++static void spice_chr_guest_close(struct CharDriverState *chr)
++{
++ SpiceCharDriver *s = chr->opaque;
++ vmc_unregister_interface(s);
++}
++
+ static void print_allowed_subtypes(void)
+ {
+ const char** psubtype;
+@@ -207,6 +219,8 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+ chr->opaque = s;
+ chr->chr_write = spice_chr_write;
+ chr->chr_close = spice_chr_close;
++ chr->chr_guest_open = spice_chr_guest_open;
++ chr->chr_guest_close = spice_chr_guest_close;
+ s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s);
+
+ qemu_chr_generic_open(chr);
+--
+1.7.3.2
+
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch
new file mode 100644
index 0000000..a6c2445
--- /dev/null
+++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch
@@ -0,0 +1,56 @@
+>From 7a9e7aaa30abf42879d3f13b41679513045c31ec Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 22 Mar 2011 16:28:41 +0100
+Subject: [PATCH 18/18] spice-qemu-char: Fix flow control in client -> guest direction
+
+In the old spice-vmc device we used to have:
+last_out = virtio_serial_write(&svc->port, p, MIN(len, VMC_MAX_HOST_WRITE));
+if (last_out > 0)
+ ...
+
+Now in the chardev backend we have:
+last_out = MIN(len, VMC_MAX_HOST_WRITE);
+qemu_chr_read(scd->chr, p, last_out);
+if (last_out > 0) {
+ ...
+
+Which causes us to no longer detect if the virtio port is not ready
+to receive data from us. chardev actually has a mechanism to detect this,
+but it requires a separate call to qemu_chr_can_read, before calling
+qemu_chr_read (which return void).
+
+This patch uses qemu_chr_can_read to fix the flow control from client to
+guest.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ spice-qemu-char.c | 11 +++++------
+ 1 files changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/spice-qemu-char.c b/spice-qemu-char.c
+index 343146c..def713a 100644
+--- a/spice-qemu-char.c
++++ b/spice-qemu-char.c
+@@ -38,14 +38,13 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+
+ while (len > 0) {
+ last_out = MIN(len, VMC_MAX_HOST_WRITE);
+- qemu_chr_read(scd->chr, p, last_out);
+- if (last_out > 0) {
+- out += last_out;
+- len -= last_out;
+- p += last_out;
+- } else {
++ if (qemu_chr_can_read(scd->chr) < last_out) {
+ break;
+ }
++ qemu_chr_read(scd->chr, p, last_out);
++ out += last_out;
++ len -= last_out;
++ p += last_out;
+ }
+
+ dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out);
+--
+1.7.3.2
+
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/qemu-kvm-0.14.0.ebuild b/app-emulation/qemu-kvm/qemu-kvm-0.14.0.ebuild
new file mode 100644
index 0000000..7324273
--- /dev/null
+++ b/app-emulation/qemu-kvm/qemu-kvm-0.14.0.ebuild
@@ -0,0 +1,260 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu-kvm/qemu-kvm-9999.ebuild,v 1.16 2011/03/28 03:31:46 flameeyes Exp $
+
+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 multilib
+
+if [[ ${PV} = *9999* ]]; then
+ SRC_URI=""
+ KEYWORDS=""
+else
+ SRC_URI="mirror://sourceforge/kvm/${PN}/${P}.tar.gz
+ ${BACKPORTS:+mirror://gentoo/${P}-backports-${BACKPORTS}.tar.bz2}"
+ 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 rbd sasl sdl ssl spice static vde vhost-net xen"
+
+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 )
+ rbd? ( sys-cluster/ceph )
+ sasl? ( dev-libs/cyrus-sasl )
+ sdl? ( >=media-libs/libsdl-1.2.11[X] )
+ spice? ( app-emulation/spice )
+ ssl? ( net-libs/gnutls )
+ vde? ( net-misc/vde )
+ xen? ( app-emulation/xen )
+"
+
+DEPEND="${RDEPEND}
+ app-text/texi2html
+ >=sys-kernel/linux-headers-2.6.35
+ 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
+ if use vhost-net && ! linux_chkconfig_present VHOST_NET ; then
+ ewarn "You have to enable CONFIG_VHOST_NET in the kernel to get vhost-net support."
+ 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
+
+ epatch "${FILESDIR}/qemu-0.11.0-mips64-user-fix.patch"
+ EPATCH_SOURCE="${FILESDIR}/patches-from-fedora" EPATCH_SUFFIX="patch" \
+ EPATCH_FORCE="yes" epatch
+}
+
+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 rbd)"
+ 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 spice)"
+ conf_opts="${conf_opts} $(use_enable vde)"
+ conf_opts="${conf_opts} $(use_enable vhost-net)"
+ conf_opts="${conf_opts} $(use_enable xen)"
+ conf_opts="${conf_opts} --disable-darwin-user --disable-bsd-user"
+
+ # 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 /$(get_libdir)/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
+}
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [gentoo-commits] dev/dev-zero:master commit in: app-emulation/qemu-kvm/, app-emulation/qemu-kvm/files/patches-from-fedora/, ...
@ 2012-07-13 13:47 Tiziano Müller
0 siblings, 0 replies; 2+ messages in thread
From: Tiziano Müller @ 2012-07-13 13:47 UTC (permalink / raw
To: gentoo-commits
commit: 31bedbcc6ea45c758af339d236b2acd229a21c05
Author: Tiziano Müller <tm <AT> dev-zero <DOT> ch>
AuthorDate: Fri Jul 13 13:47:23 2012 +0000
Commit: Tiziano Müller <dev-zero <AT> gentoo <DOT> org>
CommitDate: Fri Jul 13 13:47:23 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=dev/dev-zero.git;a=commit;h=31bedbcc
cleanup
---
app-emulation/qemu-kvm/Manifest | 23 -
.../0001-qxl-spice-display-move-pipe-to-ssd.patch | 143 -----
...ent-get_command-in-vga-mode-without-locks.patch | 312 ---------
...emove-qemu_mutex_-un-lock_iothread-around.patch | 148 -----
...ender-drop-cursor-locks-replace-with-pipe.patch | 249 --------
...out-tcp-socket-close-code-in-a-separate-f.patch | 56 --
...QemuChrHandlers-struct-to-initialise-char.patch | 673 --------------------
...Add-enable-disable_write_fd_handler-funct.patch | 76 ---
...-framework-for-a-write-unblocked-callback.patch | 62 --
...-send_all-to-handle-nonblocking-chardev-w.patch | 197 ------
...the-unix-tcp-backend-to-handle-nonblockin.patch | 80 ---
...har-Throttle-when-host-connection-is-down.patch | 56 --
...ole-Enable-port-throttling-when-chardev-i.patch | 48 --
.../0013-spice-qemu-char.c-add-throttling.patch | 133 ----
...ce-qemu-char.c-remove-intermediate-buffer.patch | 71 --
...ow-frontends-to-notify-backends-of-guest-.patch | 76 ---
...onsole-notify-backend-of-guest-open-close.patch | 49 --
...ardev-listen-to-frontend-guest-open-close.patch | 49 --
...char-Fix-flow-control-in-client-guest-dir.patch | 56 --
.../files/qemu-0.11.0-mips64-user-fix.patch | 11 -
app-emulation/qemu-kvm/files/qemu-kvm | 2 -
app-emulation/qemu-kvm/qemu-kvm-0.14.1-r2.ebuild | 273 --------
22 files changed, 0 insertions(+), 2843 deletions(-)
diff --git a/app-emulation/qemu-kvm/Manifest b/app-emulation/qemu-kvm/Manifest
deleted file mode 100644
index 74bcae3..0000000
--- a/app-emulation/qemu-kvm/Manifest
+++ /dev/null
@@ -1,23 +0,0 @@
-AUX patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch 4618 RMD160 f8bee2614fd8791cf478b09cb0babbf5c113ff4b SHA1 29bbe1bd0b1d5bd54e4d22aa062ed5fe9d7b80e7 SHA256 22152847a75d9f14d4d73f5f2042d83e0de2d882c066bf7524827127230b7d2d
-AUX patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch 10176 RMD160 316ed43c95137c49c25ef0d1d8faca736850f0b2 SHA1 61663c85a06ae2aaeff12887e609fcd76cbc1b31 SHA256 c788c617ee226716657dbfd778790f6b87734235e5d9fe702099bdd6e7147edb
-AUX patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch 5073 RMD160 3ce5594c2144edaff73a929c47260674724c3bbd SHA1 17844d9a38ef837098a492a994a60c7d06aeb007 SHA256 a656f4b0faac207578edf0171676799680da4427d2e332c144350dec2699bced
-AUX patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch 7783 RMD160 4261b2ad8ee333c31fe4fe700e40b27c794b60cb SHA1 8d5b0ab3a6d2a247d3197ba65cd2d1fb8f99eba7 SHA256 bb6aeaecb66e2d0215191c64e580c1ca5bbe004accddff9f7454d222b5af74de
-AUX patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch 1733 RMD160 30e31570c31d68be3b0f9f12870c13d51a18b3aa SHA1 f80a973a826693accd331c6d3d3cdddc8f47a9b6 SHA256 e123d523c974617510c59d026fdc26ec7e502bcda6c1652797dad9ae404167db
-AUX patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch 22320 RMD160 50ba6be5ef638865a18ef0c65ff8c13800d70169 SHA1 85ea8ae83047d576e69bb45cacd2f6291d7c9d3c SHA256 69192c8b9d530c4bb21c002803812d42f8bedf6f99f86a17b2493ae58ef0aff2
-AUX patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch 1913 RMD160 3c2b3fe8087de960064e33f4c3dcda74cf1ad028 SHA1 7d4ad12e0f5e019155ab4f02186cc1db0360560b SHA256 3778a50b0065ea51a52f624a6d080d0a8c260bb9bdfb23ec7646018f228b3716
-AUX patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch 2182 RMD160 8bef66b38c3b90e011c20d7a2d23f680be2fa2fc SHA1 783ce01d2ba57f7ff94dc2e3899f2ecdbf5ba528 SHA256 01a72c82db6da782854b2cdaaf094d103b3854c7ad26328d84e97c356b150ae8
-AUX patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch 6678 RMD160 e929fb838a590ade9cde62804f2d0503c14fd734 SHA1 ce4917bb9c3b580286c31137c46c7e034463503f SHA256 5b9e50e98c39523c790e2ec75c65e6576b13580ccb01c9e22e51caa40c4a40be
-AUX patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch 2583 RMD160 dd6080a4e259410b7dd6ba6b51a0af51b6a8ca0c SHA1 73f62b43270f4b6369efd7e6015e3f6e7d0cb9a9 SHA256 61dd33665fad5bfb4df1d387cebec1e0bed6128bbf427c9f8a3c60f91c713c6c
-AUX patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch 2000 RMD160 3fa3bd27d69d90f26e30b3cc5c899cb49554639a SHA1 3d662d181d77f8e4420b6f8c5fa57687d11f3858 SHA256 c496a5bd77aa973f6368b06d8a0a67568ae53a0990cec65897b57918f6fee6e7
-AUX patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch 1650 RMD160 0e94375a02675398d1627bdbc6617661139ae0d7 SHA1 10371019b8053965e63ccd8d5472c11a05ccc3d2 SHA256 6eabb8a5f3207fd24a7c27dbbfb47168c7a4778771a84f00622c3cadc21b4674
-AUX patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch 5036 RMD160 8cf7d356f1664b32f462ad2b957194031d3e6126 SHA1 35cce42333140d5c65f54cbab5e438b0de7f7d95 SHA256 c7d863e59849c732f3fef3a425f1f32843fd2e542a94b61fae61ce36a087f0e3
-AUX patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch 2822 RMD160 5d5ab6de3e5a0e8ebea6001127d61c0f730c609f SHA1 ddd50cf6e52ca8dae01f7253417946e2f4cc4cbe SHA256 d7cb0159ac28d78a68208a99ec5dbfaf43e01bde68b90528d7cfb629c78e7247
-AUX patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch 2807 RMD160 5193a86c3400d78d1a0190f98532738fbc53aa77 SHA1 f7365f2eb85fb2cd824f5dbcd198a406354e04e5 SHA256 077b6a431156a5a7fbadabfdc7543f4096fd46a7990b56332c1b82928941f4b2
-AUX patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch 1592 RMD160 a024a9fced5e3a44580ae6ae78409e0e4b8e5265 SHA1 243028b1f28ab67b04341ea22492bd58e9dab231 SHA256 0bbc7fa3d32dae0d812baac88fb4dff7ba075221f16ed90116432562aa5be9b8
-AUX patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch 1536 RMD160 a62580485c1cecc5cd979b67cd8567947d223d2f SHA1 2df9fe95487101ed1fea739d106c8fbb3633d8f0 SHA256 86623ce9e32fee56d1f13ee51770d89043d1c6fb7a4d972e15840fab95a0b04d
-AUX patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch 1784 RMD160 25fe156aafa2070905476ccdd0e4f2946729bec8 SHA1 7ed5fa3d92ed45d2e0d95247cc5d437304419074 SHA256 68215f7f55f749aa8333d840e40c0c58e957c12c90b47eb8b0c5cad3f6249fec
-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
-EBUILD qemu-kvm-0.14.1-r2.ebuild 8699 RMD160 0fb62c998fed745f3879d443715bf047a220ab97 SHA1 e6ec074f8459e81409f1a31a90a346269367299b SHA256 0f4c87eb7d3f01400c8ff4901dc350422746f8642f3c2d0db977b2760a06125e
-DIST qemu-kvm-0.14.1.tar.gz 5321321 RMD160 e3d69b4756bb0e45d14baad72d85827d949e0ae0 SHA1 7378f10ea04db19e5a5009cae1ecb65517e82877 SHA256 a59c4f6ab8646f2f019d2f9f15443e4db8289cf7cf47743d3c63d18fc584da27
-DIST qemu-kvm-0.14.1-backports-1.tar.bz2 1127 RMD160 7868908c1328cfcbc3e2c60124155f64fb8688e0 SHA1 a4ce58828516b60596c8fea878d6f2cb6bab40d0 SHA256 e636759e1a04aacc49247c1d1eb40d0f2c9e5c642b5404441990f1445483370a
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch
deleted file mode 100644
index b542f54..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch
+++ /dev/null
@@ -1,143 +0,0 @@
->From fd04276a00b172e6fbba3e3c72b1d13a0f179414 Mon Sep 17 00:00:00 2001
-From: Alon Levy <alevy@redhat.com>
-Date: Wed, 16 Mar 2011 15:21:03 +0100
-Subject: [PATCH 1/4] qxl/spice-display: move pipe to ssd
-
-This moves the int pipe[2] and pthread_t main data from the
-PCIQXLDevice struct to the SimpleSpiceDisplay. This will let us
-reuse it in the next patch for both -spice with no -qxl usage and
-for vga mode from qxl.
-
-Also move the pipe creation function (which is effectively completely rewritten
-by this patch anyways) from hw/qxl.c to ui/spice-display.c, since
-spice-display will depend on it after the next patch and qemu can be build
-with ui/spice-display.c in combination with no hw/qxl.c.
----
- hw/qxl.c | 22 +++++-----------------
- hw/qxl.h | 4 ----
- ui/spice-display.c | 21 +++++++++++++++++++++
- ui/spice-display.h | 8 ++++++++
- 4 files changed, 34 insertions(+), 21 deletions(-)
-
-diff --git a/hw/qxl.c b/hw/qxl.c
-index fe4212b..201698f 100644
---- a/hw/qxl.c
-+++ b/hw/qxl.c
-@@ -1062,7 +1062,7 @@ static void pipe_read(void *opaque)
- int len;
-
- do {
-- len = read(d->pipe[0], &dummy, sizeof(dummy));
-+ len = read(d->ssd.pipe[0], &dummy, sizeof(dummy));
- } while (len == sizeof(dummy));
- qxl_set_irq(d);
- }
-@@ -1078,10 +1078,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
- if ((old_pending & le_events) == le_events) {
- return;
- }
-- if (pthread_self() == d->main) {
-+ if (pthread_self() == d->ssd.main) {
-+ /* running in io_thread thread */
- qxl_set_irq(d);
- } else {
-- if (write(d->pipe[1], d, 1) != 1) {
-+ if (write(d->ssd.pipe[1], d, 1) != 1) {
- dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
- }
- }
-@@ -1089,20 +1090,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
-
- static void init_pipe_signaling(PCIQXLDevice *d)
- {
-- if (pipe(d->pipe) < 0) {
-- dprint(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);
-+ qxl_create_server_to_iothread_pipe(&d->ssd, pipe_read);
- }
-
- /* graphics console */
-diff --git a/hw/qxl.h b/hw/qxl.h
-index f6c450d..701245f 100644
---- a/hw/qxl.h
-+++ b/hw/qxl.h
-@@ -55,10 +55,6 @@ typedef struct PCIQXLDevice {
- } guest_surfaces;
- QXLPHYSICAL guest_cursor;
-
-- /* thread signaling */
-- pthread_t main;
-- int pipe[2];
--
- /* ram pci bar */
- QXLRam *ram;
- VGACommonState vga;
-diff --git a/ui/spice-display.c b/ui/spice-display.c
-index 020b423..ec6e0cb 100644
---- a/ui/spice-display.c
-+++ b/ui/spice-display.c
-@@ -394,6 +394,27 @@ static DisplayChangeListener display_listener = {
- .dpy_refresh = display_refresh,
- };
-
-+void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
-+ IOHandler *pipe_read)
-+{
-+ if (pipe(ssd->pipe) < 0) {
-+ fprintf(stderr, "%s: pipe creation failed\n", __FUNCTION__);
-+ return;
-+ }
-+
-+#ifdef CONFIG_IOTHREAD
-+ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK);
-+#else
-+ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
-+#endif
-+ fcntl(ssd->pipe[1], F_SETFL, O_NONBLOCK);
-+
-+ fcntl(ssd->pipe[0], F_SETOWN, getpid());
-+
-+ qemu_set_fd_handler(ssd->pipe[0], pipe_read, NULL, ssd);
-+ ssd->main = pthread_self();
-+}
-+
- void qemu_spice_display_init(DisplayState *ds)
- {
- assert(sdpy.ds == NULL);
-diff --git a/ui/spice-display.h b/ui/spice-display.h
-index aef0464..3e6cf7c 100644
---- a/ui/spice-display.h
-+++ b/ui/spice-display.h
-@@ -43,6 +43,11 @@ typedef struct SimpleSpiceDisplay {
- QXLRect dirty;
- int notify;
- int running;
-+
-+ /* thread signaling - used both in qxl (in vga mode
-+ * and in native mode) and without qxl */
-+ pthread_t main;
-+ int pipe[2]; /* to iothread */
- } SimpleSpiceDisplay;
-
- typedef struct SimpleSpiceUpdate {
-@@ -66,3 +71,6 @@ 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);
-+/* used by both qxl and spice-display */
-+void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
-+ IOHandler *pipe_read);
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch
deleted file mode 100644
index d221d5f..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch
+++ /dev/null
@@ -1,312 +0,0 @@
->From 97e291086fef45762e0278e85ab1d231a9902bbb Mon Sep 17 00:00:00 2001
-From: Uri Lublin <uril@redhat.com>
-Date: Wed, 16 Mar 2011 15:43:45 +0100
-Subject: [PATCH 2/4] qxl: implement get_command in vga mode without locks
-
-This patch and the next drop the requirement to lose the global qemu
-mutex during dispatcher calls. This patch enables it, the next drops
-the unlock/lock pairs around dispatcher calls.
-
-The current solution of dropping the locks is buggy:
- * it allows multiple dispatcher calls from two vcpu threads, the
- dispatcher doesn't handle that by design (single fd, not locked, can't
- handle writes from two threads)
- * it requires us to keep track of cpu_single_env, which is magic.
-
-The solution implemented in this patch and the next (the next just
-drops the locks, this patch allows that to work):
- * the only operation that needed locking was qemu_create_simple_update,
- * it required locking because it was called from the spice-server thread.
- * do it in the iothread by reusing the existing pipe used for set_irq.
-
-The current flow implemented is now:
-spice-server thread:
- qxl.c:interface_get_command (called either by polling or from wakeup)
- if update!=NULL:
- waiting_for_update=0
- update=NULL
- return update
- else:
- if not waiting_for_update:
- waiting_for_update=1
- write to pipe, which is read by iothread (main thread)
-
-iothread:
- wakeup from select,
- qxl.c:pipe_read
- update=qemu_create_simple_update()
- wakeup spice-server thread by calling d.worker->wakeup(d.worker)
----
- hw/qxl.c | 81 +++++++++++++++++++++++++++++++++++++++------------
- ui/spice-display.c | 75 +++++++++++++++++++++++++++++++++++++++++++----
- ui/spice-display.h | 16 ++++++++++
- 3 files changed, 146 insertions(+), 26 deletions(-)
-
-diff --git a/hw/qxl.c b/hw/qxl.c
-index 201698f..64580f1 100644
---- a/hw/qxl.c
-+++ b/hw/qxl.c
-@@ -340,7 +340,6 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
- 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;
-@@ -348,16 +347,25 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
- switch (qxl->mode) {
- case QXL_MODE_VGA:
- dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
-- update = qemu_spice_create_update(&qxl->ssd);
-- if (update == NULL) {
-- return false;
-+ if (qxl_vga_mode_get_command(&qxl->ssd, ext)) {
-+ qxl_log_command(qxl, "vga", ext);
-+ return true;
- }
-- *ext = update->ext;
-- qxl_log_command(qxl, "vga", ext);
-- return true;
-+ return false;
- case QXL_MODE_COMPAT:
- case QXL_MODE_NATIVE:
- case QXL_MODE_UNDEFINED:
-+ /* flush any existing updates that we didn't send to the guest.
-+ * since update != NULL it means the server didn't get it, and
-+ * because we changed mode to != QXL_MODE_VGA, it won't. */
-+ if (qxl->ssd.update != NULL) {
-+ if (qxl->ssd.update != QXL_EMPTY_UPDATE) {
-+ qemu_spice_destroy_update(&qxl->ssd, qxl->ssd.update);
-+ }
-+ qxl->ssd.update = NULL;
-+ qxl->ssd.waiting_for_update = 0;
-+ }
-+ /* */
- dprint(qxl, 2, "%s: %s\n", __FUNCTION__,
- qxl->cmdflags ? "compat" : "native");
- ring = &qxl->ram->cmd_ring;
-@@ -1057,17 +1065,50 @@ static void qxl_map(PCIDevice *pci, int region_num,
-
- static void pipe_read(void *opaque)
- {
-- PCIQXLDevice *d = opaque;
-- char dummy;
-- int len;
--
-- do {
-- len = read(d->ssd.pipe[0], &dummy, sizeof(dummy));
-- } while (len == sizeof(dummy));
-- qxl_set_irq(d);
-+ SimpleSpiceDisplay *ssd = opaque;
-+ unsigned char cmd;
-+ int len, set_irq = 0;
-+ int create_update = 0;
-+
-+ while (1) {
-+ cmd = 0;
-+ len = read(ssd->pipe[0], &cmd, sizeof(cmd));
-+ if (len < 0) {
-+ if (errno == EINTR) {
-+ continue;
-+ }
-+ if (errno == EAGAIN) {
-+ break;
-+ }
-+ perror("qxl: pipe_read: read failed");
-+ break;
-+ }
-+ switch (cmd) {
-+ case QXL_SERVER_SET_IRQ:
-+ set_irq = 1;
-+ break;
-+ case QXL_SERVER_CREATE_UPDATE:
-+ create_update = 1;
-+ break;
-+ default:
-+ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
-+ abort();
-+ }
-+ }
-+ /* no need to do either operation more than once */
-+ if (create_update) {
-+ assert(ssd->update == NULL);
-+ ssd->update = qemu_spice_create_update(ssd);
-+ if (ssd->update == NULL) {
-+ ssd->update = QXL_EMPTY_UPDATE;
-+ }
-+ ssd->worker->wakeup(ssd->worker);
-+ }
-+ if (set_irq) {
-+ qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd));
-+ }
- }
-
--/* called from spice server thread context only */
- static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
- {
- uint32_t old_pending;
-@@ -1082,9 +1123,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
- /* running in io_thread thread */
- qxl_set_irq(d);
- } else {
-- if (write(d->ssd.pipe[1], d, 1) != 1) {
-- dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
-- }
-+ /* called from spice-server thread */
-+ int ret;
-+ unsigned char ack = QXL_SERVER_SET_IRQ;
-+ ret = write(d->ssd.pipe[1], &ack, 1);
-+ assert(ret == 1);
- }
- }
-
-diff --git a/ui/spice-display.c b/ui/spice-display.c
-index ec6e0cb..bdd14b8 100644
---- a/ui/spice-display.c
-+++ b/ui/spice-display.c
-@@ -294,18 +294,39 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
- info->n_surfaces = NUM_SURFACES;
- }
-
-+/* Called from spice server thread context (via interface_get_command) */
-+int qxl_vga_mode_get_command(
-+ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext)
-+{
-+ SimpleSpiceUpdate *update;
-+ unsigned char req;
-+ int r;
-+
-+ update = ssd->update;
-+ if (update != NULL) {
-+ ssd->waiting_for_update = 0;
-+ ssd->update = NULL;
-+ if (update != QXL_EMPTY_UPDATE) {
-+ *ext = update->ext;
-+ return true;
-+ }
-+ } else {
-+ if (!ssd->waiting_for_update) {
-+ ssd->waiting_for_update = 1;
-+ req = QXL_SERVER_CREATE_UPDATE;
-+ r = write(ssd->pipe[1], &req , 1);
-+ assert(r == 1);
-+ }
-+ }
-+ return false;
-+}
-+
- static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
- {
- SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
-- SimpleSpiceUpdate *update;
-
- dprint(3, "%s:\n", __FUNCTION__);
-- update = qemu_spice_create_update(ssd);
-- if (update == NULL) {
-- return false;
-- }
-- *ext = update->ext;
-- return true;
-+ return qxl_vga_mode_get_command(ssd, ext);
- }
-
- static int interface_req_cmd_notification(QXLInstance *sin)
-@@ -394,6 +415,45 @@ static DisplayChangeListener display_listener = {
- .dpy_refresh = display_refresh,
- };
-
-+static void pipe_read(void *opaque)
-+{
-+ SimpleSpiceDisplay *ssd = opaque;
-+ unsigned char cmd;
-+ int len, create_update = 0;
-+
-+ while (1) {
-+ cmd = 0;
-+ len = read(ssd->pipe[0], &cmd, sizeof(cmd));
-+ if (len < 0) {
-+ if (errno == EINTR) {
-+ continue;
-+ }
-+ if (errno == EAGAIN) {
-+ break;
-+ }
-+ perror("qxl: pipe_read: read failed");
-+ break;
-+ }
-+ switch (cmd) {
-+ case QXL_SERVER_CREATE_UPDATE:
-+ create_update = 1;
-+ break;
-+ default:
-+ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
-+ abort();
-+ }
-+ }
-+ /* no need to do this more than once */
-+ if (create_update) {
-+ assert(ssd->update == NULL);
-+ ssd->update = qemu_spice_create_update(ssd);
-+ if (ssd->update == NULL) {
-+ ssd->update = QXL_EMPTY_UPDATE;
-+ }
-+ ssd->worker->wakeup(ssd->worker);
-+ }
-+}
-+
- void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
- IOHandler *pipe_read)
- {
-@@ -427,6 +487,7 @@ void qemu_spice_display_init(DisplayState *ds)
- qemu_spice_add_interface(&sdpy.qxl.base);
- assert(sdpy.worker);
-
-+ qxl_create_server_to_iothread_pipe(&sdpy, pipe_read);
- 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 --git a/ui/spice-display.h b/ui/spice-display.h
-index 3e6cf7c..2be6a34 100644
---- a/ui/spice-display.h
-+++ b/ui/spice-display.h
-@@ -31,6 +31,15 @@
-
- #define NUM_SURFACES 1024
-
-+/* For commands/requests from server thread to iothread */
-+#define QXL_EMPTY_UPDATE ((void *)-1)
-+enum {
-+ QXL_SERVER_SET_IRQ = 1,
-+ QXL_SERVER_CREATE_UPDATE,
-+};
-+
-+struct SimpleSpiceUpdate;
-+
- typedef struct SimpleSpiceDisplay {
- DisplayState *ds;
- void *buf;
-@@ -48,6 +57,10 @@ typedef struct SimpleSpiceDisplay {
- * and in native mode) and without qxl */
- pthread_t main;
- int pipe[2]; /* to iothread */
-+
-+ /* ssd updates (one request/command at a time) */
-+ struct SimpleSpiceUpdate *update;
-+ int waiting_for_update;
- } SimpleSpiceDisplay;
-
- typedef struct SimpleSpiceUpdate {
-@@ -71,6 +84,9 @@ 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);
-+/* shared with qxl.c in vga mode and ui/spice-display (no qxl mode) */
-+int qxl_vga_mode_get_command(
-+ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext);
- /* used by both qxl and spice-display */
- void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
- IOHandler *pipe_read);
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch
deleted file mode 100644
index 92a148e..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch
+++ /dev/null
@@ -1,148 +0,0 @@
->From d413b3c36cbd9820c5b9492b52caa421abccf745 Mon Sep 17 00:00:00 2001
-From: Alon Levy <alevy@redhat.com>
-Date: Wed, 16 Mar 2011 15:46:22 +0100
-Subject: [PATCH 3/4] qxl/spice: remove qemu_mutex_{un,}lock_iothread around dispatcher
-
-with the previous patch making sure get_command no longer needs to lock,
-there is no reason to drop the qemu iothread mutex in qxl.c and in
-ui/spice-display.c
-
-The only location where the lock remains are the cursor related callbacks,
-that path is currently broken. It is only triggered if running spice and sdl,
-which is broken already before that.
----
- hw/qxl.c | 8 --------
- ui/spice-display.c | 19 +++----------------
- 2 files changed, 3 insertions(+), 24 deletions(-)
-
-diff --git a/hw/qxl.c b/hw/qxl.c
-index 64580f1..cf3c938 100644
---- a/hw/qxl.c
-+++ b/hw/qxl.c
-@@ -670,10 +670,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
- dprint(d, 1, "%s: start%s\n", __FUNCTION__,
- loadvm ? " (loadvm)" : "");
-
-- qemu_mutex_unlock_iothread();
- d->ssd.worker->reset_cursor(d->ssd.worker);
- d->ssd.worker->reset_image_cache(d->ssd.worker);
-- qemu_mutex_lock_iothread();
- qxl_reset_surfaces(d);
- qxl_reset_memslots(d);
-
-@@ -803,9 +801,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
- {
- dprint(d, 1, "%s:\n", __FUNCTION__);
- d->mode = QXL_MODE_UNDEFINED;
-- qemu_mutex_unlock_iothread();
- d->ssd.worker->destroy_surfaces(d->ssd.worker);
-- qemu_mutex_lock_iothread();
- memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
- }
-
-@@ -874,9 +870,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d)
- dprint(d, 1, "%s\n", __FUNCTION__);
-
- d->mode = QXL_MODE_UNDEFINED;
-- qemu_mutex_unlock_iothread();
- d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
-- qemu_mutex_lock_iothread();
- }
-
- static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
-@@ -946,10 +940,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
- case QXL_IO_UPDATE_AREA:
- {
- QXLRect update = d->ram->update_area;
-- qemu_mutex_unlock_iothread();
- d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
- &update, NULL, 0, 0);
-- qemu_mutex_lock_iothread();
- break;
- }
- case QXL_IO_NOTIFY_CMD:
-diff --git a/ui/spice-display.c b/ui/spice-display.c
-index bdd14b8..ecb22cc 100644
---- a/ui/spice-display.c
-+++ b/ui/spice-display.c
-@@ -62,13 +62,7 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
- dest->right = MAX(dest->right, r->right);
- }
-
--/*
-- * Called from spice server thread context (via interface_get_command).
-- *
-- * We must aquire the global qemu mutex here to make sure the
-- * DisplayState (+DisplaySurface) we are accessing doesn't change
-- * underneath us.
-- */
-+/* Called from io-thread context (via pipe_read) */
- SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
- {
- SimpleSpiceUpdate *update;
-@@ -78,9 +72,7 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
- uint8_t *src, *dst;
- int by, bw, bh;
-
-- qemu_mutex_lock_iothread();
- if (qemu_spice_rect_is_empty(&ssd->dirty)) {
-- qemu_mutex_unlock_iothread();
- return NULL;
- };
-
-@@ -141,7 +133,6 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
- cmd->data = (intptr_t)drawable;
-
- memset(&ssd->dirty, 0, sizeof(ssd->dirty));
-- qemu_mutex_unlock_iothread();
- return update;
- }
-
-@@ -169,6 +160,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
- ssd->worker->add_memslot(ssd->worker, &memslot);
- }
-
-+/* called from iothread (main) or a vcpu-thread */
- void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
- {
- QXLDevSurfaceCreate surface;
-@@ -186,18 +178,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
- surface.mem = (intptr_t)ssd->buf;
- surface.group_id = MEMSLOT_GROUP_HOST;
-
-- qemu_mutex_unlock_iothread();
- ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
-- qemu_mutex_lock_iothread();
- }
-
- void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
- {
- dprint(1, "%s:\n", __FUNCTION__);
-
-- qemu_mutex_unlock_iothread();
- ssd->worker->destroy_primary_surface(ssd->worker, 0);
-- qemu_mutex_lock_iothread();
- }
-
- void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
-@@ -207,9 +195,7 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
- if (running) {
- ssd->worker->start(ssd->worker);
- } else {
-- qemu_mutex_unlock_iothread();
- ssd->worker->stop(ssd->worker);
-- qemu_mutex_lock_iothread();
- }
- ssd->running = running;
- }
-@@ -233,6 +219,7 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
- qemu_spice_rect_union(&ssd->dirty, &update_area);
- }
-
-+/* called only from iothread (main) */
- void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
- {
- dprint(1, "%s:\n", __FUNCTION__);
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch
deleted file mode 100644
index 03daba4..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch
+++ /dev/null
@@ -1,249 +0,0 @@
->From 1a33e5f2fa6de800047517a6f3251dc7191c97b5 Mon Sep 17 00:00:00 2001
-From: Alon Levy <alevy@redhat.com>
-Date: Wed, 16 Mar 2011 16:02:16 +0100
-Subject: [PATCH 4/4] hw/qxl-render: drop cursor locks, replace with pipe
-
-Switching locking protection of ds->cursor_set/cursor_move to moving
-every call to these functions into the iothread and using the ssd->pipe
-to transfer that, adding QXL_SERVER_CURSOR_SET, QXL_SERVER_CURSOR_MOVE.
-
-This is tested with both -vnc :0 -spice and -sdl -spice.
----
- hw/qxl-render.c | 25 +++++++++-----
- hw/qxl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
- hw/qxl.h | 4 ++
- ui/spice-display.h | 13 +++++++-
- 4 files changed, 122 insertions(+), 10 deletions(-)
-
-diff --git a/hw/qxl-render.c b/hw/qxl-render.c
-index 58965e0..6759edb 100644
---- a/hw/qxl-render.c
-+++ b/hw/qxl-render.c
-@@ -178,7 +178,6 @@ fail:
- return NULL;
- }
-
--
- /* called from spice server thread context only */
- void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
- {
-@@ -209,18 +208,26 @@ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
- if (c == NULL) {
- c = cursor_builtin_left_ptr();
- }
-- qemu_mutex_lock_iothread();
-- qxl->ssd.ds->cursor_define(c);
-- qxl->ssd.ds->mouse_set(x, y, 1);
-- qemu_mutex_unlock_iothread();
-- cursor_put(c);
-+ qxl_server_request_cursor_set(qxl, c, x, y);
- break;
- case QXL_CURSOR_MOVE:
- x = cmd->u.position.x;
- y = cmd->u.position.y;
-- qemu_mutex_lock_iothread();
-- qxl->ssd.ds->mouse_set(x, y, 1);
-- qemu_mutex_unlock_iothread();
-+ qxl_server_request_cursor_move(qxl, x, y);
- break;
- }
- }
-+
-+/* called from iothread only (via qxl.c:pipe_read) */
-+void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y)
-+{
-+ ssd->ds->cursor_define(c);
-+ ssd->ds->mouse_set(x, y, 1);
-+ cursor_put(c);
-+}
-+
-+/* called from iothread only (via qxl.c:pipe_read) */
-+void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y)
-+{
-+ ssd->ds->mouse_set(x, y, 1);
-+}
-diff --git a/hw/qxl.c b/hw/qxl.c
-index cf3c938..4c27deb 100644
---- a/hw/qxl.c
-+++ b/hw/qxl.c
-@@ -117,6 +117,27 @@ static QXLMode qxl_modes[] = {
- #endif
- };
-
-+typedef struct __attribute__ ((__packed__)) {
-+ QEMUCursor *c;
-+ int x;
-+ int y;
-+} QXLServerCursorSet;
-+
-+typedef struct __attribute__ ((__packed__)) {
-+ int x;
-+ int y;
-+} QXLServerCursorMove;
-+
-+typedef struct __attribute__ ((__packed__)) {
-+ unsigned char req;
-+ QXLServerCursorMove data;
-+} QXLServerCursorMoveRequest;
-+
-+typedef struct __attribute__ ((__packed__)) {
-+ unsigned char req;
-+ QXLServerCursorSet data;
-+} QXLServerCursorSetRequest;
-+
- static PCIQXLDevice *qxl0;
-
- static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
-@@ -337,6 +358,33 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
- }
-
- /* called from spice server thread context only */
-+void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y)
-+{
-+ QXLServerCursorSetRequest req;
-+ int r;
-+
-+ req.req = QXL_SERVER_CURSOR_SET;
-+ req.data.c = c;
-+ req.data.x = x;
-+ req.data.y = y;
-+ r = write(qxl->ssd.pipe[1], &req, sizeof(req));
-+ assert(r == sizeof(req));
-+}
-+
-+/* called from spice server thread context only */
-+void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y)
-+{
-+ QXLServerCursorMoveRequest req;
-+ int r;
-+
-+ req.req = QXL_SERVER_CURSOR_MOVE;
-+ req.data.x = x;
-+ req.data.y = y;
-+ r = write(qxl->ssd.pipe[1], &req, sizeof(req));
-+ assert(r == sizeof(req));
-+}
-+
-+/* called from spice server thread context only */
- static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
- {
- PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
-@@ -1055,12 +1103,37 @@ static void qxl_map(PCIDevice *pci, int region_num,
- }
- }
-
-+static void read_bytes(int fd, void *buf, int len_requested)
-+{
-+ int len;
-+ int total_len = 0;
-+
-+ do {
-+ len = read(fd, buf, len_requested - total_len);
-+ if (len < 0) {
-+ if (errno == EINTR || errno == EAGAIN) {
-+ continue;
-+ }
-+ perror("qxl: pipe_read: read failed");
-+ /* will abort once it's out of the while loop */
-+ break;
-+ }
-+ total_len += len;
-+ buf = (uint8_t *)buf + len;
-+ } while (total_len < len_requested);
-+ assert(total_len == len_requested);
-+}
-+
- static void pipe_read(void *opaque)
- {
- SimpleSpiceDisplay *ssd = opaque;
- unsigned char cmd;
- int len, set_irq = 0;
- int create_update = 0;
-+ int cursor_set = 0;
-+ int cursor_move = 0;
-+ QXLServerCursorSet cursor_set_data;
-+ QXLServerCursorMove cursor_move_data;
-
- while (1) {
- cmd = 0;
-@@ -1082,6 +1155,17 @@ static void pipe_read(void *opaque)
- case QXL_SERVER_CREATE_UPDATE:
- create_update = 1;
- break;
-+ case QXL_SERVER_CURSOR_SET:
-+ if (cursor_set == 1) {
-+ cursor_put(cursor_set_data.c);
-+ }
-+ cursor_set = 1;
-+ read_bytes(ssd->pipe[0], &cursor_set_data, sizeof(cursor_set_data));
-+ break;
-+ case QXL_SERVER_CURSOR_MOVE:
-+ cursor_move = 1;
-+ read_bytes(ssd->pipe[0], &cursor_move_data, sizeof(cursor_move_data));
-+ break;
- default:
- fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
- abort();
-@@ -1099,6 +1183,12 @@ static void pipe_read(void *opaque)
- if (set_irq) {
- qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd));
- }
-+ if (cursor_move) {
-+ qxl_render_cursor_move(ssd, cursor_move_data.x, cursor_move_data.y);
-+ }
-+ if (cursor_set) {
-+ qxl_render_cursor_set(ssd, cursor_set_data.c, cursor_set_data.x, cursor_set_data.y);
-+ }
- }
-
- static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
-diff --git a/hw/qxl.h b/hw/qxl.h
-index 701245f..f4f99ec 100644
---- a/hw/qxl.h
-+++ b/hw/qxl.h
-@@ -93,6 +93,8 @@ typedef struct PCIQXLDevice {
-
- /* qxl.c */
- void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
-+void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y);
-+void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y);
-
- /* qxl-logger.c */
- void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
-@@ -102,3 +104,5 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
- void qxl_render_resize(PCIQXLDevice *qxl);
- void qxl_render_update(PCIQXLDevice *qxl);
- void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
-+void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y);
-+void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y);
-diff --git a/ui/spice-display.h b/ui/spice-display.h
-index 2be6a34..bbfd689 100644
---- a/ui/spice-display.h
-+++ b/ui/spice-display.h
-@@ -31,11 +31,22 @@
-
- #define NUM_SURFACES 1024
-
--/* For commands/requests from server thread to iothread */
-+/*
-+ * Commands/requests from server thread to iothread.
-+ * Note that CREATE_UPDATE is used both with qxl and without it (spice-display)
-+ * the others are only used with the qxl device.
-+ *
-+ * SET_IRQ - just the request is sent (1 byte)
-+ * CREATE_UPDATE - jus the request is sent (1 byte)
-+ * CURSOR_SET - send QXLServerRequestCursorSet
-+ * CURSOR_MOVE - send QXLServerRequestCursorMove
-+ */
- #define QXL_EMPTY_UPDATE ((void *)-1)
- enum {
- QXL_SERVER_SET_IRQ = 1,
- QXL_SERVER_CREATE_UPDATE,
-+ QXL_SERVER_CURSOR_SET,
-+ QXL_SERVER_CURSOR_MOVE
- };
-
- struct SimpleSpiceUpdate;
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
deleted file mode 100644
index 0ec25a0..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
+++ /dev/null
@@ -1,56 +0,0 @@
->From b248befcd93bcd713971b15147fcaa217a3d1bb7 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 21:57:47 +0100
-Subject: [PATCH 05/17] char: Split out tcp socket close code in a separate function
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c | 25 ++++++++++++++++---------
- 1 files changed, 16 insertions(+), 9 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index bd4e944..4b57af9 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -1911,6 +1911,21 @@ typedef struct {
-
- static void tcp_chr_accept(void *opaque);
-
-+static void tcp_closed(void *opaque)
-+{
-+ CharDriverState *chr = opaque;
-+ TCPCharDriver *s = chr->opaque;
-+
-+ s->connected = 0;
-+ if (s->listen_fd >= 0) {
-+ qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
-+ }
-+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-+ closesocket(s->fd);
-+ s->fd = -1;
-+ qemu_chr_event(chr, CHR_EVENT_CLOSED);
-+}
-+
- static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
- TCPCharDriver *s = chr->opaque;
-@@ -2061,15 +2076,7 @@ static void tcp_chr_read(void *opaque)
- len = s->max_size;
- size = tcp_chr_recv(chr, (void *)buf, len);
- if (size == 0) {
-- /* connection closed */
-- s->connected = 0;
-- if (s->listen_fd >= 0) {
-- qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
-- }
-- qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-- closesocket(s->fd);
-- s->fd = -1;
-- qemu_chr_event(chr, CHR_EVENT_CLOSED);
-+ tcp_closed(chr);
- } else if (size > 0) {
- if (s->do_telnetopt)
- tcp_chr_process_IAC_bytes(chr, s, buf, &size);
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
deleted file mode 100644
index 095e7ff..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
+++ /dev/null
@@ -1,673 +0,0 @@
->From 003cc09f8fc34e7571ebd4a89ea6aa6324a80b54 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 20:31:45 +0100
-Subject: [PATCH 06/19] char: Add a QemuChrHandlers struct to initialise chardev handlers
-
-Instead of passing each handler in the qemu_add_handlers() function,
-create a struct of handlers that can be passed to the function instead.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- gdbstub.c | 9 +++++++--
- hw/debugcon.c | 2 +-
- hw/escc.c | 9 +++++++--
- hw/etraxfs_ser.c | 13 +++++++++----
- hw/grlib_apbuart.c | 12 +++++++-----
- hw/ivshmem.c | 28 ++++++++++++++++++++++------
- hw/mcf_uart.c | 9 +++++++--
- hw/pl011.c | 9 +++++++--
- hw/pxa2xx.c | 13 +++++++++----
- hw/serial.c | 9 +++++++--
- hw/sh_serial.c | 12 +++++++++---
- hw/syborg_serial.c | 9 +++++++--
- hw/usb-serial.c | 9 +++++++--
- hw/virtio-console.c | 9 +++++++--
- hw/xen_console.c | 16 +++++++++++-----
- hw/xilinx_uartlite.c | 11 +++++++++--
- monitor.c | 18 ++++++++++++++----
- net/slirp.c | 8 ++++++--
- qemu-char.c | 30 +++++++++++++++++++++---------
- qemu-char.h | 13 +++++++++----
- 20 files changed, 183 insertions(+), 65 deletions(-)
-
-diff --git a/gdbstub.c b/gdbstub.c
-index 14e8b9b..4190ac7 100644
---- a/gdbstub.c
-+++ b/gdbstub.c
-@@ -2634,6 +2634,12 @@ static void gdb_sigterm_handler(int signal)
- }
- #endif
-
-+static const QemuChrHandlers gdb_handlers = {
-+ .fd_can_read = gdb_chr_can_receive,
-+ .fd_read = gdb_chr_receive,
-+ .fd_event = gdb_chr_event,
-+};
-+
- int gdbserver_start(const char *device)
- {
- GDBState *s;
-@@ -2663,8 +2669,7 @@ int gdbserver_start(const char *device)
- if (!chr)
- return -1;
-
-- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
-- gdb_chr_event, NULL);
-+ qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
- }
-
- s = gdbserver_state;
-diff --git a/hw/debugcon.c b/hw/debugcon.c
-index 5ee6821..e79a595 100644
---- a/hw/debugcon.c
-+++ b/hw/debugcon.c
-@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
- exit(1);
- }
-
-- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
-+ qemu_chr_add_handlers(s->chr, NULL, s);
- }
-
- static int debugcon_isa_initfn(ISADevice *dev)
-diff --git a/hw/escc.c b/hw/escc.c
-index f6fd919..dfa329a 100644
---- a/hw/escc.c
-+++ b/hw/escc.c
-@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
- sysbus_mmio_map(s, 0, base);
- }
-
-+static const QemuChrHandlers serial_handlers = {
-+ .fd_can_read = serial_can_receive,
-+ .fd_read = serial_receive1,
-+ .fd_event = serial_event,
-+};
-+
- static int escc_init1(SysBusDevice *dev)
- {
- SerialState *s = FROM_SYSBUS(SerialState, dev);
-@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev)
- s->chn[i].chn = 1 - i;
- s->chn[i].clock = s->frequency / 2;
- if (s->chn[i].chr) {
-- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
-- serial_receive1, serial_event, &s->chn[i]);
-+ qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
- }
- }
- s->chn[0].otherchn = &s->chn[1];
-diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
-index 2787ebd..406121c 100644
---- a/hw/etraxfs_ser.c
-+++ b/hw/etraxfs_ser.c
-@@ -190,6 +190,12 @@ static void serial_event(void *opaque, int event)
-
- }
-
-+static const QemuChrHandlers serial_handlers = {
-+ .fd_can_read = serial_can_receive,
-+ .fd_read = serial_receive,
-+ .fd_event = serial_event,
-+};
-+
- static int etraxfs_ser_init(SysBusDevice *dev)
- {
- struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
-@@ -204,10 +210,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
- s->chr = qdev_init_chardev(&dev->qdev);
-- if (s->chr)
-- qemu_chr_add_handlers(s->chr,
-- serial_can_receive, serial_receive,
-- serial_event, s);
-+ if (s->chr) {
-+ qemu_chr_add_handlers(s->chr, &serial_handlers, s);
-+ }
- return 0;
- }
-
-diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
-index 101b150..40d6968 100644
---- a/hw/grlib_apbuart.c
-+++ b/hw/grlib_apbuart.c
-@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
- NULL, NULL, grlib_apbuart_writel,
- };
-
-+static const QemuChrHandlers grlib_handlers = {
-+ .fd_can_read = grlib_apbuart_can_receive,
-+ .fd_read = grlib_apbuart_receive,
-+ .fd_event = grlib_apbuart_event,
-+};
-+
- static int grlib_apbuart_init(SysBusDevice *dev)
- {
- UART *uart = FROM_SYSBUS(typeof(*uart), dev);
- int uart_regs = 0;
-
-- qemu_chr_add_handlers(uart->chr,
-- grlib_apbuart_can_receive,
-- grlib_apbuart_receive,
-- grlib_apbuart_event,
-- uart);
-+ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
-
- sysbus_init_irq(dev, &uart->irq);
-
-diff --git a/hw/ivshmem.c b/hw/ivshmem.c
-index 7b19a81..ef8e5ce 100644
---- a/hw/ivshmem.c
-+++ b/hw/ivshmem.c
-@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
- msix_notify(pdev, entry->vector);
- }
-
-+static const QemuChrHandlers ivshmem_handlers = {
-+ .fd_can_read = ivshmem_can_receive,
-+ .fd_read = ivshmem_receive,
-+ .fd_event = ivshmem_event,
-+};
-+
-+static const QemuChrHandlers ivshmem_msi_handlers = {
-+ .fd_can_read = ivshmem_can_receive,
-+ .fd_read = fake_irqfd,
-+ .fd_event = ivshmem_event,
-+};
-+
- static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
- int vector)
- {
-@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
- s->eventfd_table[vector].pdev = &s->dev;
- s->eventfd_table[vector].vector = vector;
-
-- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
-- ivshmem_event, &s->eventfd_table[vector]);
-+ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
-+ &s->eventfd_table[vector]);
- } else {
-- qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
-- ivshmem_event, s);
-+ qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
- }
-
- return chr;
-@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
- return 0;
- }
-
-+static const QemuChrHandlers ivshmem_server_handlers = {
-+ .fd_can_read = ivshmem_can_receive,
-+ .fd_read = ivshmem_read,
-+ .fd_event = ivshmem_event,
-+};
-+
- static int pci_ivshmem_init(PCIDevice *dev)
- {
- IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
-@@ -754,8 +771,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
-
- s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *));
-
-- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
-- ivshmem_event, s);
-+ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
- } else {
- /* just map the file immediately, we're not using a server */
- int fd;
-diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
-index db57096..9928c11 100644
---- a/hw/mcf_uart.c
-+++ b/hw/mcf_uart.c
-@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
- mcf_uart_push_byte(s, buf[0]);
- }
-
-+static const QemuChrHandlers mcf_uart_handlers = {
-+ .fd_can_read = mcf_uart_can_receive,
-+ .fd_read = mcf_uart_receive,
-+ .fd_event = mcf_uart_event,
-+};
-+
- void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
- {
- mcf_uart_state *s;
-@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
- s->chr = chr;
- s->irq = irq;
- if (chr) {
-- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
-- mcf_uart_event, s);
-+ qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
- }
- mcf_uart_reset(s);
- return s;
-diff --git a/hw/pl011.c b/hw/pl011.c
-index 77f0dbf..d93c655 100644
---- a/hw/pl011.c
-+++ b/hw/pl011.c
-@@ -286,6 +286,12 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id)
- return 0;
- }
-
-+static const QemuChrHandlers pl011_handlers = {
-+ .fd_can_read = pl011_can_receive,
-+ .fd_read = pl011_receive,
-+ .fd_event = pl011_event,
-+};
-+
- static int pl011_init(SysBusDevice *dev, const unsigned char *id)
- {
- int iomemtype;
-@@ -304,8 +310,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
- s->cr = 0x300;
- s->flags = 0x90;
- if (s->chr) {
-- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
-- pl011_event, s);
-+ qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
- }
- register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
- return 0;
-diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
-index d966846..d7ebf33 100644
---- a/hw/pxa2xx.c
-+++ b/hw/pxa2xx.c
-@@ -1995,6 +1995,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
- return 0;
- }
-
-+static const QemuChrHandlers pxa2xx_handlers = {
-+ .fd_can_read = pxa2xx_fir_is_empty,
-+ .fd_read = pxa2xx_fir_rx,
-+ .fd_event = pxa2xx_fir_event,
-+};
-+
- static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
- qemu_irq irq, PXA2xxDMAState *dma,
- CharDriverState *chr)
-@@ -2013,10 +2019,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
- pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(base, 0x1000, iomemtype);
-
-- if (chr)
-- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
-- pxa2xx_fir_rx, pxa2xx_fir_event, s);
--
-+ if (chr) {
-+ qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
-+ }
- register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
- pxa2xx_fir_load, s);
-
-diff --git a/hw/serial.c b/hw/serial.c
-index 2c4af61..65265e2 100644
---- a/hw/serial.c
-+++ b/hw/serial.c
-@@ -727,6 +727,12 @@ static void serial_reset(void *opaque)
- qemu_irq_lower(s->irq);
- }
-
-+static const QemuChrHandlers serial_handlers = {
-+ .fd_can_read = serial_can_receive1,
-+ .fd_read = serial_receive1,
-+ .fd_event = serial_event,
-+};
-+
- static void serial_init_core(SerialState *s)
- {
- if (!s->chr) {
-@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s)
-
- qemu_register_reset(serial_reset, s);
-
-- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
-- serial_event, s);
-+ qemu_chr_add_handlers(s->chr, &serial_handlers, s);
- }
-
- /* Change the main reference oscillator frequency. */
-diff --git a/hw/sh_serial.c b/hw/sh_serial.c
-index 191f4a6..8b6460d 100644
---- a/hw/sh_serial.c
-+++ b/hw/sh_serial.c
-@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
- &sh_serial_write,
- };
-
-+static const QemuChrHandlers sh_serial_handlers = {
-+ .fd_can_read = sh_serial_can_receive1,
-+ .fd_read = sh_serial_receive1,
-+ .fd_event = sh_serial_event,
-+};
-+
- void sh_serial_init (target_phys_addr_t base, int feat,
- uint32_t freq, CharDriverState *chr,
- qemu_irq eri_source,
-@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
-
- s->chr = chr;
-
-- if (chr)
-- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
-- sh_serial_event, s);
-+ if (chr) {
-+ qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
-+ }
-
- s->eri = eri_source;
- s->rxi = rxi_source;
-diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
-index 34ce076..124b636 100644
---- a/hw/syborg_serial.c
-+++ b/hw/syborg_serial.c
-@@ -315,6 +315,12 @@ static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
- return 0;
- }
-
-+static const QemuChrHandlers syborg_serial_handlers = {
-+ .fd_can_read = syborg_serial_can_receive,
-+ .fd_read = syborg_serial_receive,
-+ .fd_event = syborg_serial_event,
-+};
-+
- static int syborg_serial_init(SysBusDevice *dev)
- {
- SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
-@@ -327,8 +333,7 @@ static int syborg_serial_init(SysBusDevice *dev)
- sysbus_init_mmio(dev, 0x1000, iomemtype);
- s->chr = qdev_init_chardev(&dev->qdev);
- if (s->chr) {
-- qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
-- syborg_serial_receive, syborg_serial_event, s);
-+ qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s);
- }
- if (s->fifo_size <= 0) {
- fprintf(stderr, "syborg_serial: fifo too small\n");
-diff --git a/hw/usb-serial.c b/hw/usb-serial.c
-index 6763d52..2435d9d 100644
---- a/hw/usb-serial.c
-+++ b/hw/usb-serial.c
-@@ -475,6 +475,12 @@ static void usb_serial_event(void *opaque, int event)
- }
- }
-
-+static const QemuChrHandlers usb_serial_handlers = {
-+ .fd_can_read = usb_serial_can_read,
-+ .fd_read = usb_serial_read,
-+ .fd_event = usb_serial_event,
-+};
-+
- static int usb_serial_initfn(USBDevice *dev)
- {
- USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
-@@ -486,8 +492,7 @@ static int usb_serial_initfn(USBDevice *dev)
- return -1;
- }
-
-- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
-- usb_serial_event, s);
-+ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
- usb_serial_handle_reset(dev);
- return 0;
- }
-diff --git a/hw/virtio-console.c b/hw/virtio-console.c
-index 62624ec..22cf28c 100644
---- a/hw/virtio-console.c
-+++ b/hw/virtio-console.c
-@@ -57,13 +57,18 @@ static void chr_event(void *opaque, int event)
- }
- }
-
-+static const QemuChrHandlers chr_handlers = {
-+ .fd_can_read = chr_can_read,
-+ .fd_read = chr_read,
-+ .fd_event = chr_event,
-+};
-+
- static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
- {
- vcon->port.info = dev->info;
-
- if (vcon->chr) {
-- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
-- vcon);
-+ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
- vcon->port.info->have_data = flush_buf;
- }
- return 0;
-diff --git a/hw/xen_console.c b/hw/xen_console.c
-index d2261f4..8327e4e 100644
---- a/hw/xen_console.c
-+++ b/hw/xen_console.c
-@@ -202,6 +202,11 @@ static int con_init(struct XenDevice *xendev)
- return 0;
- }
-
-+static const QemuChrHandlers xencons_handlers = {
-+ .fd_can_read = xencons_can_receive,
-+ .fd_read = xencons_receive,
-+};
-+
- static int con_connect(struct XenDevice *xendev)
- {
- struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
-@@ -222,9 +227,9 @@ static int con_connect(struct XenDevice *xendev)
- return -1;
-
- xen_be_bind_evtchn(&con->xendev);
-- if (con->chr)
-- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
-- NULL, con);
-+ if (con->chr) {
-+ qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
-+ }
-
- xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
- con->ring_ref,
-@@ -238,8 +243,9 @@ static void con_disconnect(struct XenDevice *xendev)
- {
- struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
-
-- if (con->chr)
-- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
-+ if (con->chr) {
-+ qemu_chr_add_handlers(con->chr, NULL, NULL);
-+ }
- xen_be_unbind_evtchn(&con->xendev);
-
- if (con->sring) {
-diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
-index 9b94e98..1845577 100644
---- a/hw/xilinx_uartlite.c
-+++ b/hw/xilinx_uartlite.c
-@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event)
-
- }
-
-+static const QemuChrHandlers uart_handlers = {
-+ .fd_can_read = uart_can_rx,
-+ .fd_read = uart_rx,
-+ .fd_event = uart_event,
-+};
-+
- static int xilinx_uartlite_init(SysBusDevice *dev)
- {
- struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
-@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
- sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
-
- s->chr = qdev_init_chardev(&dev->qdev);
-- if (s->chr)
-- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-+ if (s->chr) {
-+ qemu_chr_add_handlers(s->chr, &uart_handlers, s);
-+ }
- return 0;
- }
-
-diff --git a/monitor.c b/monitor.c
-index 096d42b..a00a233 100644
---- a/monitor.c
-+++ b/monitor.c
-@@ -5179,6 +5179,18 @@ static void monitor_event(void *opaque, int event)
- * End:
- */
-
-+static const QemuChrHandlers monitor_handlers = {
-+ .fd_can_read = monitor_can_read,
-+ .fd_read = monitor_read,
-+ .fd_event = monitor_event,
-+};
-+
-+static const QemuChrHandlers monitor_control_handlers = {
-+ .fd_can_read = monitor_can_read,
-+ .fd_read = monitor_control_read,
-+ .fd_event = monitor_control_event,
-+};
-+
- void monitor_init(CharDriverState *chr, int flags)
- {
- static int is_first_init = 1;
-@@ -5201,12 +5213,10 @@ void monitor_init(CharDriverState *chr, int flags)
- if (monitor_ctrl_mode(mon)) {
- mon->mc = qemu_mallocz(sizeof(MonitorControl));
- /* Control mode requires special handlers */
-- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
-- monitor_control_event, mon);
-+ qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
- qemu_chr_set_echo(chr, true);
- } else {
-- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
-- monitor_event, mon);
-+ qemu_chr_add_handlers(chr, &monitor_handlers, mon);
- }
-
- QLIST_INSERT_HEAD(&mon_list, mon, entry);
-diff --git a/net/slirp.c b/net/slirp.c
-index b41c60a..437be46 100644
---- a/net/slirp.c
-+++ b/net/slirp.c
-@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
- slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
- }
-
-+static const QemuChrHandlers guestfwd_handlers = {
-+ .fd_can_read = guestfwd_can_read,
-+ .fd_read = guestfwd_read,
-+};
-+
- static int slirp_guestfwd(SlirpState *s, const char *config_str,
- int legacy_format)
- {
-@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
- fwd->port = port;
- fwd->slirp = s->slirp;
-
-- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
-- NULL, fwd);
-+ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
- return 0;
-
- fail_syntax:
-diff --git a/qemu-char.c b/qemu-char.c
-index 4b57af9..3a31d8b 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -191,15 +191,22 @@ void qemu_chr_send_event(CharDriverState *s, int event)
- s->chr_send_event(s, event);
- }
-
-+static const QemuChrHandlers null_handlers = {
-+ /* All handlers are initialised to NULL */
-+};
-+
- void qemu_chr_add_handlers(CharDriverState *s,
-- IOCanReadHandler *fd_can_read,
-- IOReadHandler *fd_read,
-- IOEventHandler *fd_event,
-- void *opaque)
--{
-- s->chr_can_read = fd_can_read;
-- s->chr_read = fd_read;
-- s->chr_event = fd_event;
-+ const QemuChrHandlers *handlers, void *opaque)
-+{
-+ if (!s) {
-+ return;
-+ }
-+ if (!handlers) {
-+ handlers = &null_handlers;
-+ }
-+ s->chr_can_read = handlers->fd_can_read;
-+ s->chr_read = handlers->fd_read;
-+ s->chr_event = handlers->fd_event;
- s->handler_opaque = opaque;
- if (s->chr_update_read_handler)
- s->chr_update_read_handler(s);
-@@ -437,6 +444,12 @@ static void mux_chr_event(void *opaque, int event)
- mux_chr_send_event(d, i, event);
- }
-
-+static const QemuChrHandlers mux_chr_handlers = {
-+ .fd_can_read = mux_chr_can_read,
-+ .fd_read = mux_chr_read,
-+ .fd_event = mux_chr_event,
-+};
-+
- static void mux_chr_update_read_handler(CharDriverState *chr)
- {
- MuxDriver *d = chr->opaque;
-@@ -451,8 +464,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
- d->chr_event[d->mux_cnt] = chr->chr_event;
- /* Fix up the real driver with mux routines */
- if (d->mux_cnt == 0) {
-- qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
-- mux_chr_event, chr);
-+ qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
- }
- if (d->focus != -1) {
- mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
-diff --git a/qemu-char.h b/qemu-char.h
-index 56d9954..7a1924c 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -1,6 +1,7 @@
- #ifndef QEMU_CHAR_H
- #define QEMU_CHAR_H
-
-+#include <stdbool.h>
- #include "qemu-common.h"
- #include "qemu-queue.h"
- #include "qemu-option.h"
-@@ -73,6 +74,13 @@ struct CharDriverState {
- QTAILQ_ENTRY(CharDriverState) next;
- };
-
-+typedef struct QemuChrHandlers {
-+ IOCanReadHandler *fd_can_read;
-+ IOReadHandler *fd_read;
-+ IOHandler *fd_write_unblocked;
-+ IOEventHandler *fd_event;
-+} QemuChrHandlers;
-+
- QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
- CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
- void (*init)(struct CharDriverState *s));
-@@ -83,10 +91,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
- GCC_FMT_ATTR(2, 3);
- int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
- void qemu_chr_send_event(CharDriverState *s, int event);
--void qemu_chr_add_handlers(CharDriverState *s,
-- IOCanReadHandler *fd_can_read,
-- IOReadHandler *fd_read,
-- IOEventHandler *fd_event,
-+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
- void *opaque);
- int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
- void qemu_chr_generic_open(CharDriverState *s);
---
-1.7.4.1
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
deleted file mode 100644
index 336c582..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
+++ /dev/null
@@ -1,76 +0,0 @@
->From da7e6cd863ed0cffe885cd2d3639f92c82baf6e2 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 20:32:58 +0100
-Subject: [PATCH 07/17] iohandlers: Add enable/disable_write_fd_handler() functions
-
-These will be used to provide a cleaner API for the nonblocking case.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.h | 3 +++
- vl.c | 35 +++++++++++++++++++++++++++++++++++
- 2 files changed, 38 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.h b/qemu-char.h
-index 7a1924c..185377c 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -116,6 +116,9 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr);
-
- /* async I/O support */
-
-+void enable_write_fd_handler(int fd, IOHandler *fd_write);
-+void disable_write_fd_handler(int fd);
-+
- int qemu_set_fd_handler2(int fd,
- IOCanReadHandler *fd_read_poll,
- IOHandler *fd_read,
-diff --git a/vl.c b/vl.c
-index 85c36e3..95f51cb 100644
---- a/vl.c
-+++ b/vl.c
-@@ -1044,6 +1044,41 @@ typedef struct IOHandlerRecord {
- static QLIST_HEAD(, IOHandlerRecord) io_handlers =
- QLIST_HEAD_INITIALIZER(io_handlers);
-
-+static IOHandlerRecord *find_iohandler(int fd)
-+{
-+ IOHandlerRecord *ioh;
-+
-+ QLIST_FOREACH(ioh, &io_handlers, next) {
-+ if (ioh->fd == fd) {
-+ return ioh;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+void enable_write_fd_handler(int fd, IOHandler *fd_write)
-+{
-+ IOHandlerRecord *ioh;
-+
-+ ioh = find_iohandler(fd);
-+ if (!ioh) {
-+ return;
-+ }
-+
-+ ioh->fd_write = fd_write;
-+}
-+
-+void disable_write_fd_handler(int fd)
-+{
-+ IOHandlerRecord *ioh;
-+
-+ ioh = find_iohandler(fd);
-+ if (!ioh) {
-+ return;
-+ }
-+
-+ ioh->fd_write = NULL;
-+}
-
- /* XXX: fd_read_poll should be suppressed, but an API change is
- necessary in the character devices to suppress fd_can_read(). */
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch
deleted file mode 100644
index ab3eb1f..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch
+++ /dev/null
@@ -1,62 +0,0 @@
->From daf37480ffe37b3e7a781ff010beb4fa89821c29 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 21:41:42 +0100
-Subject: [PATCH 08/17] char: Add framework for a 'write unblocked' callback
-
-The char layer can let users know that the driver will block on further
-input. For users interested in not blocking, they can assign a function
-pointer that will be called back when the driver becomes writable. This
-patch just adds the function pointers to the CharDriverState structure,
-future patches will enable the nonblocking and callback functionality.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c | 3 +++
- qemu-char.h | 5 +++++
- 2 files changed, 8 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 3a31d8b..ce76411 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -206,11 +206,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
- }
- s->chr_can_read = handlers->fd_can_read;
- s->chr_read = handlers->fd_read;
-+ s->chr_write_unblocked = handlers->fd_write_unblocked;
- s->chr_event = handlers->fd_event;
- s->handler_opaque = opaque;
- if (s->chr_update_read_handler)
- s->chr_update_read_handler(s);
-
-+ s->write_blocked = false;
-+
- /* We're connecting to an already opened device, so let's make sure we
- also get the open event */
- if (s->opened) {
-diff --git a/qemu-char.h b/qemu-char.h
-index 185377c..bf06da0 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -61,6 +61,9 @@ struct CharDriverState {
- IOEventHandler *chr_event;
- IOCanReadHandler *chr_can_read;
- IOReadHandler *chr_read;
-+ IOHandler *chr_write_unblocked;
-+ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
-+ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
- void *handler_opaque;
- void (*chr_send_event)(struct CharDriverState *chr, int event);
- void (*chr_close)(struct CharDriverState *chr);
-@@ -71,6 +74,8 @@ struct CharDriverState {
- char *label;
- char *filename;
- int opened;
-+ /* Are we in a blocked state? */
-+ bool write_blocked;
- QTAILQ_ENTRY(CharDriverState) next;
- };
-
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
deleted file mode 100644
index ccf98ad..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
+++ /dev/null
@@ -1,197 +0,0 @@
->From 8b73193a8584da4e93bccd93fe6f0b8f1a1612b3 Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:00:27 +0100
-Subject: [PATCH 09/17] char: Update send_all() to handle nonblocking chardev write requests
-
-The send_all function is modified to return to the caller in case the
-driver cannot handle any more data. It returns -EAGAIN or
-WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This
-is only done when the caller sets a callback function handler indicating
-it's not interested in blocking till the driver has written out all the
-data.
-
-Currently there's no driver or caller that supports this. Future
-commits will add such capability.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- net/socket.c | 4 +-
- qemu-char.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
- qemu_socket.h | 2 +-
- 3 files changed, 76 insertions(+), 9 deletions(-)
-
-diff --git a/net/socket.c b/net/socket.c
-index 3182b37..5dedd78 100644
---- a/net/socket.c
-+++ b/net/socket.c
-@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
- uint32_t len;
- len = htonl(size);
-
-- send_all(s->fd, (const uint8_t *)&len, sizeof(len));
-- return send_all(s->fd, buf, size);
-+ send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len));
-+ return send_all(NULL, s->fd, buf, size);
- }
-
- static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
-diff --git a/qemu-char.c b/qemu-char.c
-index ce76411..eed61d6 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -500,7 +500,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
-
-
- #ifdef _WIN32
--int send_all(int fd, const void *buf, int len1)
-+static int do_send(int fd, const void *buf, int len1, bool nonblock)
- {
- int ret, len;
-
-@@ -508,9 +508,14 @@ int send_all(int fd, const void *buf, int len1)
- while (len > 0) {
- ret = send(fd, buf, len, 0);
- if (ret < 0) {
-+ if (nonblock && len1 - len) {
-+ return len1 - len;
-+ }
- errno = WSAGetLastError();
- if (errno != WSAEWOULDBLOCK) {
- return -1;
-+ } else if (errno == WSAEWOULDBLOCK && nonblock) {
-+ return WSAEWOULDBLOCK;
- }
- } else if (ret == 0) {
- break;
-@@ -524,7 +529,7 @@ int send_all(int fd, const void *buf, int len1)
-
- #else
-
--int send_all(int fd, const void *_buf, int len1)
-+static int do_send(int fd, const void *_buf, int len1, bool nonblock)
- {
- int ret, len;
- const uint8_t *buf = _buf;
-@@ -533,8 +538,15 @@ int send_all(int fd, const void *_buf, int len1)
- while (len > 0) {
- ret = write(fd, buf, len);
- if (ret < 0) {
-- if (errno != EINTR && errno != EAGAIN)
-+ if (nonblock && len1 - len) {
-+ return len1 - len;
-+ }
-+ if (errno == EAGAIN && nonblock) {
-+ return -EAGAIN;
-+ }
-+ if (errno != EINTR && errno != EAGAIN) {
- return -1;
-+ }
- } else if (ret == 0) {
- break;
- } else {
-@@ -546,6 +558,55 @@ int send_all(int fd, const void *_buf, int len1)
- }
- #endif /* !_WIN32 */
-
-+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
-+{
-+ int ret, eagain_errno;
-+ bool nonblock;
-+
-+ if (chr && chr->write_blocked) {
-+ /*
-+ * We don't handle this situation: the caller should not send
-+ * us data while we're blocked.
-+ *
-+ * We could buffer this data here but that'll only encourage
-+ * bad behaviour on part of the callers.
-+ *
-+ * Also, the data already in fd's buffers isn't easily
-+ * migratable. If we want full migration support, all the
-+ * data landing here needs to be buffered and on migration,
-+ * anything that's unsent needs to be transferred to the
-+ * dest. machine (which again isn't a very good way of solving
-+ * the problem, as the src may become writable just during
-+ * migration and the reader could receive some data twice,
-+ * essentially corrupting the data).
-+ */
-+ abort();
-+ }
-+
-+ nonblock = false;
-+ /*
-+ * Ensure the char backend is able to receive and handle the
-+ * 'write unblocked' event before we turn on nonblock support.
-+ */
-+ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
-+ nonblock = true;
-+ }
-+ ret = do_send(fd, _buf, len1, nonblock);
-+
-+#ifdef _WIN32
-+ eagain_errno = WSAEWOULDBLOCK;
-+#else
-+ eagain_errno = -EAGAIN;
-+#endif
-+
-+ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
-+ /* Update fd handler to wake up when chr becomes writable */
-+ chr->chr_enable_write_fd_handler(chr);
-+ chr->write_blocked = true;
-+ }
-+ return ret;
-+}
-+
- #ifndef _WIN32
-
- typedef struct {
-@@ -559,7 +620,7 @@ static int stdio_nb_clients = 0;
- static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
- FDCharDriver *s = chr->opaque;
-- return send_all(s->fd_out, buf, len);
-+ return send_all(chr, s->fd_out, buf, len);
- }
-
- static int fd_chr_read_poll(void *opaque)
-@@ -875,7 +936,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- pty_chr_update_read_handler(chr);
- return 0;
- }
-- return send_all(s->fd, buf, len);
-+ return send_all(chr, s->fd, buf, len);
- }
-
- static int pty_chr_read_poll(void *opaque)
-@@ -1944,8 +2005,14 @@ static void tcp_closed(void *opaque)
- static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
- TCPCharDriver *s = chr->opaque;
-+
- if (s->connected) {
-- return send_all(s->fd, buf, len);
-+ int ret;
-+
-+ ret = send_all(chr, s->fd, buf, len);
-+ if (ret == -1 && errno == EPIPE) {
-+ tcp_closed(chr);
-+ }
- } else {
- /* XXX: indicate an error ? */
- return len;
-diff --git a/qemu_socket.h b/qemu_socket.h
-index 897a8ae..97dd24a 100644
---- a/qemu_socket.h
-+++ b/qemu_socket.h
-@@ -36,7 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
- int qemu_socket(int domain, int type, int protocol);
- int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
- void socket_set_nonblock(int fd);
--int send_all(int fd, const void *buf, int len1);
-+int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
-
- /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
- int inet_listen_opts(QemuOpts *opts, int port_offset);
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
deleted file mode 100644
index f08d700..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
+++ /dev/null
@@ -1,80 +0,0 @@
->From 7d8cbead9454da6dbfdc050c6828faae39621a1b Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:02:47 +0100
-Subject: [PATCH 10/17] char: Equip the unix/tcp backend to handle nonblocking writes#
-
-Now that the infrastructure is in place to return -EAGAIN to callers,
-individual char drivers can set their update_fd_handlers() function to
-set or remove an fd's write handler. This handler checks if the driver
-became writable.
-
-A generic callback routine is used for unblocking writes and letting
-users of chardevs know that a driver became writable again.
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c | 34 ++++++++++++++++++++++++++++++++++
- 1 files changed, 34 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index eed61d6..7517f64 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -107,6 +107,19 @@
- static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
- QTAILQ_HEAD_INITIALIZER(chardevs);
-
-+/*
-+ * Generic routine that gets called when chardev becomes writable.
-+ * Lets chardev user know it's OK to send more data.
-+ */
-+static void char_write_unblocked(void *opaque)
-+{
-+ CharDriverState *chr = opaque;
-+
-+ chr->write_blocked = false;
-+ chr->chr_disable_write_fd_handler(chr);
-+ chr->chr_write_unblocked(chr->handler_opaque);
-+}
-+
- static void qemu_chr_event(CharDriverState *s, int event)
- {
- /* Keep track if the char device is open */
-@@ -2261,6 +2274,25 @@ static void tcp_chr_close(CharDriverState *chr)
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
- }
-
-+static void tcp_enable_write_fd_handler(CharDriverState *chr)
-+{
-+ TCPCharDriver *s = chr->opaque;
-+
-+ /*
-+ * This function is called only after tcp_chr_connect() is called
-+ * (either in 'server' mode or client mode. So we're sure of
-+ * s->fd being initialised.
-+ */
-+ enable_write_fd_handler(s->fd, char_write_unblocked);
-+}
-+
-+static void tcp_disable_write_fd_handler(CharDriverState *chr)
-+{
-+ TCPCharDriver *s = chr->opaque;
-+
-+ disable_write_fd_handler(s->fd);
-+}
-+
- static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
- {
- CharDriverState *chr = NULL;
-@@ -2313,6 +2345,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
- chr->chr_write = tcp_chr_write;
- chr->chr_close = tcp_chr_close;
- chr->get_msgfd = tcp_get_msgfd;
-+ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
-+ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
-
- if (is_listen) {
- s->listen_fd = fd;
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch
deleted file mode 100644
index 78f906a..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch
+++ /dev/null
@@ -1,56 +0,0 @@
->From 473be206466567646e3377b8eb64e25ffc2b3afe Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:05:10 +0100
-Subject: [PATCH 11/17] char: Throttle when host connection is down#
-
-When the host-side connection goes down, throttle the virtio-serial bus
-and later unthrottle when a connection gets established. This helps
-prevent any lost IO (guest->host) while the host connection was down.
-
-Bugzilla: 621484
-
-This commit actually helps the bug mentioned above as no writes will now
-get lost because of the throttling done here. With just the patches
-sent earlier for that bug, one write will end up getting lost in the
-worst case (host d/c, guest write, host connect).
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- qemu-char.c | 14 ++++++++++++++
- 1 files changed, 14 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 7517f64..2ef972f 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -141,6 +141,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
- {
- CharDriverState *s = opaque;
- qemu_chr_event(s, CHR_EVENT_OPENED);
-+ if (s->write_blocked) {
-+ char_write_unblocked(s);
-+ }
- qemu_bh_delete(s->bh);
- s->bh = NULL;
- }
-@@ -2025,6 +2028,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- ret = send_all(chr, s->fd, buf, len);
- if (ret == -1 && errno == EPIPE) {
- tcp_closed(chr);
-+
-+ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
-+ /*
-+ * Since we haven't written out anything, let's say
-+ * we're throttled. This will prevent any output from
-+ * the guest getting lost if host-side chardev goes
-+ * down. Unthrottle when we re-connect.
-+ */
-+ chr->write_blocked = true;
-+ return 0;
-+ }
- }
- } else {
- /* XXX: indicate an error ? */
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch
deleted file mode 100644
index 90f7629..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch
+++ /dev/null
@@ -1,48 +0,0 @@
->From 94e8b44e4fdfbf312e54b78ca7bbb95271cc83ae Mon Sep 17 00:00:00 2001
-From: Amit Shah <amit.shah@redhat.com>
-Date: Mon, 21 Mar 2011 22:06:41 +0100
-Subject: [PATCH 12/17] virtio-console: Enable port throttling when chardev is slow to consume data
-
-When a chardev indicates it can't accept more data, we tell the
-virtio-serial code to stop sending us any more data till we tell
-otherwise. This helps in guests continuing to run normally while the vq
-keeps getting full and eventually the guest stops queueing more data.
-As soon as the chardev indicates it can accept more data, start pushing!
-
-Signed-off-by: Amit Shah <amit.shah@redhat.com>
----
- hw/virtio-console.c | 11 +++++++++++
- 1 files changed, 11 insertions(+), 0 deletions(-)
-
-diff --git a/hw/virtio-console.c b/hw/virtio-console.c
-index 22cf28c..eecbdf7 100644
---- a/hw/virtio-console.c
-+++ b/hw/virtio-console.c
-@@ -18,6 +18,16 @@ typedef struct VirtConsole {
- CharDriverState *chr;
- } VirtConsole;
-
-+/*
-+ * Callback function that's called from chardevs when backend becomes
-+ * writable.
-+ */
-+static void chr_write_unblocked(void *opaque)
-+{
-+ VirtConsole *vcon = opaque;
-+
-+ virtio_serial_throttle_port(&vcon->port, false);
-+}
-
- /* Callback function that's called when the guest sends us data */
- static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
-@@ -61,6 +71,7 @@ static const QemuChrHandlers chr_handlers = {
- .fd_can_read = chr_can_read,
- .fd_read = chr_read,
- .fd_event = chr_event,
-+ .fd_write_unblocked = chr_write_unblocked,
- };
-
- static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch
deleted file mode 100644
index 34cb283..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch
+++ /dev/null
@@ -1,133 +0,0 @@
->From 06ad256d2939aea4086428dcb5e5e7d5f86eb335 Mon Sep 17 00:00:00 2001
-From: Alon Levy <alevy@redhat.com>
-Date: Tue, 22 Mar 2011 12:27:59 +0200
-Subject: [PATCH 13/17] spice-qemu-char.c: add throttling
-
-BZ: 672191
-
-upstream: not submitted (explained below)
-
-Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
-1. spice-server: reds.c: read_from_vdi_port
-2. qemu: spice-qemu-char.c: vmc_read
-3. chr_write_unblocked
- (calls virtio_serial_throttle_port(port, false))
-4. qemu: virtio ...
-5. qemu: spice-qemu-char.c: spice_chr_write
-6. qemu: spice-qemu-char.c: wakeup (calls into spice-server)
-7. spice-server: ...
-8. qemu: spice-qemu-char.c: vmc_read
-
-Instead, in vmc_read if we were throttled and we are just about to return
-all the bytes we will set a timer to be triggered immediately to call
-chr_write_unblocked. Then we return after 2 above, and 3 is called from the
-timer callback. This also means we can later remove some ugly recursion protection
-from spice-server.
-
-The other tricky point in this patch is not returning the leftover chunk twice.
-When we throttle, by definition we have data that spice server didn't consume.
-It is being kept by virtio-serial, and by us. The next vmc_read callback needs
-to not return it, but just do unthrottling. Then virtio will give us the remaining
-chunk as usual in spice_chr_write, and we will pass it to spice server in the
-next vmc_read.
-
-This patch relies on Amit's series to expose throttling to chardev's, which
-was not accepted upstream, and will not be accepted upstream until the mainloop
-is reworked to use glib.
----
- spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++----
- 1 files changed, 35 insertions(+), 4 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index 517f337..91467d5 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -1,4 +1,6 @@
- #include "config-host.h"
-+#include "qemu-common.h"
-+#include "qemu-timer.h"
- #include "trace.h"
- #include "ui/qemu-spice.h"
- #include <spice.h>
-@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
- uint8_t *datapos;
- ssize_t bufsize, datalen;
- uint32_t debug;
-+ QEMUTimer *unblock_timer;
- } SpiceCharDriver;
-
- static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-@@ -51,6 +54,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
- return out;
- }
-
-+static void spice_chr_unblock(void *opaque)
-+{
-+ SpiceCharDriver *scd = opaque;
-+
-+ if (scd->chr->chr_write_unblocked == NULL) {
-+ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
-+ return;
-+ }
-+ scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
-+}
-+
- static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
- {
- SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
-@@ -62,9 +76,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
- scd->datapos += bytes;
- scd->datalen -= bytes;
- assert(scd->datalen >= 0);
-- if (scd->datalen == 0) {
-- scd->datapos = 0;
-- }
-+ }
-+ if (scd->datalen == 0 && scd->chr->write_blocked) {
-+ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
-+ scd->chr->write_blocked = false;
-+ /*
-+ * set a timer instead of calling scd->chr->chr_write_unblocked directly,
-+ * because that will call back into spice_chr_write (see
-+ * virtio-console.c:chr_write_unblocked), which is unwanted.
-+ */
-+ qemu_mod_timer(scd->unblock_timer, 0);
- }
- trace_spice_vmc_read(bytes, len);
- return bytes;
-@@ -107,6 +128,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
- static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- {
- SpiceCharDriver *s = chr->opaque;
-+ int read_bytes;
-
- dprintf(s, 2, "%s: %d\n", __func__, len);
- vmc_register_interface(s);
-@@ -119,7 +141,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- s->datapos = s->buffer;
- s->datalen = len;
- spice_server_char_device_wakeup(&s->sin);
-- return len;
-+ read_bytes = len - s->datalen;
-+ if (read_bytes != len) {
-+ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
-+ read_bytes, len, s->bufsize);
-+ s->chr->write_blocked = true;
-+ /* We'll get passed in the unconsumed data with the next call */
-+ s->datalen = 0;
-+ }
-+ return read_bytes;
- }
-
- static void spice_chr_close(struct CharDriverState *chr)
-@@ -183,6 +213,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
- chr->opaque = s;
- chr->chr_write = spice_chr_write;
- chr->chr_close = spice_chr_close;
-+ s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s);
-
- qemu_chr_generic_open(chr);
-
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch
deleted file mode 100644
index 2f56ce6..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch
+++ /dev/null
@@ -1,71 +0,0 @@
->From 6ce8a141a37387a5138d0361cbe92885130010fe Mon Sep 17 00:00:00 2001
-From: Alon Levy <alevy@redhat.com>
-Date: Tue, 22 Mar 2011 12:28:00 +0200
-Subject: [PATCH 14/17] spice-qemu-char.c: remove intermediate buffer
-
-BZ: 672191
-upstream: not submitted (explained below)
-
-virtio-serial's buffer is valid when it calls us, and we don't
-access it otherwise: vmc_read is only called in response to wakeup,
-or else we set datalen=0 and throttle. Then vmc_read is called back,
-we return 0 (not accessing the buffer) and set the timer to unthrottle.
-
-Also make datalen int and not ssize_t (to fit spice_chr_write signature).
-
-This relied on the previous patch that introduces throttling, which
-can't go upstream right now as explained in that patch.
----
- spice-qemu-char.c | 18 ++++++------------
- 1 files changed, 6 insertions(+), 12 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index 91467d5..ed7851e 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
- SpiceCharDeviceInstance sin;
- char *subtype;
- bool active;
-- uint8_t *buffer;
-- uint8_t *datapos;
-- ssize_t bufsize, datalen;
-+ const uint8_t *datapos;
-+ int datalen;
- uint32_t debug;
- QEMUTimer *unblock_timer;
- } SpiceCharDriver;
-@@ -70,7 +69,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
- SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
- int bytes = MIN(len, scd->datalen);
-
-- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
-+ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
- if (bytes > 0) {
- memcpy(buf, scd->datapos, bytes);
- scd->datapos += bytes;
-@@ -133,18 +132,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
- dprintf(s, 2, "%s: %d\n", __func__, len);
- vmc_register_interface(s);
- assert(s->datalen == 0);
-- if (s->bufsize < len) {
-- s->bufsize = len;
-- s->buffer = qemu_realloc(s->buffer, s->bufsize);
-- }
-- memcpy(s->buffer, buf, len);
-- s->datapos = s->buffer;
-+ s->datapos = buf;
- s->datalen = len;
- spice_server_char_device_wakeup(&s->sin);
- read_bytes = len - s->datalen;
- if (read_bytes != len) {
-- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
-- read_bytes, len, s->bufsize);
-+ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
-+ read_bytes, len);
- s->chr->write_blocked = true;
- /* We'll get passed in the unconsumed data with the next call */
- s->datalen = 0;
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch
deleted file mode 100644
index bae63b8..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch
+++ /dev/null
@@ -1,76 +0,0 @@
->From c8cb28f0791ab38945c7facb5a63e445b4b6f41f Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 18 Mar 2011 15:23:21 +0100
-Subject: [PATCH 15/17] chardev: Allow frontends to notify backends of guest open / close
-
-Some frontends know when the guest has opened the "channel" and is actively
-listening to it, for example virtio-serial. This patch adds 2 new qemu-chardev
-functions which can be used by frontends to signal guest open / close, and
-allows interested backends to listen to this.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- qemu-char.c | 17 +++++++++++++++++
- qemu-char.h | 4 ++++
- 2 files changed, 21 insertions(+), 0 deletions(-)
-
-diff --git a/qemu-char.c b/qemu-char.c
-index 2ef972f..d52eb51 100644
---- a/qemu-char.c
-+++ b/qemu-char.c
-@@ -507,6 +507,9 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
- chr->chr_write = mux_chr_write;
- chr->chr_update_read_handler = mux_chr_update_read_handler;
- chr->chr_accept_input = mux_chr_accept_input;
-+ /* Frontend guest-open / -close notification is not support with muxes */
-+ chr->chr_guest_open = NULL;
-+ chr->chr_guest_close = NULL;
-
- /* Muxes are always open on creation */
- qemu_chr_generic_open(chr);
-@@ -2712,6 +2715,20 @@ void qemu_chr_set_echo(struct CharDriverState *chr, bool echo)
- }
- }
-
-+void qemu_chr_guest_open(struct CharDriverState *chr)
-+{
-+ if (chr->chr_guest_open) {
-+ chr->chr_guest_open(chr);
-+ }
-+}
-+
-+void qemu_chr_guest_close(struct CharDriverState *chr)
-+{
-+ if (chr->chr_guest_close) {
-+ chr->chr_guest_close(chr);
-+ }
-+}
-+
- void qemu_chr_close(CharDriverState *chr)
- {
- QTAILQ_REMOVE(&chardevs, chr, next);
-diff --git a/qemu-char.h b/qemu-char.h
-index bf06da0..f3b9bf4 100644
---- a/qemu-char.h
-+++ b/qemu-char.h
-@@ -69,6 +69,8 @@ struct CharDriverState {
- void (*chr_close)(struct CharDriverState *chr);
- void (*chr_accept_input)(struct CharDriverState *chr);
- void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
-+ void (*chr_guest_open)(struct CharDriverState *chr);
-+ void (*chr_guest_close)(struct CharDriverState *chr);
- void *opaque;
- QEMUBH *bh;
- char *label;
-@@ -91,6 +93,8 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
- void (*init)(struct CharDriverState *s));
- CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
- void qemu_chr_set_echo(struct CharDriverState *chr, bool echo);
-+void qemu_chr_guest_open(struct CharDriverState *chr);
-+void qemu_chr_guest_close(struct CharDriverState *chr);
- void qemu_chr_close(CharDriverState *chr);
- void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
- GCC_FMT_ATTR(2, 3);
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch
deleted file mode 100644
index 0b3e3f8..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch
+++ /dev/null
@@ -1,49 +0,0 @@
->From 3baf76e384c04f58f032632c078860d66c8c9db3 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 18 Mar 2011 15:30:45 +0100
-Subject: [PATCH 16/17] virtio-console: notify backend of guest open / close
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- hw/virtio-console.c | 18 ++++++++++++++++++
- 1 files changed, 18 insertions(+), 0 deletions(-)
-
-diff --git a/hw/virtio-console.c b/hw/virtio-console.c
-index eecbdf7..828a1a3 100644
---- a/hw/virtio-console.c
-+++ b/hw/virtio-console.c
-@@ -37,6 +37,22 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
- return qemu_chr_write(vcon->chr, buf, len);
- }
-
-+/* Callback function that's called when the guest opens the port */
-+static void guest_open(VirtIOSerialPort *port)
-+{
-+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-+
-+ qemu_chr_guest_open(vcon->chr);
-+}
-+
-+/* Callback function that's called when the guest closes the port */
-+static void guest_close(VirtIOSerialPort *port)
-+{
-+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-+
-+ qemu_chr_guest_close(vcon->chr);
-+}
-+
- /* Readiness of the guest to accept data on a port */
- static int chr_can_read(void *opaque)
- {
-@@ -81,6 +97,8 @@ static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
- if (vcon->chr) {
- qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
- vcon->port.info->have_data = flush_buf;
-+ vcon->port.info->guest_open = guest_open;
-+ vcon->port.info->guest_close = guest_close;
- }
- return 0;
- }
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch
deleted file mode 100644
index 1944bbc..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch
+++ /dev/null
@@ -1,49 +0,0 @@
->From c169795bed5374f0071af201da2dd32b3c5a2417 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 18 Mar 2011 15:35:27 +0100
-Subject: [PATCH 17/17] spice-chardev: listen to frontend guest open / close
-
-Note the vmc_register_interface() in spice_chr_write is left in place
-in case someone uses spice-chardev with a frontend which does not have
-guest open / close notification.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- spice-qemu-char.c | 14 ++++++++++++++
- 1 files changed, 14 insertions(+), 0 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index ed7851e..343146c 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -155,6 +155,18 @@ static void spice_chr_close(struct CharDriverState *chr)
- qemu_free(s);
- }
-
-+static void spice_chr_guest_open(struct CharDriverState *chr)
-+{
-+ SpiceCharDriver *s = chr->opaque;
-+ vmc_register_interface(s);
-+}
-+
-+static void spice_chr_guest_close(struct CharDriverState *chr)
-+{
-+ SpiceCharDriver *s = chr->opaque;
-+ vmc_unregister_interface(s);
-+}
-+
- static void print_allowed_subtypes(void)
- {
- const char** psubtype;
-@@ -207,6 +219,8 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
- chr->opaque = s;
- chr->chr_write = spice_chr_write;
- chr->chr_close = spice_chr_close;
-+ chr->chr_guest_open = spice_chr_guest_open;
-+ chr->chr_guest_close = spice_chr_guest_close;
- s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s);
-
- qemu_chr_generic_open(chr);
---
-1.7.3.2
-
diff --git a/app-emulation/qemu-kvm/files/patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch b/app-emulation/qemu-kvm/files/patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch
deleted file mode 100644
index a6c2445..0000000
--- a/app-emulation/qemu-kvm/files/patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch
+++ /dev/null
@@ -1,56 +0,0 @@
->From 7a9e7aaa30abf42879d3f13b41679513045c31ec Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 22 Mar 2011 16:28:41 +0100
-Subject: [PATCH 18/18] spice-qemu-char: Fix flow control in client -> guest direction
-
-In the old spice-vmc device we used to have:
-last_out = virtio_serial_write(&svc->port, p, MIN(len, VMC_MAX_HOST_WRITE));
-if (last_out > 0)
- ...
-
-Now in the chardev backend we have:
-last_out = MIN(len, VMC_MAX_HOST_WRITE);
-qemu_chr_read(scd->chr, p, last_out);
-if (last_out > 0) {
- ...
-
-Which causes us to no longer detect if the virtio port is not ready
-to receive data from us. chardev actually has a mechanism to detect this,
-but it requires a separate call to qemu_chr_can_read, before calling
-qemu_chr_read (which return void).
-
-This patch uses qemu_chr_can_read to fix the flow control from client to
-guest.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- spice-qemu-char.c | 11 +++++------
- 1 files changed, 5 insertions(+), 6 deletions(-)
-
-diff --git a/spice-qemu-char.c b/spice-qemu-char.c
-index 343146c..def713a 100644
---- a/spice-qemu-char.c
-+++ b/spice-qemu-char.c
-@@ -38,14 +38,13 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-
- while (len > 0) {
- last_out = MIN(len, VMC_MAX_HOST_WRITE);
-- qemu_chr_read(scd->chr, p, last_out);
-- if (last_out > 0) {
-- out += last_out;
-- len -= last_out;
-- p += last_out;
-- } else {
-+ if (qemu_chr_can_read(scd->chr) < last_out) {
- break;
- }
-+ qemu_chr_read(scd->chr, p, last_out);
-+ out += last_out;
-+ len -= last_out;
-+ p += last_out;
- }
-
- dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out);
---
-1.7.3.2
-
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
deleted file mode 100644
index c069f89..0000000
--- a/app-emulation/qemu-kvm/files/qemu-0.11.0-mips64-user-fix.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- 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
deleted file mode 100644
index 844147d..0000000
--- a/app-emulation/qemu-kvm/files/qemu-kvm
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec /usr/bin/qemu-system-x86_64 --enable-kvm "$@"
diff --git a/app-emulation/qemu-kvm/qemu-kvm-0.14.1-r2.ebuild b/app-emulation/qemu-kvm/qemu-kvm-0.14.1-r2.ebuild
deleted file mode 100644
index e26fdc3..0000000
--- a/app-emulation/qemu-kvm/qemu-kvm-0.14.1-r2.ebuild
+++ /dev/null
@@ -1,273 +0,0 @@
-# Copyright 1999-2011 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu-kvm/qemu-kvm-9999.ebuild,v 1.16 2011/03/28 03:31:46 flameeyes Exp $
-
-BACKPORTS=1
-
-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 multilib
-
-if [[ ${PV} = *9999* ]]; then
- SRC_URI=""
- KEYWORDS=""
-else
- SRC_URI="mirror://sourceforge/kvm/${PN}/${P}.tar.gz
- ${BACKPORTS:+http://dev.gentoo.org/~cardoe/distfiles/${P}-backports-${BACKPORTS}.tar.bz2}"
- 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 debug esd fdt hardened jpeg ncurses \
-png pulseaudio qemu-ifup rbd sasl sdl spice ssl threads vde \
-+vhost-net xen"
-# static, depends on libsdl being built with USE=static-libs, which can not
-# be expressed in current EAPI's
-
-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 )
- rbd? ( sys-cluster/ceph )
- sasl? ( dev-libs/cyrus-sasl )
- sdl? ( >=media-libs/libsdl-1.2.11[X] )
- spice? ( app-emulation/spice )
- ssl? ( net-libs/gnutls )
- vde? ( net-misc/vde )
- xen? ( app-emulation/xen )
-"
-
-DEPEND="${RDEPEND}
- app-text/texi2html
- >=sys-kernel/linux-headers-2.6.35
- 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
- if use vhost-net && ! linux_chkconfig_present VHOST_NET ; then
- ewarn "You have to enable CONFIG_VHOST_NET in the kernel"
- ewarn "to have vhost-net support."
- 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"
-
- [[ -n ${BACKPORTS} ]] && \
- EPATCH_FORCE=yes EPATCH_SUFFIX="patch" EPATCH_SOURCE="${S}/patches" \
- epatch
-
- EPATCH_SOURCE="${FILESDIR}/patches-from-fedora" EPATCH_SUFFIX="patch" \
- EPATCH_FORCE="yes" epatch
-}
-
-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"
-
- # Support debug USE flag
- use debug && conf_opts="${conf_opts} --enable-debug --disable-strip"
-
- # 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 rbd)"
- conf_opts="${conf_opts} $(use_enable sasl vnc-sasl)"
- conf_opts="${conf_opts} $(use_enable sdl)"
- conf_opts="${conf_opts} $(use_enable spice)"
- conf_opts="${conf_opts} $(use_enable ssl vnc-tls)"
- conf_opts="${conf_opts} $(use_enable threads vnc-thread)"
- conf_opts="${conf_opts} $(use_enable vde)"
- conf_opts="${conf_opts} $(use_enable vhost-net)"
- conf_opts="${conf_opts} $(use_enable xen)"
- conf_opts="${conf_opts} --disable-darwin-user --disable-bsd-user"
-
- # 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_install() {
- emake DESTDIR="${D}" install || die "make install failed"
-
- if [ ! -z "${softmmu_targets}" ]; then
- insinto /$(get_libdir)/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
-}
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-07-13 13:47 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-13 13:47 [gentoo-commits] dev/dev-zero:master commit in: app-emulation/qemu-kvm/, app-emulation/qemu-kvm/files/patches-from-fedora/, Tiziano Müller
-- strict thread matches above, loose matches on Subject: below --
2011-04-29 6:26 Tiziano Müller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox