Gentoo Archives: gentoo-commits

From: "Tiziano Müller" <dev-zero@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] dev/dev-zero:master commit in: app-emulation/qemu-kvm/, app-emulation/qemu-kvm/files/patches-from-fedora/, ...
Date: Fri, 29 Apr 2011 06:27:05
Message-Id: 9f68be096ca9520cd1639b5e25bf522d4e02d48d.dev-zero@gentoo
1 commit: 9f68be096ca9520cd1639b5e25bf522d4e02d48d
2 Author: Tiziano Mueller <dev-zero <AT> gentoo <DOT> org>
3 AuthorDate: Fri Apr 29 06:26:23 2011 +0000
4 Commit: Tiziano Müller <dev-zero <AT> gentoo <DOT> org>
5 CommitDate: Fri Apr 29 06:26:23 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=dev/dev-zero.git;a=commit;h=9f68be09
7
8 Added qemu-kvm-0.14.0 bump including patches from Fedora.
9
10 ---
11 app-emulation/qemu-kvm/Manifest | 24 +
12 .../0000-qemu-fix-non-PCI-target-build.patch | 53 ++
13 .../0000-qemu-vhost-fix-dirty-page-handling.patch | 31 +
14 .../0001-qxl-spice-display-move-pipe-to-ssd.patch | 143 +++++
15 ...ent-get_command-in-vga-mode-without-locks.patch | 312 +++++++++
16 ...emove-qemu_mutex_-un-lock_iothread-around.patch | 148 +++++
17 ...ender-drop-cursor-locks-replace-with-pipe.patch | 249 ++++++++
18 ...out-tcp-socket-close-code-in-a-separate-f.patch | 56 ++
19 ...QemuChrHandlers-struct-to-initialise-char.patch | 673 ++++++++++++++++++++
20 ...Add-enable-disable_write_fd_handler-funct.patch | 76 +++
21 ...-framework-for-a-write-unblocked-callback.patch | 62 ++
22 ...-send_all-to-handle-nonblocking-chardev-w.patch | 197 ++++++
23 ...the-unix-tcp-backend-to-handle-nonblockin.patch | 80 +++
24 ...har-Throttle-when-host-connection-is-down.patch | 56 ++
25 ...ole-Enable-port-throttling-when-chardev-i.patch | 48 ++
26 .../0013-spice-qemu-char.c-add-throttling.patch | 133 ++++
27 ...ce-qemu-char.c-remove-intermediate-buffer.patch | 71 ++
28 ...ow-frontends-to-notify-backends-of-guest-.patch | 76 +++
29 ...onsole-notify-backend-of-guest-open-close.patch | 49 ++
30 ...ardev-listen-to-frontend-guest-open-close.patch | 49 ++
31 ...char-Fix-flow-control-in-client-guest-dir.patch | 56 ++
32 .../files/qemu-0.11.0-mips64-user-fix.patch | 11 +
33 app-emulation/qemu-kvm/files/qemu-kvm | 2 +
34 app-emulation/qemu-kvm/qemu-kvm-0.14.0.ebuild | 260 ++++++++
35 24 files changed, 2915 insertions(+), 0 deletions(-)
36
37 diff --git a/app-emulation/qemu-kvm/Manifest b/app-emulation/qemu-kvm/Manifest
38 new file mode 100644
39 index 0000000..e81f2a3
40 --- /dev/null
41 +++ b/app-emulation/qemu-kvm/Manifest
42 @@ -0,0 +1,24 @@
43 +AUX patches-from-fedora/0000-qemu-fix-non-PCI-target-build.patch 1748 RMD160 6b74c349fa036728a38fe1ee56bf2ed567da2fb8 SHA1 08563c7e311d1c350065a6e4790e2abddc71c3d4 SHA256 9bd9e44061763aae606ee4cc19a0a54dc1c88830fe59432693be6a3a32a65328
44 +AUX patches-from-fedora/0000-qemu-vhost-fix-dirty-page-handling.patch 1045 RMD160 abbfe09dd7136ff2e89d0a4aee12903ac07dd38f SHA1 d544c845b2f782327babcfc8167d8fb4974db5d8 SHA256 9f78073f23657feef5e0bf017315476356d9cf6a0b953e39e54199e0a5e0c7b5
45 +AUX patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch 4618 RMD160 f8bee2614fd8791cf478b09cb0babbf5c113ff4b SHA1 29bbe1bd0b1d5bd54e4d22aa062ed5fe9d7b80e7 SHA256 22152847a75d9f14d4d73f5f2042d83e0de2d882c066bf7524827127230b7d2d
46 +AUX patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch 10176 RMD160 316ed43c95137c49c25ef0d1d8faca736850f0b2 SHA1 61663c85a06ae2aaeff12887e609fcd76cbc1b31 SHA256 c788c617ee226716657dbfd778790f6b87734235e5d9fe702099bdd6e7147edb
47 +AUX patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch 5073 RMD160 3ce5594c2144edaff73a929c47260674724c3bbd SHA1 17844d9a38ef837098a492a994a60c7d06aeb007 SHA256 a656f4b0faac207578edf0171676799680da4427d2e332c144350dec2699bced
48 +AUX patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch 7783 RMD160 4261b2ad8ee333c31fe4fe700e40b27c794b60cb SHA1 8d5b0ab3a6d2a247d3197ba65cd2d1fb8f99eba7 SHA256 bb6aeaecb66e2d0215191c64e580c1ca5bbe004accddff9f7454d222b5af74de
49 +AUX patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch 1733 RMD160 30e31570c31d68be3b0f9f12870c13d51a18b3aa SHA1 f80a973a826693accd331c6d3d3cdddc8f47a9b6 SHA256 e123d523c974617510c59d026fdc26ec7e502bcda6c1652797dad9ae404167db
50 +AUX patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch 22320 RMD160 50ba6be5ef638865a18ef0c65ff8c13800d70169 SHA1 85ea8ae83047d576e69bb45cacd2f6291d7c9d3c SHA256 69192c8b9d530c4bb21c002803812d42f8bedf6f99f86a17b2493ae58ef0aff2
51 +AUX patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch 1913 RMD160 3c2b3fe8087de960064e33f4c3dcda74cf1ad028 SHA1 7d4ad12e0f5e019155ab4f02186cc1db0360560b SHA256 3778a50b0065ea51a52f624a6d080d0a8c260bb9bdfb23ec7646018f228b3716
52 +AUX patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch 2182 RMD160 8bef66b38c3b90e011c20d7a2d23f680be2fa2fc SHA1 783ce01d2ba57f7ff94dc2e3899f2ecdbf5ba528 SHA256 01a72c82db6da782854b2cdaaf094d103b3854c7ad26328d84e97c356b150ae8
53 +AUX patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch 6678 RMD160 e929fb838a590ade9cde62804f2d0503c14fd734 SHA1 ce4917bb9c3b580286c31137c46c7e034463503f SHA256 5b9e50e98c39523c790e2ec75c65e6576b13580ccb01c9e22e51caa40c4a40be
54 +AUX patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch 2583 RMD160 dd6080a4e259410b7dd6ba6b51a0af51b6a8ca0c SHA1 73f62b43270f4b6369efd7e6015e3f6e7d0cb9a9 SHA256 61dd33665fad5bfb4df1d387cebec1e0bed6128bbf427c9f8a3c60f91c713c6c
55 +AUX patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch 2000 RMD160 3fa3bd27d69d90f26e30b3cc5c899cb49554639a SHA1 3d662d181d77f8e4420b6f8c5fa57687d11f3858 SHA256 c496a5bd77aa973f6368b06d8a0a67568ae53a0990cec65897b57918f6fee6e7
56 +AUX patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch 1650 RMD160 0e94375a02675398d1627bdbc6617661139ae0d7 SHA1 10371019b8053965e63ccd8d5472c11a05ccc3d2 SHA256 6eabb8a5f3207fd24a7c27dbbfb47168c7a4778771a84f00622c3cadc21b4674
57 +AUX patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch 5036 RMD160 8cf7d356f1664b32f462ad2b957194031d3e6126 SHA1 35cce42333140d5c65f54cbab5e438b0de7f7d95 SHA256 c7d863e59849c732f3fef3a425f1f32843fd2e542a94b61fae61ce36a087f0e3
58 +AUX patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch 2822 RMD160 5d5ab6de3e5a0e8ebea6001127d61c0f730c609f SHA1 ddd50cf6e52ca8dae01f7253417946e2f4cc4cbe SHA256 d7cb0159ac28d78a68208a99ec5dbfaf43e01bde68b90528d7cfb629c78e7247
59 +AUX patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch 2807 RMD160 5193a86c3400d78d1a0190f98532738fbc53aa77 SHA1 f7365f2eb85fb2cd824f5dbcd198a406354e04e5 SHA256 077b6a431156a5a7fbadabfdc7543f4096fd46a7990b56332c1b82928941f4b2
60 +AUX patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch 1592 RMD160 a024a9fced5e3a44580ae6ae78409e0e4b8e5265 SHA1 243028b1f28ab67b04341ea22492bd58e9dab231 SHA256 0bbc7fa3d32dae0d812baac88fb4dff7ba075221f16ed90116432562aa5be9b8
61 +AUX patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch 1536 RMD160 a62580485c1cecc5cd979b67cd8567947d223d2f SHA1 2df9fe95487101ed1fea739d106c8fbb3633d8f0 SHA256 86623ce9e32fee56d1f13ee51770d89043d1c6fb7a4d972e15840fab95a0b04d
62 +AUX patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch 1784 RMD160 25fe156aafa2070905476ccdd0e4f2946729bec8 SHA1 7ed5fa3d92ed45d2e0d95247cc5d437304419074 SHA256 68215f7f55f749aa8333d840e40c0c58e957c12c90b47eb8b0c5cad3f6249fec
63 +AUX qemu-0.11.0-mips64-user-fix.patch 313 RMD160 db016e0a48990a435dd6cf6e807145b33ada4908 SHA1 2ea913b1bcd29734a6d4011794bdb4aa3599a184 SHA256 b4173fc177bd0d0ba67f5551a3512047a19a9b2c0a122f968e32fbd834848d2f
64 +AUX qemu-kvm 61 RMD160 83882e881a067065258f562ad1e60440666c85d3 SHA1 a965f19031e303d583bd541c9d8fff2214262e6b SHA256 211d51f0a7d3d2ba8c53016c75e2b483feadbb65e383b1eec81d9cebf6a22c29
65 +EBUILD qemu-kvm-0.14.0.ebuild 8262 RMD160 cea3db6007a7ddf1f274b95b7cfc67091d99dc64 SHA1 cdfd9bd633b2f2453b613a99796b0e6dd97bad2b SHA256 52ec87addca7e8db2164dc09b02116c3335aa9eac49c2b2744dfe5b480559d88
66 +DIST qemu-kvm-0.14.0.tar.gz 5320696 RMD160 9b55c252390ece716295fdc6a012eaa6091f7b90 SHA1 dba0b9484084374b6191608051f40e1991c54ea0 SHA256 2f62aff3655c7b904ccd088e80927b021126d91125e9d9515ee9dda8835c0635
67
68 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
69 new file mode 100644
70 index 0000000..b479efa
71 --- /dev/null
72 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-fix-non-PCI-target-build.patch
73 @@ -0,0 +1,53 @@
74 +commit 1a8364456c2f3946b4feb8fc78eaf00d974f4c03
75 +Author: Jan Kiszka <jan.kiszka@×××××××.com>
76 +Date: Wed Feb 23 09:28:53 2011 +0100
77 +
78 + qemu-kvm: Fix non-PCI target build
79 +
80 + Replace obsolete qemu-kvm.h with kvm.h in pci.c and build that module
81 + just like upstream does. This fixes non-x86 targets which have no PCI
82 + support.
83 +
84 + Signed-off-by: Jan Kiszka <jan.kiszka@×××××××.com>
85 + Signed-off-by: Avi Kivity <avi@××××××.com>
86 +
87 +diff --git a/Makefile.objs b/Makefile.objs
88 +index f5702eb..3ec7121 100644
89 +--- a/Makefile.objs
90 ++++ b/Makefile.objs
91 +@@ -170,7 +170,7 @@ hw-obj-y =
92 + hw-obj-y += loader.o
93 + hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
94 + hw-obj-y += fw_cfg.o
95 +-hw-obj-$(CONFIG_PCI) += pci_bridge.o
96 ++hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
97 + hw-obj-$(CONFIG_PCI) += msix.o msi.o
98 + hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
99 + hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
100 +diff --git a/Makefile.target b/Makefile.target
101 +index 6e9a024..23367eb 100644
102 +--- a/Makefile.target
103 ++++ b/Makefile.target
104 +@@ -195,7 +195,7 @@ endif #CONFIG_BSD_USER
105 + # System emulator target
106 + ifdef CONFIG_SOFTMMU
107 +
108 +-obj-y = arch_init.o cpus.o monitor.o pci.o machine.o gdbstub.o vl.o balloon.o
109 ++obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o vl.o balloon.o
110 + # virtio has to be here due to weird dependency between PCI and virtio-net.
111 + # need to fix this properly
112 + obj-$(CONFIG_NO_PCI) += pci-stub.o
113 +diff --git a/hw/pci.c b/hw/pci.c
114 +index 0c44939..1f6cebe 100644
115 +--- a/hw/pci.c
116 ++++ b/hw/pci.c
117 +@@ -29,8 +29,8 @@
118 + #include "net.h"
119 + #include "sysemu.h"
120 + #include "loader.h"
121 +-#include "qemu-kvm.h"
122 + #include "hw/pc.h"
123 ++#include "kvm.h"
124 + #include "device-assignment.h"
125 + #include "qemu-objects.h"
126 + #include "range.h"
127
128 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
129 new file mode 100644
130 index 0000000..e3fabb7
131 --- /dev/null
132 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0000-qemu-vhost-fix-dirty-page-handling.patch
133 @@ -0,0 +1,31 @@
134 +vhost was passing a physical address to cpu_physical_memory_set_dirty,
135 +which is wrong: we need to translate to ram address first.
136 +
137 +Signed-off-by: Michael S. Tsirkin <mst@××××××.com>
138 +
139 +Note: this lead to crashes during migration, so the patch
140 +is needed on the stable branch too.
141 +
142 +---
143 + hw/vhost.c | 4 +++-
144 + 1 files changed, 3 insertions(+), 1 deletions(-)
145 +
146 +diff --git a/hw/vhost.c b/hw/vhost.c
147 +index aaa34e4..97a1299 100644
148 +--- a/hw/vhost.c
149 ++++ b/hw/vhost.c
150 +@@ -49,8 +49,10 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
151 + log = __sync_fetch_and_and(from, 0);
152 + while ((bit = sizeof(log) > sizeof(int) ?
153 + ffsll(log) : ffs(log))) {
154 ++ ram_addr_t ram_addr;
155 + bit -= 1;
156 +- cpu_physical_memory_set_dirty(addr + bit * VHOST_LOG_PAGE);
157 ++ ram_addr = cpu_get_physical_page_desc(addr + bit * VHOST_LOG_PAGE);
158 ++ cpu_physical_memory_set_dirty(ram_addr);
159 + log &= ~(0x1ull << bit);
160 + }
161 + addr += VHOST_LOG_CHUNK;
162 +--
163 +1.7.3.2.91.g446ac
164 +
165
166 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
167 new file mode 100644
168 index 0000000..b542f54
169 --- /dev/null
170 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0001-qxl-spice-display-move-pipe-to-ssd.patch
171 @@ -0,0 +1,143 @@
172 +>From fd04276a00b172e6fbba3e3c72b1d13a0f179414 Mon Sep 17 00:00:00 2001
173 +From: Alon Levy <alevy@××××××.com>
174 +Date: Wed, 16 Mar 2011 15:21:03 +0100
175 +Subject: [PATCH 1/4] qxl/spice-display: move pipe to ssd
176 +
177 +This moves the int pipe[2] and pthread_t main data from the
178 +PCIQXLDevice struct to the SimpleSpiceDisplay. This will let us
179 +reuse it in the next patch for both -spice with no -qxl usage and
180 +for vga mode from qxl.
181 +
182 +Also move the pipe creation function (which is effectively completely rewritten
183 +by this patch anyways) from hw/qxl.c to ui/spice-display.c, since
184 +spice-display will depend on it after the next patch and qemu can be build
185 +with ui/spice-display.c in combination with no hw/qxl.c.
186 +---
187 + hw/qxl.c | 22 +++++-----------------
188 + hw/qxl.h | 4 ----
189 + ui/spice-display.c | 21 +++++++++++++++++++++
190 + ui/spice-display.h | 8 ++++++++
191 + 4 files changed, 34 insertions(+), 21 deletions(-)
192 +
193 +diff --git a/hw/qxl.c b/hw/qxl.c
194 +index fe4212b..201698f 100644
195 +--- a/hw/qxl.c
196 ++++ b/hw/qxl.c
197 +@@ -1062,7 +1062,7 @@ static void pipe_read(void *opaque)
198 + int len;
199 +
200 + do {
201 +- len = read(d->pipe[0], &dummy, sizeof(dummy));
202 ++ len = read(d->ssd.pipe[0], &dummy, sizeof(dummy));
203 + } while (len == sizeof(dummy));
204 + qxl_set_irq(d);
205 + }
206 +@@ -1078,10 +1078,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
207 + if ((old_pending & le_events) == le_events) {
208 + return;
209 + }
210 +- if (pthread_self() == d->main) {
211 ++ if (pthread_self() == d->ssd.main) {
212 ++ /* running in io_thread thread */
213 + qxl_set_irq(d);
214 + } else {
215 +- if (write(d->pipe[1], d, 1) != 1) {
216 ++ if (write(d->ssd.pipe[1], d, 1) != 1) {
217 + dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
218 + }
219 + }
220 +@@ -1089,20 +1090,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
221 +
222 + static void init_pipe_signaling(PCIQXLDevice *d)
223 + {
224 +- if (pipe(d->pipe) < 0) {
225 +- dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
226 +- return;
227 +- }
228 +-#ifdef CONFIG_IOTHREAD
229 +- fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
230 +-#else
231 +- fcntl(d->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
232 +-#endif
233 +- fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
234 +- fcntl(d->pipe[0], F_SETOWN, getpid());
235 +-
236 +- d->main = pthread_self();
237 +- qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
238 ++ qxl_create_server_to_iothread_pipe(&d->ssd, pipe_read);
239 + }
240 +
241 + /* graphics console */
242 +diff --git a/hw/qxl.h b/hw/qxl.h
243 +index f6c450d..701245f 100644
244 +--- a/hw/qxl.h
245 ++++ b/hw/qxl.h
246 +@@ -55,10 +55,6 @@ typedef struct PCIQXLDevice {
247 + } guest_surfaces;
248 + QXLPHYSICAL guest_cursor;
249 +
250 +- /* thread signaling */
251 +- pthread_t main;
252 +- int pipe[2];
253 +-
254 + /* ram pci bar */
255 + QXLRam *ram;
256 + VGACommonState vga;
257 +diff --git a/ui/spice-display.c b/ui/spice-display.c
258 +index 020b423..ec6e0cb 100644
259 +--- a/ui/spice-display.c
260 ++++ b/ui/spice-display.c
261 +@@ -394,6 +394,27 @@ static DisplayChangeListener display_listener = {
262 + .dpy_refresh = display_refresh,
263 + };
264 +
265 ++void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
266 ++ IOHandler *pipe_read)
267 ++{
268 ++ if (pipe(ssd->pipe) < 0) {
269 ++ fprintf(stderr, "%s: pipe creation failed\n", __FUNCTION__);
270 ++ return;
271 ++ }
272 ++
273 ++#ifdef CONFIG_IOTHREAD
274 ++ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK);
275 ++#else
276 ++ fcntl(ssd->pipe[0], F_SETFL, O_NONBLOCK /* | O_ASYNC */);
277 ++#endif
278 ++ fcntl(ssd->pipe[1], F_SETFL, O_NONBLOCK);
279 ++
280 ++ fcntl(ssd->pipe[0], F_SETOWN, getpid());
281 ++
282 ++ qemu_set_fd_handler(ssd->pipe[0], pipe_read, NULL, ssd);
283 ++ ssd->main = pthread_self();
284 ++}
285 ++
286 + void qemu_spice_display_init(DisplayState *ds)
287 + {
288 + assert(sdpy.ds == NULL);
289 +diff --git a/ui/spice-display.h b/ui/spice-display.h
290 +index aef0464..3e6cf7c 100644
291 +--- a/ui/spice-display.h
292 ++++ b/ui/spice-display.h
293 +@@ -43,6 +43,11 @@ typedef struct SimpleSpiceDisplay {
294 + QXLRect dirty;
295 + int notify;
296 + int running;
297 ++
298 ++ /* thread signaling - used both in qxl (in vga mode
299 ++ * and in native mode) and without qxl */
300 ++ pthread_t main;
301 ++ int pipe[2]; /* to iothread */
302 + } SimpleSpiceDisplay;
303 +
304 + typedef struct SimpleSpiceUpdate {
305 +@@ -66,3 +71,6 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
306 + int x, int y, int w, int h);
307 + void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
308 + void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
309 ++/* used by both qxl and spice-display */
310 ++void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
311 ++ IOHandler *pipe_read);
312 +--
313 +1.7.3.2
314 +
315
316 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
317 new file mode 100644
318 index 0000000..d221d5f
319 --- /dev/null
320 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0002-qxl-implement-get_command-in-vga-mode-without-locks.patch
321 @@ -0,0 +1,312 @@
322 +>From 97e291086fef45762e0278e85ab1d231a9902bbb Mon Sep 17 00:00:00 2001
323 +From: Uri Lublin <uril@××××××.com>
324 +Date: Wed, 16 Mar 2011 15:43:45 +0100
325 +Subject: [PATCH 2/4] qxl: implement get_command in vga mode without locks
326 +
327 +This patch and the next drop the requirement to lose the global qemu
328 +mutex during dispatcher calls. This patch enables it, the next drops
329 +the unlock/lock pairs around dispatcher calls.
330 +
331 +The current solution of dropping the locks is buggy:
332 + * it allows multiple dispatcher calls from two vcpu threads, the
333 + dispatcher doesn't handle that by design (single fd, not locked, can't
334 + handle writes from two threads)
335 + * it requires us to keep track of cpu_single_env, which is magic.
336 +
337 +The solution implemented in this patch and the next (the next just
338 +drops the locks, this patch allows that to work):
339 + * the only operation that needed locking was qemu_create_simple_update,
340 + * it required locking because it was called from the spice-server thread.
341 + * do it in the iothread by reusing the existing pipe used for set_irq.
342 +
343 +The current flow implemented is now:
344 +spice-server thread:
345 + qxl.c:interface_get_command (called either by polling or from wakeup)
346 + if update!=NULL:
347 + waiting_for_update=0
348 + update=NULL
349 + return update
350 + else:
351 + if not waiting_for_update:
352 + waiting_for_update=1
353 + write to pipe, which is read by iothread (main thread)
354 +
355 +iothread:
356 + wakeup from select,
357 + qxl.c:pipe_read
358 + update=qemu_create_simple_update()
359 + wakeup spice-server thread by calling d.worker->wakeup(d.worker)
360 +---
361 + hw/qxl.c | 81 +++++++++++++++++++++++++++++++++++++++------------
362 + ui/spice-display.c | 75 +++++++++++++++++++++++++++++++++++++++++++----
363 + ui/spice-display.h | 16 ++++++++++
364 + 3 files changed, 146 insertions(+), 26 deletions(-)
365 +
366 +diff --git a/hw/qxl.c b/hw/qxl.c
367 +index 201698f..64580f1 100644
368 +--- a/hw/qxl.c
369 ++++ b/hw/qxl.c
370 +@@ -340,7 +340,6 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
371 + static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
372 + {
373 + PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
374 +- SimpleSpiceUpdate *update;
375 + QXLCommandRing *ring;
376 + QXLCommand *cmd;
377 + int notify;
378 +@@ -348,16 +347,25 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
379 + switch (qxl->mode) {
380 + case QXL_MODE_VGA:
381 + dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
382 +- update = qemu_spice_create_update(&qxl->ssd);
383 +- if (update == NULL) {
384 +- return false;
385 ++ if (qxl_vga_mode_get_command(&qxl->ssd, ext)) {
386 ++ qxl_log_command(qxl, "vga", ext);
387 ++ return true;
388 + }
389 +- *ext = update->ext;
390 +- qxl_log_command(qxl, "vga", ext);
391 +- return true;
392 ++ return false;
393 + case QXL_MODE_COMPAT:
394 + case QXL_MODE_NATIVE:
395 + case QXL_MODE_UNDEFINED:
396 ++ /* flush any existing updates that we didn't send to the guest.
397 ++ * since update != NULL it means the server didn't get it, and
398 ++ * because we changed mode to != QXL_MODE_VGA, it won't. */
399 ++ if (qxl->ssd.update != NULL) {
400 ++ if (qxl->ssd.update != QXL_EMPTY_UPDATE) {
401 ++ qemu_spice_destroy_update(&qxl->ssd, qxl->ssd.update);
402 ++ }
403 ++ qxl->ssd.update = NULL;
404 ++ qxl->ssd.waiting_for_update = 0;
405 ++ }
406 ++ /* */
407 + dprint(qxl, 2, "%s: %s\n", __FUNCTION__,
408 + qxl->cmdflags ? "compat" : "native");
409 + ring = &qxl->ram->cmd_ring;
410 +@@ -1057,17 +1065,50 @@ static void qxl_map(PCIDevice *pci, int region_num,
411 +
412 + static void pipe_read(void *opaque)
413 + {
414 +- PCIQXLDevice *d = opaque;
415 +- char dummy;
416 +- int len;
417 +-
418 +- do {
419 +- len = read(d->ssd.pipe[0], &dummy, sizeof(dummy));
420 +- } while (len == sizeof(dummy));
421 +- qxl_set_irq(d);
422 ++ SimpleSpiceDisplay *ssd = opaque;
423 ++ unsigned char cmd;
424 ++ int len, set_irq = 0;
425 ++ int create_update = 0;
426 ++
427 ++ while (1) {
428 ++ cmd = 0;
429 ++ len = read(ssd->pipe[0], &cmd, sizeof(cmd));
430 ++ if (len < 0) {
431 ++ if (errno == EINTR) {
432 ++ continue;
433 ++ }
434 ++ if (errno == EAGAIN) {
435 ++ break;
436 ++ }
437 ++ perror("qxl: pipe_read: read failed");
438 ++ break;
439 ++ }
440 ++ switch (cmd) {
441 ++ case QXL_SERVER_SET_IRQ:
442 ++ set_irq = 1;
443 ++ break;
444 ++ case QXL_SERVER_CREATE_UPDATE:
445 ++ create_update = 1;
446 ++ break;
447 ++ default:
448 ++ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
449 ++ abort();
450 ++ }
451 ++ }
452 ++ /* no need to do either operation more than once */
453 ++ if (create_update) {
454 ++ assert(ssd->update == NULL);
455 ++ ssd->update = qemu_spice_create_update(ssd);
456 ++ if (ssd->update == NULL) {
457 ++ ssd->update = QXL_EMPTY_UPDATE;
458 ++ }
459 ++ ssd->worker->wakeup(ssd->worker);
460 ++ }
461 ++ if (set_irq) {
462 ++ qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd));
463 ++ }
464 + }
465 +
466 +-/* called from spice server thread context only */
467 + static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
468 + {
469 + uint32_t old_pending;
470 +@@ -1082,9 +1123,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
471 + /* running in io_thread thread */
472 + qxl_set_irq(d);
473 + } else {
474 +- if (write(d->ssd.pipe[1], d, 1) != 1) {
475 +- dprint(d, 1, "%s: write to pipe failed\n", __FUNCTION__);
476 +- }
477 ++ /* called from spice-server thread */
478 ++ int ret;
479 ++ unsigned char ack = QXL_SERVER_SET_IRQ;
480 ++ ret = write(d->ssd.pipe[1], &ack, 1);
481 ++ assert(ret == 1);
482 + }
483 + }
484 +
485 +diff --git a/ui/spice-display.c b/ui/spice-display.c
486 +index ec6e0cb..bdd14b8 100644
487 +--- a/ui/spice-display.c
488 ++++ b/ui/spice-display.c
489 +@@ -294,18 +294,39 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
490 + info->n_surfaces = NUM_SURFACES;
491 + }
492 +
493 ++/* Called from spice server thread context (via interface_get_command) */
494 ++int qxl_vga_mode_get_command(
495 ++ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext)
496 ++{
497 ++ SimpleSpiceUpdate *update;
498 ++ unsigned char req;
499 ++ int r;
500 ++
501 ++ update = ssd->update;
502 ++ if (update != NULL) {
503 ++ ssd->waiting_for_update = 0;
504 ++ ssd->update = NULL;
505 ++ if (update != QXL_EMPTY_UPDATE) {
506 ++ *ext = update->ext;
507 ++ return true;
508 ++ }
509 ++ } else {
510 ++ if (!ssd->waiting_for_update) {
511 ++ ssd->waiting_for_update = 1;
512 ++ req = QXL_SERVER_CREATE_UPDATE;
513 ++ r = write(ssd->pipe[1], &req , 1);
514 ++ assert(r == 1);
515 ++ }
516 ++ }
517 ++ return false;
518 ++}
519 ++
520 + static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
521 + {
522 + SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
523 +- SimpleSpiceUpdate *update;
524 +
525 + dprint(3, "%s:\n", __FUNCTION__);
526 +- update = qemu_spice_create_update(ssd);
527 +- if (update == NULL) {
528 +- return false;
529 +- }
530 +- *ext = update->ext;
531 +- return true;
532 ++ return qxl_vga_mode_get_command(ssd, ext);
533 + }
534 +
535 + static int interface_req_cmd_notification(QXLInstance *sin)
536 +@@ -394,6 +415,45 @@ static DisplayChangeListener display_listener = {
537 + .dpy_refresh = display_refresh,
538 + };
539 +
540 ++static void pipe_read(void *opaque)
541 ++{
542 ++ SimpleSpiceDisplay *ssd = opaque;
543 ++ unsigned char cmd;
544 ++ int len, create_update = 0;
545 ++
546 ++ while (1) {
547 ++ cmd = 0;
548 ++ len = read(ssd->pipe[0], &cmd, sizeof(cmd));
549 ++ if (len < 0) {
550 ++ if (errno == EINTR) {
551 ++ continue;
552 ++ }
553 ++ if (errno == EAGAIN) {
554 ++ break;
555 ++ }
556 ++ perror("qxl: pipe_read: read failed");
557 ++ break;
558 ++ }
559 ++ switch (cmd) {
560 ++ case QXL_SERVER_CREATE_UPDATE:
561 ++ create_update = 1;
562 ++ break;
563 ++ default:
564 ++ fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
565 ++ abort();
566 ++ }
567 ++ }
568 ++ /* no need to do this more than once */
569 ++ if (create_update) {
570 ++ assert(ssd->update == NULL);
571 ++ ssd->update = qemu_spice_create_update(ssd);
572 ++ if (ssd->update == NULL) {
573 ++ ssd->update = QXL_EMPTY_UPDATE;
574 ++ }
575 ++ ssd->worker->wakeup(ssd->worker);
576 ++ }
577 ++}
578 ++
579 + void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
580 + IOHandler *pipe_read)
581 + {
582 +@@ -427,6 +487,7 @@ void qemu_spice_display_init(DisplayState *ds)
583 + qemu_spice_add_interface(&sdpy.qxl.base);
584 + assert(sdpy.worker);
585 +
586 ++ qxl_create_server_to_iothread_pipe(&sdpy, pipe_read);
587 + qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy);
588 + qemu_spice_create_host_memslot(&sdpy);
589 + qemu_spice_create_host_primary(&sdpy);
590 +diff --git a/ui/spice-display.h b/ui/spice-display.h
591 +index 3e6cf7c..2be6a34 100644
592 +--- a/ui/spice-display.h
593 ++++ b/ui/spice-display.h
594 +@@ -31,6 +31,15 @@
595 +
596 + #define NUM_SURFACES 1024
597 +
598 ++/* For commands/requests from server thread to iothread */
599 ++#define QXL_EMPTY_UPDATE ((void *)-1)
600 ++enum {
601 ++ QXL_SERVER_SET_IRQ = 1,
602 ++ QXL_SERVER_CREATE_UPDATE,
603 ++};
604 ++
605 ++struct SimpleSpiceUpdate;
606 ++
607 + typedef struct SimpleSpiceDisplay {
608 + DisplayState *ds;
609 + void *buf;
610 +@@ -48,6 +57,10 @@ typedef struct SimpleSpiceDisplay {
611 + * and in native mode) and without qxl */
612 + pthread_t main;
613 + int pipe[2]; /* to iothread */
614 ++
615 ++ /* ssd updates (one request/command at a time) */
616 ++ struct SimpleSpiceUpdate *update;
617 ++ int waiting_for_update;
618 + } SimpleSpiceDisplay;
619 +
620 + typedef struct SimpleSpiceUpdate {
621 +@@ -71,6 +84,9 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
622 + int x, int y, int w, int h);
623 + void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
624 + void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
625 ++/* shared with qxl.c in vga mode and ui/spice-display (no qxl mode) */
626 ++int qxl_vga_mode_get_command(
627 ++ SimpleSpiceDisplay *ssd, struct QXLCommandExt *ext);
628 + /* used by both qxl and spice-display */
629 + void qxl_create_server_to_iothread_pipe(SimpleSpiceDisplay *ssd,
630 + IOHandler *pipe_read);
631 +--
632 +1.7.3.2
633 +
634
635 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
636 new file mode 100644
637 index 0000000..92a148e
638 --- /dev/null
639 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0003-qxl-spice-remove-qemu_mutex_-un-lock_iothread-around.patch
640 @@ -0,0 +1,148 @@
641 +>From d413b3c36cbd9820c5b9492b52caa421abccf745 Mon Sep 17 00:00:00 2001
642 +From: Alon Levy <alevy@××××××.com>
643 +Date: Wed, 16 Mar 2011 15:46:22 +0100
644 +Subject: [PATCH 3/4] qxl/spice: remove qemu_mutex_{un,}lock_iothread around dispatcher
645 +
646 +with the previous patch making sure get_command no longer needs to lock,
647 +there is no reason to drop the qemu iothread mutex in qxl.c and in
648 +ui/spice-display.c
649 +
650 +The only location where the lock remains are the cursor related callbacks,
651 +that path is currently broken. It is only triggered if running spice and sdl,
652 +which is broken already before that.
653 +---
654 + hw/qxl.c | 8 --------
655 + ui/spice-display.c | 19 +++----------------
656 + 2 files changed, 3 insertions(+), 24 deletions(-)
657 +
658 +diff --git a/hw/qxl.c b/hw/qxl.c
659 +index 64580f1..cf3c938 100644
660 +--- a/hw/qxl.c
661 ++++ b/hw/qxl.c
662 +@@ -670,10 +670,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
663 + dprint(d, 1, "%s: start%s\n", __FUNCTION__,
664 + loadvm ? " (loadvm)" : "");
665 +
666 +- qemu_mutex_unlock_iothread();
667 + d->ssd.worker->reset_cursor(d->ssd.worker);
668 + d->ssd.worker->reset_image_cache(d->ssd.worker);
669 +- qemu_mutex_lock_iothread();
670 + qxl_reset_surfaces(d);
671 + qxl_reset_memslots(d);
672 +
673 +@@ -803,9 +801,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
674 + {
675 + dprint(d, 1, "%s:\n", __FUNCTION__);
676 + d->mode = QXL_MODE_UNDEFINED;
677 +- qemu_mutex_unlock_iothread();
678 + d->ssd.worker->destroy_surfaces(d->ssd.worker);
679 +- qemu_mutex_lock_iothread();
680 + memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
681 + }
682 +
683 +@@ -874,9 +870,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d)
684 + dprint(d, 1, "%s\n", __FUNCTION__);
685 +
686 + d->mode = QXL_MODE_UNDEFINED;
687 +- qemu_mutex_unlock_iothread();
688 + d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
689 +- qemu_mutex_lock_iothread();
690 + }
691 +
692 + static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
693 +@@ -946,10 +940,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
694 + case QXL_IO_UPDATE_AREA:
695 + {
696 + QXLRect update = d->ram->update_area;
697 +- qemu_mutex_unlock_iothread();
698 + d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
699 + &update, NULL, 0, 0);
700 +- qemu_mutex_lock_iothread();
701 + break;
702 + }
703 + case QXL_IO_NOTIFY_CMD:
704 +diff --git a/ui/spice-display.c b/ui/spice-display.c
705 +index bdd14b8..ecb22cc 100644
706 +--- a/ui/spice-display.c
707 ++++ b/ui/spice-display.c
708 +@@ -62,13 +62,7 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
709 + dest->right = MAX(dest->right, r->right);
710 + }
711 +
712 +-/*
713 +- * Called from spice server thread context (via interface_get_command).
714 +- *
715 +- * We must aquire the global qemu mutex here to make sure the
716 +- * DisplayState (+DisplaySurface) we are accessing doesn't change
717 +- * underneath us.
718 +- */
719 ++/* Called from io-thread context (via pipe_read) */
720 + SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
721 + {
722 + SimpleSpiceUpdate *update;
723 +@@ -78,9 +72,7 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
724 + uint8_t *src, *dst;
725 + int by, bw, bh;
726 +
727 +- qemu_mutex_lock_iothread();
728 + if (qemu_spice_rect_is_empty(&ssd->dirty)) {
729 +- qemu_mutex_unlock_iothread();
730 + return NULL;
731 + };
732 +
733 +@@ -141,7 +133,6 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
734 + cmd->data = (intptr_t)drawable;
735 +
736 + memset(&ssd->dirty, 0, sizeof(ssd->dirty));
737 +- qemu_mutex_unlock_iothread();
738 + return update;
739 + }
740 +
741 +@@ -169,6 +160,7 @@ void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
742 + ssd->worker->add_memslot(ssd->worker, &memslot);
743 + }
744 +
745 ++/* called from iothread (main) or a vcpu-thread */
746 + void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
747 + {
748 + QXLDevSurfaceCreate surface;
749 +@@ -186,18 +178,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
750 + surface.mem = (intptr_t)ssd->buf;
751 + surface.group_id = MEMSLOT_GROUP_HOST;
752 +
753 +- qemu_mutex_unlock_iothread();
754 + ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
755 +- qemu_mutex_lock_iothread();
756 + }
757 +
758 + void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
759 + {
760 + dprint(1, "%s:\n", __FUNCTION__);
761 +
762 +- qemu_mutex_unlock_iothread();
763 + ssd->worker->destroy_primary_surface(ssd->worker, 0);
764 +- qemu_mutex_lock_iothread();
765 + }
766 +
767 + void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
768 +@@ -207,9 +195,7 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
769 + if (running) {
770 + ssd->worker->start(ssd->worker);
771 + } else {
772 +- qemu_mutex_unlock_iothread();
773 + ssd->worker->stop(ssd->worker);
774 +- qemu_mutex_lock_iothread();
775 + }
776 + ssd->running = running;
777 + }
778 +@@ -233,6 +219,7 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
779 + qemu_spice_rect_union(&ssd->dirty, &update_area);
780 + }
781 +
782 ++/* called only from iothread (main) */
783 + void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
784 + {
785 + dprint(1, "%s:\n", __FUNCTION__);
786 +--
787 +1.7.3.2
788 +
789
790 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
791 new file mode 100644
792 index 0000000..03daba4
793 --- /dev/null
794 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0004-hw-qxl-render-drop-cursor-locks-replace-with-pipe.patch
795 @@ -0,0 +1,249 @@
796 +>From 1a33e5f2fa6de800047517a6f3251dc7191c97b5 Mon Sep 17 00:00:00 2001
797 +From: Alon Levy <alevy@××××××.com>
798 +Date: Wed, 16 Mar 2011 16:02:16 +0100
799 +Subject: [PATCH 4/4] hw/qxl-render: drop cursor locks, replace with pipe
800 +
801 +Switching locking protection of ds->cursor_set/cursor_move to moving
802 +every call to these functions into the iothread and using the ssd->pipe
803 +to transfer that, adding QXL_SERVER_CURSOR_SET, QXL_SERVER_CURSOR_MOVE.
804 +
805 +This is tested with both -vnc :0 -spice and -sdl -spice.
806 +---
807 + hw/qxl-render.c | 25 +++++++++-----
808 + hw/qxl.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
809 + hw/qxl.h | 4 ++
810 + ui/spice-display.h | 13 +++++++-
811 + 4 files changed, 122 insertions(+), 10 deletions(-)
812 +
813 +diff --git a/hw/qxl-render.c b/hw/qxl-render.c
814 +index 58965e0..6759edb 100644
815 +--- a/hw/qxl-render.c
816 ++++ b/hw/qxl-render.c
817 +@@ -178,7 +178,6 @@ fail:
818 + return NULL;
819 + }
820 +
821 +-
822 + /* called from spice server thread context only */
823 + void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
824 + {
825 +@@ -209,18 +208,26 @@ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
826 + if (c == NULL) {
827 + c = cursor_builtin_left_ptr();
828 + }
829 +- qemu_mutex_lock_iothread();
830 +- qxl->ssd.ds->cursor_define(c);
831 +- qxl->ssd.ds->mouse_set(x, y, 1);
832 +- qemu_mutex_unlock_iothread();
833 +- cursor_put(c);
834 ++ qxl_server_request_cursor_set(qxl, c, x, y);
835 + break;
836 + case QXL_CURSOR_MOVE:
837 + x = cmd->u.position.x;
838 + y = cmd->u.position.y;
839 +- qemu_mutex_lock_iothread();
840 +- qxl->ssd.ds->mouse_set(x, y, 1);
841 +- qemu_mutex_unlock_iothread();
842 ++ qxl_server_request_cursor_move(qxl, x, y);
843 + break;
844 + }
845 + }
846 ++
847 ++/* called from iothread only (via qxl.c:pipe_read) */
848 ++void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y)
849 ++{
850 ++ ssd->ds->cursor_define(c);
851 ++ ssd->ds->mouse_set(x, y, 1);
852 ++ cursor_put(c);
853 ++}
854 ++
855 ++/* called from iothread only (via qxl.c:pipe_read) */
856 ++void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y)
857 ++{
858 ++ ssd->ds->mouse_set(x, y, 1);
859 ++}
860 +diff --git a/hw/qxl.c b/hw/qxl.c
861 +index cf3c938..4c27deb 100644
862 +--- a/hw/qxl.c
863 ++++ b/hw/qxl.c
864 +@@ -117,6 +117,27 @@ static QXLMode qxl_modes[] = {
865 + #endif
866 + };
867 +
868 ++typedef struct __attribute__ ((__packed__)) {
869 ++ QEMUCursor *c;
870 ++ int x;
871 ++ int y;
872 ++} QXLServerCursorSet;
873 ++
874 ++typedef struct __attribute__ ((__packed__)) {
875 ++ int x;
876 ++ int y;
877 ++} QXLServerCursorMove;
878 ++
879 ++typedef struct __attribute__ ((__packed__)) {
880 ++ unsigned char req;
881 ++ QXLServerCursorMove data;
882 ++} QXLServerCursorMoveRequest;
883 ++
884 ++typedef struct __attribute__ ((__packed__)) {
885 ++ unsigned char req;
886 ++ QXLServerCursorSet data;
887 ++} QXLServerCursorSetRequest;
888 ++
889 + static PCIQXLDevice *qxl0;
890 +
891 + static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
892 +@@ -337,6 +358,33 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
893 + }
894 +
895 + /* called from spice server thread context only */
896 ++void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y)
897 ++{
898 ++ QXLServerCursorSetRequest req;
899 ++ int r;
900 ++
901 ++ req.req = QXL_SERVER_CURSOR_SET;
902 ++ req.data.c = c;
903 ++ req.data.x = x;
904 ++ req.data.y = y;
905 ++ r = write(qxl->ssd.pipe[1], &req, sizeof(req));
906 ++ assert(r == sizeof(req));
907 ++}
908 ++
909 ++/* called from spice server thread context only */
910 ++void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y)
911 ++{
912 ++ QXLServerCursorMoveRequest req;
913 ++ int r;
914 ++
915 ++ req.req = QXL_SERVER_CURSOR_MOVE;
916 ++ req.data.x = x;
917 ++ req.data.y = y;
918 ++ r = write(qxl->ssd.pipe[1], &req, sizeof(req));
919 ++ assert(r == sizeof(req));
920 ++}
921 ++
922 ++/* called from spice server thread context only */
923 + static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
924 + {
925 + PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
926 +@@ -1055,12 +1103,37 @@ static void qxl_map(PCIDevice *pci, int region_num,
927 + }
928 + }
929 +
930 ++static void read_bytes(int fd, void *buf, int len_requested)
931 ++{
932 ++ int len;
933 ++ int total_len = 0;
934 ++
935 ++ do {
936 ++ len = read(fd, buf, len_requested - total_len);
937 ++ if (len < 0) {
938 ++ if (errno == EINTR || errno == EAGAIN) {
939 ++ continue;
940 ++ }
941 ++ perror("qxl: pipe_read: read failed");
942 ++ /* will abort once it's out of the while loop */
943 ++ break;
944 ++ }
945 ++ total_len += len;
946 ++ buf = (uint8_t *)buf + len;
947 ++ } while (total_len < len_requested);
948 ++ assert(total_len == len_requested);
949 ++}
950 ++
951 + static void pipe_read(void *opaque)
952 + {
953 + SimpleSpiceDisplay *ssd = opaque;
954 + unsigned char cmd;
955 + int len, set_irq = 0;
956 + int create_update = 0;
957 ++ int cursor_set = 0;
958 ++ int cursor_move = 0;
959 ++ QXLServerCursorSet cursor_set_data;
960 ++ QXLServerCursorMove cursor_move_data;
961 +
962 + while (1) {
963 + cmd = 0;
964 +@@ -1082,6 +1155,17 @@ static void pipe_read(void *opaque)
965 + case QXL_SERVER_CREATE_UPDATE:
966 + create_update = 1;
967 + break;
968 ++ case QXL_SERVER_CURSOR_SET:
969 ++ if (cursor_set == 1) {
970 ++ cursor_put(cursor_set_data.c);
971 ++ }
972 ++ cursor_set = 1;
973 ++ read_bytes(ssd->pipe[0], &cursor_set_data, sizeof(cursor_set_data));
974 ++ break;
975 ++ case QXL_SERVER_CURSOR_MOVE:
976 ++ cursor_move = 1;
977 ++ read_bytes(ssd->pipe[0], &cursor_move_data, sizeof(cursor_move_data));
978 ++ break;
979 + default:
980 + fprintf(stderr, "%s: unknown cmd %u\n", __FUNCTION__, cmd);
981 + abort();
982 +@@ -1099,6 +1183,12 @@ static void pipe_read(void *opaque)
983 + if (set_irq) {
984 + qxl_set_irq(container_of(ssd, PCIQXLDevice, ssd));
985 + }
986 ++ if (cursor_move) {
987 ++ qxl_render_cursor_move(ssd, cursor_move_data.x, cursor_move_data.y);
988 ++ }
989 ++ if (cursor_set) {
990 ++ qxl_render_cursor_set(ssd, cursor_set_data.c, cursor_set_data.x, cursor_set_data.y);
991 ++ }
992 + }
993 +
994 + static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
995 +diff --git a/hw/qxl.h b/hw/qxl.h
996 +index 701245f..f4f99ec 100644
997 +--- a/hw/qxl.h
998 ++++ b/hw/qxl.h
999 +@@ -93,6 +93,8 @@ typedef struct PCIQXLDevice {
1000 +
1001 + /* qxl.c */
1002 + void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
1003 ++void qxl_server_request_cursor_set(PCIQXLDevice *qxl, QEMUCursor *c, int x, int y);
1004 ++void qxl_server_request_cursor_move(PCIQXLDevice *qxl, int x, int y);
1005 +
1006 + /* qxl-logger.c */
1007 + void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
1008 +@@ -102,3 +104,5 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
1009 + void qxl_render_resize(PCIQXLDevice *qxl);
1010 + void qxl_render_update(PCIQXLDevice *qxl);
1011 + void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
1012 ++void qxl_render_cursor_set(SimpleSpiceDisplay *ssd, QEMUCursor *c, int x, int y);
1013 ++void qxl_render_cursor_move(SimpleSpiceDisplay *ssd, int x, int y);
1014 +diff --git a/ui/spice-display.h b/ui/spice-display.h
1015 +index 2be6a34..bbfd689 100644
1016 +--- a/ui/spice-display.h
1017 ++++ b/ui/spice-display.h
1018 +@@ -31,11 +31,22 @@
1019 +
1020 + #define NUM_SURFACES 1024
1021 +
1022 +-/* For commands/requests from server thread to iothread */
1023 ++/*
1024 ++ * Commands/requests from server thread to iothread.
1025 ++ * Note that CREATE_UPDATE is used both with qxl and without it (spice-display)
1026 ++ * the others are only used with the qxl device.
1027 ++ *
1028 ++ * SET_IRQ - just the request is sent (1 byte)
1029 ++ * CREATE_UPDATE - jus the request is sent (1 byte)
1030 ++ * CURSOR_SET - send QXLServerRequestCursorSet
1031 ++ * CURSOR_MOVE - send QXLServerRequestCursorMove
1032 ++ */
1033 + #define QXL_EMPTY_UPDATE ((void *)-1)
1034 + enum {
1035 + QXL_SERVER_SET_IRQ = 1,
1036 + QXL_SERVER_CREATE_UPDATE,
1037 ++ QXL_SERVER_CURSOR_SET,
1038 ++ QXL_SERVER_CURSOR_MOVE
1039 + };
1040 +
1041 + struct SimpleSpiceUpdate;
1042 +--
1043 +1.7.3.2
1044 +
1045
1046 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
1047 new file mode 100644
1048 index 0000000..0ec25a0
1049 --- /dev/null
1050 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0005-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
1051 @@ -0,0 +1,56 @@
1052 +>From b248befcd93bcd713971b15147fcaa217a3d1bb7 Mon Sep 17 00:00:00 2001
1053 +From: Amit Shah <amit.shah@××××××.com>
1054 +Date: Mon, 21 Mar 2011 21:57:47 +0100
1055 +Subject: [PATCH 05/17] char: Split out tcp socket close code in a separate function
1056 +
1057 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
1058 +---
1059 + qemu-char.c | 25 ++++++++++++++++---------
1060 + 1 files changed, 16 insertions(+), 9 deletions(-)
1061 +
1062 +diff --git a/qemu-char.c b/qemu-char.c
1063 +index bd4e944..4b57af9 100644
1064 +--- a/qemu-char.c
1065 ++++ b/qemu-char.c
1066 +@@ -1911,6 +1911,21 @@ typedef struct {
1067 +
1068 + static void tcp_chr_accept(void *opaque);
1069 +
1070 ++static void tcp_closed(void *opaque)
1071 ++{
1072 ++ CharDriverState *chr = opaque;
1073 ++ TCPCharDriver *s = chr->opaque;
1074 ++
1075 ++ s->connected = 0;
1076 ++ if (s->listen_fd >= 0) {
1077 ++ qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
1078 ++ }
1079 ++ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
1080 ++ closesocket(s->fd);
1081 ++ s->fd = -1;
1082 ++ qemu_chr_event(chr, CHR_EVENT_CLOSED);
1083 ++}
1084 ++
1085 + static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
1086 + {
1087 + TCPCharDriver *s = chr->opaque;
1088 +@@ -2061,15 +2076,7 @@ static void tcp_chr_read(void *opaque)
1089 + len = s->max_size;
1090 + size = tcp_chr_recv(chr, (void *)buf, len);
1091 + if (size == 0) {
1092 +- /* connection closed */
1093 +- s->connected = 0;
1094 +- if (s->listen_fd >= 0) {
1095 +- qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
1096 +- }
1097 +- qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
1098 +- closesocket(s->fd);
1099 +- s->fd = -1;
1100 +- qemu_chr_event(chr, CHR_EVENT_CLOSED);
1101 ++ tcp_closed(chr);
1102 + } else if (size > 0) {
1103 + if (s->do_telnetopt)
1104 + tcp_chr_process_IAC_bytes(chr, s, buf, &size);
1105 +--
1106 +1.7.3.2
1107 +
1108
1109 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
1110 new file mode 100644
1111 index 0000000..095e7ff
1112 --- /dev/null
1113 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0006-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
1114 @@ -0,0 +1,673 @@
1115 +>From 003cc09f8fc34e7571ebd4a89ea6aa6324a80b54 Mon Sep 17 00:00:00 2001
1116 +From: Amit Shah <amit.shah@××××××.com>
1117 +Date: Mon, 21 Mar 2011 20:31:45 +0100
1118 +Subject: [PATCH 06/19] char: Add a QemuChrHandlers struct to initialise chardev handlers
1119 +
1120 +Instead of passing each handler in the qemu_add_handlers() function,
1121 +create a struct of handlers that can be passed to the function instead.
1122 +
1123 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
1124 +---
1125 + gdbstub.c | 9 +++++++--
1126 + hw/debugcon.c | 2 +-
1127 + hw/escc.c | 9 +++++++--
1128 + hw/etraxfs_ser.c | 13 +++++++++----
1129 + hw/grlib_apbuart.c | 12 +++++++-----
1130 + hw/ivshmem.c | 28 ++++++++++++++++++++++------
1131 + hw/mcf_uart.c | 9 +++++++--
1132 + hw/pl011.c | 9 +++++++--
1133 + hw/pxa2xx.c | 13 +++++++++----
1134 + hw/serial.c | 9 +++++++--
1135 + hw/sh_serial.c | 12 +++++++++---
1136 + hw/syborg_serial.c | 9 +++++++--
1137 + hw/usb-serial.c | 9 +++++++--
1138 + hw/virtio-console.c | 9 +++++++--
1139 + hw/xen_console.c | 16 +++++++++++-----
1140 + hw/xilinx_uartlite.c | 11 +++++++++--
1141 + monitor.c | 18 ++++++++++++++----
1142 + net/slirp.c | 8 ++++++--
1143 + qemu-char.c | 30 +++++++++++++++++++++---------
1144 + qemu-char.h | 13 +++++++++----
1145 + 20 files changed, 183 insertions(+), 65 deletions(-)
1146 +
1147 +diff --git a/gdbstub.c b/gdbstub.c
1148 +index 14e8b9b..4190ac7 100644
1149 +--- a/gdbstub.c
1150 ++++ b/gdbstub.c
1151 +@@ -2634,6 +2634,12 @@ static void gdb_sigterm_handler(int signal)
1152 + }
1153 + #endif
1154 +
1155 ++static const QemuChrHandlers gdb_handlers = {
1156 ++ .fd_can_read = gdb_chr_can_receive,
1157 ++ .fd_read = gdb_chr_receive,
1158 ++ .fd_event = gdb_chr_event,
1159 ++};
1160 ++
1161 + int gdbserver_start(const char *device)
1162 + {
1163 + GDBState *s;
1164 +@@ -2663,8 +2669,7 @@ int gdbserver_start(const char *device)
1165 + if (!chr)
1166 + return -1;
1167 +
1168 +- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
1169 +- gdb_chr_event, NULL);
1170 ++ qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
1171 + }
1172 +
1173 + s = gdbserver_state;
1174 +diff --git a/hw/debugcon.c b/hw/debugcon.c
1175 +index 5ee6821..e79a595 100644
1176 +--- a/hw/debugcon.c
1177 ++++ b/hw/debugcon.c
1178 +@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
1179 + exit(1);
1180 + }
1181 +
1182 +- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
1183 ++ qemu_chr_add_handlers(s->chr, NULL, s);
1184 + }
1185 +
1186 + static int debugcon_isa_initfn(ISADevice *dev)
1187 +diff --git a/hw/escc.c b/hw/escc.c
1188 +index f6fd919..dfa329a 100644
1189 +--- a/hw/escc.c
1190 ++++ b/hw/escc.c
1191 +@@ -898,6 +898,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
1192 + sysbus_mmio_map(s, 0, base);
1193 + }
1194 +
1195 ++static const QemuChrHandlers serial_handlers = {
1196 ++ .fd_can_read = serial_can_receive,
1197 ++ .fd_read = serial_receive1,
1198 ++ .fd_event = serial_event,
1199 ++};
1200 ++
1201 + static int escc_init1(SysBusDevice *dev)
1202 + {
1203 + SerialState *s = FROM_SYSBUS(SerialState, dev);
1204 +@@ -911,8 +917,7 @@ static int escc_init1(SysBusDevice *dev)
1205 + s->chn[i].chn = 1 - i;
1206 + s->chn[i].clock = s->frequency / 2;
1207 + if (s->chn[i].chr) {
1208 +- qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
1209 +- serial_receive1, serial_event, &s->chn[i]);
1210 ++ qemu_chr_add_handlers(s->chn[i].chr, &serial_handlers, &s->chn[i]);
1211 + }
1212 + }
1213 + s->chn[0].otherchn = &s->chn[1];
1214 +diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
1215 +index 2787ebd..406121c 100644
1216 +--- a/hw/etraxfs_ser.c
1217 ++++ b/hw/etraxfs_ser.c
1218 +@@ -190,6 +190,12 @@ static void serial_event(void *opaque, int event)
1219 +
1220 + }
1221 +
1222 ++static const QemuChrHandlers serial_handlers = {
1223 ++ .fd_can_read = serial_can_receive,
1224 ++ .fd_read = serial_receive,
1225 ++ .fd_event = serial_event,
1226 ++};
1227 ++
1228 + static int etraxfs_ser_init(SysBusDevice *dev)
1229 + {
1230 + struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
1231 +@@ -204,10 +210,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
1232 + DEVICE_NATIVE_ENDIAN);
1233 + sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
1234 + s->chr = qdev_init_chardev(&dev->qdev);
1235 +- if (s->chr)
1236 +- qemu_chr_add_handlers(s->chr,
1237 +- serial_can_receive, serial_receive,
1238 +- serial_event, s);
1239 ++ if (s->chr) {
1240 ++ qemu_chr_add_handlers(s->chr, &serial_handlers, s);
1241 ++ }
1242 + return 0;
1243 + }
1244 +
1245 +diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
1246 +index 101b150..40d6968 100644
1247 +--- a/hw/grlib_apbuart.c
1248 ++++ b/hw/grlib_apbuart.c
1249 +@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
1250 + NULL, NULL, grlib_apbuart_writel,
1251 + };
1252 +
1253 ++static const QemuChrHandlers grlib_handlers = {
1254 ++ .fd_can_read = grlib_apbuart_can_receive,
1255 ++ .fd_read = grlib_apbuart_receive,
1256 ++ .fd_event = grlib_apbuart_event,
1257 ++};
1258 ++
1259 + static int grlib_apbuart_init(SysBusDevice *dev)
1260 + {
1261 + UART *uart = FROM_SYSBUS(typeof(*uart), dev);
1262 + int uart_regs = 0;
1263 +
1264 +- qemu_chr_add_handlers(uart->chr,
1265 +- grlib_apbuart_can_receive,
1266 +- grlib_apbuart_receive,
1267 +- grlib_apbuart_event,
1268 +- uart);
1269 ++ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
1270 +
1271 + sysbus_init_irq(dev, &uart->irq);
1272 +
1273 +diff --git a/hw/ivshmem.c b/hw/ivshmem.c
1274 +index 7b19a81..ef8e5ce 100644
1275 +--- a/hw/ivshmem.c
1276 ++++ b/hw/ivshmem.c
1277 +@@ -312,6 +312,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
1278 + msix_notify(pdev, entry->vector);
1279 + }
1280 +
1281 ++static const QemuChrHandlers ivshmem_handlers = {
1282 ++ .fd_can_read = ivshmem_can_receive,
1283 ++ .fd_read = ivshmem_receive,
1284 ++ .fd_event = ivshmem_event,
1285 ++};
1286 ++
1287 ++static const QemuChrHandlers ivshmem_msi_handlers = {
1288 ++ .fd_can_read = ivshmem_can_receive,
1289 ++ .fd_read = fake_irqfd,
1290 ++ .fd_event = ivshmem_event,
1291 ++};
1292 ++
1293 + static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
1294 + int vector)
1295 + {
1296 +@@ -331,11 +343,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
1297 + s->eventfd_table[vector].pdev = &s->dev;
1298 + s->eventfd_table[vector].vector = vector;
1299 +
1300 +- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
1301 +- ivshmem_event, &s->eventfd_table[vector]);
1302 ++ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
1303 ++ &s->eventfd_table[vector]);
1304 + } else {
1305 +- qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive,
1306 +- ivshmem_event, s);
1307 ++ qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
1308 + }
1309 +
1310 + return chr;
1311 +@@ -666,6 +677,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
1312 + return 0;
1313 + }
1314 +
1315 ++static const QemuChrHandlers ivshmem_server_handlers = {
1316 ++ .fd_can_read = ivshmem_can_receive,
1317 ++ .fd_read = ivshmem_read,
1318 ++ .fd_event = ivshmem_event,
1319 ++};
1320 ++
1321 + static int pci_ivshmem_init(PCIDevice *dev)
1322 + {
1323 + IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
1324 +@@ -754,8 +771,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
1325 +
1326 + s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *));
1327 +
1328 +- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
1329 +- ivshmem_event, s);
1330 ++ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
1331 + } else {
1332 + /* just map the file immediately, we're not using a server */
1333 + int fd;
1334 +diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
1335 +index db57096..9928c11 100644
1336 +--- a/hw/mcf_uart.c
1337 ++++ b/hw/mcf_uart.c
1338 +@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
1339 + mcf_uart_push_byte(s, buf[0]);
1340 + }
1341 +
1342 ++static const QemuChrHandlers mcf_uart_handlers = {
1343 ++ .fd_can_read = mcf_uart_can_receive,
1344 ++ .fd_read = mcf_uart_receive,
1345 ++ .fd_event = mcf_uart_event,
1346 ++};
1347 ++
1348 + void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
1349 + {
1350 + mcf_uart_state *s;
1351 +@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
1352 + s->chr = chr;
1353 + s->irq = irq;
1354 + if (chr) {
1355 +- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
1356 +- mcf_uart_event, s);
1357 ++ qemu_chr_add_handlers(chr, &mcf_uart_handlers, s);
1358 + }
1359 + mcf_uart_reset(s);
1360 + return s;
1361 +diff --git a/hw/pl011.c b/hw/pl011.c
1362 +index 77f0dbf..d93c655 100644
1363 +--- a/hw/pl011.c
1364 ++++ b/hw/pl011.c
1365 +@@ -286,6 +286,12 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id)
1366 + return 0;
1367 + }
1368 +
1369 ++static const QemuChrHandlers pl011_handlers = {
1370 ++ .fd_can_read = pl011_can_receive,
1371 ++ .fd_read = pl011_receive,
1372 ++ .fd_event = pl011_event,
1373 ++};
1374 ++
1375 + static int pl011_init(SysBusDevice *dev, const unsigned char *id)
1376 + {
1377 + int iomemtype;
1378 +@@ -304,8 +310,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
1379 + s->cr = 0x300;
1380 + s->flags = 0x90;
1381 + if (s->chr) {
1382 +- qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
1383 +- pl011_event, s);
1384 ++ qemu_chr_add_handlers(s->chr, &pl011_handlers, s);
1385 + }
1386 + register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
1387 + return 0;
1388 +diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
1389 +index d966846..d7ebf33 100644
1390 +--- a/hw/pxa2xx.c
1391 ++++ b/hw/pxa2xx.c
1392 +@@ -1995,6 +1995,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
1393 + return 0;
1394 + }
1395 +
1396 ++static const QemuChrHandlers pxa2xx_handlers = {
1397 ++ .fd_can_read = pxa2xx_fir_is_empty,
1398 ++ .fd_read = pxa2xx_fir_rx,
1399 ++ .fd_event = pxa2xx_fir_event,
1400 ++};
1401 ++
1402 + static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
1403 + qemu_irq irq, PXA2xxDMAState *dma,
1404 + CharDriverState *chr)
1405 +@@ -2013,10 +2019,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
1406 + pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
1407 + cpu_register_physical_memory(base, 0x1000, iomemtype);
1408 +
1409 +- if (chr)
1410 +- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
1411 +- pxa2xx_fir_rx, pxa2xx_fir_event, s);
1412 +-
1413 ++ if (chr) {
1414 ++ qemu_chr_add_handlers(chr, &pxa2xx_handlers, s);
1415 ++ }
1416 + register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
1417 + pxa2xx_fir_load, s);
1418 +
1419 +diff --git a/hw/serial.c b/hw/serial.c
1420 +index 2c4af61..65265e2 100644
1421 +--- a/hw/serial.c
1422 ++++ b/hw/serial.c
1423 +@@ -727,6 +727,12 @@ static void serial_reset(void *opaque)
1424 + qemu_irq_lower(s->irq);
1425 + }
1426 +
1427 ++static const QemuChrHandlers serial_handlers = {
1428 ++ .fd_can_read = serial_can_receive1,
1429 ++ .fd_read = serial_receive1,
1430 ++ .fd_event = serial_event,
1431 ++};
1432 ++
1433 + static void serial_init_core(SerialState *s)
1434 + {
1435 + if (!s->chr) {
1436 +@@ -741,8 +747,7 @@ static void serial_init_core(SerialState *s)
1437 +
1438 + qemu_register_reset(serial_reset, s);
1439 +
1440 +- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
1441 +- serial_event, s);
1442 ++ qemu_chr_add_handlers(s->chr, &serial_handlers, s);
1443 + }
1444 +
1445 + /* Change the main reference oscillator frequency. */
1446 +diff --git a/hw/sh_serial.c b/hw/sh_serial.c
1447 +index 191f4a6..8b6460d 100644
1448 +--- a/hw/sh_serial.c
1449 ++++ b/hw/sh_serial.c
1450 +@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
1451 + &sh_serial_write,
1452 + };
1453 +
1454 ++static const QemuChrHandlers sh_serial_handlers = {
1455 ++ .fd_can_read = sh_serial_can_receive1,
1456 ++ .fd_read = sh_serial_receive1,
1457 ++ .fd_event = sh_serial_event,
1458 ++};
1459 ++
1460 + void sh_serial_init (target_phys_addr_t base, int feat,
1461 + uint32_t freq, CharDriverState *chr,
1462 + qemu_irq eri_source,
1463 +@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
1464 +
1465 + s->chr = chr;
1466 +
1467 +- if (chr)
1468 +- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
1469 +- sh_serial_event, s);
1470 ++ if (chr) {
1471 ++ qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
1472 ++ }
1473 +
1474 + s->eri = eri_source;
1475 + s->rxi = rxi_source;
1476 +diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
1477 +index 34ce076..124b636 100644
1478 +--- a/hw/syborg_serial.c
1479 ++++ b/hw/syborg_serial.c
1480 +@@ -315,6 +315,12 @@ static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
1481 + return 0;
1482 + }
1483 +
1484 ++static const QemuChrHandlers syborg_serial_handlers = {
1485 ++ .fd_can_read = syborg_serial_can_receive,
1486 ++ .fd_read = syborg_serial_receive,
1487 ++ .fd_event = syborg_serial_event,
1488 ++};
1489 ++
1490 + static int syborg_serial_init(SysBusDevice *dev)
1491 + {
1492 + SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
1493 +@@ -327,8 +333,7 @@ static int syborg_serial_init(SysBusDevice *dev)
1494 + sysbus_init_mmio(dev, 0x1000, iomemtype);
1495 + s->chr = qdev_init_chardev(&dev->qdev);
1496 + if (s->chr) {
1497 +- qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
1498 +- syborg_serial_receive, syborg_serial_event, s);
1499 ++ qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s);
1500 + }
1501 + if (s->fifo_size <= 0) {
1502 + fprintf(stderr, "syborg_serial: fifo too small\n");
1503 +diff --git a/hw/usb-serial.c b/hw/usb-serial.c
1504 +index 6763d52..2435d9d 100644
1505 +--- a/hw/usb-serial.c
1506 ++++ b/hw/usb-serial.c
1507 +@@ -475,6 +475,12 @@ static void usb_serial_event(void *opaque, int event)
1508 + }
1509 + }
1510 +
1511 ++static const QemuChrHandlers usb_serial_handlers = {
1512 ++ .fd_can_read = usb_serial_can_read,
1513 ++ .fd_read = usb_serial_read,
1514 ++ .fd_event = usb_serial_event,
1515 ++};
1516 ++
1517 + static int usb_serial_initfn(USBDevice *dev)
1518 + {
1519 + USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
1520 +@@ -486,8 +492,7 @@ static int usb_serial_initfn(USBDevice *dev)
1521 + return -1;
1522 + }
1523 +
1524 +- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
1525 +- usb_serial_event, s);
1526 ++ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
1527 + usb_serial_handle_reset(dev);
1528 + return 0;
1529 + }
1530 +diff --git a/hw/virtio-console.c b/hw/virtio-console.c
1531 +index 62624ec..22cf28c 100644
1532 +--- a/hw/virtio-console.c
1533 ++++ b/hw/virtio-console.c
1534 +@@ -57,13 +57,18 @@ static void chr_event(void *opaque, int event)
1535 + }
1536 + }
1537 +
1538 ++static const QemuChrHandlers chr_handlers = {
1539 ++ .fd_can_read = chr_can_read,
1540 ++ .fd_read = chr_read,
1541 ++ .fd_event = chr_event,
1542 ++};
1543 ++
1544 + static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
1545 + {
1546 + vcon->port.info = dev->info;
1547 +
1548 + if (vcon->chr) {
1549 +- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
1550 +- vcon);
1551 ++ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
1552 + vcon->port.info->have_data = flush_buf;
1553 + }
1554 + return 0;
1555 +diff --git a/hw/xen_console.c b/hw/xen_console.c
1556 +index d2261f4..8327e4e 100644
1557 +--- a/hw/xen_console.c
1558 ++++ b/hw/xen_console.c
1559 +@@ -202,6 +202,11 @@ static int con_init(struct XenDevice *xendev)
1560 + return 0;
1561 + }
1562 +
1563 ++static const QemuChrHandlers xencons_handlers = {
1564 ++ .fd_can_read = xencons_can_receive,
1565 ++ .fd_read = xencons_receive,
1566 ++};
1567 ++
1568 + static int con_connect(struct XenDevice *xendev)
1569 + {
1570 + struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
1571 +@@ -222,9 +227,9 @@ static int con_connect(struct XenDevice *xendev)
1572 + return -1;
1573 +
1574 + xen_be_bind_evtchn(&con->xendev);
1575 +- if (con->chr)
1576 +- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
1577 +- NULL, con);
1578 ++ if (con->chr) {
1579 ++ qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
1580 ++ }
1581 +
1582 + xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
1583 + con->ring_ref,
1584 +@@ -238,8 +243,9 @@ static void con_disconnect(struct XenDevice *xendev)
1585 + {
1586 + struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
1587 +
1588 +- if (con->chr)
1589 +- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
1590 ++ if (con->chr) {
1591 ++ qemu_chr_add_handlers(con->chr, NULL, NULL);
1592 ++ }
1593 + xen_be_unbind_evtchn(&con->xendev);
1594 +
1595 + if (con->sring) {
1596 +diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
1597 +index 9b94e98..1845577 100644
1598 +--- a/hw/xilinx_uartlite.c
1599 ++++ b/hw/xilinx_uartlite.c
1600 +@@ -193,6 +193,12 @@ static void uart_event(void *opaque, int event)
1601 +
1602 + }
1603 +
1604 ++static const QemuChrHandlers uart_handlers = {
1605 ++ .fd_can_read = uart_can_rx,
1606 ++ .fd_read = uart_rx,
1607 ++ .fd_event = uart_event,
1608 ++};
1609 ++
1610 + static int xilinx_uartlite_init(SysBusDevice *dev)
1611 + {
1612 + struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
1613 +@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
1614 + sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
1615 +
1616 + s->chr = qdev_init_chardev(&dev->qdev);
1617 +- if (s->chr)
1618 +- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
1619 ++ if (s->chr) {
1620 ++ qemu_chr_add_handlers(s->chr, &uart_handlers, s);
1621 ++ }
1622 + return 0;
1623 + }
1624 +
1625 +diff --git a/monitor.c b/monitor.c
1626 +index 096d42b..a00a233 100644
1627 +--- a/monitor.c
1628 ++++ b/monitor.c
1629 +@@ -5179,6 +5179,18 @@ static void monitor_event(void *opaque, int event)
1630 + * End:
1631 + */
1632 +
1633 ++static const QemuChrHandlers monitor_handlers = {
1634 ++ .fd_can_read = monitor_can_read,
1635 ++ .fd_read = monitor_read,
1636 ++ .fd_event = monitor_event,
1637 ++};
1638 ++
1639 ++static const QemuChrHandlers monitor_control_handlers = {
1640 ++ .fd_can_read = monitor_can_read,
1641 ++ .fd_read = monitor_control_read,
1642 ++ .fd_event = monitor_control_event,
1643 ++};
1644 ++
1645 + void monitor_init(CharDriverState *chr, int flags)
1646 + {
1647 + static int is_first_init = 1;
1648 +@@ -5201,12 +5213,10 @@ void monitor_init(CharDriverState *chr, int flags)
1649 + if (monitor_ctrl_mode(mon)) {
1650 + mon->mc = qemu_mallocz(sizeof(MonitorControl));
1651 + /* Control mode requires special handlers */
1652 +- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
1653 +- monitor_control_event, mon);
1654 ++ qemu_chr_add_handlers(chr, &monitor_control_handlers, mon);
1655 + qemu_chr_set_echo(chr, true);
1656 + } else {
1657 +- qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
1658 +- monitor_event, mon);
1659 ++ qemu_chr_add_handlers(chr, &monitor_handlers, mon);
1660 + }
1661 +
1662 + QLIST_INSERT_HEAD(&mon_list, mon, entry);
1663 +diff --git a/net/slirp.c b/net/slirp.c
1664 +index b41c60a..437be46 100644
1665 +--- a/net/slirp.c
1666 ++++ b/net/slirp.c
1667 +@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
1668 + slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
1669 + }
1670 +
1671 ++static const QemuChrHandlers guestfwd_handlers = {
1672 ++ .fd_can_read = guestfwd_can_read,
1673 ++ .fd_read = guestfwd_read,
1674 ++};
1675 ++
1676 + static int slirp_guestfwd(SlirpState *s, const char *config_str,
1677 + int legacy_format)
1678 + {
1679 +@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
1680 + fwd->port = port;
1681 + fwd->slirp = s->slirp;
1682 +
1683 +- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
1684 +- NULL, fwd);
1685 ++ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
1686 + return 0;
1687 +
1688 + fail_syntax:
1689 +diff --git a/qemu-char.c b/qemu-char.c
1690 +index 4b57af9..3a31d8b 100644
1691 +--- a/qemu-char.c
1692 ++++ b/qemu-char.c
1693 +@@ -191,15 +191,22 @@ void qemu_chr_send_event(CharDriverState *s, int event)
1694 + s->chr_send_event(s, event);
1695 + }
1696 +
1697 ++static const QemuChrHandlers null_handlers = {
1698 ++ /* All handlers are initialised to NULL */
1699 ++};
1700 ++
1701 + void qemu_chr_add_handlers(CharDriverState *s,
1702 +- IOCanReadHandler *fd_can_read,
1703 +- IOReadHandler *fd_read,
1704 +- IOEventHandler *fd_event,
1705 +- void *opaque)
1706 +-{
1707 +- s->chr_can_read = fd_can_read;
1708 +- s->chr_read = fd_read;
1709 +- s->chr_event = fd_event;
1710 ++ const QemuChrHandlers *handlers, void *opaque)
1711 ++{
1712 ++ if (!s) {
1713 ++ return;
1714 ++ }
1715 ++ if (!handlers) {
1716 ++ handlers = &null_handlers;
1717 ++ }
1718 ++ s->chr_can_read = handlers->fd_can_read;
1719 ++ s->chr_read = handlers->fd_read;
1720 ++ s->chr_event = handlers->fd_event;
1721 + s->handler_opaque = opaque;
1722 + if (s->chr_update_read_handler)
1723 + s->chr_update_read_handler(s);
1724 +@@ -437,6 +444,12 @@ static void mux_chr_event(void *opaque, int event)
1725 + mux_chr_send_event(d, i, event);
1726 + }
1727 +
1728 ++static const QemuChrHandlers mux_chr_handlers = {
1729 ++ .fd_can_read = mux_chr_can_read,
1730 ++ .fd_read = mux_chr_read,
1731 ++ .fd_event = mux_chr_event,
1732 ++};
1733 ++
1734 + static void mux_chr_update_read_handler(CharDriverState *chr)
1735 + {
1736 + MuxDriver *d = chr->opaque;
1737 +@@ -451,8 +464,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
1738 + d->chr_event[d->mux_cnt] = chr->chr_event;
1739 + /* Fix up the real driver with mux routines */
1740 + if (d->mux_cnt == 0) {
1741 +- qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
1742 +- mux_chr_event, chr);
1743 ++ qemu_chr_add_handlers(d->drv, &mux_chr_handlers, chr);
1744 + }
1745 + if (d->focus != -1) {
1746 + mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
1747 +diff --git a/qemu-char.h b/qemu-char.h
1748 +index 56d9954..7a1924c 100644
1749 +--- a/qemu-char.h
1750 ++++ b/qemu-char.h
1751 +@@ -1,6 +1,7 @@
1752 + #ifndef QEMU_CHAR_H
1753 + #define QEMU_CHAR_H
1754 +
1755 ++#include <stdbool.h>
1756 + #include "qemu-common.h"
1757 + #include "qemu-queue.h"
1758 + #include "qemu-option.h"
1759 +@@ -73,6 +74,13 @@ struct CharDriverState {
1760 + QTAILQ_ENTRY(CharDriverState) next;
1761 + };
1762 +
1763 ++typedef struct QemuChrHandlers {
1764 ++ IOCanReadHandler *fd_can_read;
1765 ++ IOReadHandler *fd_read;
1766 ++ IOHandler *fd_write_unblocked;
1767 ++ IOEventHandler *fd_event;
1768 ++} QemuChrHandlers;
1769 ++
1770 + QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
1771 + CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
1772 + void (*init)(struct CharDriverState *s));
1773 +@@ -83,10 +91,7 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
1774 + GCC_FMT_ATTR(2, 3);
1775 + int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
1776 + void qemu_chr_send_event(CharDriverState *s, int event);
1777 +-void qemu_chr_add_handlers(CharDriverState *s,
1778 +- IOCanReadHandler *fd_can_read,
1779 +- IOReadHandler *fd_read,
1780 +- IOEventHandler *fd_event,
1781 ++void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
1782 + void *opaque);
1783 + int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
1784 + void qemu_chr_generic_open(CharDriverState *s);
1785 +--
1786 +1.7.4.1
1787 +
1788
1789 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
1790 new file mode 100644
1791 index 0000000..336c582
1792 --- /dev/null
1793 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0007-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
1794 @@ -0,0 +1,76 @@
1795 +>From da7e6cd863ed0cffe885cd2d3639f92c82baf6e2 Mon Sep 17 00:00:00 2001
1796 +From: Amit Shah <amit.shah@××××××.com>
1797 +Date: Mon, 21 Mar 2011 20:32:58 +0100
1798 +Subject: [PATCH 07/17] iohandlers: Add enable/disable_write_fd_handler() functions
1799 +
1800 +These will be used to provide a cleaner API for the nonblocking case.
1801 +
1802 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
1803 +---
1804 + qemu-char.h | 3 +++
1805 + vl.c | 35 +++++++++++++++++++++++++++++++++++
1806 + 2 files changed, 38 insertions(+), 0 deletions(-)
1807 +
1808 +diff --git a/qemu-char.h b/qemu-char.h
1809 +index 7a1924c..185377c 100644
1810 +--- a/qemu-char.h
1811 ++++ b/qemu-char.h
1812 +@@ -116,6 +116,9 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr);
1813 +
1814 + /* async I/O support */
1815 +
1816 ++void enable_write_fd_handler(int fd, IOHandler *fd_write);
1817 ++void disable_write_fd_handler(int fd);
1818 ++
1819 + int qemu_set_fd_handler2(int fd,
1820 + IOCanReadHandler *fd_read_poll,
1821 + IOHandler *fd_read,
1822 +diff --git a/vl.c b/vl.c
1823 +index 85c36e3..95f51cb 100644
1824 +--- a/vl.c
1825 ++++ b/vl.c
1826 +@@ -1044,6 +1044,41 @@ typedef struct IOHandlerRecord {
1827 + static QLIST_HEAD(, IOHandlerRecord) io_handlers =
1828 + QLIST_HEAD_INITIALIZER(io_handlers);
1829 +
1830 ++static IOHandlerRecord *find_iohandler(int fd)
1831 ++{
1832 ++ IOHandlerRecord *ioh;
1833 ++
1834 ++ QLIST_FOREACH(ioh, &io_handlers, next) {
1835 ++ if (ioh->fd == fd) {
1836 ++ return ioh;
1837 ++ }
1838 ++ }
1839 ++ return NULL;
1840 ++}
1841 ++
1842 ++void enable_write_fd_handler(int fd, IOHandler *fd_write)
1843 ++{
1844 ++ IOHandlerRecord *ioh;
1845 ++
1846 ++ ioh = find_iohandler(fd);
1847 ++ if (!ioh) {
1848 ++ return;
1849 ++ }
1850 ++
1851 ++ ioh->fd_write = fd_write;
1852 ++}
1853 ++
1854 ++void disable_write_fd_handler(int fd)
1855 ++{
1856 ++ IOHandlerRecord *ioh;
1857 ++
1858 ++ ioh = find_iohandler(fd);
1859 ++ if (!ioh) {
1860 ++ return;
1861 ++ }
1862 ++
1863 ++ ioh->fd_write = NULL;
1864 ++}
1865 +
1866 + /* XXX: fd_read_poll should be suppressed, but an API change is
1867 + necessary in the character devices to suppress fd_can_read(). */
1868 +--
1869 +1.7.3.2
1870 +
1871
1872 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
1873 new file mode 100644
1874 index 0000000..ab3eb1f
1875 --- /dev/null
1876 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0008-char-Add-framework-for-a-write-unblocked-callback.patch
1877 @@ -0,0 +1,62 @@
1878 +>From daf37480ffe37b3e7a781ff010beb4fa89821c29 Mon Sep 17 00:00:00 2001
1879 +From: Amit Shah <amit.shah@××××××.com>
1880 +Date: Mon, 21 Mar 2011 21:41:42 +0100
1881 +Subject: [PATCH 08/17] char: Add framework for a 'write unblocked' callback
1882 +
1883 +The char layer can let users know that the driver will block on further
1884 +input. For users interested in not blocking, they can assign a function
1885 +pointer that will be called back when the driver becomes writable. This
1886 +patch just adds the function pointers to the CharDriverState structure,
1887 +future patches will enable the nonblocking and callback functionality.
1888 +
1889 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
1890 +---
1891 + qemu-char.c | 3 +++
1892 + qemu-char.h | 5 +++++
1893 + 2 files changed, 8 insertions(+), 0 deletions(-)
1894 +
1895 +diff --git a/qemu-char.c b/qemu-char.c
1896 +index 3a31d8b..ce76411 100644
1897 +--- a/qemu-char.c
1898 ++++ b/qemu-char.c
1899 +@@ -206,11 +206,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
1900 + }
1901 + s->chr_can_read = handlers->fd_can_read;
1902 + s->chr_read = handlers->fd_read;
1903 ++ s->chr_write_unblocked = handlers->fd_write_unblocked;
1904 + s->chr_event = handlers->fd_event;
1905 + s->handler_opaque = opaque;
1906 + if (s->chr_update_read_handler)
1907 + s->chr_update_read_handler(s);
1908 +
1909 ++ s->write_blocked = false;
1910 ++
1911 + /* We're connecting to an already opened device, so let's make sure we
1912 + also get the open event */
1913 + if (s->opened) {
1914 +diff --git a/qemu-char.h b/qemu-char.h
1915 +index 185377c..bf06da0 100644
1916 +--- a/qemu-char.h
1917 ++++ b/qemu-char.h
1918 +@@ -61,6 +61,9 @@ struct CharDriverState {
1919 + IOEventHandler *chr_event;
1920 + IOCanReadHandler *chr_can_read;
1921 + IOReadHandler *chr_read;
1922 ++ IOHandler *chr_write_unblocked;
1923 ++ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
1924 ++ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
1925 + void *handler_opaque;
1926 + void (*chr_send_event)(struct CharDriverState *chr, int event);
1927 + void (*chr_close)(struct CharDriverState *chr);
1928 +@@ -71,6 +74,8 @@ struct CharDriverState {
1929 + char *label;
1930 + char *filename;
1931 + int opened;
1932 ++ /* Are we in a blocked state? */
1933 ++ bool write_blocked;
1934 + QTAILQ_ENTRY(CharDriverState) next;
1935 + };
1936 +
1937 +--
1938 +1.7.3.2
1939 +
1940
1941 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
1942 new file mode 100644
1943 index 0000000..ccf98ad
1944 --- /dev/null
1945 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0009-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
1946 @@ -0,0 +1,197 @@
1947 +>From 8b73193a8584da4e93bccd93fe6f0b8f1a1612b3 Mon Sep 17 00:00:00 2001
1948 +From: Amit Shah <amit.shah@××××××.com>
1949 +Date: Mon, 21 Mar 2011 22:00:27 +0100
1950 +Subject: [PATCH 09/17] char: Update send_all() to handle nonblocking chardev write requests
1951 +
1952 +The send_all function is modified to return to the caller in case the
1953 +driver cannot handle any more data. It returns -EAGAIN or
1954 +WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This
1955 +is only done when the caller sets a callback function handler indicating
1956 +it's not interested in blocking till the driver has written out all the
1957 +data.
1958 +
1959 +Currently there's no driver or caller that supports this. Future
1960 +commits will add such capability.
1961 +
1962 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
1963 +---
1964 + net/socket.c | 4 +-
1965 + qemu-char.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1966 + qemu_socket.h | 2 +-
1967 + 3 files changed, 76 insertions(+), 9 deletions(-)
1968 +
1969 +diff --git a/net/socket.c b/net/socket.c
1970 +index 3182b37..5dedd78 100644
1971 +--- a/net/socket.c
1972 ++++ b/net/socket.c
1973 +@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
1974 + uint32_t len;
1975 + len = htonl(size);
1976 +
1977 +- send_all(s->fd, (const uint8_t *)&len, sizeof(len));
1978 +- return send_all(s->fd, buf, size);
1979 ++ send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len));
1980 ++ return send_all(NULL, s->fd, buf, size);
1981 + }
1982 +
1983 + static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
1984 +diff --git a/qemu-char.c b/qemu-char.c
1985 +index ce76411..eed61d6 100644
1986 +--- a/qemu-char.c
1987 ++++ b/qemu-char.c
1988 +@@ -500,7 +500,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
1989 +
1990 +
1991 + #ifdef _WIN32
1992 +-int send_all(int fd, const void *buf, int len1)
1993 ++static int do_send(int fd, const void *buf, int len1, bool nonblock)
1994 + {
1995 + int ret, len;
1996 +
1997 +@@ -508,9 +508,14 @@ int send_all(int fd, const void *buf, int len1)
1998 + while (len > 0) {
1999 + ret = send(fd, buf, len, 0);
2000 + if (ret < 0) {
2001 ++ if (nonblock && len1 - len) {
2002 ++ return len1 - len;
2003 ++ }
2004 + errno = WSAGetLastError();
2005 + if (errno != WSAEWOULDBLOCK) {
2006 + return -1;
2007 ++ } else if (errno == WSAEWOULDBLOCK && nonblock) {
2008 ++ return WSAEWOULDBLOCK;
2009 + }
2010 + } else if (ret == 0) {
2011 + break;
2012 +@@ -524,7 +529,7 @@ int send_all(int fd, const void *buf, int len1)
2013 +
2014 + #else
2015 +
2016 +-int send_all(int fd, const void *_buf, int len1)
2017 ++static int do_send(int fd, const void *_buf, int len1, bool nonblock)
2018 + {
2019 + int ret, len;
2020 + const uint8_t *buf = _buf;
2021 +@@ -533,8 +538,15 @@ int send_all(int fd, const void *_buf, int len1)
2022 + while (len > 0) {
2023 + ret = write(fd, buf, len);
2024 + if (ret < 0) {
2025 +- if (errno != EINTR && errno != EAGAIN)
2026 ++ if (nonblock && len1 - len) {
2027 ++ return len1 - len;
2028 ++ }
2029 ++ if (errno == EAGAIN && nonblock) {
2030 ++ return -EAGAIN;
2031 ++ }
2032 ++ if (errno != EINTR && errno != EAGAIN) {
2033 + return -1;
2034 ++ }
2035 + } else if (ret == 0) {
2036 + break;
2037 + } else {
2038 +@@ -546,6 +558,55 @@ int send_all(int fd, const void *_buf, int len1)
2039 + }
2040 + #endif /* !_WIN32 */
2041 +
2042 ++int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
2043 ++{
2044 ++ int ret, eagain_errno;
2045 ++ bool nonblock;
2046 ++
2047 ++ if (chr && chr->write_blocked) {
2048 ++ /*
2049 ++ * We don't handle this situation: the caller should not send
2050 ++ * us data while we're blocked.
2051 ++ *
2052 ++ * We could buffer this data here but that'll only encourage
2053 ++ * bad behaviour on part of the callers.
2054 ++ *
2055 ++ * Also, the data already in fd's buffers isn't easily
2056 ++ * migratable. If we want full migration support, all the
2057 ++ * data landing here needs to be buffered and on migration,
2058 ++ * anything that's unsent needs to be transferred to the
2059 ++ * dest. machine (which again isn't a very good way of solving
2060 ++ * the problem, as the src may become writable just during
2061 ++ * migration and the reader could receive some data twice,
2062 ++ * essentially corrupting the data).
2063 ++ */
2064 ++ abort();
2065 ++ }
2066 ++
2067 ++ nonblock = false;
2068 ++ /*
2069 ++ * Ensure the char backend is able to receive and handle the
2070 ++ * 'write unblocked' event before we turn on nonblock support.
2071 ++ */
2072 ++ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
2073 ++ nonblock = true;
2074 ++ }
2075 ++ ret = do_send(fd, _buf, len1, nonblock);
2076 ++
2077 ++#ifdef _WIN32
2078 ++ eagain_errno = WSAEWOULDBLOCK;
2079 ++#else
2080 ++ eagain_errno = -EAGAIN;
2081 ++#endif
2082 ++
2083 ++ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
2084 ++ /* Update fd handler to wake up when chr becomes writable */
2085 ++ chr->chr_enable_write_fd_handler(chr);
2086 ++ chr->write_blocked = true;
2087 ++ }
2088 ++ return ret;
2089 ++}
2090 ++
2091 + #ifndef _WIN32
2092 +
2093 + typedef struct {
2094 +@@ -559,7 +620,7 @@ static int stdio_nb_clients = 0;
2095 + static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2096 + {
2097 + FDCharDriver *s = chr->opaque;
2098 +- return send_all(s->fd_out, buf, len);
2099 ++ return send_all(chr, s->fd_out, buf, len);
2100 + }
2101 +
2102 + static int fd_chr_read_poll(void *opaque)
2103 +@@ -875,7 +936,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2104 + pty_chr_update_read_handler(chr);
2105 + return 0;
2106 + }
2107 +- return send_all(s->fd, buf, len);
2108 ++ return send_all(chr, s->fd, buf, len);
2109 + }
2110 +
2111 + static int pty_chr_read_poll(void *opaque)
2112 +@@ -1944,8 +2005,14 @@ static void tcp_closed(void *opaque)
2113 + static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2114 + {
2115 + TCPCharDriver *s = chr->opaque;
2116 ++
2117 + if (s->connected) {
2118 +- return send_all(s->fd, buf, len);
2119 ++ int ret;
2120 ++
2121 ++ ret = send_all(chr, s->fd, buf, len);
2122 ++ if (ret == -1 && errno == EPIPE) {
2123 ++ tcp_closed(chr);
2124 ++ }
2125 + } else {
2126 + /* XXX: indicate an error ? */
2127 + return len;
2128 +diff --git a/qemu_socket.h b/qemu_socket.h
2129 +index 897a8ae..97dd24a 100644
2130 +--- a/qemu_socket.h
2131 ++++ b/qemu_socket.h
2132 +@@ -36,7 +36,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
2133 + int qemu_socket(int domain, int type, int protocol);
2134 + int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
2135 + void socket_set_nonblock(int fd);
2136 +-int send_all(int fd, const void *buf, int len1);
2137 ++int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
2138 +
2139 + /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
2140 + int inet_listen_opts(QemuOpts *opts, int port_offset);
2141 +--
2142 +1.7.3.2
2143 +
2144
2145 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
2146 new file mode 100644
2147 index 0000000..f08d700
2148 --- /dev/null
2149 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0010-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
2150 @@ -0,0 +1,80 @@
2151 +>From 7d8cbead9454da6dbfdc050c6828faae39621a1b Mon Sep 17 00:00:00 2001
2152 +From: Amit Shah <amit.shah@××××××.com>
2153 +Date: Mon, 21 Mar 2011 22:02:47 +0100
2154 +Subject: [PATCH 10/17] char: Equip the unix/tcp backend to handle nonblocking writes#
2155 +
2156 +Now that the infrastructure is in place to return -EAGAIN to callers,
2157 +individual char drivers can set their update_fd_handlers() function to
2158 +set or remove an fd's write handler. This handler checks if the driver
2159 +became writable.
2160 +
2161 +A generic callback routine is used for unblocking writes and letting
2162 +users of chardevs know that a driver became writable again.
2163 +
2164 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
2165 +---
2166 + qemu-char.c | 34 ++++++++++++++++++++++++++++++++++
2167 + 1 files changed, 34 insertions(+), 0 deletions(-)
2168 +
2169 +diff --git a/qemu-char.c b/qemu-char.c
2170 +index eed61d6..7517f64 100644
2171 +--- a/qemu-char.c
2172 ++++ b/qemu-char.c
2173 +@@ -107,6 +107,19 @@
2174 + static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
2175 + QTAILQ_HEAD_INITIALIZER(chardevs);
2176 +
2177 ++/*
2178 ++ * Generic routine that gets called when chardev becomes writable.
2179 ++ * Lets chardev user know it's OK to send more data.
2180 ++ */
2181 ++static void char_write_unblocked(void *opaque)
2182 ++{
2183 ++ CharDriverState *chr = opaque;
2184 ++
2185 ++ chr->write_blocked = false;
2186 ++ chr->chr_disable_write_fd_handler(chr);
2187 ++ chr->chr_write_unblocked(chr->handler_opaque);
2188 ++}
2189 ++
2190 + static void qemu_chr_event(CharDriverState *s, int event)
2191 + {
2192 + /* Keep track if the char device is open */
2193 +@@ -2261,6 +2274,25 @@ static void tcp_chr_close(CharDriverState *chr)
2194 + qemu_chr_event(chr, CHR_EVENT_CLOSED);
2195 + }
2196 +
2197 ++static void tcp_enable_write_fd_handler(CharDriverState *chr)
2198 ++{
2199 ++ TCPCharDriver *s = chr->opaque;
2200 ++
2201 ++ /*
2202 ++ * This function is called only after tcp_chr_connect() is called
2203 ++ * (either in 'server' mode or client mode. So we're sure of
2204 ++ * s->fd being initialised.
2205 ++ */
2206 ++ enable_write_fd_handler(s->fd, char_write_unblocked);
2207 ++}
2208 ++
2209 ++static void tcp_disable_write_fd_handler(CharDriverState *chr)
2210 ++{
2211 ++ TCPCharDriver *s = chr->opaque;
2212 ++
2213 ++ disable_write_fd_handler(s->fd);
2214 ++}
2215 ++
2216 + static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
2217 + {
2218 + CharDriverState *chr = NULL;
2219 +@@ -2313,6 +2345,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
2220 + chr->chr_write = tcp_chr_write;
2221 + chr->chr_close = tcp_chr_close;
2222 + chr->get_msgfd = tcp_get_msgfd;
2223 ++ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
2224 ++ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
2225 +
2226 + if (is_listen) {
2227 + s->listen_fd = fd;
2228 +--
2229 +1.7.3.2
2230 +
2231
2232 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
2233 new file mode 100644
2234 index 0000000..78f906a
2235 --- /dev/null
2236 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0011-char-Throttle-when-host-connection-is-down.patch
2237 @@ -0,0 +1,56 @@
2238 +>From 473be206466567646e3377b8eb64e25ffc2b3afe Mon Sep 17 00:00:00 2001
2239 +From: Amit Shah <amit.shah@××××××.com>
2240 +Date: Mon, 21 Mar 2011 22:05:10 +0100
2241 +Subject: [PATCH 11/17] char: Throttle when host connection is down#
2242 +
2243 +When the host-side connection goes down, throttle the virtio-serial bus
2244 +and later unthrottle when a connection gets established. This helps
2245 +prevent any lost IO (guest->host) while the host connection was down.
2246 +
2247 +Bugzilla: 621484
2248 +
2249 +This commit actually helps the bug mentioned above as no writes will now
2250 +get lost because of the throttling done here. With just the patches
2251 +sent earlier for that bug, one write will end up getting lost in the
2252 +worst case (host d/c, guest write, host connect).
2253 +
2254 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
2255 +---
2256 + qemu-char.c | 14 ++++++++++++++
2257 + 1 files changed, 14 insertions(+), 0 deletions(-)
2258 +
2259 +diff --git a/qemu-char.c b/qemu-char.c
2260 +index 7517f64..2ef972f 100644
2261 +--- a/qemu-char.c
2262 ++++ b/qemu-char.c
2263 +@@ -141,6 +141,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
2264 + {
2265 + CharDriverState *s = opaque;
2266 + qemu_chr_event(s, CHR_EVENT_OPENED);
2267 ++ if (s->write_blocked) {
2268 ++ char_write_unblocked(s);
2269 ++ }
2270 + qemu_bh_delete(s->bh);
2271 + s->bh = NULL;
2272 + }
2273 +@@ -2025,6 +2028,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2274 + ret = send_all(chr, s->fd, buf, len);
2275 + if (ret == -1 && errno == EPIPE) {
2276 + tcp_closed(chr);
2277 ++
2278 ++ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
2279 ++ /*
2280 ++ * Since we haven't written out anything, let's say
2281 ++ * we're throttled. This will prevent any output from
2282 ++ * the guest getting lost if host-side chardev goes
2283 ++ * down. Unthrottle when we re-connect.
2284 ++ */
2285 ++ chr->write_blocked = true;
2286 ++ return 0;
2287 ++ }
2288 + }
2289 + } else {
2290 + /* XXX: indicate an error ? */
2291 +--
2292 +1.7.3.2
2293 +
2294
2295 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
2296 new file mode 100644
2297 index 0000000..90f7629
2298 --- /dev/null
2299 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0012-virtio-console-Enable-port-throttling-when-chardev-i.patch
2300 @@ -0,0 +1,48 @@
2301 +>From 94e8b44e4fdfbf312e54b78ca7bbb95271cc83ae Mon Sep 17 00:00:00 2001
2302 +From: Amit Shah <amit.shah@××××××.com>
2303 +Date: Mon, 21 Mar 2011 22:06:41 +0100
2304 +Subject: [PATCH 12/17] virtio-console: Enable port throttling when chardev is slow to consume data
2305 +
2306 +When a chardev indicates it can't accept more data, we tell the
2307 +virtio-serial code to stop sending us any more data till we tell
2308 +otherwise. This helps in guests continuing to run normally while the vq
2309 +keeps getting full and eventually the guest stops queueing more data.
2310 +As soon as the chardev indicates it can accept more data, start pushing!
2311 +
2312 +Signed-off-by: Amit Shah <amit.shah@××××××.com>
2313 +---
2314 + hw/virtio-console.c | 11 +++++++++++
2315 + 1 files changed, 11 insertions(+), 0 deletions(-)
2316 +
2317 +diff --git a/hw/virtio-console.c b/hw/virtio-console.c
2318 +index 22cf28c..eecbdf7 100644
2319 +--- a/hw/virtio-console.c
2320 ++++ b/hw/virtio-console.c
2321 +@@ -18,6 +18,16 @@ typedef struct VirtConsole {
2322 + CharDriverState *chr;
2323 + } VirtConsole;
2324 +
2325 ++/*
2326 ++ * Callback function that's called from chardevs when backend becomes
2327 ++ * writable.
2328 ++ */
2329 ++static void chr_write_unblocked(void *opaque)
2330 ++{
2331 ++ VirtConsole *vcon = opaque;
2332 ++
2333 ++ virtio_serial_throttle_port(&vcon->port, false);
2334 ++}
2335 +
2336 + /* Callback function that's called when the guest sends us data */
2337 + static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
2338 +@@ -61,6 +71,7 @@ static const QemuChrHandlers chr_handlers = {
2339 + .fd_can_read = chr_can_read,
2340 + .fd_read = chr_read,
2341 + .fd_event = chr_event,
2342 ++ .fd_write_unblocked = chr_write_unblocked,
2343 + };
2344 +
2345 + static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
2346 +--
2347 +1.7.3.2
2348 +
2349
2350 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
2351 new file mode 100644
2352 index 0000000..34cb283
2353 --- /dev/null
2354 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0013-spice-qemu-char.c-add-throttling.patch
2355 @@ -0,0 +1,133 @@
2356 +>From 06ad256d2939aea4086428dcb5e5e7d5f86eb335 Mon Sep 17 00:00:00 2001
2357 +From: Alon Levy <alevy@××××××.com>
2358 +Date: Tue, 22 Mar 2011 12:27:59 +0200
2359 +Subject: [PATCH 13/17] spice-qemu-char.c: add throttling
2360 +
2361 +BZ: 672191
2362 +
2363 +upstream: not submitted (explained below)
2364 +
2365 +Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
2366 +1. spice-server: reds.c: read_from_vdi_port
2367 +2. qemu: spice-qemu-char.c: vmc_read
2368 +3. chr_write_unblocked
2369 + (calls virtio_serial_throttle_port(port, false))
2370 +4. qemu: virtio ...
2371 +5. qemu: spice-qemu-char.c: spice_chr_write
2372 +6. qemu: spice-qemu-char.c: wakeup (calls into spice-server)
2373 +7. spice-server: ...
2374 +8. qemu: spice-qemu-char.c: vmc_read
2375 +
2376 +Instead, in vmc_read if we were throttled and we are just about to return
2377 +all the bytes we will set a timer to be triggered immediately to call
2378 +chr_write_unblocked. Then we return after 2 above, and 3 is called from the
2379 +timer callback. This also means we can later remove some ugly recursion protection
2380 +from spice-server.
2381 +
2382 +The other tricky point in this patch is not returning the leftover chunk twice.
2383 +When we throttle, by definition we have data that spice server didn't consume.
2384 +It is being kept by virtio-serial, and by us. The next vmc_read callback needs
2385 +to not return it, but just do unthrottling. Then virtio will give us the remaining
2386 +chunk as usual in spice_chr_write, and we will pass it to spice server in the
2387 +next vmc_read.
2388 +
2389 +This patch relies on Amit's series to expose throttling to chardev's, which
2390 +was not accepted upstream, and will not be accepted upstream until the mainloop
2391 +is reworked to use glib.
2392 +---
2393 + spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++----
2394 + 1 files changed, 35 insertions(+), 4 deletions(-)
2395 +
2396 +diff --git a/spice-qemu-char.c b/spice-qemu-char.c
2397 +index 517f337..91467d5 100644
2398 +--- a/spice-qemu-char.c
2399 ++++ b/spice-qemu-char.c
2400 +@@ -1,4 +1,6 @@
2401 + #include "config-host.h"
2402 ++#include "qemu-common.h"
2403 ++#include "qemu-timer.h"
2404 + #include "trace.h"
2405 + #include "ui/qemu-spice.h"
2406 + #include <spice.h>
2407 +@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
2408 + uint8_t *datapos;
2409 + ssize_t bufsize, datalen;
2410 + uint32_t debug;
2411 ++ QEMUTimer *unblock_timer;
2412 + } SpiceCharDriver;
2413 +
2414 + static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
2415 +@@ -51,6 +54,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
2416 + return out;
2417 + }
2418 +
2419 ++static void spice_chr_unblock(void *opaque)
2420 ++{
2421 ++ SpiceCharDriver *scd = opaque;
2422 ++
2423 ++ if (scd->chr->chr_write_unblocked == NULL) {
2424 ++ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
2425 ++ return;
2426 ++ }
2427 ++ scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
2428 ++}
2429 ++
2430 + static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
2431 + {
2432 + SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
2433 +@@ -62,9 +76,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
2434 + scd->datapos += bytes;
2435 + scd->datalen -= bytes;
2436 + assert(scd->datalen >= 0);
2437 +- if (scd->datalen == 0) {
2438 +- scd->datapos = 0;
2439 +- }
2440 ++ }
2441 ++ if (scd->datalen == 0 && scd->chr->write_blocked) {
2442 ++ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
2443 ++ scd->chr->write_blocked = false;
2444 ++ /*
2445 ++ * set a timer instead of calling scd->chr->chr_write_unblocked directly,
2446 ++ * because that will call back into spice_chr_write (see
2447 ++ * virtio-console.c:chr_write_unblocked), which is unwanted.
2448 ++ */
2449 ++ qemu_mod_timer(scd->unblock_timer, 0);
2450 + }
2451 + trace_spice_vmc_read(bytes, len);
2452 + return bytes;
2453 +@@ -107,6 +128,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
2454 + static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2455 + {
2456 + SpiceCharDriver *s = chr->opaque;
2457 ++ int read_bytes;
2458 +
2459 + dprintf(s, 2, "%s: %d\n", __func__, len);
2460 + vmc_register_interface(s);
2461 +@@ -119,7 +141,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2462 + s->datapos = s->buffer;
2463 + s->datalen = len;
2464 + spice_server_char_device_wakeup(&s->sin);
2465 +- return len;
2466 ++ read_bytes = len - s->datalen;
2467 ++ if (read_bytes != len) {
2468 ++ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
2469 ++ read_bytes, len, s->bufsize);
2470 ++ s->chr->write_blocked = true;
2471 ++ /* We'll get passed in the unconsumed data with the next call */
2472 ++ s->datalen = 0;
2473 ++ }
2474 ++ return read_bytes;
2475 + }
2476 +
2477 + static void spice_chr_close(struct CharDriverState *chr)
2478 +@@ -183,6 +213,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
2479 + chr->opaque = s;
2480 + chr->chr_write = spice_chr_write;
2481 + chr->chr_close = spice_chr_close;
2482 ++ s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s);
2483 +
2484 + qemu_chr_generic_open(chr);
2485 +
2486 +--
2487 +1.7.3.2
2488 +
2489
2490 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
2491 new file mode 100644
2492 index 0000000..2f56ce6
2493 --- /dev/null
2494 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0014-spice-qemu-char.c-remove-intermediate-buffer.patch
2495 @@ -0,0 +1,71 @@
2496 +>From 6ce8a141a37387a5138d0361cbe92885130010fe Mon Sep 17 00:00:00 2001
2497 +From: Alon Levy <alevy@××××××.com>
2498 +Date: Tue, 22 Mar 2011 12:28:00 +0200
2499 +Subject: [PATCH 14/17] spice-qemu-char.c: remove intermediate buffer
2500 +
2501 +BZ: 672191
2502 +upstream: not submitted (explained below)
2503 +
2504 +virtio-serial's buffer is valid when it calls us, and we don't
2505 +access it otherwise: vmc_read is only called in response to wakeup,
2506 +or else we set datalen=0 and throttle. Then vmc_read is called back,
2507 +we return 0 (not accessing the buffer) and set the timer to unthrottle.
2508 +
2509 +Also make datalen int and not ssize_t (to fit spice_chr_write signature).
2510 +
2511 +This relied on the previous patch that introduces throttling, which
2512 +can't go upstream right now as explained in that patch.
2513 +---
2514 + spice-qemu-char.c | 18 ++++++------------
2515 + 1 files changed, 6 insertions(+), 12 deletions(-)
2516 +
2517 +diff --git a/spice-qemu-char.c b/spice-qemu-char.c
2518 +index 91467d5..ed7851e 100644
2519 +--- a/spice-qemu-char.c
2520 ++++ b/spice-qemu-char.c
2521 +@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
2522 + SpiceCharDeviceInstance sin;
2523 + char *subtype;
2524 + bool active;
2525 +- uint8_t *buffer;
2526 +- uint8_t *datapos;
2527 +- ssize_t bufsize, datalen;
2528 ++ const uint8_t *datapos;
2529 ++ int datalen;
2530 + uint32_t debug;
2531 + QEMUTimer *unblock_timer;
2532 + } SpiceCharDriver;
2533 +@@ -70,7 +69,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
2534 + SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
2535 + int bytes = MIN(len, scd->datalen);
2536 +
2537 +- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
2538 ++ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
2539 + if (bytes > 0) {
2540 + memcpy(buf, scd->datapos, bytes);
2541 + scd->datapos += bytes;
2542 +@@ -133,18 +132,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2543 + dprintf(s, 2, "%s: %d\n", __func__, len);
2544 + vmc_register_interface(s);
2545 + assert(s->datalen == 0);
2546 +- if (s->bufsize < len) {
2547 +- s->bufsize = len;
2548 +- s->buffer = qemu_realloc(s->buffer, s->bufsize);
2549 +- }
2550 +- memcpy(s->buffer, buf, len);
2551 +- s->datapos = s->buffer;
2552 ++ s->datapos = buf;
2553 + s->datalen = len;
2554 + spice_server_char_device_wakeup(&s->sin);
2555 + read_bytes = len - s->datalen;
2556 + if (read_bytes != len) {
2557 +- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
2558 +- read_bytes, len, s->bufsize);
2559 ++ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
2560 ++ read_bytes, len);
2561 + s->chr->write_blocked = true;
2562 + /* We'll get passed in the unconsumed data with the next call */
2563 + s->datalen = 0;
2564 +--
2565 +1.7.3.2
2566 +
2567
2568 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
2569 new file mode 100644
2570 index 0000000..bae63b8
2571 --- /dev/null
2572 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0015-chardev-Allow-frontends-to-notify-backends-of-guest-.patch
2573 @@ -0,0 +1,76 @@
2574 +>From c8cb28f0791ab38945c7facb5a63e445b4b6f41f Mon Sep 17 00:00:00 2001
2575 +From: Hans de Goede <hdegoede@××××××.com>
2576 +Date: Fri, 18 Mar 2011 15:23:21 +0100
2577 +Subject: [PATCH 15/17] chardev: Allow frontends to notify backends of guest open / close
2578 +
2579 +Some frontends know when the guest has opened the "channel" and is actively
2580 +listening to it, for example virtio-serial. This patch adds 2 new qemu-chardev
2581 +functions which can be used by frontends to signal guest open / close, and
2582 +allows interested backends to listen to this.
2583 +
2584 +Signed-off-by: Hans de Goede <hdegoede@××××××.com>
2585 +---
2586 + qemu-char.c | 17 +++++++++++++++++
2587 + qemu-char.h | 4 ++++
2588 + 2 files changed, 21 insertions(+), 0 deletions(-)
2589 +
2590 +diff --git a/qemu-char.c b/qemu-char.c
2591 +index 2ef972f..d52eb51 100644
2592 +--- a/qemu-char.c
2593 ++++ b/qemu-char.c
2594 +@@ -507,6 +507,9 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
2595 + chr->chr_write = mux_chr_write;
2596 + chr->chr_update_read_handler = mux_chr_update_read_handler;
2597 + chr->chr_accept_input = mux_chr_accept_input;
2598 ++ /* Frontend guest-open / -close notification is not support with muxes */
2599 ++ chr->chr_guest_open = NULL;
2600 ++ chr->chr_guest_close = NULL;
2601 +
2602 + /* Muxes are always open on creation */
2603 + qemu_chr_generic_open(chr);
2604 +@@ -2712,6 +2715,20 @@ void qemu_chr_set_echo(struct CharDriverState *chr, bool echo)
2605 + }
2606 + }
2607 +
2608 ++void qemu_chr_guest_open(struct CharDriverState *chr)
2609 ++{
2610 ++ if (chr->chr_guest_open) {
2611 ++ chr->chr_guest_open(chr);
2612 ++ }
2613 ++}
2614 ++
2615 ++void qemu_chr_guest_close(struct CharDriverState *chr)
2616 ++{
2617 ++ if (chr->chr_guest_close) {
2618 ++ chr->chr_guest_close(chr);
2619 ++ }
2620 ++}
2621 ++
2622 + void qemu_chr_close(CharDriverState *chr)
2623 + {
2624 + QTAILQ_REMOVE(&chardevs, chr, next);
2625 +diff --git a/qemu-char.h b/qemu-char.h
2626 +index bf06da0..f3b9bf4 100644
2627 +--- a/qemu-char.h
2628 ++++ b/qemu-char.h
2629 +@@ -69,6 +69,8 @@ struct CharDriverState {
2630 + void (*chr_close)(struct CharDriverState *chr);
2631 + void (*chr_accept_input)(struct CharDriverState *chr);
2632 + void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
2633 ++ void (*chr_guest_open)(struct CharDriverState *chr);
2634 ++ void (*chr_guest_close)(struct CharDriverState *chr);
2635 + void *opaque;
2636 + QEMUBH *bh;
2637 + char *label;
2638 +@@ -91,6 +93,8 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
2639 + void (*init)(struct CharDriverState *s));
2640 + CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
2641 + void qemu_chr_set_echo(struct CharDriverState *chr, bool echo);
2642 ++void qemu_chr_guest_open(struct CharDriverState *chr);
2643 ++void qemu_chr_guest_close(struct CharDriverState *chr);
2644 + void qemu_chr_close(CharDriverState *chr);
2645 + void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
2646 + GCC_FMT_ATTR(2, 3);
2647 +--
2648 +1.7.3.2
2649 +
2650
2651 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
2652 new file mode 100644
2653 index 0000000..0b3e3f8
2654 --- /dev/null
2655 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0016-virtio-console-notify-backend-of-guest-open-close.patch
2656 @@ -0,0 +1,49 @@
2657 +>From 3baf76e384c04f58f032632c078860d66c8c9db3 Mon Sep 17 00:00:00 2001
2658 +From: Hans de Goede <hdegoede@××××××.com>
2659 +Date: Fri, 18 Mar 2011 15:30:45 +0100
2660 +Subject: [PATCH 16/17] virtio-console: notify backend of guest open / close
2661 +
2662 +Signed-off-by: Hans de Goede <hdegoede@××××××.com>
2663 +---
2664 + hw/virtio-console.c | 18 ++++++++++++++++++
2665 + 1 files changed, 18 insertions(+), 0 deletions(-)
2666 +
2667 +diff --git a/hw/virtio-console.c b/hw/virtio-console.c
2668 +index eecbdf7..828a1a3 100644
2669 +--- a/hw/virtio-console.c
2670 ++++ b/hw/virtio-console.c
2671 +@@ -37,6 +37,22 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
2672 + return qemu_chr_write(vcon->chr, buf, len);
2673 + }
2674 +
2675 ++/* Callback function that's called when the guest opens the port */
2676 ++static void guest_open(VirtIOSerialPort *port)
2677 ++{
2678 ++ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
2679 ++
2680 ++ qemu_chr_guest_open(vcon->chr);
2681 ++}
2682 ++
2683 ++/* Callback function that's called when the guest closes the port */
2684 ++static void guest_close(VirtIOSerialPort *port)
2685 ++{
2686 ++ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
2687 ++
2688 ++ qemu_chr_guest_close(vcon->chr);
2689 ++}
2690 ++
2691 + /* Readiness of the guest to accept data on a port */
2692 + static int chr_can_read(void *opaque)
2693 + {
2694 +@@ -81,6 +97,8 @@ static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
2695 + if (vcon->chr) {
2696 + qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
2697 + vcon->port.info->have_data = flush_buf;
2698 ++ vcon->port.info->guest_open = guest_open;
2699 ++ vcon->port.info->guest_close = guest_close;
2700 + }
2701 + return 0;
2702 + }
2703 +--
2704 +1.7.3.2
2705 +
2706
2707 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
2708 new file mode 100644
2709 index 0000000..1944bbc
2710 --- /dev/null
2711 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0017-spice-chardev-listen-to-frontend-guest-open-close.patch
2712 @@ -0,0 +1,49 @@
2713 +>From c169795bed5374f0071af201da2dd32b3c5a2417 Mon Sep 17 00:00:00 2001
2714 +From: Hans de Goede <hdegoede@××××××.com>
2715 +Date: Fri, 18 Mar 2011 15:35:27 +0100
2716 +Subject: [PATCH 17/17] spice-chardev: listen to frontend guest open / close
2717 +
2718 +Note the vmc_register_interface() in spice_chr_write is left in place
2719 +in case someone uses spice-chardev with a frontend which does not have
2720 +guest open / close notification.
2721 +
2722 +Signed-off-by: Hans de Goede <hdegoede@××××××.com>
2723 +---
2724 + spice-qemu-char.c | 14 ++++++++++++++
2725 + 1 files changed, 14 insertions(+), 0 deletions(-)
2726 +
2727 +diff --git a/spice-qemu-char.c b/spice-qemu-char.c
2728 +index ed7851e..343146c 100644
2729 +--- a/spice-qemu-char.c
2730 ++++ b/spice-qemu-char.c
2731 +@@ -155,6 +155,18 @@ static void spice_chr_close(struct CharDriverState *chr)
2732 + qemu_free(s);
2733 + }
2734 +
2735 ++static void spice_chr_guest_open(struct CharDriverState *chr)
2736 ++{
2737 ++ SpiceCharDriver *s = chr->opaque;
2738 ++ vmc_register_interface(s);
2739 ++}
2740 ++
2741 ++static void spice_chr_guest_close(struct CharDriverState *chr)
2742 ++{
2743 ++ SpiceCharDriver *s = chr->opaque;
2744 ++ vmc_unregister_interface(s);
2745 ++}
2746 ++
2747 + static void print_allowed_subtypes(void)
2748 + {
2749 + const char** psubtype;
2750 +@@ -207,6 +219,8 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
2751 + chr->opaque = s;
2752 + chr->chr_write = spice_chr_write;
2753 + chr->chr_close = spice_chr_close;
2754 ++ chr->chr_guest_open = spice_chr_guest_open;
2755 ++ chr->chr_guest_close = spice_chr_guest_close;
2756 + s->unblock_timer = qemu_new_timer(vm_clock, spice_chr_unblock, s);
2757 +
2758 + qemu_chr_generic_open(chr);
2759 +--
2760 +1.7.3.2
2761 +
2762
2763 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
2764 new file mode 100644
2765 index 0000000..a6c2445
2766 --- /dev/null
2767 +++ b/app-emulation/qemu-kvm/files/patches-from-fedora/0018-spice-qemu-char-Fix-flow-control-in-client-guest-dir.patch
2768 @@ -0,0 +1,56 @@
2769 +>From 7a9e7aaa30abf42879d3f13b41679513045c31ec Mon Sep 17 00:00:00 2001
2770 +From: Hans de Goede <hdegoede@××××××.com>
2771 +Date: Tue, 22 Mar 2011 16:28:41 +0100
2772 +Subject: [PATCH 18/18] spice-qemu-char: Fix flow control in client -> guest direction
2773 +
2774 +In the old spice-vmc device we used to have:
2775 +last_out = virtio_serial_write(&svc->port, p, MIN(len, VMC_MAX_HOST_WRITE));
2776 +if (last_out > 0)
2777 + ...
2778 +
2779 +Now in the chardev backend we have:
2780 +last_out = MIN(len, VMC_MAX_HOST_WRITE);
2781 +qemu_chr_read(scd->chr, p, last_out);
2782 +if (last_out > 0) {
2783 + ...
2784 +
2785 +Which causes us to no longer detect if the virtio port is not ready
2786 +to receive data from us. chardev actually has a mechanism to detect this,
2787 +but it requires a separate call to qemu_chr_can_read, before calling
2788 +qemu_chr_read (which return void).
2789 +
2790 +This patch uses qemu_chr_can_read to fix the flow control from client to
2791 +guest.
2792 +
2793 +Signed-off-by: Hans de Goede <hdegoede@××××××.com>
2794 +---
2795 + spice-qemu-char.c | 11 +++++------
2796 + 1 files changed, 5 insertions(+), 6 deletions(-)
2797 +
2798 +diff --git a/spice-qemu-char.c b/spice-qemu-char.c
2799 +index 343146c..def713a 100644
2800 +--- a/spice-qemu-char.c
2801 ++++ b/spice-qemu-char.c
2802 +@@ -38,14 +38,13 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
2803 +
2804 + while (len > 0) {
2805 + last_out = MIN(len, VMC_MAX_HOST_WRITE);
2806 +- qemu_chr_read(scd->chr, p, last_out);
2807 +- if (last_out > 0) {
2808 +- out += last_out;
2809 +- len -= last_out;
2810 +- p += last_out;
2811 +- } else {
2812 ++ if (qemu_chr_can_read(scd->chr) < last_out) {
2813 + break;
2814 + }
2815 ++ qemu_chr_read(scd->chr, p, last_out);
2816 ++ out += last_out;
2817 ++ len -= last_out;
2818 ++ p += last_out;
2819 + }
2820 +
2821 + dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out);
2822 +--
2823 +1.7.3.2
2824 +
2825
2826 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
2827 new file mode 100644
2828 index 0000000..c069f89
2829 --- /dev/null
2830 +++ b/app-emulation/qemu-kvm/files/qemu-0.11.0-mips64-user-fix.patch
2831 @@ -0,0 +1,11 @@
2832 +--- qemu-0.11.0.orig/linux-user/main.c 2009-10-23 02:19:57.000000000 +0200
2833 ++++ qemu-0.11.0/linux-user/main.c 2009-10-23 02:47:09.000000000 +0200
2834 +@@ -1469,6 +1469,8 @@
2835 +
2836 + #ifdef TARGET_MIPS
2837 +
2838 ++#define TARGET_QEMU_ESIGRETURN 255
2839 ++
2840 + #define MIPS_SYS(name, args) args,
2841 +
2842 + static const uint8_t mips_syscall_args[] = {
2843
2844 diff --git a/app-emulation/qemu-kvm/files/qemu-kvm b/app-emulation/qemu-kvm/files/qemu-kvm
2845 new file mode 100644
2846 index 0000000..844147d
2847 --- /dev/null
2848 +++ b/app-emulation/qemu-kvm/files/qemu-kvm
2849 @@ -0,0 +1,2 @@
2850 +#!/bin/sh
2851 +exec /usr/bin/qemu-system-x86_64 --enable-kvm "$@"
2852
2853 diff --git a/app-emulation/qemu-kvm/qemu-kvm-0.14.0.ebuild b/app-emulation/qemu-kvm/qemu-kvm-0.14.0.ebuild
2854 new file mode 100644
2855 index 0000000..7324273
2856 --- /dev/null
2857 +++ b/app-emulation/qemu-kvm/qemu-kvm-0.14.0.ebuild
2858 @@ -0,0 +1,260 @@
2859 +# Copyright 1999-2011 Gentoo Foundation
2860 +# Distributed under the terms of the GNU General Public License v2
2861 +# $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu-kvm/qemu-kvm-9999.ebuild,v 1.16 2011/03/28 03:31:46 flameeyes Exp $
2862 +
2863 +EAPI="2"
2864 +
2865 +if [[ ${PV} = *9999* ]]; then
2866 + EGIT_REPO_URI="git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git"
2867 + GIT_ECLASS="git"
2868 +fi
2869 +
2870 +inherit eutils flag-o-matic ${GIT_ECLASS} linux-info toolchain-funcs multilib
2871 +
2872 +if [[ ${PV} = *9999* ]]; then
2873 + SRC_URI=""
2874 + KEYWORDS=""
2875 +else
2876 + SRC_URI="mirror://sourceforge/kvm/${PN}/${P}.tar.gz
2877 + ${BACKPORTS:+mirror://gentoo/${P}-backports-${BACKPORTS}.tar.bz2}"
2878 + KEYWORDS="~amd64 ~ppc ~ppc64 ~x86"
2879 +fi
2880 +
2881 +DESCRIPTION="QEMU + Kernel-based Virtual Machine userland tools"
2882 +HOMEPAGE="http://www.linux-kvm.org"
2883 +
2884 +LICENSE="GPL-2"
2885 +SLOT="0"
2886 +# xen is disabled until the deps are fixed
2887 +IUSE="+aio alsa bluetooth brltty curl esd fdt hardened jpeg ncurses \
2888 +png pulseaudio qemu-ifup rbd sasl sdl ssl spice static vde vhost-net xen"
2889 +
2890 +COMMON_TARGETS="i386 x86_64 arm cris m68k microblaze mips mipsel ppc ppc64 sh4 sh4eb sparc sparc64"
2891 +IUSE_SOFTMMU_TARGETS="${COMMON_TARGETS} mips64 mips64el ppcemb"
2892 +IUSE_USER_TARGETS="${COMMON_TARGETS} alpha armeb ppc64abi32 sparc32plus"
2893 +
2894 +for target in ${IUSE_SOFTMMU_TARGETS}; do
2895 + IUSE="${IUSE} +qemu_softmmu_targets_${target}"
2896 +done
2897 +
2898 +for target in ${IUSE_USER_TARGETS}; do
2899 + IUSE="${IUSE} +qemu_user_targets_${target}"
2900 +done
2901 +
2902 +RESTRICT="test"
2903 +
2904 +RDEPEND="
2905 + !app-emulation/kqemu
2906 + !app-emulation/qemu
2907 + !app-emulation/qemu-softmmu
2908 + !app-emulation/qemu-user
2909 + !app-emulation/qemu-kvm-spice
2910 + sys-apps/pciutils
2911 + >=sys-apps/util-linux-2.16.0
2912 + sys-libs/zlib
2913 + aio? ( dev-libs/libaio )
2914 + alsa? ( >=media-libs/alsa-lib-1.0.13 )
2915 + bluetooth? ( net-wireless/bluez )
2916 + brltty? ( app-accessibility/brltty )
2917 + curl? ( net-misc/curl )
2918 + esd? ( media-sound/esound )
2919 + fdt? ( >=sys-apps/dtc-1.2.0 )
2920 + jpeg? ( virtual/jpeg )
2921 + ncurses? ( sys-libs/ncurses )
2922 + png? ( media-libs/libpng )
2923 + pulseaudio? ( media-sound/pulseaudio )
2924 + qemu-ifup? ( sys-apps/iproute2 net-misc/bridge-utils )
2925 + rbd? ( sys-cluster/ceph )
2926 + sasl? ( dev-libs/cyrus-sasl )
2927 + sdl? ( >=media-libs/libsdl-1.2.11[X] )
2928 + spice? ( app-emulation/spice )
2929 + ssl? ( net-libs/gnutls )
2930 + vde? ( net-misc/vde )
2931 + xen? ( app-emulation/xen )
2932 +"
2933 +
2934 +DEPEND="${RDEPEND}
2935 + app-text/texi2html
2936 + >=sys-kernel/linux-headers-2.6.35
2937 + ssl? ( dev-util/pkgconfig )
2938 +"
2939 +
2940 +kvm_kern_warn() {
2941 + eerror "Please enable KVM support in your kernel, found at:"
2942 + eerror
2943 + eerror " Virtualization"
2944 + eerror " Kernel-based Virtual Machine (KVM) support"
2945 + eerror
2946 +}
2947 +
2948 +pkg_setup() {
2949 + use qemu_softmmu_targets_x86_64 || ewarn "You disabled default target QEMU_SOFTMMU_TARGETS=x86_64"
2950 +
2951 + if kernel_is lt 2 6 25; then
2952 + eerror "This version of KVM requres a host kernel of 2.6.25 or higher."
2953 + eerror "Either upgrade your kernel"
2954 + else
2955 + if ! linux_config_exists; then
2956 + eerror "Unable to check your kernel for KVM support"
2957 + kvm_kern_warn
2958 + elif ! linux_chkconfig_present KVM; then
2959 + kvm_kern_warn
2960 + fi
2961 + if use vhost-net && ! linux_chkconfig_present VHOST_NET ; then
2962 + ewarn "You have to enable CONFIG_VHOST_NET in the kernel to get vhost-net support."
2963 + fi
2964 + fi
2965 +
2966 + enewgroup kvm
2967 +}
2968 +
2969 +src_prepare() {
2970 + # prevent docs to get automatically installed
2971 + sed -i '/$(DESTDIR)$(docdir)/d' Makefile || die
2972 + # Alter target makefiles to accept CFLAGS set via flag-o
2973 + sed -i 's/^\(C\|OP_C\|HELPER_C\)FLAGS=/\1FLAGS+=/' \
2974 + Makefile Makefile.target || die
2975 + # append CFLAGS while linking
2976 + sed -i 's/$(LDFLAGS)/$(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS)/' rules.mak || die
2977 +
2978 + # remove part to make udev happy
2979 + sed -e 's~NAME="%k", ~~' -i kvm/scripts/65-kvm.rules || die
2980 +
2981 + epatch "${FILESDIR}/qemu-0.11.0-mips64-user-fix.patch"
2982 + EPATCH_SOURCE="${FILESDIR}/patches-from-fedora" EPATCH_SUFFIX="patch" \
2983 + EPATCH_FORCE="yes" epatch
2984 +}
2985 +
2986 +src_configure() {
2987 + local conf_opts audio_opts user_targets
2988 +
2989 + for target in ${IUSE_SOFTMMU_TARGETS} ; do
2990 + use "qemu_softmmu_targets_${target}" && \
2991 + softmmu_targets="${softmmu_targets} ${target}-softmmu"
2992 + done
2993 +
2994 + for target in ${IUSE_USER_TARGETS} ; do
2995 + use "qemu_user_targets_${target}" && \
2996 + user_targets="${user_targets} ${target}-linux-user"
2997 + done
2998 +
2999 + if [ -z "${softmmu_targets}" ]; then
3000 + conf_opts="${conf_opts} --disable-system"
3001 + else
3002 + einfo "Building the following softmmu targets: ${softmmu_targets}"
3003 + fi
3004 +
3005 + if [ ! -z "${user_targets}" ]; then
3006 + einfo "Building the following user targets: ${user_targets}"
3007 + conf_opts="${conf_opts} --enable-linux-user"
3008 + else
3009 + conf_opts="${conf_opts} --disable-linux-user"
3010 + fi
3011 +
3012 + # Fix QA issues. QEMU needs executable heaps and we need to mark it as such
3013 + conf_opts="${conf_opts} --extra-ldflags=-Wl,-z,execheap"
3014 +
3015 + # Add support for static builds
3016 + use static && conf_opts="${conf_opts} --static"
3017 +
3018 + # Fix the $(prefix)/etc issue
3019 + conf_opts="${conf_opts} --sysconfdir=/etc"
3020 +
3021 + #config options
3022 + conf_opts="${conf_opts} $(use_enable aio linux-aio)"
3023 + conf_opts="${conf_opts} $(use_enable bluetooth bluez)"
3024 + conf_opts="${conf_opts} $(use_enable brltty brlapi)"
3025 + conf_opts="${conf_opts} $(use_enable curl)"
3026 + conf_opts="${conf_opts} $(use_enable fdt)"
3027 + conf_opts="${conf_opts} $(use_enable hardened user-pie)"
3028 + conf_opts="${conf_opts} $(use_enable jpeg vnc-jpeg)"
3029 + conf_opts="${conf_opts} $(use_enable ncurses curses)"
3030 + conf_opts="${conf_opts} $(use_enable png vnc-png)"
3031 + conf_opts="${conf_opts} $(use_enable rbd)"
3032 + conf_opts="${conf_opts} $(use_enable sasl vnc-sasl)"
3033 + conf_opts="${conf_opts} $(use_enable sdl)"
3034 + conf_opts="${conf_opts} $(use_enable ssl vnc-tls)"
3035 + conf_opts="${conf_opts} $(use_enable spice)"
3036 + conf_opts="${conf_opts} $(use_enable vde)"
3037 + conf_opts="${conf_opts} $(use_enable vhost-net)"
3038 + conf_opts="${conf_opts} $(use_enable xen)"
3039 + conf_opts="${conf_opts} --disable-darwin-user --disable-bsd-user"
3040 +
3041 + # audio options
3042 + audio_opts="oss"
3043 + use alsa && audio_opts="alsa ${audio_opts}"
3044 + use esd && audio_opts="esd ${audio_opts}"
3045 + use pulseaudio && audio_opts="pa ${audio_opts}"
3046 + use sdl && audio_opts="sdl ${audio_opts}"
3047 + ./configure --prefix=/usr \
3048 + --disable-strip \
3049 + --disable-werror \
3050 + --enable-kvm \
3051 + --enable-nptl \
3052 + --enable-uuid \
3053 + ${conf_opts} \
3054 + --audio-drv-list="${audio_opts}" \
3055 + --target-list="${softmmu_targets} ${user_targets}" \
3056 + --cc="$(tc-getCC)" \
3057 + --host-cc="$(tc-getBUILD_CC)" \
3058 + || die "configure failed"
3059 +
3060 + # this is for qemu upstream's threaded support which is
3061 + # in development and broken
3062 + # the kvm project has its own support for threaded IO
3063 + # which is always on and works
3064 + # --enable-io-thread \
3065 +}
3066 +
3067 +src_compile() {
3068 + # Restricting parallel build until we get a patch to fix this
3069 + emake -j1 || die
3070 +}
3071 +src_install() {
3072 + emake DESTDIR="${D}" install || die "make install failed"
3073 +
3074 + if [ ! -z "${softmmu_targets}" ]; then
3075 + insinto /$(get_libdir)/udev/rules.d/
3076 + doins kvm/scripts/65-kvm.rules || die
3077 +
3078 + if use qemu-ifup; then
3079 + insinto /etc/qemu/
3080 + insopts -m0755
3081 + doins kvm/scripts/qemu-ifup || die
3082 + fi
3083 +
3084 + if use qemu_softmmu_targets_x86_64 ; then
3085 + dobin "${FILESDIR}"/qemu-kvm
3086 + dosym /usr/bin/qemu-kvm /usr/bin/kvm
3087 + else
3088 + elog "You disabled QEMU_SOFTMMU_TARGETS=x86_64, this disables install"
3089 + elog "of /usr/bin/qemu-kvm and /usr/bin/kvm"
3090 + fi
3091 + fi
3092 +
3093 + dodoc Changelog MAINTAINERS TODO pci-ids.txt || die
3094 + newdoc pc-bios/README README.pc-bios || die
3095 + dohtml qemu-doc.html qemu-tech.html || die
3096 +}
3097 +
3098 +pkg_postinst() {
3099 + if [ ! -z "${softmmu_targets}" ]; then
3100 + elog "If you don't have kvm compiled into the kernel, make sure you have"
3101 + elog "the kernel module loaded before running kvm. The easiest way to"
3102 + elog "ensure that the kernel module is loaded is to load it on boot."
3103 + elog "For AMD CPUs the module is called 'kvm-amd'"
3104 + elog "For Intel CPUs the module is called 'kvm-intel'"
3105 + elog "Please review /etc/conf.d/modules for how to load these"
3106 + elog
3107 + elog "Make sure your user is in the 'kvm' group"
3108 + elog "Just run 'gpasswd -a <USER> kvm', then have <USER> re-login."
3109 + elog
3110 + elog "You will need the Universal TUN/TAP driver compiled into your"
3111 + elog "kernel or loaded as a module to use the virtual network device"
3112 + elog "if using -net tap. You will also need support for 802.1d"
3113 + elog "Ethernet Bridging and a configured bridge if using the provided"
3114 + elog "kvm-ifup script from /etc/kvm."
3115 + elog
3116 + elog "The gnutls use flag was renamed to ssl, so adjust your use flags."
3117 + fi
3118 +}