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 |
+} |