Compare commits
644 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
646ce0f5b5 | ||
|
4b48a789ef | ||
|
108c22f518 | ||
|
f0d2afbe43 | ||
|
fd795fc4d0 | ||
|
9d15b88230 | ||
|
e837494495 | ||
|
5ff8af4aaa | ||
|
0b61e57fbe | ||
|
3f5e1104a8 | ||
|
5bc1125531 | ||
|
28222ce611 | ||
|
581fcfe335 | ||
|
9fb824102c | ||
|
357c686a3e | ||
|
65b2a489f4 | ||
|
744e70f72e | ||
|
cd21b7f45d | ||
|
efaa1cda68 | ||
|
748c8c3268 | ||
|
d9af2bbdff | ||
|
f2839fea71 | ||
|
af50bf7b78 | ||
|
13e7c30edf | ||
|
4e321e2f5c | ||
|
458e07e8d7 | ||
|
3c0f9e810a | ||
|
dc03f389d3 | ||
|
3927dda118 | ||
|
3fa99d6aac | ||
|
9b60ebfd67 | ||
|
2b132a41aa | ||
|
a840dd697e | ||
|
884b734123 | ||
|
b35e952c0c | ||
|
25b0302679 | ||
|
a90ffcbc2c | ||
|
e84a93a247 | ||
|
d20fa70a4e | ||
|
c9c298d7a8 | ||
|
f4bee9e135 | ||
|
7ffd7f7fdf | ||
|
bdc5a0bca1 | ||
|
4269c70e28 | ||
|
0133142152 | ||
|
3da886a924 | ||
|
8c45437b3a | ||
|
9f833efd2d | ||
|
fa1d6ea0cd | ||
|
7e9fe41b78 | ||
|
76b4bc9d96 | ||
|
9f8e48750c | ||
|
e2b4e80d3c | ||
|
e1b832b513 | ||
|
17655806bf | ||
|
dd41f1a7ca | ||
|
8833af8dcd | ||
|
492d6c1fff | ||
|
377bb253e3 | ||
|
023288b71a | ||
|
1d442bb612 | ||
|
b98348b411 | ||
|
ba6f50c7d7 | ||
|
57a3231073 | ||
|
46ea403d2f | ||
|
e6e2c63c09 | ||
|
1d0e437ac8 | ||
|
6732563c65 | ||
|
46eefb217c | ||
|
ff9bb15b16 | ||
|
993f4157b6 | ||
|
41cffcfad7 | ||
|
b4072bd645 | ||
|
fddfbd9637 | ||
|
16769836d7 | ||
|
0038f84388 | ||
|
8e6758e973 | ||
|
fe24ece8af | ||
|
f4c127bbc1 | ||
|
918c70b1aa | ||
|
964eff6ae8 | ||
|
481596d7a6 | ||
|
c36918674f | ||
|
9db63cb5df | ||
|
5084436959 | ||
|
70269497f2 | ||
|
2a7146a2ca | ||
|
70b6670bdf | ||
|
28828da2e3 | ||
|
e4599b5e27 | ||
|
bd59499379 | ||
|
6acd45ea32 | ||
|
e0a72f8f2d | ||
|
160bf4b4d5 | ||
|
8e85e5e9aa | ||
|
419868beaf | ||
|
e5504b6ad4 | ||
|
40fbd86194 | ||
|
8a7ac9c97e | ||
29c3523ef3 | |||
|
17efd80578 | ||
|
70ef327d5f | ||
|
af6274808b | ||
|
c67ebc8192 | ||
|
cdc7e4ca72 | ||
|
e14a8ce4ef | ||
|
09f7c02959 | ||
|
4266c9b33e | ||
|
c9654a07d8 | ||
|
fd86380c5b | ||
|
1515438fd3 | ||
|
e3d6ad24ae | ||
|
9687314304 | ||
|
7da5fc303e | ||
|
f3518876c6 | ||
|
d3ff788791 | ||
|
941a4c0548 | ||
|
e1923c9eb5 | ||
|
a60ad61787 | ||
|
f1fa58e582 | ||
|
e24cbbb32e | ||
|
de10d8e08e | ||
|
2679bc30fc | ||
|
8e22bbd1e0 | ||
|
f1ea04bd67 | ||
|
e0155fb5be | ||
|
8433925433 | ||
|
61ad1f41fd | ||
|
5704646898 | ||
|
a4b3db7151 | ||
|
0af132aa98 | ||
|
007776f3e4 | ||
|
e4323bc8b2 | ||
|
a6f68877d0 | ||
|
91efacc572 | ||
|
748bb2f566 | ||
|
c90305980d | ||
|
13b2fd93a9 | ||
|
e4ec8b672d | ||
|
5bdb061bca | ||
|
d4c4507533 | ||
|
b12f5aef3a | ||
|
b91dae7a8f | ||
|
330481bc1c | ||
|
97eed6b145 | ||
|
6dab4a0cbd | ||
|
7b9b67b1ec | ||
|
0d2d5cc76d | ||
|
80404b03be | ||
|
a28cfa8216 | ||
|
e9e03fcd1c | ||
|
6269069f27 | ||
|
3930e8ff37 | ||
|
3758f8a137 | ||
|
e13261f947 | ||
|
3c6a0ca337 | ||
|
55054b88c9 | ||
|
6b1a7d80a5 | ||
|
a7e2480deb | ||
|
29249a79a8 | ||
|
52904050aa | ||
|
603dd9e50a | ||
|
28d4d1f5e7 | ||
|
34056732a5 | ||
|
1d16c17085 | ||
|
8253c01b09 | ||
|
ec520ba35e | ||
|
167a6b72c2 | ||
|
f81be8f026 | ||
|
f95699bf90 | ||
|
90a3c96cff | ||
|
a76e086590 | ||
|
e978b4fe84 | ||
|
bfe7b8124e | ||
|
700f126a07 | ||
|
2a2b49f85b | ||
|
59eb7ad892 | ||
|
b0a7742ccd | ||
|
8699737f6d | ||
|
ac5e33cbfe | ||
|
a8c6008b7d | ||
|
9acefb8589 | ||
|
4b7bd99c46 | ||
|
fd8ba3896b | ||
|
0fb2b27d3a | ||
|
0945e0bba3 | ||
|
98b428ff80 | ||
|
0b42e7fc18 | ||
|
3b6c813012 | ||
|
45cb87a59c | ||
|
5264c6a895 | ||
|
c2f33c885f | ||
|
c333713fea | ||
|
14cfc78b3c | ||
|
0323a03914 | ||
|
1a4355e536 | ||
|
26c1ceeaa3 | ||
|
6e16c07206 | ||
|
a3b9d99ab2 | ||
|
a949744f38 | ||
|
20b2275a19 | ||
|
22c2909bc1 | ||
|
f73c470a02 | ||
|
1e96c68c3d | ||
|
cf6afbb855 | ||
|
895ba8da7d | ||
|
335584f502 | ||
|
5eae33f189 | ||
|
faa9df96ad | ||
|
33f79e5eb1 | ||
|
514d6bc543 | ||
|
5dd6a73c80 | ||
|
74c0a82292 | ||
|
0db3257f1a | ||
|
996634350a | ||
|
1db5811d26 | ||
|
1c7073d8dd | ||
|
6a041ef569 | ||
|
c1f9c0e4d7 | ||
|
8b317f0917 | ||
|
50bb158a7a | ||
|
8288677cfa | ||
|
9074eea4bb | ||
|
17a6dacdca | ||
|
84eeb10ee8 | ||
|
151958b44b | ||
|
3bbbcdcb07 | ||
|
6f55752c5f | ||
|
b68b5fed43 | ||
|
0583426e3d | ||
|
820948cb49 | ||
|
ecbe006bda | ||
|
8a588691e2 | ||
|
b8878c0ca6 | ||
|
cf816402f7 | ||
|
d19693d908 | ||
|
8dd6b5e9c8 | ||
|
3a13ddd514 | ||
|
a2729a240b | ||
|
504e25420b | ||
|
57dbb7a5be | ||
|
435be3635e | ||
|
94ddf1cc6a | ||
|
d52607ebe6 | ||
|
4ff778e7b3 | ||
|
ef34be9e72 | ||
|
84e6ecadd9 | ||
|
51223f941f | ||
|
d0bc223280 | ||
|
9868109a5e | ||
|
ecee1eccfe | ||
|
a8a5dc38f8 | ||
|
9e71574671 | ||
|
0835325a86 | ||
|
cf91b1dfd9 | ||
|
f9730dab94 | ||
|
f0208c9e42 | ||
|
f8dc431e37 | ||
|
c3911a29b3 | ||
|
837eb7efa2 | ||
|
e200903264 | ||
|
35faab4c45 | ||
|
bc7ce050b0 | ||
|
b455e4b103 | ||
|
b0b55fdca8 | ||
|
6138a983a3 | ||
|
c752245c96 | ||
|
fa6cd1dad5 | ||
|
a503b12a16 | ||
|
4097206ab3 | ||
|
54cb1301c6 | ||
|
ae11374147 | ||
|
43821749cc | ||
|
73731f9ecd | ||
|
7d975d9810 | ||
|
95a588650f | ||
|
b24b7f1644 | ||
|
78f4db5d1d | ||
|
2a77992272 | ||
|
e8a6e4f833 | ||
|
205399c1ee | ||
|
c9396159e8 | ||
|
15489f4108 | ||
|
0d5e9f6618 | ||
|
dda6c386a5 | ||
|
6176f1d7e2 | ||
|
89aacd5f7a | ||
|
6baf84acf1 | ||
|
191c302918 | ||
|
7bf1a680e6 | ||
|
48e07c5c6e | ||
|
88b3793f29 | ||
|
4f68392c26 | ||
|
86d7b9f29b | ||
|
b448bfad34 | ||
|
1ae1f09f33 | ||
|
cf8819083b | ||
|
c5e57685f9 | ||
|
8211390ac8 | ||
|
74717053dc | ||
|
d5417f465c | ||
|
6ac2a80eae | ||
|
6214bfdcf3 | ||
|
4c6dc5b3d6 | ||
|
de4550957e | ||
|
61ce511be4 | ||
|
74ab99f1a6 | ||
|
77b7d81b2b | ||
|
bcb37b2ec0 | ||
|
d4803feead | ||
|
1ec8e52bb2 | ||
|
806ecbe49c | ||
|
749c3c43c3 | ||
|
260c0ac680 | ||
|
6626651b28 | ||
|
94a40ce774 | ||
|
6fc6504bd8 | ||
|
d43799b0b3 | ||
|
7bf3158612 | ||
|
aa972b9106 | ||
|
198e142c7d | ||
|
31085aa400 | ||
|
7c5a423647 | ||
|
18eddd1631 | ||
|
af53ec630c | ||
|
343c57952d | ||
|
5059f25c8e | ||
|
41aca9586f | ||
|
b26fb5a551 | ||
|
9b9ad7bb74 | ||
|
c61e67e86b | ||
|
c2770435bf | ||
|
355b03ef5c | ||
|
6a451ba509 | ||
|
8055ee2da9 | ||
|
5a454effcf | ||
|
76a74e853f | ||
|
6c3741c276 | ||
|
391fb81c16 | ||
|
f287dc5662 | ||
|
fc57f44566 | ||
|
cad2bcb6a1 | ||
|
0716c2e68a | ||
|
10fa62ffc3 | ||
|
c88cc7e403 | ||
|
bd7b20725b | ||
|
1be48f0df6 | ||
|
259393612c | ||
|
725f84b743 | ||
|
145f8dccfa | ||
|
fbbbab2c57 | ||
|
215b584050 | ||
|
3a39bf78f1 | ||
|
6c2b2d8a11 | ||
|
6ce0be8333 | ||
|
46f3a5c276 | ||
|
e84b901375 | ||
|
2f5a0ef6e6 | ||
|
723d95470d | ||
|
87bbaebdd6 | ||
|
f2a088a4af | ||
|
d92cc55200 | ||
|
e144c654aa | ||
|
4ced99fb02 | ||
|
592e6889a5 | ||
|
bc6fc976b4 | ||
|
a6c45000fe | ||
|
bcd9d80d1a | ||
|
cc110b43ed | ||
|
3561d33ea5 | ||
|
d35cbd0d7e | ||
|
4773d3c9c6 | ||
|
b440863c6b | ||
|
ad339ad339 | ||
|
0410ae29c0 | ||
|
200da9cdce | ||
|
12cd546161 | ||
|
660494c491 | ||
|
70114f9e56 | ||
|
5461c5246c | ||
|
762d9e1463 | ||
|
21cd6fac34 | ||
|
269942c0fd | ||
|
f03d6d0588 | ||
|
7ce01f8f81 | ||
|
17908043da | ||
|
75f0c8715a | ||
|
1560ff70e8 | ||
|
3400e70a32 | ||
|
ac843bf3ce | ||
|
755ac92dbf | ||
|
5b4ee6cf96 | ||
|
aa1e9b6b3f | ||
|
e65bbe3b55 | ||
|
c4896d008b | ||
|
c4025101e7 | ||
|
cba9c935f9 | ||
|
cf5f9d239e | ||
|
46c39e954f | ||
|
bacd9b0468 | ||
|
dd16baaeb5 | ||
|
45bdef1ab0 | ||
|
4b57421a2c | ||
|
acbc4a5d3a | ||
|
0c698d13b9 | ||
|
2983660f65 | ||
|
840b28a1f8 | ||
|
52cf04624c | ||
|
9e0a86718c | ||
|
81ec822962 | ||
|
54891983e0 | ||
|
89d8790801 | ||
|
bfefcc20b8 | ||
|
f950cd7985 | ||
|
64e123aeee | ||
|
76dcac38f6 | ||
|
54ffecd5cf | ||
|
2ed53bed7d | ||
|
558d4c194e | ||
|
1c81baa208 | ||
|
67ad330b45 | ||
|
b6a83a54d0 | ||
|
bc2c95de5f | ||
|
8a0cce2bab | ||
|
81a3da8be9 | ||
|
09747c8a31 | ||
|
562b652dea | ||
|
05409c7381 | ||
|
77dc39eae6 | ||
|
e1f7cc577f | ||
|
441340007b | ||
|
f81e73803f | ||
|
979ec18948 | ||
|
b9a8d04040 | ||
|
7fae7fbaf1 | ||
|
d8d9ba50c6 | ||
|
cc240d482d | ||
|
af14887e96 | ||
|
1c306606ca | ||
|
0194f981be | ||
|
b049f1674f | ||
|
44aa5d78d7 | ||
|
49c3b9cb0c | ||
|
d1a627e27f | ||
|
32fdc73a1f | ||
|
933c1850b6 | ||
|
6b31a2a39a | ||
|
30823602b7 | ||
|
625ba4a454 | ||
|
c0e5414d6e | ||
|
55b1cb43bd | ||
|
96a5f8d770 | ||
|
475c910487 | ||
|
b58f704893 | ||
|
2c0fbb0128 | ||
|
6be650bd29 | ||
|
0fdf09c7f4 | ||
|
9e8e016378 | ||
|
83b95606fe | ||
|
6986e10cf3 | ||
|
4e26a3bcc1 | ||
|
911f928556 | ||
|
22d63f488d | ||
|
7e50c47580 | ||
|
8a456cc8a4 | ||
|
c8a79ad751 | ||
|
7ebab2ca78 | ||
|
2daa1c5706 | ||
|
254dd04afb | ||
|
cc85c43370 | ||
|
0fe1b70a59 | ||
|
d195bae2d0 | ||
|
bd903e8207 | ||
|
156e0fb737 | ||
|
31bb198284 | ||
|
773d5bd0fe | ||
|
64c339471e | ||
|
771708e988 | ||
|
5544c1b492 | ||
|
ae1cd7de6a | ||
|
31c6335e4b | ||
|
c32efea44f | ||
|
40e61a7815 | ||
|
b7a1ff8921 | ||
|
a8e3fc5c28 | ||
|
e5989dca67 | ||
|
861e5caceb | ||
|
cede367975 | ||
|
2803fc8daa | ||
|
74cc437ed3 | ||
|
8cc727f1fa | ||
|
ca70dc3e47 | ||
|
5ba1a77e21 | ||
|
93b7e385db | ||
|
a7058a8d2f | ||
|
f933b63504 | ||
|
a7d1ff8071 | ||
|
9ab3f1d107 | ||
|
a6d8d36a6d | ||
|
1fbcf81188 | ||
|
06561ef59b | ||
|
1305d5e81b | ||
|
e224718dc0 | ||
|
6ae593a9b4 | ||
|
dbb388cc95 | ||
|
af1c587229 | ||
|
3e10261f1d | ||
|
fd902e46ea | ||
|
393f81befe | ||
|
c0a9abc299 | ||
|
c8dfc65f53 | ||
|
308e2405ce | ||
|
9acdac90af | ||
|
021e58e0d3 | ||
|
bd56df9b7a | ||
|
a580d5ae6d | ||
|
a383819763 | ||
|
68195c49fc | ||
|
d7a2863e19 | ||
|
93c32ff4aa | ||
|
a90c98ade8 | ||
|
b5b3696547 | ||
|
17b55bc021 | ||
|
c5cd364aca | ||
|
57c57a19f5 | ||
|
71430da381 | ||
|
eb68249eeb | ||
|
891cc0fdb7 | ||
|
ff015c192d | ||
|
b6dd5ac167 | ||
|
cd9d161514 | ||
|
8e54b56c40 | ||
|
8452a89533 | ||
|
5439f9b0ec | ||
|
207a244702 | ||
|
d2798f56e7 | ||
|
9e4ae06b20 | ||
|
5da8fbc4fb | ||
|
a1f6edcc3a | ||
|
91a090265a | ||
|
ad66101689 | ||
|
0552ca5eb7 | ||
|
852ee389bc | ||
|
d979973623 | ||
|
5c9ec95e32 | ||
|
79efbf73df | ||
|
46f7a97f71 | ||
|
4a5845b98b | ||
|
329b588089 | ||
|
2dedc013fc | ||
|
20c0da0067 | ||
|
188256aae3 | ||
|
45f96fecc4 | ||
|
34104a5fe7 | ||
|
56753ff081 | ||
|
c7f7fc0b56 | ||
|
07beaa0b7a | ||
|
78e14dee0d | ||
|
a96ffe838d | ||
|
ffa1ccd156 | ||
|
4548120aef | ||
|
18e520ad7a | ||
|
18956f263a | ||
|
0fa3e51f4b | ||
|
4b1ec2e2e4 | ||
|
49427c5345 | ||
|
34ccbbead5 | ||
|
5a3baf68a8 | ||
|
5c86ae917c | ||
|
4b952370af | ||
|
2ee6c28339 | ||
|
e907ae40c4 | ||
|
4b637e1a59 | ||
|
1127b2e918 | ||
|
075dd061a6 | ||
|
84395157f9 | ||
|
52a7a6ecbd | ||
|
84237cca87 | ||
|
3bd490d2d0 | ||
|
fbe43c5562 | ||
|
ed047fd061 | ||
|
1b1995dd67 | ||
|
eaebe4482c | ||
|
e458971726 | ||
|
e7a45f871f | ||
|
261b9ddbcd | ||
|
357a44f060 | ||
|
5ba935aeca | ||
|
828c7cadf2 | ||
|
f7e102ac55 | ||
|
6f9d9cf506 | ||
|
9890a7aa2a | ||
|
abd594bf31 | ||
|
4d9bbd115e | ||
|
ff620283c7 | ||
|
d4cdad5451 | ||
|
27c3309077 | ||
|
45e84a0f42 | ||
|
45e28a1ee3 | ||
|
f30960ada5 | ||
|
d5ae0255c0 | ||
|
2bea147667 | ||
|
603dd6670b | ||
|
2a5d7215d6 | ||
|
307d8081ac | ||
|
25a35cc7fb | ||
|
1ad1f9a1d1 | ||
|
f057293300 | ||
|
a2bc394c0a | ||
|
cb9bff32fe | ||
|
7d651b69de | ||
|
292d6df61c | ||
|
4a7239aade | ||
|
a9305073c7 | ||
|
7b1d66018c | ||
|
8b8e0f3039 | ||
|
eb1968bffe | ||
|
4111552b44 | ||
|
6ba4785b4a | ||
|
1528fef34a | ||
|
20374e9503 | ||
|
fc5c27b497 | ||
|
58c34c6ec3 | ||
|
b51ebd0cd2 | ||
|
13f703fb9a | ||
|
1e4ec795ab | ||
|
db8fd942f7 | ||
|
5e10b14df0 | ||
|
3f1f2961c6 | ||
|
0c846be9ae | ||
|
2af28c1745 | ||
|
7a6484a3d9 | ||
|
6c5f3fbce9 | ||
|
252f3af86e | ||
|
c65e6f2b3d | ||
|
67f4e9ba09 | ||
|
da929861c3 | ||
|
bc9e714751 | ||
|
a0e5e9b322 | ||
|
eccd73a543 | ||
|
bcdf016c02 | ||
|
6473047323 | ||
|
839ed04f82 | ||
|
6a630c531a |
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
qemu-kvm-0.13.0-b81fe95.tar.gz
|
||||
qemu-kvm-0.13.0-25fdf4a.tar.gz
|
||||
/qemu-kvm-0.13.0-rc1.tar.gz
|
||||
/qemu-kvm-0.13.0.tar.gz
|
||||
/.build*.log
|
||||
/x86_64/
|
||||
/*.src.rpm
|
||||
/qemu-*.tar.xz
|
||||
|
@ -1,259 +0,0 @@
|
||||
From 09992bc6b432987ed3871dd7e4327ab6a589b865 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 09:54:27 +0200
|
||||
Subject: [PATCH 01/39] add pflib: PixelFormat conversion library.
|
||||
|
||||
---
|
||||
Makefile.objs | 1 +
|
||||
pflib.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
pflib.h | 6 ++
|
||||
3 files changed, 220 insertions(+), 0 deletions(-)
|
||||
create mode 100644 pflib.c
|
||||
create mode 100644 pflib.h
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index dbee210..147051f 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -84,6 +84,7 @@ common-obj-y += qemu-char.o savevm.o #aio.o
|
||||
common-obj-y += msmouse.o ps2.o
|
||||
common-obj-y += qdev.o qdev-properties.o
|
||||
common-obj-y += block-migration.o
|
||||
+common-obj-y += pflib.o
|
||||
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
diff --git a/pflib.c b/pflib.c
|
||||
new file mode 100644
|
||||
index 0000000..1154d0c
|
||||
--- /dev/null
|
||||
+++ b/pflib.c
|
||||
@@ -0,0 +1,213 @@
|
||||
+/*
|
||||
+ * PixelFormat conversion library.
|
||||
+ *
|
||||
+ * Author: Gerd Hoffmann <kraxel@redhat.com>
|
||||
+ *
|
||||
+ * This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
+ * the COPYING file in the top-level directory.
|
||||
+ *
|
||||
+ */
|
||||
+#include "qemu-common.h"
|
||||
+#include "console.h"
|
||||
+#include "pflib.h"
|
||||
+
|
||||
+typedef struct QemuPixel QemuPixel;
|
||||
+
|
||||
+typedef void (*pf_convert)(QemuPfConv *conv,
|
||||
+ void *dst, void *src, uint32_t cnt);
|
||||
+typedef void (*pf_convert_from)(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt);
|
||||
+typedef void (*pf_convert_to)(PixelFormat *pf,
|
||||
+ void *dst, QemuPixel *src, uint32_t cnt);
|
||||
+
|
||||
+struct QemuPfConv {
|
||||
+ pf_convert convert;
|
||||
+ PixelFormat src;
|
||||
+ PixelFormat dst;
|
||||
+
|
||||
+ /* for copy_generic() */
|
||||
+ pf_convert_from conv_from;
|
||||
+ pf_convert_to conv_to;
|
||||
+ QemuPixel *conv_buf;
|
||||
+ uint32_t conv_cnt;
|
||||
+};
|
||||
+
|
||||
+struct QemuPixel {
|
||||
+ uint8_t red;
|
||||
+ uint8_t green;
|
||||
+ uint8_t blue;
|
||||
+ uint8_t alpha;
|
||||
+};
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* PixelFormat -> QemuPixel conversions */
|
||||
+
|
||||
+static void conv_16_to_pixel(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint16_t *src16 = src;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ dst->red = ((*src16 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
|
||||
+ dst->green = ((*src16 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
|
||||
+ dst->blue = ((*src16 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
|
||||
+ dst->alpha = ((*src16 & pf->amask) >> pf->ashift) << (8 - pf->abits);
|
||||
+ dst++, src16++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* assumes pf->{r,g,b,a}bits == 8 */
|
||||
+static void conv_32_to_pixel_fast(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t *src32 = src;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ dst->red = (*src32 & pf->rmask) >> pf->rshift;
|
||||
+ dst->green = (*src32 & pf->gmask) >> pf->gshift;
|
||||
+ dst->blue = (*src32 & pf->bmask) >> pf->bshift;
|
||||
+ dst->alpha = (*src32 & pf->amask) >> pf->ashift;
|
||||
+ dst++, src32++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void conv_32_to_pixel_generic(PixelFormat *pf,
|
||||
+ QemuPixel *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t *src32 = src;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ if (pf->rbits < 8) {
|
||||
+ dst->red = ((*src32 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
|
||||
+ } else {
|
||||
+ dst->red = ((*src32 & pf->rmask) >> pf->rshift) >> (pf->rbits - 8);
|
||||
+ }
|
||||
+ if (pf->gbits < 8) {
|
||||
+ dst->green = ((*src32 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
|
||||
+ } else {
|
||||
+ dst->green = ((*src32 & pf->gmask) >> pf->gshift) >> (pf->gbits - 8);
|
||||
+ }
|
||||
+ if (pf->bbits < 8) {
|
||||
+ dst->blue = ((*src32 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
|
||||
+ } else {
|
||||
+ dst->blue = ((*src32 & pf->bmask) >> pf->bshift) >> (pf->bbits - 8);
|
||||
+ }
|
||||
+ if (pf->abits < 8) {
|
||||
+ dst->alpha = ((*src32 & pf->amask) >> pf->ashift) << (8 - pf->abits);
|
||||
+ } else {
|
||||
+ dst->alpha = ((*src32 & pf->amask) >> pf->ashift) >> (pf->abits - 8);
|
||||
+ }
|
||||
+ dst++, src32++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* QemuPixel -> PixelFormat conversions */
|
||||
+
|
||||
+static void conv_pixel_to_16(PixelFormat *pf,
|
||||
+ void *dst, QemuPixel *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint16_t *dst16 = dst;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ *dst16 = ((uint16_t)src->red >> (8 - pf->rbits)) << pf->rshift;
|
||||
+ *dst16 |= ((uint16_t)src->green >> (8 - pf->gbits)) << pf->gshift;
|
||||
+ *dst16 |= ((uint16_t)src->blue >> (8 - pf->bbits)) << pf->bshift;
|
||||
+ *dst16 |= ((uint16_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
|
||||
+ dst16++, src++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void conv_pixel_to_32(PixelFormat *pf,
|
||||
+ void *dst, QemuPixel *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t *dst32 = dst;
|
||||
+
|
||||
+ while (cnt > 0) {
|
||||
+ *dst32 = ((uint32_t)src->red >> (8 - pf->rbits)) << pf->rshift;
|
||||
+ *dst32 |= ((uint32_t)src->green >> (8 - pf->gbits)) << pf->gshift;
|
||||
+ *dst32 |= ((uint32_t)src->blue >> (8 - pf->bbits)) << pf->bshift;
|
||||
+ *dst32 |= ((uint32_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
|
||||
+ dst32++, src++, cnt--;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* PixelFormat -> PixelFormat conversions */
|
||||
+
|
||||
+static void convert_copy(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ uint32_t bytes = cnt * conv->src.bytes_per_pixel;
|
||||
+ memcpy(dst, src, bytes);
|
||||
+}
|
||||
+
|
||||
+static void convert_generic(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ if (conv->conv_cnt < cnt) {
|
||||
+ conv->conv_cnt = cnt;
|
||||
+ conv->conv_buf = qemu_realloc(conv->conv_buf, sizeof(QemuPixel) * conv->conv_cnt);
|
||||
+ }
|
||||
+ conv->conv_from(&conv->src, conv->conv_buf, src, cnt);
|
||||
+ conv->conv_to(&conv->dst, dst, conv->conv_buf, cnt);
|
||||
+}
|
||||
+
|
||||
+/* ----------------------------------------------------------------------- */
|
||||
+/* public interface */
|
||||
+
|
||||
+QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src)
|
||||
+{
|
||||
+ QemuPfConv *conv = qemu_mallocz(sizeof(QemuPfConv));
|
||||
+
|
||||
+ conv->src = *src;
|
||||
+ conv->dst = *dst;
|
||||
+
|
||||
+ if (memcmp(&conv->src, &conv->dst, sizeof(PixelFormat)) == 0) {
|
||||
+ /* formats identical, can simply copy */
|
||||
+ conv->convert = convert_copy;
|
||||
+ } else {
|
||||
+ /* generic two-step conversion: src -> QemuPixel -> dst */
|
||||
+ switch (conv->src.bytes_per_pixel) {
|
||||
+ case 2:
|
||||
+ conv->conv_from = conv_16_to_pixel;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ if (conv->src.rbits == 8 && conv->src.gbits == 8 && conv->src.bbits == 8) {
|
||||
+ conv->conv_from = conv_32_to_pixel_fast;
|
||||
+ } else {
|
||||
+ conv->conv_from = conv_32_to_pixel_generic;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto err;
|
||||
+ }
|
||||
+ switch (conv->dst.bytes_per_pixel) {
|
||||
+ case 2:
|
||||
+ conv->conv_to = conv_pixel_to_16;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ conv->conv_to = conv_pixel_to_32;
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto err;
|
||||
+ }
|
||||
+ conv->convert = convert_generic;
|
||||
+ }
|
||||
+ return conv;
|
||||
+
|
||||
+err:
|
||||
+ qemu_free(conv);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
|
||||
+{
|
||||
+ conv->convert(conv, dst, src, cnt);
|
||||
+}
|
||||
+
|
||||
+void qemu_pf_conv_put(QemuPfConv *conv)
|
||||
+{
|
||||
+ if (conv) {
|
||||
+ qemu_free(conv->conv_buf);
|
||||
+ qemu_free(conv);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/pflib.h b/pflib.h
|
||||
new file mode 100644
|
||||
index 0000000..8d73fdd
|
||||
--- /dev/null
|
||||
+++ b/pflib.h
|
||||
@@ -0,0 +1,6 @@
|
||||
+/* public */
|
||||
+typedef struct QemuPfConv QemuPfConv;
|
||||
+
|
||||
+QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src);
|
||||
+void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt);
|
||||
+void qemu_pf_conv_put(QemuPfConv *conv);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,39 +0,0 @@
|
||||
From 89df4f8cf7ecde07e3dc5e2ea3c19cbcd02165d0 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 23 Apr 2010 13:44:10 +0200
|
||||
Subject: [PATCH 02/39] configure: add logging
|
||||
|
||||
Write compile commands and messages to config.log.
|
||||
Useful for debugging configure.
|
||||
---
|
||||
configure | 7 +++++--
|
||||
1 files changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index b85590f..e09c442 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -16,15 +16,18 @@ TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
|
||||
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
|
||||
|
||||
trap "rm -f $TMPC $TMPO $TMPE ; exit" EXIT INT QUIT TERM
|
||||
+rm -f config.log
|
||||
|
||||
compile_object() {
|
||||
- $cc $QEMU_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null
|
||||
+ echo $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log
|
||||
+ $cc $QEMU_CFLAGS -c -o $TMPO $TMPC >> config.log 2>&1
|
||||
}
|
||||
|
||||
compile_prog() {
|
||||
local_cflags="$1"
|
||||
local_ldflags="$2"
|
||||
- $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags > /dev/null 2> /dev/null
|
||||
+ echo $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log
|
||||
+ $cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log 2>&1
|
||||
}
|
||||
|
||||
# check whether a command is available to this shell (may be either an
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,94 +0,0 @@
|
||||
From 0034da7fb15d1225e0fd725009743d48511a90b7 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 24 Mar 2010 10:26:51 +0100
|
||||
Subject: [PATCH 03/39] add spice into the configure file
|
||||
|
||||
---
|
||||
configure | 36 ++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 36 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index e09c442..2aaa6d7 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -331,6 +331,7 @@ cpu_emulation="yes"
|
||||
check_utests="no"
|
||||
user_pie="no"
|
||||
zero_malloc=""
|
||||
+spice=""
|
||||
|
||||
# OS specific
|
||||
if check_define __linux__ ; then
|
||||
@@ -647,6 +648,10 @@ for opt do
|
||||
;;
|
||||
--enable-kvm-device-assignment) kvm_cap_device_assignment="yes"
|
||||
;;
|
||||
+ --disable-spice) spice="no"
|
||||
+ ;;
|
||||
+ --enable-spice) spice="yes"
|
||||
+ ;;
|
||||
--enable-profiler) profiler="yes"
|
||||
;;
|
||||
--enable-cocoa)
|
||||
@@ -933,6 +938,8 @@ echo " --enable-docs enable documentation build"
|
||||
echo " --disable-docs disable documentation build"
|
||||
echo " --disable-vhost-net disable vhost-net acceleration support"
|
||||
echo " --enable-vhost-net enable vhost-net acceleration support"
|
||||
+echo " --disable-spice disable spice"
|
||||
+echo " --enable-spice enable spice"
|
||||
echo ""
|
||||
echo "NOTE: The object files are built at the place where configure is launched"
|
||||
exit 1
|
||||
@@ -2184,6 +2191,30 @@ if compile_prog "" ""; then
|
||||
gcc_attribute_warn_unused_result=yes
|
||||
fi
|
||||
|
||||
+# spice probe
|
||||
+if test "$spice" != "no" ; then
|
||||
+ cat > $TMPC << EOF
|
||||
+#include <spice.h>
|
||||
+int main(void) { spice_server_new(); return 0; }
|
||||
+EOF
|
||||
+ spice_proto_ver=$($pkgconfig --modversion spice-protocol 2>/dev/null)
|
||||
+ spice_server_ver=$($pkgconfig --modversion spice-server 2>/dev/null)
|
||||
+ spice_cflags=$($pkgconfig --cflags spice-protocol spice-server 2>/dev/null)
|
||||
+ spice_libs=$($pkgconfig --libs spice-protocol spice-server 2>/dev/null)
|
||||
+ if compile_prog "$spice_cflags" "$spice_libs" ; then
|
||||
+ spice="yes"
|
||||
+ libs_softmmu="$libs_softmmu $spice_libs"
|
||||
+ QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
|
||||
+ else
|
||||
+ if test "$spice" = "yes" ; then
|
||||
+ feature_not_found "spice"
|
||||
+ fi
|
||||
+ spice="no"
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
+##########################################
|
||||
+
|
||||
##########################################
|
||||
# check if we have fdatasync
|
||||
|
||||
@@ -2329,6 +2360,7 @@ echo "preadv support $preadv"
|
||||
echo "fdatasync $fdatasync"
|
||||
echo "uuid support $uuid"
|
||||
echo "vhost-net support $vhost_net"
|
||||
+echo "spice support $spice"
|
||||
|
||||
if test $sdl_too_old = "yes"; then
|
||||
echo "-> Your SDL version is too old - please upgrade to have SDL support"
|
||||
@@ -2574,6 +2606,10 @@ else
|
||||
echo "CONFIG_NO_CPU_EMULATION=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
+if test "$spice" = "yes" ; then
|
||||
+ echo "CONFIG_SPICE=y" >> $config_host_mak
|
||||
+fi
|
||||
+
|
||||
# XXX: suppress that
|
||||
if [ "$bsd" = "yes" ] ; then
|
||||
echo "CONFIG_BSD=y" >> $config_host_mak
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,333 +0,0 @@
|
||||
From 67361a4ad5c99c5dfecdb9d2fc1ba794c38c44ff Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:27 -0300
|
||||
Subject: [PATCH 04/39] spice: core bits
|
||||
|
||||
Add -spice command line switch. Has support setting passwd and port for
|
||||
now. With this patch applied the spice client can successfully connect
|
||||
to qemu. You can't do anything useful yet though.
|
||||
---
|
||||
Makefile.objs | 2 +
|
||||
qemu-config.c | 23 ++++++++
|
||||
qemu-config.h | 1 +
|
||||
qemu-options.hx | 8 +++
|
||||
qemu-spice.h | 22 ++++++++
|
||||
spice.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
vl.c | 15 ++++++
|
||||
7 files changed, 222 insertions(+), 0 deletions(-)
|
||||
create mode 100644 qemu-spice.h
|
||||
create mode 100644 spice.c
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index 147051f..569b458 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -89,6 +89,8 @@ common-obj-y += pflib.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
|
||||
+common-obj-$(CONFIG_SPICE) += spice.o
|
||||
+
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
audio-obj-$(CONFIG_OSS) += ossaudio.o
|
||||
diff --git a/qemu-config.c b/qemu-config.c
|
||||
index 08ee553..8a894cf 100644
|
||||
--- a/qemu-config.c
|
||||
+++ b/qemu-config.c
|
||||
@@ -346,6 +346,26 @@ QemuOptsList qemu_cpudef_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_SPICE
|
||||
+QemuOptsList qemu_spice_opts = {
|
||||
+ .name = "spice",
|
||||
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
|
||||
+ .desc = {
|
||||
+ {
|
||||
+ .name = "port",
|
||||
+ .type = QEMU_OPT_NUMBER,
|
||||
+ },{
|
||||
+ .name = "password",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "disable-ticketing",
|
||||
+ .type = QEMU_OPT_BOOL,
|
||||
+ },
|
||||
+ { /* end if list */ }
|
||||
+ },
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
static QemuOptsList *vm_config_groups[] = {
|
||||
&qemu_drive_opts,
|
||||
&qemu_chardev_opts,
|
||||
@@ -356,6 +376,9 @@ static QemuOptsList *vm_config_groups[] = {
|
||||
&qemu_global_opts,
|
||||
&qemu_mon_opts,
|
||||
&qemu_cpudef_opts,
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ &qemu_spice_opts,
|
||||
+#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
diff --git a/qemu-config.h b/qemu-config.h
|
||||
index dca69d4..3a90213 100644
|
||||
--- a/qemu-config.h
|
||||
+++ b/qemu-config.h
|
||||
@@ -14,6 +14,7 @@ extern QemuOptsList qemu_rtc_opts;
|
||||
extern QemuOptsList qemu_global_opts;
|
||||
extern QemuOptsList qemu_mon_opts;
|
||||
extern QemuOptsList qemu_cpudef_opts;
|
||||
+extern QemuOptsList qemu_spice_opts;
|
||||
|
||||
QemuOptsList *qemu_find_opts(const char *group);
|
||||
int qemu_set_option(const char *str);
|
||||
diff --git a/qemu-options.hx b/qemu-options.hx
|
||||
index 66c84a0..85551cc 100644
|
||||
--- a/qemu-options.hx
|
||||
+++ b/qemu-options.hx
|
||||
@@ -676,6 +676,14 @@ STEXI
|
||||
Enable SDL.
|
||||
ETEXI
|
||||
|
||||
+#ifdef CONFIG_SPICE
|
||||
+DEF("spice", HAS_ARG, QEMU_OPTION_spice,
|
||||
+ "-spice <args> use spice\n", QEMU_ARCH_ALL)
|
||||
+STEXI
|
||||
+Use Spice.
|
||||
+ETEXI
|
||||
+#endif
|
||||
+
|
||||
DEF("portrait", 0, QEMU_OPTION_portrait,
|
||||
"-portrait rotate graphical output 90 deg left (only PXA LCD)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
new file mode 100644
|
||||
index 0000000..5597576
|
||||
--- /dev/null
|
||||
+++ b/qemu-spice.h
|
||||
@@ -0,0 +1,22 @@
|
||||
+#ifndef QEMU_SPICE_H
|
||||
+#define QEMU_SPICE_H
|
||||
+
|
||||
+#ifdef CONFIG_SPICE
|
||||
+
|
||||
+#include <spice.h>
|
||||
+
|
||||
+#include "qemu-option.h"
|
||||
+#include "qemu-config.h"
|
||||
+
|
||||
+extern SpiceServer *spice_server;
|
||||
+extern int using_spice;
|
||||
+
|
||||
+void qemu_spice_init(void);
|
||||
+
|
||||
+#else /* CONFIG_SPICE */
|
||||
+
|
||||
+#define using_spice 0
|
||||
+
|
||||
+#endif /* CONFIG_SPICE */
|
||||
+
|
||||
+#endif /* QEMU_SPICE_H */
|
||||
diff --git a/spice.c b/spice.c
|
||||
new file mode 100644
|
||||
index 0000000..50fa5ca
|
||||
--- /dev/null
|
||||
+++ b/spice.c
|
||||
@@ -0,0 +1,151 @@
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "qemu-queue.h"
|
||||
+#include "monitor.h"
|
||||
+
|
||||
+/* core bits */
|
||||
+
|
||||
+SpiceServer *spice_server;
|
||||
+int using_spice = 0;
|
||||
+
|
||||
+struct SpiceTimer {
|
||||
+ QEMUTimer *timer;
|
||||
+ QTAILQ_ENTRY(SpiceTimer) next;
|
||||
+};
|
||||
+static QTAILQ_HEAD(, SpiceTimer) timers = QTAILQ_HEAD_INITIALIZER(timers);
|
||||
+
|
||||
+static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque)
|
||||
+{
|
||||
+ SpiceTimer *timer;
|
||||
+
|
||||
+ timer = qemu_mallocz(sizeof(*timer));
|
||||
+ timer->timer = qemu_new_timer(rt_clock, func, opaque);
|
||||
+ QTAILQ_INSERT_TAIL(&timers, timer, next);
|
||||
+ return timer;
|
||||
+}
|
||||
+
|
||||
+static void timer_start(SpiceTimer *timer, uint32_t ms)
|
||||
+{
|
||||
+ qemu_mod_timer(timer->timer, qemu_get_clock(rt_clock) + ms);
|
||||
+}
|
||||
+
|
||||
+static void timer_cancel(SpiceTimer *timer)
|
||||
+{
|
||||
+ qemu_del_timer(timer->timer);
|
||||
+}
|
||||
+
|
||||
+static void timer_remove(SpiceTimer *timer)
|
||||
+{
|
||||
+ qemu_del_timer(timer->timer);
|
||||
+ qemu_free_timer(timer->timer);
|
||||
+ QTAILQ_REMOVE(&timers, timer, next);
|
||||
+ free(timer);
|
||||
+}
|
||||
+
|
||||
+struct SpiceWatch {
|
||||
+ int fd;
|
||||
+ int event_mask;
|
||||
+ SpiceWatchFunc func;
|
||||
+ void *opaque;
|
||||
+ QTAILQ_ENTRY(SpiceWatch) next;
|
||||
+};
|
||||
+static QTAILQ_HEAD(, SpiceWatch) watches = QTAILQ_HEAD_INITIALIZER(watches);
|
||||
+
|
||||
+static void watch_read(void *opaque)
|
||||
+{
|
||||
+ SpiceWatch *watch = opaque;
|
||||
+ watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
|
||||
+}
|
||||
+
|
||||
+static void watch_write(void *opaque)
|
||||
+{
|
||||
+ SpiceWatch *watch = opaque;
|
||||
+ watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
|
||||
+}
|
||||
+
|
||||
+static void watch_update_mask(SpiceWatch *watch, int event_mask)
|
||||
+{
|
||||
+ IOHandler *on_read = NULL;
|
||||
+ IOHandler *on_write = NULL;
|
||||
+
|
||||
+ watch->event_mask = event_mask;
|
||||
+ if (watch->event_mask & SPICE_WATCH_EVENT_READ)
|
||||
+ on_read = watch_read;
|
||||
+ if (watch->event_mask & SPICE_WATCH_EVENT_WRITE)
|
||||
+ on_read = watch_write;
|
||||
+ qemu_set_fd_handler(watch->fd, on_read, on_write, watch);
|
||||
+}
|
||||
+
|
||||
+static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
|
||||
+{
|
||||
+ SpiceWatch *watch;
|
||||
+
|
||||
+ watch = qemu_mallocz(sizeof(*watch));
|
||||
+ watch->fd = fd;
|
||||
+ watch->func = func;
|
||||
+ watch->opaque = opaque;
|
||||
+ QTAILQ_INSERT_TAIL(&watches, watch, next);
|
||||
+
|
||||
+ watch_update_mask(watch, event_mask);
|
||||
+ return watch;
|
||||
+}
|
||||
+
|
||||
+static void watch_remove(SpiceWatch *watch)
|
||||
+{
|
||||
+ watch_update_mask(watch, 0);
|
||||
+ QTAILQ_REMOVE(&watches, watch, next);
|
||||
+ qemu_free(watch);
|
||||
+}
|
||||
+
|
||||
+static SpiceCoreInterface core_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_CORE,
|
||||
+ .base.description = "qemu core services",
|
||||
+ .base.major_version = SPICE_INTERFACE_CORE_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_CORE_MINOR,
|
||||
+
|
||||
+ .timer_add = timer_add,
|
||||
+ .timer_start = timer_start,
|
||||
+ .timer_cancel = timer_cancel,
|
||||
+ .timer_remove = timer_remove,
|
||||
+
|
||||
+ .watch_add = watch_add,
|
||||
+ .watch_update_mask = watch_update_mask,
|
||||
+ .watch_remove = watch_remove,
|
||||
+};
|
||||
+
|
||||
+/* functions for the rest of qemu */
|
||||
+
|
||||
+void qemu_spice_init(void)
|
||||
+{
|
||||
+ QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
+ const char *password;
|
||||
+ int port;
|
||||
+
|
||||
+ if (!opts)
|
||||
+ return;
|
||||
+ port = qemu_opt_get_number(opts, "port", 0);
|
||||
+ if (!port)
|
||||
+ return;
|
||||
+ password = qemu_opt_get(opts, "password");
|
||||
+
|
||||
+ spice_server = spice_server_new();
|
||||
+ spice_server_set_port(spice_server, port);
|
||||
+ if (password)
|
||||
+ spice_server_set_ticket(spice_server, password, 0, 0, 0);
|
||||
+ if (qemu_opt_get_bool(opts, "disable-ticketing", 0))
|
||||
+ spice_server_set_noauth(spice_server);
|
||||
+
|
||||
+ /* TODO: make configurable via cmdline */
|
||||
+ spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
|
||||
+
|
||||
+ spice_server_init(spice_server, &core_interface);
|
||||
+ using_spice = 1;
|
||||
+}
|
||||
diff --git a/vl.c b/vl.c
|
||||
index de8bad1..97897e0 100644
|
||||
--- a/vl.c
|
||||
+++ b/vl.c
|
||||
@@ -162,6 +162,8 @@ int main(int argc, char **argv)
|
||||
#include "cpus.h"
|
||||
#include "arch_init.h"
|
||||
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
//#define DEBUG_NET
|
||||
//#define DEBUG_SLIRP
|
||||
|
||||
@@ -2677,6 +2679,15 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
break;
|
||||
}
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ case QEMU_OPTION_spice:
|
||||
+ opts = qemu_opts_parse(&qemu_spice_opts, optarg, 0);
|
||||
+ if (!opts) {
|
||||
+ fprintf(stderr, "parse error: %s\n", optarg);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ break;
|
||||
+#endif
|
||||
case QEMU_OPTION_writeconfig:
|
||||
{
|
||||
FILE *fp;
|
||||
@@ -2951,6 +2962,10 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
qemu_add_globals();
|
||||
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ qemu_spice_init();
|
||||
+#endif
|
||||
+
|
||||
machine->init(ram_size, boot_devices,
|
||||
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,118 +0,0 @@
|
||||
From 90f6ec84332857752c252b1c3b89d86eb9714b0e Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:28 -0300
|
||||
Subject: [PATCH 05/39] spice: add keyboard
|
||||
|
||||
Open keyboard channel. Now you can type into the spice client and the
|
||||
keyboard events are sent to your guest. You'll need some other display
|
||||
like vnc to actually see the guest responding to them though.
|
||||
---
|
||||
Makefile.objs | 2 +-
|
||||
qemu-spice.h | 1 +
|
||||
spice-input.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
spice.c | 2 ++
|
||||
4 files changed, 61 insertions(+), 1 deletions(-)
|
||||
create mode 100644 spice-input.c
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index 569b458..023a0dc 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -89,7 +89,7 @@ common-obj-y += pflib.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
|
||||
-common-obj-$(CONFIG_SPICE) += spice.o
|
||||
+common-obj-$(CONFIG_SPICE) += spice.o spice-input.o
|
||||
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index 5597576..ceb3db2 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -12,6 +12,7 @@ extern SpiceServer *spice_server;
|
||||
extern int using_spice;
|
||||
|
||||
void qemu_spice_init(void);
|
||||
+void qemu_spice_input_init(void);
|
||||
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
diff --git a/spice-input.c b/spice-input.c
|
||||
new file mode 100644
|
||||
index 0000000..e1014d7
|
||||
--- /dev/null
|
||||
+++ b/spice-input.c
|
||||
@@ -0,0 +1,57 @@
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <spice.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "console.h"
|
||||
+
|
||||
+/* keyboard bits */
|
||||
+
|
||||
+typedef struct QemuSpiceKbd {
|
||||
+ SpiceKbdInstance sin;
|
||||
+ int ledstate;
|
||||
+} QemuSpiceKbd;
|
||||
+
|
||||
+static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag);
|
||||
+static uint8_t kbd_get_leds(SpiceKbdInstance *sin);
|
||||
+static void kbd_leds(void *opaque, int l);
|
||||
+
|
||||
+static const SpiceKbdInterface kbd_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_KEYBOARD,
|
||||
+ .base.description = "qemu keyboard",
|
||||
+ .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR,
|
||||
+ .push_scan_freg = kbd_push_key,
|
||||
+ .get_leds = kbd_get_leds,
|
||||
+};
|
||||
+
|
||||
+static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
||||
+{
|
||||
+ kbd_put_keycode(frag);
|
||||
+}
|
||||
+
|
||||
+static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
|
||||
+{
|
||||
+ QemuSpiceKbd *kbd = container_of(sin, QemuSpiceKbd, sin);
|
||||
+ return kbd->ledstate;
|
||||
+}
|
||||
+
|
||||
+static void kbd_leds(void *opaque, int ledstate)
|
||||
+{
|
||||
+ QemuSpiceKbd *kbd = opaque;
|
||||
+ kbd->ledstate = ledstate;
|
||||
+ spice_server_kbd_leds(&kbd->sin, ledstate);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_input_init(void)
|
||||
+{
|
||||
+ QemuSpiceKbd *kbd;
|
||||
+
|
||||
+ kbd = qemu_mallocz(sizeof(*kbd));
|
||||
+ kbd->sin.base.sif = &kbd_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &kbd->sin.base);
|
||||
+ qemu_add_led_event_handler(kbd_leds, kbd);
|
||||
+}
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 50fa5ca..c763d52 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -148,4 +148,6 @@ void qemu_spice_init(void)
|
||||
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
using_spice = 1;
|
||||
+
|
||||
+ qemu_spice_input_init();
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,62 +0,0 @@
|
||||
From e18846175191cbc590ac46fa3820726aeebd6d48 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:29 -0300
|
||||
Subject: [PATCH 06/39] spice: add mouse
|
||||
|
||||
Open mouse channel. Now you can move the guests mouse pointer.
|
||||
No tablet / absolute positioning (yet) though.
|
||||
---
|
||||
spice-input.c | 31 +++++++++++++++++++++++++++++++
|
||||
1 files changed, 31 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/spice-input.c b/spice-input.c
|
||||
index e1014d7..8f3deb4 100644
|
||||
--- a/spice-input.c
|
||||
+++ b/spice-input.c
|
||||
@@ -46,12 +46,43 @@ static void kbd_leds(void *opaque, int ledstate)
|
||||
spice_server_kbd_leds(&kbd->sin, ledstate);
|
||||
}
|
||||
|
||||
+/* mouse bits */
|
||||
+
|
||||
+typedef struct QemuSpiceMouse {
|
||||
+ SpiceMouseInstance sin;
|
||||
+} QemuSpiceMouse;
|
||||
+
|
||||
+static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ kbd_mouse_event(dx, dy, dz, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static void mouse_buttons(SpiceMouseInstance *sin, uint32_t buttons_state)
|
||||
+{
|
||||
+ kbd_mouse_event(0, 0, 0, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static const SpiceMouseInterface mouse_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_MOUSE,
|
||||
+ .base.description = "mouse",
|
||||
+ .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR,
|
||||
+ .motion = mouse_motion,
|
||||
+ .buttons = mouse_buttons,
|
||||
+};
|
||||
+
|
||||
void qemu_spice_input_init(void)
|
||||
{
|
||||
QemuSpiceKbd *kbd;
|
||||
+ QemuSpiceMouse *mouse;
|
||||
|
||||
kbd = qemu_mallocz(sizeof(*kbd));
|
||||
kbd->sin.base.sif = &kbd_interface.base;
|
||||
spice_server_add_interface(spice_server, &kbd->sin.base);
|
||||
qemu_add_led_event_handler(kbd_leds, kbd);
|
||||
+
|
||||
+ mouse = qemu_mallocz(sizeof(*mouse));
|
||||
+ mouse->sin.base.sif = &mouse_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &mouse->sin.base);
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,532 +0,0 @@
|
||||
From 0143117eb5e6233fdeff3b679492b51148cc8f85 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 24 Mar 2010 15:47:18 +0100
|
||||
Subject: [PATCH 07/39] spice: simple display
|
||||
|
||||
With that patch applied you'll actually see the guests screen in the
|
||||
spice client. This does *not* bring qxl and full spice support though.
|
||||
This is basically the qxl vga mode made more generic, so it plays
|
||||
together with any qemu-emulated gfx card. You can display stdvga or
|
||||
cirrus via spice client. You can have both vnc and spice enabled and
|
||||
clients connected at the same time.
|
||||
---
|
||||
Makefile.objs | 2 +-
|
||||
qemu-spice.h | 1 +
|
||||
spice-display.c | 394 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
spice-display.h | 52 ++++++++
|
||||
vl.c | 7 +-
|
||||
5 files changed, 454 insertions(+), 2 deletions(-)
|
||||
create mode 100644 spice-display.c
|
||||
create mode 100644 spice-display.h
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index 023a0dc..d05643f 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -89,7 +89,7 @@ common-obj-y += pflib.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
|
||||
-common-obj-$(CONFIG_SPICE) += spice.o spice-input.o
|
||||
+common-obj-$(CONFIG_SPICE) += spice.o spice-input.o spice-display.o
|
||||
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index ceb3db2..f061004 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -13,6 +13,7 @@ extern int using_spice;
|
||||
|
||||
void qemu_spice_init(void);
|
||||
void qemu_spice_input_init(void);
|
||||
+void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
new file mode 100644
|
||||
index 0000000..13a620e
|
||||
--- /dev/null
|
||||
+++ b/spice-display.c
|
||||
@@ -0,0 +1,394 @@
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdint.h>
|
||||
+#include <string.h>
|
||||
+#include <pthread.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "qemu-queue.h"
|
||||
+#include "monitor.h"
|
||||
+#include "console.h"
|
||||
+#include "sysemu.h"
|
||||
+
|
||||
+#include "spice-display.h"
|
||||
+
|
||||
+static int debug = 1;
|
||||
+
|
||||
+int qemu_spice_rect_is_empty(const QXLRect* r)
|
||||
+{
|
||||
+ return r->top == r->bottom || r->left == r->right;
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
|
||||
+{
|
||||
+ if (qemu_spice_rect_is_empty(r)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (qemu_spice_rect_is_empty(dest)) {
|
||||
+ *dest = *r;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ dest->top = MIN(dest->top, r->top);
|
||||
+ dest->left = MIN(dest->left, r->left);
|
||||
+ dest->bottom = MAX(dest->bottom, r->bottom);
|
||||
+ dest->right = MAX(dest->right, r->right);
|
||||
+}
|
||||
+
|
||||
+SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ SimpleSpiceUpdate *update;
|
||||
+ QXLDrawable *drawable;
|
||||
+ QXLImage *image;
|
||||
+ QXLCommand *cmd;
|
||||
+ uint8_t *src, *dst;
|
||||
+ int by, bw, bh;
|
||||
+
|
||||
+ if (qemu_spice_rect_is_empty(&ssd->dirty)) {
|
||||
+ return NULL;
|
||||
+ };
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__,
|
||||
+ ssd->dirty.left, ssd->dirty.right,
|
||||
+ ssd->dirty.top, ssd->dirty.bottom);
|
||||
+
|
||||
+ update = qemu_mallocz(sizeof(*update));
|
||||
+ drawable = &update->drawable;
|
||||
+ image = &update->image;
|
||||
+ cmd = &update->ext.cmd;
|
||||
+
|
||||
+ bw = ssd->dirty.right - ssd->dirty.left;
|
||||
+ bh = ssd->dirty.bottom - ssd->dirty.top;
|
||||
+ update->bitmap = qemu_malloc(bw * bh * 4);
|
||||
+
|
||||
+ drawable->bbox = ssd->dirty;
|
||||
+ drawable->clip.type = SPICE_CLIP_TYPE_NONE;
|
||||
+ drawable->effect = QXL_EFFECT_OPAQUE;
|
||||
+ drawable->release_info.id = (intptr_t)update;
|
||||
+ drawable->type = QXL_DRAW_COPY;
|
||||
+
|
||||
+ drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
|
||||
+ drawable->u.copy.src_bitmap = (intptr_t)image;
|
||||
+ drawable->u.copy.src_area.right = bw;
|
||||
+ drawable->u.copy.src_area.bottom = bh;
|
||||
+
|
||||
+ QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ssd->unique++);
|
||||
+ image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
|
||||
+ image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
|
||||
+ image->bitmap.stride = bw * 4;
|
||||
+ image->descriptor.width = image->bitmap.x = bw;
|
||||
+ image->descriptor.height = image->bitmap.y = bh;
|
||||
+ image->bitmap.data = (intptr_t)(update->bitmap);
|
||||
+ image->bitmap.palette = 0;
|
||||
+ image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
|
||||
+
|
||||
+ if (ssd->conv == NULL) {
|
||||
+ PixelFormat dst = qemu_default_pixelformat(32);
|
||||
+ ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf);
|
||||
+ assert(ssd->conv);
|
||||
+ }
|
||||
+
|
||||
+ src = ds_get_data(ssd->ds) +
|
||||
+ ssd->dirty.top * ds_get_linesize(ssd->ds) +
|
||||
+ ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds);
|
||||
+ dst = update->bitmap;
|
||||
+ for (by = 0; by < bh; by++) {
|
||||
+ qemu_pf_conv_run(ssd->conv, dst, src, bw);
|
||||
+ src += ds_get_linesize(ssd->ds);
|
||||
+ dst += image->bitmap.stride;
|
||||
+ }
|
||||
+
|
||||
+ cmd->type = QXL_CMD_DRAW;
|
||||
+ cmd->data = (intptr_t)drawable;
|
||||
+
|
||||
+ memset(&ssd->dirty, 0, sizeof(ssd->dirty));
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+ return update;
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update)
|
||||
+{
|
||||
+ qemu_free(update->bitmap);
|
||||
+ qemu_free(update);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ QXLDevMemSlot memslot;
|
||||
+
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+
|
||||
+ memset(&memslot, 0, sizeof(memslot));
|
||||
+ memslot.slot_group_id = MEMSLOT_GROUP_HOST;
|
||||
+ memslot.virt_end = ~0;
|
||||
+ ssd->worker->add_memslot(ssd->worker, &memslot);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ QXLDevSurfaceCreate surface;
|
||||
+
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s: %dx%d\n", __FUNCTION__,
|
||||
+ ds_get_width(ssd->ds), ds_get_height(ssd->ds));
|
||||
+
|
||||
+ surface.format = SPICE_SURFACE_FMT_32_xRGB;
|
||||
+ surface.width = ds_get_width(ssd->ds);
|
||||
+ surface.height = ds_get_height(ssd->ds);
|
||||
+ surface.stride = -surface.width * 4;
|
||||
+ surface.mouse_mode = 0;
|
||||
+ surface.flags = 0;
|
||||
+ surface.type = 0;
|
||||
+ surface.mem = (intptr_t)ssd->buf;
|
||||
+ surface.group_id = MEMSLOT_GROUP_HOST;
|
||||
+ ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+
|
||||
+ ssd->worker->destroy_primary_surface(ssd->worker, 0);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = opaque;
|
||||
+
|
||||
+ if (running) {
|
||||
+ ssd->worker->start(ssd->worker);
|
||||
+ } else {
|
||||
+ ssd->worker->stop(ssd->worker);
|
||||
+ }
|
||||
+ ssd->running = running;
|
||||
+}
|
||||
+
|
||||
+/* display listener callbacks */
|
||||
+
|
||||
+void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
|
||||
+ int x, int y, int w, int h)
|
||||
+{
|
||||
+ QXLRect update_area;
|
||||
+
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s: x %d y %d w %d h %d\n", __FUNCTION__, x, y, w, h);
|
||||
+ update_area.left = x,
|
||||
+ update_area.right = x + w;
|
||||
+ update_area.top = y;
|
||||
+ update_area.bottom = y + h;
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ if (qemu_spice_rect_is_empty(&ssd->dirty)) {
|
||||
+ ssd->notify++;
|
||||
+ }
|
||||
+ qemu_spice_rect_union(&ssd->dirty, &update_area);
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ memset(&ssd->dirty, 0, sizeof(ssd->dirty));
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+
|
||||
+ qemu_spice_destroy_host_primary(ssd);
|
||||
+ qemu_spice_create_host_primary(ssd);
|
||||
+ qemu_pf_conv_put(ssd->conv);
|
||||
+ ssd->conv = NULL;
|
||||
+
|
||||
+ pthread_mutex_lock(&ssd->lock);
|
||||
+ ssd->dirty.left = 0;
|
||||
+ ssd->dirty.right = ds_get_width(ssd->ds);
|
||||
+ ssd->dirty.top = 0;
|
||||
+ ssd->dirty.bottom = ds_get_height(ssd->ds);
|
||||
+ ssd->notify++;
|
||||
+ pthread_mutex_unlock(&ssd->lock);
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ vga_hw_update();
|
||||
+ if (ssd->notify) {
|
||||
+ ssd->notify = 0;
|
||||
+ ssd->worker->wakeup(ssd->worker);
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s: notify\n", __FUNCTION__);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* spice display interface callbacks */
|
||||
+
|
||||
+static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ ssd->worker = qxl_worker;
|
||||
+}
|
||||
+
|
||||
+static void interface_set_compression_level(QXLInstance *sin, int level)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ /* nothing to do */
|
||||
+}
|
||||
+
|
||||
+static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
|
||||
+{
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ /* nothing to do */
|
||||
+}
|
||||
+
|
||||
+static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+
|
||||
+ info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
|
||||
+ info->memslot_id_bits = MEMSLOT_SLOT_BITS;
|
||||
+ info->num_memslots = NUM_MEMSLOTS;
|
||||
+ info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
|
||||
+ info->internal_groupslot_id = 0;
|
||||
+ info->qxl_ram_size = ssd->bufsize;
|
||||
+ info->n_surfaces = NUM_SURFACES;
|
||||
+}
|
||||
+
|
||||
+static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+ SimpleSpiceUpdate *update;
|
||||
+
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ update = qemu_spice_create_update(ssd);
|
||||
+ if (update == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ *ext = update->ext;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int interface_req_cmd_notification(QXLInstance *sin)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void interface_release_resource(QXLInstance *sin,
|
||||
+ struct QXLReleaseInfoExt ext)
|
||||
+{
|
||||
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
+ uintptr_t id;
|
||||
+
|
||||
+ if (debug > 1)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ id = ext.info->id;
|
||||
+ qemu_spice_destroy_update(ssd, (void*)id);
|
||||
+}
|
||||
+
|
||||
+static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
|
||||
+{
|
||||
+ if (debug > 2)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static int interface_req_cursor_notification(QXLInstance *sin)
|
||||
+{
|
||||
+ if (debug)
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
|
||||
+{
|
||||
+ fprintf(stderr, "%s: abort()\n", __FUNCTION__);
|
||||
+ abort();
|
||||
+}
|
||||
+
|
||||
+static int interface_flush_resources(QXLInstance *sin)
|
||||
+{
|
||||
+ fprintf(stderr, "%s: abort()\n", __FUNCTION__);
|
||||
+ abort();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const QXLInterface dpy_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_QXL,
|
||||
+ .base.description = "qemu simple display",
|
||||
+ .base.major_version = SPICE_INTERFACE_QXL_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_QXL_MINOR,
|
||||
+
|
||||
+ .pci_vendor = REDHAT_PCI_VENDOR_ID,
|
||||
+ .pci_id = QXL_DEVICE_ID,
|
||||
+ .pci_revision = QXL_REVISION,
|
||||
+
|
||||
+ .attache_worker = interface_attach_worker,
|
||||
+ .set_compression_level = interface_set_compression_level,
|
||||
+ .set_mm_time = interface_set_mm_time,
|
||||
+
|
||||
+ .get_init_info = interface_get_init_info,
|
||||
+ .get_command = interface_get_command,
|
||||
+ .req_cmd_notification = interface_req_cmd_notification,
|
||||
+ .release_resource = interface_release_resource,
|
||||
+ .get_cursor_command = interface_get_cursor_command,
|
||||
+ .req_cursor_notification = interface_req_cursor_notification,
|
||||
+ .notify_update = interface_notify_update,
|
||||
+ .flush_resources = interface_flush_resources,
|
||||
+};
|
||||
+
|
||||
+static SimpleSpiceDisplay sdpy;
|
||||
+
|
||||
+static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
|
||||
+{
|
||||
+ qemu_spice_display_update(&sdpy, x, y, w, h);
|
||||
+}
|
||||
+
|
||||
+static void display_resize(struct DisplayState *ds)
|
||||
+{
|
||||
+ qemu_spice_display_resize(&sdpy);
|
||||
+}
|
||||
+
|
||||
+static void display_refresh(struct DisplayState *ds)
|
||||
+{
|
||||
+ qemu_spice_display_refresh(&sdpy);
|
||||
+}
|
||||
+
|
||||
+static DisplayChangeListener display_listener = {
|
||||
+ .dpy_update = display_update,
|
||||
+ .dpy_resize = display_resize,
|
||||
+ .dpy_refresh = display_refresh,
|
||||
+};
|
||||
+
|
||||
+void qemu_spice_display_init(DisplayState *ds)
|
||||
+{
|
||||
+ assert(sdpy.ds == NULL);
|
||||
+ sdpy.ds = ds;
|
||||
+ sdpy.bufsize = (16 * 1024 * 1024);
|
||||
+ sdpy.buf = qemu_malloc(sdpy.bufsize);
|
||||
+ pthread_mutex_init(&sdpy.lock, NULL);
|
||||
+ register_displaychangelistener(ds, &display_listener);
|
||||
+
|
||||
+ sdpy.qxl.base.sif = &dpy_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &sdpy.qxl.base);
|
||||
+ assert(sdpy.worker);
|
||||
+
|
||||
+ qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy);
|
||||
+ qemu_spice_create_host_memslot(&sdpy);
|
||||
+ qemu_spice_create_host_primary(&sdpy);
|
||||
+}
|
||||
diff --git a/spice-display.h b/spice-display.h
|
||||
new file mode 100644
|
||||
index 0000000..70a7be4
|
||||
--- /dev/null
|
||||
+++ b/spice-display.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+#include <spice/ipc_ring.h>
|
||||
+#include <spice/draw.h>
|
||||
+#include <spice/qxl_dev.h>
|
||||
+
|
||||
+#include "pflib.h"
|
||||
+
|
||||
+#define NUM_MEMSLOTS 8
|
||||
+#define MEMSLOT_GENERATION_BITS 8
|
||||
+#define MEMSLOT_SLOT_BITS 8
|
||||
+
|
||||
+#define MEMSLOT_GROUP_HOST 0
|
||||
+#define MEMSLOT_GROUP_GUEST 1
|
||||
+#define NUM_MEMSLOTS_GROUPS 2
|
||||
+
|
||||
+#define NUM_SURFACES 1024
|
||||
+
|
||||
+typedef struct SimpleSpiceDisplay {
|
||||
+ DisplayState *ds;
|
||||
+ void *buf;
|
||||
+ int bufsize;
|
||||
+ QXLWorker *worker;
|
||||
+ QXLInstance qxl;
|
||||
+ uint32_t unique;
|
||||
+ QemuPfConv *conv;
|
||||
+
|
||||
+ pthread_mutex_t lock;
|
||||
+ QXLRect dirty;
|
||||
+ int notify;
|
||||
+ int running;
|
||||
+} SimpleSpiceDisplay;
|
||||
+
|
||||
+typedef struct SimpleSpiceUpdate {
|
||||
+ QXLDrawable drawable;
|
||||
+ QXLImage image;
|
||||
+ QXLCommandExt ext;
|
||||
+ uint8_t *bitmap;
|
||||
+} SimpleSpiceUpdate;
|
||||
+
|
||||
+int qemu_spice_rect_is_empty(const QXLRect* r);
|
||||
+void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r);
|
||||
+
|
||||
+SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *sdpy);
|
||||
+void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update);
|
||||
+void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason);
|
||||
+
|
||||
+void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
|
||||
+ int x, int y, int w, int h);
|
||||
+void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
|
||||
diff --git a/vl.c b/vl.c
|
||||
index 97897e0..2ccebc8 100644
|
||||
--- a/vl.c
|
||||
+++ b/vl.c
|
||||
@@ -2993,7 +2993,7 @@ int main(int argc, char **argv, char **envp)
|
||||
/* just use the first displaystate for the moment */
|
||||
ds = get_displaystate();
|
||||
|
||||
- if (display_type == DT_DEFAULT) {
|
||||
+ if (display_type == DT_DEFAULT && !using_spice) {
|
||||
#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
|
||||
display_type = DT_SDL;
|
||||
#else
|
||||
@@ -3033,6 +3033,11 @@ int main(int argc, char **argv, char **envp)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ if (using_spice) {
|
||||
+ qemu_spice_display_init(ds);
|
||||
+ }
|
||||
+#endif
|
||||
dpy_resize(ds);
|
||||
|
||||
dcl = ds->listeners;
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,160 +0,0 @@
|
||||
From e3c6e18e27f0d598b37e9be1795dbcb42f740071 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 13 Apr 2010 09:05:03 +0200
|
||||
Subject: [PATCH 08/39] spice: add tablet support
|
||||
|
||||
Add support for the spice tablet interface. The tablet interface will
|
||||
be registered (and then used by the spice client) as soon as a absolute
|
||||
pointing device is available and used by the guest, i.e. you'll have to
|
||||
configure your guest with '-usbdevice tablet'.
|
||||
---
|
||||
spice-display.c | 2 +-
|
||||
spice-input.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 93 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
index 13a620e..a749e64 100644
|
||||
--- a/spice-display.c
|
||||
+++ b/spice-display.c
|
||||
@@ -143,7 +143,7 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
|
||||
surface.width = ds_get_width(ssd->ds);
|
||||
surface.height = ds_get_height(ssd->ds);
|
||||
surface.stride = -surface.width * 4;
|
||||
- surface.mouse_mode = 0;
|
||||
+ surface.mouse_mode = true;
|
||||
surface.flags = 0;
|
||||
surface.type = 0;
|
||||
surface.mem = (intptr_t)ssd->buf;
|
||||
diff --git a/spice-input.c b/spice-input.c
|
||||
index 8f3deb4..5646ff9 100644
|
||||
--- a/spice-input.c
|
||||
+++ b/spice-input.c
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
+#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <spice.h>
|
||||
@@ -48,9 +49,13 @@ static void kbd_leds(void *opaque, int ledstate)
|
||||
|
||||
/* mouse bits */
|
||||
|
||||
-typedef struct QemuSpiceMouse {
|
||||
- SpiceMouseInstance sin;
|
||||
-} QemuSpiceMouse;
|
||||
+typedef struct QemuSpicePointer {
|
||||
+ SpiceMouseInstance mouse;
|
||||
+ SpiceTabletInstance tablet;
|
||||
+ int width, height, x, y;
|
||||
+ Notifier mouse_mode;
|
||||
+ bool absolute;
|
||||
+} QemuSpicePointer;
|
||||
|
||||
static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz,
|
||||
uint32_t buttons_state)
|
||||
@@ -72,17 +77,97 @@ static const SpiceMouseInterface mouse_interface = {
|
||||
.buttons = mouse_buttons,
|
||||
};
|
||||
|
||||
+static void tablet_set_logical_size(SpiceTabletInstance* sin, int width, int height)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ fprintf(stderr, "%s: %dx%d\n", __FUNCTION__, width, height);
|
||||
+ if (height < 16)
|
||||
+ height = 16;
|
||||
+ if (width < 16)
|
||||
+ width = 16;
|
||||
+ pointer->width = width;
|
||||
+ pointer->height = height;
|
||||
+}
|
||||
+
|
||||
+static void tablet_position(SpiceTabletInstance* sin, int x, int y,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ pointer->x = x * 0x7FFF / (pointer->width - 1);
|
||||
+ pointer->y = y * 0x7FFF / (pointer->height - 1);
|
||||
+ kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void tablet_wheel(SpiceTabletInstance* sin, int wheel,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ kbd_mouse_event(pointer->x, pointer->y, wheel, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static void tablet_buttons(SpiceTabletInstance *sin,
|
||||
+ uint32_t buttons_state)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||
+
|
||||
+ kbd_mouse_event(pointer->x, pointer->y, 0, buttons_state);
|
||||
+}
|
||||
+
|
||||
+static const SpiceTabletInterface tablet_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_TABLET,
|
||||
+ .base.description = "tablet",
|
||||
+ .base.major_version = SPICE_INTERFACE_TABLET_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_TABLET_MINOR,
|
||||
+ .set_logical_size = tablet_set_logical_size,
|
||||
+ .position = tablet_position,
|
||||
+ .wheel = tablet_wheel,
|
||||
+ .buttons = tablet_buttons,
|
||||
+};
|
||||
+
|
||||
+static void mouse_mode_notifier(Notifier *notifier)
|
||||
+{
|
||||
+ QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode);
|
||||
+ bool is_absolute = kbd_mouse_is_absolute();
|
||||
+ bool has_absolute = kbd_mouse_has_absolute();
|
||||
+
|
||||
+ fprintf(stderr, "%s: absolute pointer: %s%s\n", __FUNCTION__,
|
||||
+ has_absolute ? "present" : "not available",
|
||||
+ is_absolute ? "+active" : "");
|
||||
+
|
||||
+ if (pointer->absolute == is_absolute)
|
||||
+ return;
|
||||
+
|
||||
+ if (is_absolute) {
|
||||
+ fprintf(stderr, "%s: using absolute pointer (client mode)\n", __FUNCTION__);
|
||||
+ spice_server_add_interface(spice_server, &pointer->tablet.base);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "%s: using relative pointer (server mode)\n", __FUNCTION__);
|
||||
+ spice_server_remove_interface(&pointer->tablet.base);
|
||||
+ }
|
||||
+ pointer->absolute = is_absolute;
|
||||
+}
|
||||
+
|
||||
void qemu_spice_input_init(void)
|
||||
{
|
||||
QemuSpiceKbd *kbd;
|
||||
- QemuSpiceMouse *mouse;
|
||||
+ QemuSpicePointer *pointer;
|
||||
|
||||
kbd = qemu_mallocz(sizeof(*kbd));
|
||||
kbd->sin.base.sif = &kbd_interface.base;
|
||||
spice_server_add_interface(spice_server, &kbd->sin.base);
|
||||
qemu_add_led_event_handler(kbd_leds, kbd);
|
||||
|
||||
- mouse = qemu_mallocz(sizeof(*mouse));
|
||||
- mouse->sin.base.sif = &mouse_interface.base;
|
||||
- spice_server_add_interface(spice_server, &mouse->sin.base);
|
||||
+ pointer = qemu_mallocz(sizeof(*pointer));
|
||||
+ pointer->mouse.base.sif = &mouse_interface.base;
|
||||
+ pointer->tablet.base.sif = &tablet_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &pointer->mouse.base);
|
||||
+
|
||||
+ pointer->absolute = false;
|
||||
+ pointer->mouse_mode.notify = mouse_mode_notifier;
|
||||
+ qemu_add_mouse_mode_change_notifier(&pointer->mouse_mode);
|
||||
+ mouse_mode_notifier(&pointer->mouse_mode);
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,28 +0,0 @@
|
||||
From 0920337756cdf82dcd585efb23ae18f8086696c8 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 24 Mar 2010 11:16:54 +0100
|
||||
Subject: [PATCH 09/39] vgabios update to 0.6c + pcibios patches.
|
||||
|
||||
---
|
||||
Makefile | 5 +++--
|
||||
1 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 3cd07e0..e40c9a2 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -154,8 +154,9 @@ ar de en-us fi fr-be hr it lv nl pl ru th \
|
||||
common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
|
||||
|
||||
ifdef INSTALL_BLOBS
|
||||
-BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
|
||||
-video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
|
||||
+BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
+vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-qxldev.bin \
|
||||
+ppc_rom.bin video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
|
||||
gpxe-eepro100-80861209.rom \
|
||||
gpxe-eepro100-80861229.rom \
|
||||
pxe-e1000.bin \
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,31 +0,0 @@
|
||||
From 6ac04dff1ee3932d2ef94c1e42f4e8208fbf92bf Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 6 May 2010 11:13:11 +0200
|
||||
Subject: [PATCH 10/39] switch stdvga to pci vgabios
|
||||
|
||||
---
|
||||
hw/vga-pci.c | 7 +++----
|
||||
1 files changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
|
||||
index 3907871..8e1ed35 100644
|
||||
--- a/hw/vga-pci.c
|
||||
+++ b/hw/vga-pci.c
|
||||
@@ -105,11 +105,10 @@ static int pci_vga_initfn(PCIDevice *dev)
|
||||
bios_total_size <<= 1;
|
||||
pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
|
||||
PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
|
||||
+ } else {
|
||||
+ if (dev->romfile == NULL)
|
||||
+ dev->romfile = qemu_strdup("vgabios-stdvga.bin");
|
||||
}
|
||||
-
|
||||
- vga_init_vbe(s);
|
||||
- /* ROM BIOS */
|
||||
- rom_add_vga(VGABIOS_FILENAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,50 +0,0 @@
|
||||
From 07cdc867f1e12a4e8b4096e7f1f3ffda2f4e7d02 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 6 May 2010 11:14:11 +0200
|
||||
Subject: [PATCH 11/39] switch vmware_vga to pci vgabios
|
||||
|
||||
---
|
||||
hw/vmware_vga.c | 7 +------
|
||||
1 files changed, 1 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
|
||||
index 12bff48..682f287 100644
|
||||
--- a/hw/vmware_vga.c
|
||||
+++ b/hw/vmware_vga.c
|
||||
@@ -114,14 +114,12 @@ struct pci_vmsvga_state_s {
|
||||
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
|
||||
# define SVGA_IO_MUL 1
|
||||
# define SVGA_FIFO_SIZE 0x10000
|
||||
-# define SVGA_MEM_BASE 0xe0000000
|
||||
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2
|
||||
#else
|
||||
# define SVGA_ID SVGA_ID_1
|
||||
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
|
||||
# define SVGA_IO_MUL 4
|
||||
# define SVGA_FIFO_SIZE 0x10000
|
||||
-# define SVGA_MEM_BASE 0xe0000000
|
||||
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA
|
||||
#endif
|
||||
|
||||
@@ -1171,10 +1169,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
|
||||
vga_init(&s->vga);
|
||||
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
|
||||
|
||||
- vga_init_vbe(&s->vga);
|
||||
-
|
||||
- rom_add_vga(VGABIOS_FILENAME);
|
||||
-
|
||||
vmsvga_reset(s);
|
||||
}
|
||||
|
||||
@@ -1272,6 +1266,7 @@ static PCIDeviceInfo vmsvga_info = {
|
||||
.qdev.size = sizeof(struct pci_vmsvga_state_s),
|
||||
.qdev.vmsd = &vmstate_vmware_vga,
|
||||
.init = pci_vmsvga_initfn,
|
||||
+ .romfile = "vgabios-vmware.bin",
|
||||
};
|
||||
|
||||
static void vmsvga_register(void)
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,61 +0,0 @@
|
||||
From a659f6b472d95503657ac68a52242ce769006f17 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 11 May 2010 22:28:44 +0200
|
||||
Subject: [PATCH 12/39] all vga: refuse hotplugging.
|
||||
|
||||
Try to pci hotplug a vga card, watch qemu die with hw_error().
|
||||
This patch fixes it.
|
||||
---
|
||||
hw/cirrus_vga.c | 4 ++++
|
||||
hw/vga-pci.c | 4 ++++
|
||||
hw/vmware_vga.c | 4 ++++
|
||||
3 files changed, 12 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
|
||||
index efa7a42..dadaa80 100644
|
||||
--- a/hw/cirrus_vga.c
|
||||
+++ b/hw/cirrus_vga.c
|
||||
@@ -3206,6 +3206,10 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
|
||||
uint8_t *pci_conf = d->dev.config;
|
||||
int device_id = CIRRUS_ID_CLGD5446;
|
||||
|
||||
+ if (dev->qdev.hotplugged) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
/* setup VGA */
|
||||
vga_common_init(&s->vga, VGA_RAM_SIZE);
|
||||
cirrus_init_common(s, device_id, 1);
|
||||
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
|
||||
index 8e1ed35..4e673a5 100644
|
||||
--- a/hw/vga-pci.c
|
||||
+++ b/hw/vga-pci.c
|
||||
@@ -81,6 +81,10 @@ static int pci_vga_initfn(PCIDevice *dev)
|
||||
VGACommonState *s = &d->vga;
|
||||
uint8_t *pci_conf = d->dev.config;
|
||||
|
||||
+ if (dev->qdev.hotplugged) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
// vga + console init
|
||||
vga_common_init(s, VGA_RAM_SIZE);
|
||||
vga_init(s);
|
||||
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
|
||||
index 682f287..7ff89aa 100644
|
||||
--- a/hw/vmware_vga.c
|
||||
+++ b/hw/vmware_vga.c
|
||||
@@ -1232,6 +1232,10 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
|
||||
struct pci_vmsvga_state_s *s =
|
||||
DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
|
||||
|
||||
+ if (dev->qdev.hotplugged) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
|
||||
pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
|
||||
pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,168 +0,0 @@
|
||||
From e0d06d42a83e7796b2c39ad6cab3630c0a8c2845 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 11 Mar 2010 11:13:32 -0300
|
||||
Subject: [PATCH 13/39] spice: tls support
|
||||
|
||||
Add options to the -spice command line switch to setup tls:
|
||||
|
||||
tls-port
|
||||
listening port
|
||||
|
||||
x509-dir
|
||||
x509 file directory. Expects same filenames as
|
||||
-vnc $display,x509=$dir
|
||||
|
||||
x509-key-file
|
||||
x509-key-password
|
||||
x509-cert-file
|
||||
x509-cacert-file
|
||||
x509-dh-key-file
|
||||
x509 files can also be set individually.
|
||||
|
||||
tls-ciphers
|
||||
which ciphers to use.
|
||||
---
|
||||
qemu-config.c | 24 ++++++++++++++++++++
|
||||
spice.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 86 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/qemu-config.c b/qemu-config.c
|
||||
index 8a894cf..74bfc62 100644
|
||||
--- a/qemu-config.c
|
||||
+++ b/qemu-config.c
|
||||
@@ -355,11 +355,35 @@ QemuOptsList qemu_spice_opts = {
|
||||
.name = "port",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
},{
|
||||
+ .name = "tls-port",
|
||||
+ .type = QEMU_OPT_NUMBER,
|
||||
+ },{
|
||||
.name = "password",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},{
|
||||
.name = "disable-ticketing",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
+ },{
|
||||
+ .name = "x509-dir",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-key-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-key-password",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-cert-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-cacert-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "x509-dh-key-file",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "tls-ciphers",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /* end if list */ }
|
||||
},
|
||||
diff --git a/spice.c b/spice.c
|
||||
index c763d52..3fe76cd 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "qemu-spice.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "qemu-queue.h"
|
||||
+#include "qemu-x509.h"
|
||||
#include "monitor.h"
|
||||
|
||||
/* core bits */
|
||||
@@ -126,18 +127,71 @@ static SpiceCoreInterface core_interface = {
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
- const char *password;
|
||||
- int port;
|
||||
+ const char *password, *str, *x509_dir,
|
||||
+ *x509_key_password = NULL,
|
||||
+ *x509_dh_file = NULL,
|
||||
+ *tls_ciphers = NULL;
|
||||
+ char *x509_key_file = NULL,
|
||||
+ *x509_cert_file = NULL,
|
||||
+ *x509_cacert_file = NULL;
|
||||
+ int port, tls_port, len;
|
||||
|
||||
if (!opts)
|
||||
return;
|
||||
port = qemu_opt_get_number(opts, "port", 0);
|
||||
- if (!port)
|
||||
+ tls_port = qemu_opt_get_number(opts, "tls-port", 0);
|
||||
+ if (!port && !tls_port)
|
||||
return;
|
||||
password = qemu_opt_get(opts, "password");
|
||||
|
||||
+ if (tls_port) {
|
||||
+ x509_dir = qemu_opt_get(opts, "x509-dir");
|
||||
+ if (NULL == x509_dir)
|
||||
+ x509_dir = ".";
|
||||
+ len = strlen(x509_dir) + 32;
|
||||
+
|
||||
+ str = qemu_opt_get(opts, "x509-key-file");
|
||||
+ if (str) {
|
||||
+ x509_key_file = qemu_strdup(str);
|
||||
+ } else {
|
||||
+ x509_key_file = qemu_malloc(len);
|
||||
+ snprintf(x509_key_file, len, "%s/%s", x509_dir, X509_SERVER_KEY_FILE);
|
||||
+ }
|
||||
+
|
||||
+ str = qemu_opt_get(opts, "x509-cert-file");
|
||||
+ if (str) {
|
||||
+ x509_cert_file = qemu_strdup(str);
|
||||
+ } else {
|
||||
+ x509_cert_file = qemu_malloc(len);
|
||||
+ snprintf(x509_cert_file, len, "%s/%s", x509_dir, X509_SERVER_CERT_FILE);
|
||||
+ }
|
||||
+
|
||||
+ str = qemu_opt_get(opts, "x509-cacert-file");
|
||||
+ if (str) {
|
||||
+ x509_cacert_file = qemu_strdup(str);
|
||||
+ } else {
|
||||
+ x509_cacert_file = qemu_malloc(len);
|
||||
+ snprintf(x509_cacert_file, len, "%s/%s", x509_dir, X509_CA_CERT_FILE);
|
||||
+ }
|
||||
+
|
||||
+ x509_key_password = qemu_opt_get(opts, "x509-key-password");
|
||||
+ x509_dh_file = qemu_opt_get(opts, "x509-dh-file");
|
||||
+ tls_ciphers = qemu_opt_get(opts, "tls-ciphers");
|
||||
+ }
|
||||
+
|
||||
spice_server = spice_server_new();
|
||||
- spice_server_set_port(spice_server, port);
|
||||
+ if (port) {
|
||||
+ spice_server_set_port(spice_server, port);
|
||||
+ }
|
||||
+ if (tls_port) {
|
||||
+ spice_server_set_tls(spice_server, tls_port,
|
||||
+ x509_cacert_file,
|
||||
+ x509_cert_file,
|
||||
+ x509_key_file,
|
||||
+ x509_key_password,
|
||||
+ x509_dh_file,
|
||||
+ tls_ciphers);
|
||||
+ }
|
||||
if (password)
|
||||
spice_server_set_ticket(spice_server, password, 0, 0, 0);
|
||||
if (qemu_opt_get_bool(opts, "disable-ticketing", 0))
|
||||
@@ -150,4 +204,8 @@ void qemu_spice_init(void)
|
||||
using_spice = 1;
|
||||
|
||||
qemu_spice_input_init();
|
||||
+
|
||||
+ qemu_free(x509_key_file);
|
||||
+ qemu_free(x509_cert_file);
|
||||
+ qemu_free(x509_cacert_file);
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,405 +0,0 @@
|
||||
From f3e02bc08c4521dc53d858174612341462d588ce Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 13 Apr 2010 10:34:46 +0200
|
||||
Subject: [PATCH 15/39] spice: add audio
|
||||
|
||||
Add support for the spice audio interface.
|
||||
|
||||
The driver is first in the driver list, but can_be_default is set only
|
||||
in case spice is active. So if you are using spice the spice audio
|
||||
driver is the default one, otherwise whatever comes first after spice in
|
||||
the list. Overriding the default using QEMU_AUDIO_DRV works in any
|
||||
case.
|
||||
---
|
||||
Makefile.objs | 1 +
|
||||
audio/audio.c | 3 +
|
||||
audio/audio_int.h | 1 +
|
||||
audio/spiceaudio.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
qemu-spice.h | 1 +
|
||||
spice.c | 1 +
|
||||
6 files changed, 319 insertions(+), 0 deletions(-)
|
||||
create mode 100644 audio/spiceaudio.c
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index d05643f..9a6b0f3 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -94,6 +94,7 @@ common-obj-$(CONFIG_SPICE) += spice.o spice-input.o spice-display.o
|
||||
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
|
||||
audio-obj-$(CONFIG_SDL) += sdlaudio.o
|
||||
audio-obj-$(CONFIG_OSS) += ossaudio.o
|
||||
+audio-obj-$(CONFIG_SPICE) += spiceaudio.o
|
||||
audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o
|
||||
audio-obj-$(CONFIG_ALSA) += alsaaudio.o
|
||||
audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o
|
||||
diff --git a/audio/audio.c b/audio/audio.c
|
||||
index ad51077..ade342e 100644
|
||||
--- a/audio/audio.c
|
||||
+++ b/audio/audio.c
|
||||
@@ -44,6 +44,9 @@
|
||||
that we generate the list.
|
||||
*/
|
||||
static struct audio_driver *drvtab[] = {
|
||||
+#ifdef CONFIG_SPICE
|
||||
+ &spice_audio_driver,
|
||||
+#endif
|
||||
CONFIG_AUDIO_DRIVERS
|
||||
&no_audio_driver,
|
||||
&wav_audio_driver
|
||||
diff --git a/audio/audio_int.h b/audio/audio_int.h
|
||||
index 06e313f..d1f6c2d 100644
|
||||
--- a/audio/audio_int.h
|
||||
+++ b/audio/audio_int.h
|
||||
@@ -209,6 +209,7 @@ extern struct audio_driver coreaudio_audio_driver;
|
||||
extern struct audio_driver dsound_audio_driver;
|
||||
extern struct audio_driver esd_audio_driver;
|
||||
extern struct audio_driver pa_audio_driver;
|
||||
+extern struct audio_driver spice_audio_driver;
|
||||
extern struct audio_driver winwave_audio_driver;
|
||||
extern struct mixeng_volume nominal_volume;
|
||||
|
||||
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
|
||||
new file mode 100644
|
||||
index 0000000..8ae7499
|
||||
--- /dev/null
|
||||
+++ b/audio/spiceaudio.c
|
||||
@@ -0,0 +1,312 @@
|
||||
+#include "hw/hw.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
+#define AUDIO_CAP "spice"
|
||||
+#include "audio.h"
|
||||
+#include "audio_int.h"
|
||||
+
|
||||
+#define LINE_IN_SAMPLES 1024
|
||||
+#define LINE_OUT_SAMPLES 1024
|
||||
+
|
||||
+typedef struct SpiceVoiceOut {
|
||||
+ HWVoiceOut hw;
|
||||
+ SpicePlaybackInstance sin;
|
||||
+ int64_t prev_ticks;
|
||||
+ int active;
|
||||
+ uint32_t *frame;
|
||||
+ uint32_t *fpos;
|
||||
+ uint32_t fsize;
|
||||
+} SpiceVoiceOut;
|
||||
+
|
||||
+typedef struct SpiceVoiceIn {
|
||||
+ HWVoiceIn hw;
|
||||
+ SpiceRecordInstance sin;
|
||||
+ int64_t prev_ticks;
|
||||
+ int active;
|
||||
+ uint32_t samples[LINE_IN_SAMPLES];
|
||||
+} SpiceVoiceIn;
|
||||
+
|
||||
+static const SpicePlaybackInterface playback_sif = {
|
||||
+ .base.type = SPICE_INTERFACE_PLAYBACK,
|
||||
+ .base.description = "playback",
|
||||
+ .base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR,
|
||||
+};
|
||||
+
|
||||
+static const SpiceRecordInterface record_sif = {
|
||||
+ .base.type = SPICE_INTERFACE_RECORD,
|
||||
+ .base.description = "record",
|
||||
+ .base.major_version = SPICE_INTERFACE_RECORD_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_RECORD_MINOR,
|
||||
+};
|
||||
+
|
||||
+static void *spice_audio_init(void)
|
||||
+{
|
||||
+ if (!using_spice) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return &spice_audio_init;
|
||||
+}
|
||||
+
|
||||
+static void spice_audio_fini(void *opaque)
|
||||
+{
|
||||
+ /* nothing */
|
||||
+}
|
||||
+
|
||||
+static int calculate_samples(struct audio_pcm_info *info, int64_t *old_ticks)
|
||||
+{
|
||||
+ int64_t now;
|
||||
+ int64_t ticks;
|
||||
+ int64_t bytes;
|
||||
+ int samples;
|
||||
+
|
||||
+ now = qemu_get_clock (vm_clock);
|
||||
+ ticks = now - *old_ticks;
|
||||
+ *old_ticks = now;
|
||||
+ bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
|
||||
+ bytes = audio_MIN (bytes, INT_MAX);
|
||||
+ samples = bytes >> info->shift;
|
||||
+ return samples;
|
||||
+}
|
||||
+
|
||||
+/* playback */
|
||||
+
|
||||
+static int line_out_init(HWVoiceOut *hw, struct audsettings *as)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+ struct audsettings settings;
|
||||
+
|
||||
+ settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ;
|
||||
+ settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN;
|
||||
+ settings.fmt = AUD_FMT_S16;
|
||||
+ settings.endianness = AUDIO_HOST_ENDIANNESS;
|
||||
+
|
||||
+ audio_pcm_init_info(&hw->info, &settings);
|
||||
+ hw->samples = LINE_OUT_SAMPLES;
|
||||
+ out->active = 0;
|
||||
+
|
||||
+ out->sin.base.sif = &playback_sif.base;
|
||||
+ spice_server_add_interface(spice_server, &out->sin.base);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void line_out_fini(HWVoiceOut *hw)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+
|
||||
+ spice_server_remove_interface(&out->sin.base);
|
||||
+}
|
||||
+
|
||||
+static int line_out_run(HWVoiceOut *hw, int live)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+ int rpos, decr;
|
||||
+ int samples;
|
||||
+
|
||||
+ if (!live) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ decr = calculate_samples(&hw->info, &out->prev_ticks);
|
||||
+ decr = audio_MIN(live, decr);
|
||||
+
|
||||
+ samples = decr;
|
||||
+ rpos = hw->rpos;
|
||||
+ while (samples) {
|
||||
+ int left_till_end_samples = hw->samples - rpos;
|
||||
+ int len = audio_MIN(samples, left_till_end_samples);
|
||||
+
|
||||
+ if (!out->frame) {
|
||||
+ spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize);
|
||||
+ out->fpos = out->frame;
|
||||
+ }
|
||||
+ if (out->frame) {
|
||||
+ len = audio_MIN(len, out->fsize);
|
||||
+ hw->clip(out->fpos, hw->mix_buf + rpos, len);
|
||||
+ out->fsize -= len;
|
||||
+ out->fpos += len;
|
||||
+ if (out->fsize == 0) {
|
||||
+ spice_server_playback_put_samples(&out->sin, out->frame);
|
||||
+ out->frame = out->fpos = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ rpos = (rpos + len) % hw->samples;
|
||||
+ samples -= len;
|
||||
+ }
|
||||
+ hw->rpos = rpos;
|
||||
+ return decr;
|
||||
+}
|
||||
+
|
||||
+static int line_out_write(SWVoiceOut *sw, void *buf, int len)
|
||||
+{
|
||||
+ return audio_pcm_sw_write(sw, buf, len);
|
||||
+}
|
||||
+
|
||||
+static int line_out_ctl(HWVoiceOut *hw, int cmd, ...)
|
||||
+{
|
||||
+ SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case VOICE_ENABLE:
|
||||
+ if (out->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ out->active = 1;
|
||||
+ out->prev_ticks = qemu_get_clock (vm_clock);
|
||||
+ spice_server_playback_start(&out->sin);
|
||||
+ break;
|
||||
+ case VOICE_DISABLE:
|
||||
+ if (!out->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ out->active = 0;
|
||||
+ if (out->frame) {
|
||||
+ memset(out->fpos, 0, out->fsize << 2);
|
||||
+ spice_server_playback_put_samples(&out->sin, out->frame);
|
||||
+ out->frame = out->fpos = NULL;
|
||||
+ }
|
||||
+ spice_server_playback_stop(&out->sin);
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* record */
|
||||
+
|
||||
+static int line_in_init(HWVoiceIn *hw, struct audsettings *as)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+ struct audsettings settings;
|
||||
+
|
||||
+ settings.freq = SPICE_INTERFACE_RECORD_FREQ;
|
||||
+ settings.nchannels = SPICE_INTERFACE_RECORD_CHAN;
|
||||
+ settings.fmt = AUD_FMT_S16;
|
||||
+ settings.endianness = AUDIO_HOST_ENDIANNESS;
|
||||
+
|
||||
+ audio_pcm_init_info(&hw->info, &settings);
|
||||
+ hw->samples = LINE_IN_SAMPLES;
|
||||
+ in->active = 0;
|
||||
+
|
||||
+ in->sin.base.sif = &record_sif.base;
|
||||
+ spice_server_add_interface(spice_server, &in->sin.base);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void line_in_fini(HWVoiceIn *hw)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+
|
||||
+ spice_server_remove_interface(&in->sin.base);
|
||||
+}
|
||||
+
|
||||
+static int line_in_run(HWVoiceIn *hw)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+ int num_samples;
|
||||
+ int ready;
|
||||
+ int len[2];
|
||||
+ uint64_t delta_samp;
|
||||
+ uint32_t *samples;
|
||||
+
|
||||
+ if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in(hw))) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ delta_samp = calculate_samples(&hw->info, &in->prev_ticks);
|
||||
+ num_samples = audio_MIN(num_samples, delta_samp);
|
||||
+
|
||||
+ ready = spice_server_record_get_samples(&in->sin, in->samples, num_samples);
|
||||
+ samples = in->samples;
|
||||
+ if (ready == 0) {
|
||||
+ static uint32_t silence[LINE_IN_SAMPLES];
|
||||
+ samples = silence;
|
||||
+ ready = LINE_IN_SAMPLES;
|
||||
+ }
|
||||
+
|
||||
+ num_samples = audio_MIN(ready, num_samples);
|
||||
+
|
||||
+ if (hw->wpos + num_samples > hw->samples) {
|
||||
+ len[0] = hw->samples - hw->wpos;
|
||||
+ len[1] = num_samples - len[0];
|
||||
+ } else {
|
||||
+ len[0] = num_samples;
|
||||
+ len[1] = 0;
|
||||
+ }
|
||||
+
|
||||
+ hw->conv(hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
|
||||
+
|
||||
+ if (len[1]) {
|
||||
+ hw->conv(hw->conv_buf, samples + len[0], len[1],
|
||||
+ &nominal_volume);
|
||||
+ }
|
||||
+
|
||||
+ hw->wpos = (hw->wpos + num_samples) % hw->samples;
|
||||
+
|
||||
+ return num_samples;
|
||||
+}
|
||||
+
|
||||
+static int line_in_read(SWVoiceIn *sw, void *buf, int size)
|
||||
+{
|
||||
+ return audio_pcm_sw_read(sw, buf, size);
|
||||
+}
|
||||
+
|
||||
+static int line_in_ctl(HWVoiceIn *hw, int cmd, ...)
|
||||
+{
|
||||
+ SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw);
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case VOICE_ENABLE:
|
||||
+ if (in->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ in->active = 1;
|
||||
+ in->prev_ticks = qemu_get_clock (vm_clock);
|
||||
+ spice_server_record_start(&in->sin);
|
||||
+ break;
|
||||
+ case VOICE_DISABLE:
|
||||
+ if (!in->active) {
|
||||
+ break;
|
||||
+ }
|
||||
+ in->active = 0;
|
||||
+ spice_server_record_stop(&in->sin);
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct audio_option audio_options[] = {
|
||||
+ { /* end of list */ },
|
||||
+};
|
||||
+
|
||||
+static struct audio_pcm_ops audio_callbacks = {
|
||||
+ .init_out = line_out_init,
|
||||
+ .fini_out = line_out_fini,
|
||||
+ .run_out = line_out_run,
|
||||
+ .write = line_out_write,
|
||||
+ .ctl_out = line_out_ctl,
|
||||
+
|
||||
+ .init_in = line_in_init,
|
||||
+ .fini_in = line_in_fini,
|
||||
+ .run_in = line_in_run,
|
||||
+ .read = line_in_read,
|
||||
+ .ctl_in = line_in_ctl,
|
||||
+};
|
||||
+
|
||||
+struct audio_driver spice_audio_driver = {
|
||||
+ .name = "spice",
|
||||
+ .descr = "spice audio driver",
|
||||
+ .options = audio_options,
|
||||
+ .init = spice_audio_init,
|
||||
+ .fini = spice_audio_fini,
|
||||
+ .pcm_ops = &audio_callbacks,
|
||||
+ .max_voices_out = 1,
|
||||
+ .max_voices_in = 1,
|
||||
+ .voice_size_out = sizeof(SpiceVoiceOut),
|
||||
+ .voice_size_in = sizeof(SpiceVoiceIn),
|
||||
+};
|
||||
+
|
||||
+void qemu_spice_audio_init(void)
|
||||
+{
|
||||
+ spice_audio_driver.can_be_default = 1;
|
||||
+}
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index f061004..6f19ba7 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -13,6 +13,7 @@ extern int using_spice;
|
||||
|
||||
void qemu_spice_init(void);
|
||||
void qemu_spice_input_init(void);
|
||||
+void qemu_spice_audio_init(void);
|
||||
void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
#else /* CONFIG_SPICE */
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 3fe76cd..fc76ef7 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -204,6 +204,7 @@ void qemu_spice_init(void)
|
||||
using_spice = 1;
|
||||
|
||||
qemu_spice_input_init();
|
||||
+ qemu_spice_audio_init();
|
||||
|
||||
qemu_free(x509_key_file);
|
||||
qemu_free(x509_cert_file);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,238 +0,0 @@
|
||||
From ebf4cebd082442ed2bc11475fde301c18648298d Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 20 Apr 2010 13:33:54 +0200
|
||||
Subject: [PATCH 16/39] spice: add virtio-serial based vdi port backend.
|
||||
|
||||
Adds the spicevmc device. This is a communication channel between the
|
||||
spice client and the guest. It is used to send display information and
|
||||
mouse events from the spice clients to the guest.
|
||||
---
|
||||
Makefile.target | 1 +
|
||||
hw/spice-vmc.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 204 insertions(+), 0 deletions(-)
|
||||
create mode 100644 hw/spice-vmc.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 4da33b5..90544c5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,6 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
new file mode 100644
|
||||
index 0000000..3f6a2bb
|
||||
--- /dev/null
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -0,0 +1,203 @@
|
||||
+/*
|
||||
+
|
||||
+ Spice Virtual Machine Channel (VMC).
|
||||
+
|
||||
+ A virtio-serial port used for spice to guest communication, over
|
||||
+ which spice client and a daemon in the guest operating system
|
||||
+ communicate.
|
||||
+
|
||||
+ Replaces the old vdi_port PCI device.
|
||||
+
|
||||
+*/
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+
|
||||
+#include "virtio-serial.h"
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
+#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
+#define VMC_DEVICE_NAME "spicevmc"
|
||||
+
|
||||
+#define dprintf(_svc, _level, _fmt, ...) \
|
||||
+ do { \
|
||||
+ if (_svc->debug >= _level) { \
|
||||
+ fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
+ } \
|
||||
+ } while (0)
|
||||
+
|
||||
+typedef struct SpiceVirtualChannel {
|
||||
+ VirtIOSerialPort port;
|
||||
+ VMChangeStateEntry *vmstate;
|
||||
+ SpiceVDIPortInstance sin;
|
||||
+ bool active;
|
||||
+ uint8_t *buffer;
|
||||
+ uint8_t *datapos;
|
||||
+ ssize_t bufsize, datalen;
|
||||
+ uint32_t debug;
|
||||
+} SpiceVirtualChannel;
|
||||
+
|
||||
+static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ ssize_t out;
|
||||
+
|
||||
+ out = virtio_serial_write(&svc->port, buf, len);
|
||||
+ dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ return out;
|
||||
+}
|
||||
+
|
||||
+static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ int bytes = MIN(len, svc->datalen);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
+ if (bytes) {
|
||||
+ memcpy(buf, svc->datapos, bytes);
|
||||
+ svc->datapos += bytes;
|
||||
+ svc->datalen -= bytes;
|
||||
+ if (0 == svc->datalen) {
|
||||
+ virtio_serial_throttle_port(&svc->port, false);
|
||||
+ }
|
||||
+ }
|
||||
+ return bytes;
|
||||
+}
|
||||
+
|
||||
+static SpiceVDIPortInterface vmc_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
+ .base.description = "spice virtual channel vdi port",
|
||||
+ .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
+ .write = vmc_write,
|
||||
+ .read = vmc_read,
|
||||
+};
|
||||
+
|
||||
+static void vmc_register_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ svc->sin.base.sif = &vmc_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &svc->sin.base);
|
||||
+ svc->active = true;
|
||||
+}
|
||||
+
|
||||
+static void vmc_unregister_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (!svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ spice_server_remove_interface(&svc->sin.base);
|
||||
+ svc->active = false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void vmc_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = opaque;
|
||||
+
|
||||
+ if (running && svc->active) {
|
||||
+ spice_server_vdi_port_wakeup(&svc->sin);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * virtio-serial callbacks
|
||||
+ */
|
||||
+
|
||||
+static void vmc_guest_open(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_register_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_close(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_ready(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ if (svc->active)
|
||||
+ spice_server_vdi_port_wakeup(&svc->sin);
|
||||
+}
|
||||
+
|
||||
+static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
+ assert(svc->datapos == 0);
|
||||
+ if (svc->bufsize < len) {
|
||||
+ svc->bufsize = len;
|
||||
+ svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
+ }
|
||||
+ memcpy(svc->buffer, buf, len);
|
||||
+ svc->datapos = svc->buffer;
|
||||
+ svc->datalen = len;
|
||||
+ virtio_serial_throttle_port(&svc->port, true);
|
||||
+ spice_server_vdi_port_wakeup(&svc->sin);
|
||||
+}
|
||||
+
|
||||
+static int vmc_initfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ if (!using_spice)
|
||||
+ return -1;
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
|
||||
+ svc->vmstate = qemu_add_vm_change_state_handler(
|
||||
+ vmc_change_state_handler, svc);
|
||||
+ virtio_serial_open(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vmc_exitfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+ qemu_del_vm_change_state_handler(svc->vmstate);
|
||||
+ virtio_serial_close(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VirtIOSerialPortInfo vmc_info = {
|
||||
+ .qdev.name = VMC_DEVICE_NAME,
|
||||
+ .qdev.size = sizeof(SpiceVirtualChannel),
|
||||
+ .init = vmc_initfn,
|
||||
+ .exit = vmc_exitfn,
|
||||
+ .guest_open = vmc_guest_open,
|
||||
+ .guest_close = vmc_guest_close,
|
||||
+ .guest_ready = vmc_guest_ready,
|
||||
+ .have_data = vmc_have_data,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
+ DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static void vmc_register(void)
|
||||
+{
|
||||
+ virtio_serial_port_qdev_register(&vmc_info);
|
||||
+}
|
||||
+device_init(vmc_register)
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,592 +0,0 @@
|
||||
From ee782dec6adaced9c5bb99d02253505fb635fa12 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 12 Mar 2010 16:26:18 +0100
|
||||
Subject: [PATCH 17/39] spice: add pci vdi port backend (obsolete).
|
||||
|
||||
This is *not* intended to be merged upstream. It is just here
|
||||
because the virtio-serial windows guest drivers are not ready,
|
||||
so you can't go with the new spice-vmc yet.
|
||||
---
|
||||
Makefile.target | 2 +-
|
||||
hw/spice-vdi.c | 556 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 557 insertions(+), 1 deletions(-)
|
||||
create mode 100644 hw/spice-vdi.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 90544c5..025bdb8 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,7 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
-obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o spice-vdi.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vdi.c b/hw/spice-vdi.c
|
||||
new file mode 100644
|
||||
index 0000000..23cbbe1
|
||||
--- /dev/null
|
||||
+++ b/hw/spice-vdi.c
|
||||
@@ -0,0 +1,556 @@
|
||||
+#include <pthread.h>
|
||||
+#include <signal.h>
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu-spice.h"
|
||||
+#include "hw/hw.h"
|
||||
+#include "hw/pc.h"
|
||||
+#include "hw/pci.h"
|
||||
+#include "console.h"
|
||||
+#include "hw/vga_int.h"
|
||||
+#include "qemu-timer.h"
|
||||
+#include "sysemu.h"
|
||||
+#include "console.h"
|
||||
+#include "pci.h"
|
||||
+#include "hw.h"
|
||||
+#include "cpu-common.h"
|
||||
+
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+#include <spice/ipc_ring.h>
|
||||
+#include <spice/barrier.h>
|
||||
+
|
||||
+#undef SPICE_RING_PROD_ITEM
|
||||
+#define SPICE_RING_PROD_ITEM(r, ret) { \
|
||||
+ typeof(r) start = r; \
|
||||
+ typeof(r) end = r + 1; \
|
||||
+ uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
|
||||
+ typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
|
||||
+ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
+ abort(); \
|
||||
+ } \
|
||||
+ ret = &m_item->el; \
|
||||
+ }
|
||||
+
|
||||
+#undef SPICE_RING_CONS_ITEM
|
||||
+#define SPICE_RING_CONS_ITEM(r, ret) { \
|
||||
+ typeof(r) start = r; \
|
||||
+ typeof(r) end = r + 1; \
|
||||
+ uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
|
||||
+ typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
|
||||
+ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
+ abort(); \
|
||||
+ } \
|
||||
+ ret = &m_item->el; \
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+#undef ALIGN
|
||||
+#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
|
||||
+
|
||||
+#define REDHAT_PCI_VENDOR_ID 0x1b36
|
||||
+#define VDI_PORT_DEVICE_ID 0x0105
|
||||
+#define VDI_PORT_REVISION 0x01
|
||||
+
|
||||
+#define VDI_PORT_INTERRUPT (1 << 0)
|
||||
+
|
||||
+#define VDI_PORT_MAGIC (*(uint32_t*)"VDIP")
|
||||
+
|
||||
+#define VDI_PORT_DEV_NAME "vdi_port"
|
||||
+#define VDI_PORT_SAVE_VERSION 20
|
||||
+
|
||||
+#include <spice/start-packed.h>
|
||||
+
|
||||
+typedef struct SPICE_ATTR_PACKED VDIPortPacket {
|
||||
+ uint32_t gen;
|
||||
+ uint32_t size;
|
||||
+ uint8_t data[512 - 2 * sizeof(uint32_t)];
|
||||
+} VDIPortPacket;
|
||||
+
|
||||
+SPICE_RING_DECLARE(VDIPortRing, VDIPortPacket, 32);
|
||||
+
|
||||
+enum {
|
||||
+ VDI_PORT_IO_RANGE_INDEX,
|
||||
+ VDI_PORT_RAM_RANGE_INDEX,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ VDI_PORT_IO_CONNECTION,
|
||||
+ VDI_PORT_IO_NOTIFY = 4,
|
||||
+ VDI_PORT_IO_UPDATE_IRQ = 8,
|
||||
+
|
||||
+ VDI_PORT_IO_RANGE_SIZE = 12
|
||||
+};
|
||||
+
|
||||
+typedef struct SPICE_ATTR_PACKED VDIPortRam {
|
||||
+ uint32_t magic;
|
||||
+ uint32_t generation;
|
||||
+ uint32_t int_pending;
|
||||
+ uint32_t int_mask;
|
||||
+ VDIPortRing input;
|
||||
+ VDIPortRing output;
|
||||
+ uint32_t reserv[32];
|
||||
+} VDIPortRam;
|
||||
+
|
||||
+#include <spice/end-packed.h>
|
||||
+
|
||||
+typedef struct PCIVDIPortDevice {
|
||||
+ PCIDevice pci_dev;
|
||||
+ uint32_t io_base;
|
||||
+ uint64_t ram_offset;
|
||||
+ uint32_t ram_size;
|
||||
+ VDIPortRam *ram;
|
||||
+ uint32_t connected;
|
||||
+ int running;
|
||||
+ int new_gen_on_resume;
|
||||
+ int active_interface;
|
||||
+ SpiceVDIPortInstance sin;
|
||||
+ int plug_read_pos;
|
||||
+} PCIVDIPortDevice;
|
||||
+
|
||||
+static int debug = 1;
|
||||
+
|
||||
+static inline uint32_t msb_mask(uint32_t val)
|
||||
+{
|
||||
+ uint32_t mask;
|
||||
+
|
||||
+ do {
|
||||
+ mask = ~(val - 1) & val;
|
||||
+ val &= ~mask;
|
||||
+ } while (mask < val);
|
||||
+
|
||||
+ return mask;
|
||||
+}
|
||||
+
|
||||
+static inline void atomic_or(uint32_t *var, uint32_t add)
|
||||
+{
|
||||
+ __asm__ __volatile__ ("lock; orl %1, %0" : "+m" (*var) : "r" (add) : "memory");
|
||||
+}
|
||||
+
|
||||
+static inline uint32_t atomic_exchange(uint32_t val, uint32_t *ptr)
|
||||
+{
|
||||
+ __asm__ __volatile__("xchgl %0, %1" : "+q"(val), "+m" (*ptr) : : "memory");
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
+static void set_dirty(void *base, ram_addr_t offset, void *start, uint32_t length)
|
||||
+{
|
||||
+ assert(start >= base);
|
||||
+
|
||||
+ ram_addr_t addr = (ram_addr_t)((uint8_t*)start - (uint8_t*)base) + offset;
|
||||
+ ram_addr_t end = ALIGN(addr + length, TARGET_PAGE_SIZE);
|
||||
+
|
||||
+ do {
|
||||
+ cpu_physical_memory_set_dirty(addr);
|
||||
+ addr += TARGET_PAGE_SIZE;
|
||||
+ } while ( addr < end );
|
||||
+}
|
||||
+
|
||||
+static inline void vdi_port_set_dirty(PCIVDIPortDevice *d, void *start, uint32_t length)
|
||||
+{
|
||||
+ set_dirty(d->ram, d->ram_offset, start, length);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_new_gen(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ d->ram->generation = (d->ram->generation + 1 == 0) ? 1 : d->ram->generation + 1;
|
||||
+ vdi_port_set_dirty(d, &d->ram->generation, sizeof(d->ram->generation));
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_irq_level(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ return !!(d->ram->int_pending & d->ram->int_mask);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_notify_guest(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ uint32_t events = VDI_PORT_INTERRUPT;
|
||||
+ uint32_t old_pending;
|
||||
+
|
||||
+ if (!d->connected) {
|
||||
+ return;
|
||||
+ }
|
||||
+ old_pending = __sync_fetch_and_or(&d->ram->int_pending, events);
|
||||
+ if ((old_pending & events) == events) {
|
||||
+ return;
|
||||
+ }
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+ vdi_port_set_dirty(d, &d->ram->int_pending, sizeof(d->ram->int_pending));
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_interface_write(SpiceVDIPortInstance *sin,
|
||||
+ const uint8_t *buf, int len)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
+ VDIPortRing *ring = &d->ram->output;
|
||||
+ int do_notify = false;
|
||||
+ int actual_write = 0;
|
||||
+ int l = len;
|
||||
+
|
||||
+ if (!d->running) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ while (len) {
|
||||
+ VDIPortPacket *packet;
|
||||
+ int notify;
|
||||
+ int wait;
|
||||
+
|
||||
+ SPICE_RING_PROD_WAIT(ring, wait);
|
||||
+ if (wait) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ SPICE_RING_PROD_ITEM(ring, packet);
|
||||
+ packet->gen = d->ram->generation;
|
||||
+ packet->size = MIN(len, sizeof(packet->data));
|
||||
+ memcpy(packet->data, buf, packet->size);
|
||||
+ vdi_port_set_dirty(d, packet, sizeof(*packet) - (sizeof(packet->data) - packet->size));
|
||||
+
|
||||
+ SPICE_RING_PUSH(ring, notify);
|
||||
+ do_notify = do_notify || notify;
|
||||
+ len -= packet->size;
|
||||
+ buf += packet->size;
|
||||
+ actual_write += packet->size;
|
||||
+ }
|
||||
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
+
|
||||
+ if (do_notify) {
|
||||
+ vdi_port_notify_guest(d);
|
||||
+ }
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_write, l);
|
||||
+ }
|
||||
+ return actual_write;
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_interface_read(SpiceVDIPortInstance *sin,
|
||||
+ uint8_t *buf, int len)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
+ VDIPortRing *ring = &d->ram->input;
|
||||
+ uint32_t gen = d->ram->generation;
|
||||
+ VDIPortPacket *packet;
|
||||
+ int do_notify = false;
|
||||
+ int actual_read = 0;
|
||||
+ int l = len;
|
||||
+
|
||||
+ if (!d->running) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ while (!SPICE_RING_IS_EMPTY(ring)) {
|
||||
+ int notify;
|
||||
+
|
||||
+ SPICE_RING_CONS_ITEM(ring, packet);
|
||||
+ if (packet->gen == gen) {
|
||||
+ break;
|
||||
+ }
|
||||
+ SPICE_RING_POP(ring, notify);
|
||||
+ do_notify = do_notify || notify;
|
||||
+ }
|
||||
+ while (len) {
|
||||
+ VDIPortPacket *packet;
|
||||
+ int wait;
|
||||
+ int now;
|
||||
+
|
||||
+ SPICE_RING_CONS_WAIT(ring, wait);
|
||||
+
|
||||
+ if (wait) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ SPICE_RING_CONS_ITEM(ring, packet);
|
||||
+ if (packet->size > sizeof(packet->data)) {
|
||||
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
+ printf("%s: bad packet size\n", __FUNCTION__);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ now = MIN(len, packet->size - d->plug_read_pos);
|
||||
+ memcpy(buf, packet->data + d->plug_read_pos, now);
|
||||
+ len -= now;
|
||||
+ buf += now;
|
||||
+ actual_read += now;
|
||||
+ if ((d->plug_read_pos += now) == packet->size) {
|
||||
+ int notify;
|
||||
+
|
||||
+ d->plug_read_pos = 0;
|
||||
+ SPICE_RING_POP(ring, notify);
|
||||
+ do_notify = do_notify || notify;
|
||||
+ }
|
||||
+ }
|
||||
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
+
|
||||
+ if (do_notify) {
|
||||
+ vdi_port_notify_guest(d);
|
||||
+ }
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_read, l);
|
||||
+ }
|
||||
+ return actual_read;
|
||||
+}
|
||||
+
|
||||
+static SpiceVDIPortInterface vdi_port_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
+ .base.description = "vdi port",
|
||||
+ .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
+
|
||||
+ .write = vdi_port_interface_write,
|
||||
+ .read = vdi_port_interface_read,
|
||||
+};
|
||||
+
|
||||
+static void vdi_port_register_interface(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (d->active_interface ) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
+ }
|
||||
+ d->sin.base.sif = &vdi_port_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &d->sin.base);
|
||||
+ d->active_interface = true;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_unregister_interface(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (!d->active_interface ) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
+ }
|
||||
+ spice_server_remove_interface(&d->sin.base);
|
||||
+ d->active_interface = false;
|
||||
+}
|
||||
+
|
||||
+static uint32_t vdi_port_dev_connect(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (d->connected) {
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: already connected\n", __FUNCTION__);
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+ vdi_port_new_gen(d);
|
||||
+ d->connected = true;
|
||||
+ vdi_port_register_interface(d);
|
||||
+ return d->ram->generation;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_dev_disconnect(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ if (!d->connected) {
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ d->connected = false;
|
||||
+ vdi_port_unregister_interface(d);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_dev_notify(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ spice_server_vdi_port_wakeup(&d->sin);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_write_dword(void *opaque, uint32_t addr, uint32_t val)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = opaque;
|
||||
+ uint32_t io_port = addr - d->io_base;
|
||||
+
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: addr 0x%x val 0x%x\n", __FUNCTION__, addr, val);
|
||||
+ }
|
||||
+ switch (io_port) {
|
||||
+ case VDI_PORT_IO_NOTIFY:
|
||||
+ if (!d->connected) {
|
||||
+ fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
+ return;
|
||||
+ }
|
||||
+ vdi_port_dev_notify(d);
|
||||
+ break;
|
||||
+ case VDI_PORT_IO_UPDATE_IRQ:
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+ break;
|
||||
+ case VDI_PORT_IO_CONNECTION:
|
||||
+ vdi_port_dev_disconnect(d);
|
||||
+ break;
|
||||
+ default:
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: unexpected addr 0x%x val 0x%x\n",
|
||||
+ __FUNCTION__, addr, val);
|
||||
+ }
|
||||
+ };
|
||||
+}
|
||||
+
|
||||
+static uint32_t vdi_port_read_dword(void *opaque, uint32_t addr)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = opaque;
|
||||
+ uint32_t io_port = addr - d->io_base;
|
||||
+
|
||||
+ if (debug > 1) {
|
||||
+ fprintf(stderr, "%s: addr 0x%x\n", __FUNCTION__, addr);
|
||||
+ }
|
||||
+ if (io_port == VDI_PORT_IO_CONNECTION) {
|
||||
+ return vdi_port_dev_connect(d);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "%s: unexpected addr 0x%x\n", __FUNCTION__, addr);
|
||||
+ }
|
||||
+ return 0xffffffff;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_io_map(PCIDevice *pci_dev, int region_num,
|
||||
+ pcibus_t addr, pcibus_t size, int type)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
+
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: base 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
+ }
|
||||
+ d->io_base = addr;
|
||||
+ register_ioport_write(addr, size, 4, vdi_port_write_dword, pci_dev);
|
||||
+ register_ioport_read(addr, size, 4, vdi_port_read_dword, pci_dev);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_ram_map(PCIDevice *pci_dev, int region_num,
|
||||
+ pcibus_t addr, pcibus_t size, int type)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
+
|
||||
+ if (debug) {
|
||||
+ fprintf(stderr, "%s: addr 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
+ }
|
||||
+
|
||||
+ assert((addr & (size - 1)) == 0);
|
||||
+ assert(size == d->ram_size);
|
||||
+
|
||||
+ cpu_register_physical_memory(addr, size, d->ram_offset | IO_MEM_RAM);
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_reset(PCIVDIPortDevice *d)
|
||||
+{
|
||||
+ memset(d->ram, 0, sizeof(*d->ram));
|
||||
+ SPICE_RING_INIT(&d->ram->input);
|
||||
+ SPICE_RING_INIT(&d->ram->output);
|
||||
+ d->ram->magic = VDI_PORT_MAGIC;
|
||||
+ d->ram->generation = 0;
|
||||
+ d->ram->int_pending = 0;
|
||||
+ d->ram->int_mask = 0;
|
||||
+ d->connected = false;
|
||||
+ d->plug_read_pos = 0;
|
||||
+ vdi_port_set_dirty(d, d->ram, sizeof(*d->ram));
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_reset_handler(DeviceState *dev)
|
||||
+{
|
||||
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev.qdev, dev);
|
||||
+
|
||||
+ if (d->connected) {
|
||||
+ vdi_port_dev_disconnect(d);
|
||||
+ }
|
||||
+
|
||||
+ vdi_port_reset(d);
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_pre_load(void* opaque)
|
||||
+{
|
||||
+ PCIVDIPortDevice* d = opaque;
|
||||
+
|
||||
+ vdi_port_unregister_interface(d);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_post_load(void* opaque,int version_id)
|
||||
+{
|
||||
+ PCIVDIPortDevice* d = opaque;
|
||||
+
|
||||
+ if (d->connected) {
|
||||
+ vdi_port_register_interface(d);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void vdi_port_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ PCIVDIPortDevice* d = opaque;
|
||||
+
|
||||
+ if (running) {
|
||||
+ d->running = true;
|
||||
+ if (d->new_gen_on_resume) {
|
||||
+ d->new_gen_on_resume = false;
|
||||
+ vdi_port_new_gen(d);
|
||||
+ vdi_port_notify_guest(d);
|
||||
+ }
|
||||
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
+ vdi_port_dev_notify(d);
|
||||
+ } else {
|
||||
+ d->running = false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int vdi_port_init(PCIDevice *dev)
|
||||
+{
|
||||
+ PCIVDIPortDevice *vdi = (PCIVDIPortDevice *)dev;
|
||||
+ uint8_t* config = vdi->pci_dev.config;
|
||||
+ uint32_t ram_size = msb_mask(sizeof(VDIPortRam) * 2 - 1);
|
||||
+
|
||||
+ vdi->ram_offset = qemu_ram_alloc(&vdi->pci_dev.qdev, "bar1", ram_size);
|
||||
+ vdi->ram = qemu_get_ram_ptr(vdi->ram_offset);
|
||||
+ vdi_port_reset(vdi);
|
||||
+ vdi->ram_size = ram_size;
|
||||
+ vdi->new_gen_on_resume = false;
|
||||
+ vdi->running = false;
|
||||
+
|
||||
+ pci_config_set_vendor_id(config, REDHAT_PCI_VENDOR_ID);
|
||||
+ pci_config_set_device_id(config, VDI_PORT_DEVICE_ID);
|
||||
+ pci_config_set_class(config, PCI_CLASS_COMMUNICATION_OTHER);
|
||||
+ pci_set_byte(&config[PCI_REVISION_ID], VDI_PORT_REVISION);
|
||||
+ pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
|
||||
+
|
||||
+ pci_register_bar(dev, VDI_PORT_IO_RANGE_INDEX,
|
||||
+ msb_mask(VDI_PORT_IO_RANGE_SIZE * 2 - 1),
|
||||
+ PCI_BASE_ADDRESS_SPACE_IO, vdi_port_io_map);
|
||||
+
|
||||
+ pci_register_bar(dev, VDI_PORT_RAM_RANGE_INDEX,
|
||||
+ vdi->ram_size , PCI_BASE_ADDRESS_SPACE_MEMORY,
|
||||
+ vdi_port_ram_map);
|
||||
+
|
||||
+ qemu_add_vm_change_state_handler(vdi_port_vm_change_state_handler, vdi);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VMStateDescription vdi_port_vmstate = {
|
||||
+ .name = VDI_PORT_DEV_NAME,
|
||||
+ .version_id = VDI_PORT_SAVE_VERSION,
|
||||
+ .minimum_version_id = VDI_PORT_SAVE_VERSION,
|
||||
+ .pre_load = vdi_port_pre_load,
|
||||
+ .post_load = vdi_port_post_load,
|
||||
+ .fields = (VMStateField []) {
|
||||
+ VMSTATE_PCI_DEVICE(pci_dev, PCIVDIPortDevice),
|
||||
+ VMSTATE_UINT32(connected, PCIVDIPortDevice),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static PCIDeviceInfo vdi_port_info = {
|
||||
+ .qdev.name = VDI_PORT_DEV_NAME,
|
||||
+ .qdev.desc = "spice virtual desktop port (obsolete)",
|
||||
+ .qdev.size = sizeof(PCIVDIPortDevice),
|
||||
+ .qdev.vmsd = &vdi_port_vmstate,
|
||||
+ .qdev.reset = vdi_port_reset_handler,
|
||||
+
|
||||
+ .init = vdi_port_init,
|
||||
+};
|
||||
+
|
||||
+static void vdi_port_register(void)
|
||||
+{
|
||||
+ pci_qdev_register(&vdi_port_info);
|
||||
+}
|
||||
+
|
||||
+device_init(vdi_port_register);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,29 +0,0 @@
|
||||
From 898303cfd535d76ce971f3ac1310696937fbd286 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 09:53:48 +0200
|
||||
Subject: [PATCH 18/39] use memalign instead of posix_memalign
|
||||
|
||||
---
|
||||
osdep.c | 5 +++++
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/osdep.c b/osdep.c
|
||||
index 2375a69..ed2fd40 100644
|
||||
--- a/osdep.c
|
||||
+++ b/osdep.c
|
||||
@@ -100,7 +100,12 @@ void *qemu_memalign(size_t alignment, size_t size)
|
||||
#if defined(_POSIX_C_SOURCE) && !defined(__sun__)
|
||||
int ret;
|
||||
void *ptr;
|
||||
+#if 0
|
||||
ret = posix_memalign(&ptr, alignment, size);
|
||||
+#else
|
||||
+ ptr = memalign(alignment, size);
|
||||
+ ret = (ptr == NULL) ? -1 : 0;
|
||||
+#endif
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Failed to allocate %zu B: %s\n",
|
||||
size, strerror(ret));
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,179 +0,0 @@
|
||||
From 80b1dac2be1487d31e6766abe2359fcff1bf0481 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 23 Apr 2010 13:28:21 +0200
|
||||
Subject: [PATCH 19/39] spice: live migration (wip).
|
||||
|
||||
Handle spice client migration, i.e. inform a spice client connected
|
||||
about the new host and connection parameters, so it can move over the
|
||||
connection automatically.
|
||||
---
|
||||
monitor.c | 1 +
|
||||
qemu-monitor.hx | 11 +++++++
|
||||
qemu-spice.h | 2 +
|
||||
spice.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 101 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index e51df62..6674a8c 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "osdep.h"
|
||||
#include "exec-all.h"
|
||||
#include "qemu-kvm.h"
|
||||
+#include "qemu-spice.h"
|
||||
|
||||
//#define DEBUG
|
||||
//#define DEBUG_COMPLETION
|
||||
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
|
||||
index da7b796..c2570d9 100644
|
||||
--- a/qemu-monitor.hx
|
||||
+++ b/qemu-monitor.hx
|
||||
@@ -2510,6 +2510,17 @@ ETEXI
|
||||
|
||||
HXCOMM DO NOT add new commands after 'info', move your addition before it!
|
||||
|
||||
+#if defined(CONFIG_SPICE)
|
||||
+ {
|
||||
+ .name = "spice_migrate_info",
|
||||
+ .args_type = "hostname:s,port:i?,tls-port:i?,cert-subject:s?",
|
||||
+ .params = "hostname port tls-port cert-subject",
|
||||
+ .help = "send migration info to spice client",
|
||||
+ .user_print = monitor_user_noop,
|
||||
+ .mhandler.cmd_new = mon_spice_migrate,
|
||||
+ },
|
||||
+#endif
|
||||
+
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index 6f19ba7..3c8e959 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -16,6 +16,8 @@ void qemu_spice_input_init(void);
|
||||
void qemu_spice_audio_init(void);
|
||||
void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
+int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
+
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
#define using_spice 0
|
||||
diff --git a/spice.c b/spice.c
|
||||
index fc76ef7..1109b4f 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-x509.h"
|
||||
#include "monitor.h"
|
||||
+#include "hw/hw.h"
|
||||
|
||||
/* core bits */
|
||||
|
||||
@@ -122,8 +123,90 @@ static SpiceCoreInterface core_interface = {
|
||||
.watch_remove = watch_remove,
|
||||
};
|
||||
|
||||
+/* handle client migration */
|
||||
+
|
||||
+static int spice_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
|
||||
+{
|
||||
+ static int last_stage;
|
||||
+ static int migrate_client, client_connected;
|
||||
+ int ret = 1;
|
||||
+
|
||||
+ if (last_stage != stage) {
|
||||
+ last_stage = stage;
|
||||
+ fprintf(stderr, "%s: stage %d\n", __FUNCTION__, stage);
|
||||
+ } else {
|
||||
+ fprintf(stderr, ".");
|
||||
+ }
|
||||
+
|
||||
+ switch (stage) {
|
||||
+ case 1:
|
||||
+ migrate_client = 1;
|
||||
+ client_connected = 0;
|
||||
+ fprintf(stderr, "%s: start client migration\n", __FUNCTION__);
|
||||
+ if (spice_server_migrate_start(spice_server) != 0) {
|
||||
+ fprintf(stderr, "%s: fail -> no client migration\n", __FUNCTION__);
|
||||
+ migrate_client = 0;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ if (!migrate_client)
|
||||
+ break;
|
||||
+ switch (spice_server_migrate_client_state(spice_server)) {
|
||||
+ case SPICE_MIGRATE_CLIENT_NONE:
|
||||
+ fprintf(stderr, "%s: no client connected\n", __FUNCTION__);
|
||||
+ migrate_client = 0;
|
||||
+ break;
|
||||
+ case SPICE_MIGRATE_CLIENT_WAITING:
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ case SPICE_MIGRATE_CLIENT_READY:
|
||||
+ if (!client_connected) {
|
||||
+ fprintf(stderr, "%s: client connected to target\n", __FUNCTION__);
|
||||
+ client_connected = 1;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ if (migrate_client && client_connected) {
|
||||
+ fprintf(stderr, "%s: finish client migration\n", __FUNCTION__);
|
||||
+ spice_server_migrate_end(spice_server, 1);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void spice_save(QEMUFile *f, void *opaque)
|
||||
+{
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+}
|
||||
+
|
||||
+static int spice_load(QEMUFile *f, void *opaque, int version_id)
|
||||
+{
|
||||
+ fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* functions for the rest of qemu */
|
||||
|
||||
+int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
+{
|
||||
+ const char *hostname = qdict_get_str(qdict, "hostname");
|
||||
+ const char *subject = qdict_get_try_str(qdict, "cert-subject");
|
||||
+ int port = qdict_get_try_int(qdict, "port", -1);
|
||||
+ int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
|
||||
+
|
||||
+ if (!spice_server) {
|
||||
+ qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* TODO: Convert to QError */
|
||||
+ return spice_server_migrate_info(spice_server, hostname,
|
||||
+ port, tls_port, subject);
|
||||
+}
|
||||
+
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
@@ -206,6 +289,10 @@ void qemu_spice_init(void)
|
||||
qemu_spice_input_init();
|
||||
qemu_spice_audio_init();
|
||||
|
||||
+ register_savevm_live(NULL, "spice", -1, 1, NULL,
|
||||
+ spice_live, spice_save, spice_load,
|
||||
+ spice_server);
|
||||
+
|
||||
qemu_free(x509_key_file);
|
||||
qemu_free(x509_cert_file);
|
||||
qemu_free(x509_cacert_file);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,23 +0,0 @@
|
||||
From 7241cc479a0f4a148ae60336add6d7be80da9ff0 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 14:11:18 +0200
|
||||
Subject: [PATCH 20/39] spice-display: draw.h is internal now
|
||||
|
||||
---
|
||||
spice-display.h | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/spice-display.h b/spice-display.h
|
||||
index 70a7be4..b55e7ea 100644
|
||||
--- a/spice-display.h
|
||||
+++ b/spice-display.h
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <spice/ipc_ring.h>
|
||||
-#include <spice/draw.h>
|
||||
+#include <spice/enums.h>
|
||||
#include <spice/qxl_dev.h>
|
||||
|
||||
#include "pflib.h"
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,25 +0,0 @@
|
||||
From c269c8b87769b25c9d69d40944de0e883458af86 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 14:31:10 +0200
|
||||
Subject: [PATCH 21/39] spice-display: disable debug
|
||||
|
||||
---
|
||||
spice-display.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
index a749e64..2291cc7 100644
|
||||
--- a/spice-display.c
|
||||
+++ b/spice-display.c
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "spice-display.h"
|
||||
|
||||
-static int debug = 1;
|
||||
+static int debug = 0;
|
||||
|
||||
int qemu_spice_rect_is_empty(const QXLRect* r)
|
||||
{
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,27 +0,0 @@
|
||||
From 2912f038b4bfddd4c3dacb3b0102e45553859632 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 16:29:15 +0200
|
||||
Subject: [PATCH 22/39] spice-display: pci rev fixups
|
||||
|
||||
---
|
||||
spice-display.c | 4 ----
|
||||
1 files changed, 0 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/spice-display.c b/spice-display.c
|
||||
index 2291cc7..87a71cd 100644
|
||||
--- a/spice-display.c
|
||||
+++ b/spice-display.c
|
||||
@@ -334,10 +334,6 @@ static const QXLInterface dpy_interface = {
|
||||
.base.major_version = SPICE_INTERFACE_QXL_MAJOR,
|
||||
.base.minor_version = SPICE_INTERFACE_QXL_MINOR,
|
||||
|
||||
- .pci_vendor = REDHAT_PCI_VENDOR_ID,
|
||||
- .pci_id = QXL_DEVICE_ID,
|
||||
- .pci_revision = QXL_REVISION,
|
||||
-
|
||||
.attache_worker = interface_attach_worker,
|
||||
.set_compression_level = interface_set_compression_level,
|
||||
.set_mm_time = interface_set_mm_time,
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,52 +0,0 @@
|
||||
From 727553e1a33dccab2b27ee5e184e003440765289 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 16:29:27 +0200
|
||||
Subject: [PATCH 23/39] qxl: pci rev fixups
|
||||
|
||||
---
|
||||
hw/qxl.c | 20 ++++++++------------
|
||||
1 files changed, 8 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 475360c..2a0ea4e 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -511,10 +511,6 @@ static const QXLInterface qxl_interface = {
|
||||
.base.major_version = SPICE_INTERFACE_QXL_MAJOR,
|
||||
.base.minor_version = SPICE_INTERFACE_QXL_MINOR,
|
||||
|
||||
- .pci_vendor = REDHAT_PCI_VENDOR_ID,
|
||||
- .pci_id = QXL_DEVICE_ID,
|
||||
- .pci_revision = QXL_REVISION,
|
||||
-
|
||||
.attache_worker = interface_attach_worker,
|
||||
.set_compression_level = interface_set_compression_level,
|
||||
.set_mm_time = interface_set_mm_time,
|
||||
@@ -1136,16 +1132,16 @@ static int qxl_init(PCIDevice *dev)
|
||||
qxl->generation = 1;
|
||||
|
||||
switch (qxl->revision) {
|
||||
- case 1: /* qxl-1 */
|
||||
- pci_device_id = 0x0100;
|
||||
- pci_device_rev = 1;
|
||||
+ case 1: /* spice 0.4 -- qxl-1 */
|
||||
+ pci_device_id = QXL_DEVICE_ID_STABLE;
|
||||
+ pci_device_rev = QXL_REVISION_STABLE_V04;
|
||||
break;
|
||||
- case 2: /* qxl-2 */
|
||||
- pci_device_id = 0x0100;
|
||||
- pci_device_rev = 2;
|
||||
+ case 2: /* spice 0.6 -- qxl-2 */
|
||||
+ pci_device_id = QXL_DEVICE_ID_STABLE;
|
||||
+ pci_device_rev = QXL_REVISION_STABLE_V06;
|
||||
break;
|
||||
- default: /* unstable */
|
||||
- pci_device_id = 0x01ff;
|
||||
+ default: /* experimental */
|
||||
+ pci_device_id = QXL_DEVICE_ID_DEVEL;
|
||||
pci_device_rev = 1;
|
||||
break;
|
||||
}
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,26 +0,0 @@
|
||||
From c9f9044475d392e55de4dd6e343477ce1a57eabc Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 8 Jul 2010 17:51:09 +0200
|
||||
Subject: [PATCH 24/39] qxl: support QXL_IO_DESTROY_ALL_SURFACES
|
||||
|
||||
---
|
||||
hw/qxl.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 2a0ea4e..7bd4467 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -930,6 +930,9 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
case QXL_IO_DESTROY_SURFACE_WAIT:
|
||||
d->ssd.worker->destroy_surface_wait(d->ssd.worker, val);
|
||||
break;
|
||||
+ case QXL_IO_DESTROY_ALL_SURFACES:
|
||||
+ d->ssd.worker->destroy_surfaces(d->ssd.worker);
|
||||
+ break;
|
||||
default:
|
||||
fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port);
|
||||
abort();
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,57 +0,0 @@
|
||||
From c8fa37e075cf59e8b21af9211f6a6348c92ed098 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Mon, 12 Jul 2010 22:48:59 +0300
|
||||
Subject: [PATCH 25/39] spice-vmc: two bugfixes in vmc_read
|
||||
|
||||
* throttling with no discard means possible recursion, make
|
||||
vmc_read handle that.
|
||||
* zero datapos when data is done (from rhel6 version)
|
||||
---
|
||||
hw/spice-vmc.c | 13 ++++++++-----
|
||||
1 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 3f6a2bb..06e30e6 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -45,7 +45,7 @@ static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
ssize_t out;
|
||||
|
||||
out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -54,13 +54,16 @@ static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
int bytes = MIN(len, svc->datalen);
|
||||
|
||||
- dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
- if (bytes) {
|
||||
+ dprintf(svc, 2, "%s: %p %d/%d/%zd\n", __func__, svc->datapos, len, bytes, svc->datalen);
|
||||
+ if (bytes > 0) {
|
||||
memcpy(buf, svc->datapos, bytes);
|
||||
svc->datapos += bytes;
|
||||
svc->datalen -= bytes;
|
||||
- if (0 == svc->datalen) {
|
||||
+ assert(svc->datalen >= 0);
|
||||
+ if (svc->datalen == 0) {
|
||||
+ svc->datapos = 0;
|
||||
virtio_serial_throttle_port(&svc->port, false);
|
||||
+ // ^^^ !!! may call vmc_have_data, so don't touch svc after it!
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
@@ -140,7 +143,7 @@ static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len
|
||||
SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
|
||||
dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
- assert(svc->datapos == 0);
|
||||
+ assert(svc->datalen == 0);
|
||||
if (svc->bufsize < len) {
|
||||
svc->bufsize = len;
|
||||
svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,84 +0,0 @@
|
||||
From 0045574847883167f5c2b569811e049616ee611d Mon Sep 17 00:00:00 2001
|
||||
From: Yonit Halperin <yhalperi@redhat.com>
|
||||
Date: Wed, 14 Jul 2010 13:26:34 +0300
|
||||
Subject: [PATCH 26/39] spice: enabling/disabling jpeg and zlib-over-glz via spice command line args
|
||||
|
||||
---
|
||||
qemu-config.c | 6 ++++++
|
||||
spice.c | 29 +++++++++++++++++++++++++++++
|
||||
2 files changed, 35 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/qemu-config.c b/qemu-config.c
|
||||
index 74bfc62..3e4fcf9 100644
|
||||
--- a/qemu-config.c
|
||||
+++ b/qemu-config.c
|
||||
@@ -384,6 +384,12 @@ QemuOptsList qemu_spice_opts = {
|
||||
},{
|
||||
.name = "tls-ciphers",
|
||||
.type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "jpeg",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
+ },{
|
||||
+ .name = "zlib-glz",
|
||||
+ .type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /* end if list */ }
|
||||
},
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 1109b4f..201e53c 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -207,6 +207,23 @@ int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
port, tls_port, subject);
|
||||
}
|
||||
|
||||
+static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
+{
|
||||
+ if (!strcmp(str, "wan")) {
|
||||
+ return SPICE_WAN_COMPRESSION_AUTO;
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp(str, "never")) {
|
||||
+ return SPICE_WAN_COMPRESSION_NEVER;
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp(str, "always")) {
|
||||
+ return SPICE_WAN_COMPRESSION_ALWAYS;
|
||||
+ }
|
||||
+
|
||||
+ return SPICE_WAN_COMPRESSION_INVALID;
|
||||
+}
|
||||
+
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||
@@ -218,6 +235,7 @@ void qemu_spice_init(void)
|
||||
*x509_cert_file = NULL,
|
||||
*x509_cacert_file = NULL;
|
||||
int port, tls_port, len;
|
||||
+ const char *jpeg, *zlib_glz;
|
||||
|
||||
if (!opts)
|
||||
return;
|
||||
@@ -283,6 +301,17 @@ void qemu_spice_init(void)
|
||||
/* TODO: make configurable via cmdline */
|
||||
spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
|
||||
|
||||
+ jpeg = qemu_opt_get(opts, "jpeg");
|
||||
+ zlib_glz = qemu_opt_get(opts, "zlib-glz");
|
||||
+
|
||||
+ if (jpeg) {
|
||||
+ spice_server_set_jpeg_compression(spice_server, get_wan_compression_value(jpeg));
|
||||
+ }
|
||||
+
|
||||
+ if (zlib_glz) {
|
||||
+ spice_server_set_zlib_glz_compression(spice_server, get_wan_compression_value(zlib_glz));
|
||||
+ }
|
||||
+
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
using_spice = 1;
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,57 +0,0 @@
|
||||
From 9200133d24ee5b5dab71ce922882c3534d9e8a5a Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 15 Jul 2010 09:01:28 +0200
|
||||
Subject: [PATCH 27/39] ifdef new config options.
|
||||
|
||||
---
|
||||
spice.c | 6 +++++-
|
||||
1 files changed, 5 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 201e53c..76e6ac1 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -207,6 +207,7 @@ int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
port, tls_port, subject);
|
||||
}
|
||||
|
||||
+#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
|
||||
static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
{
|
||||
if (!strcmp(str, "wan")) {
|
||||
@@ -223,6 +224,7 @@ static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
|
||||
return SPICE_WAN_COMPRESSION_INVALID;
|
||||
}
|
||||
+#endif
|
||||
|
||||
void qemu_spice_init(void)
|
||||
{
|
||||
@@ -235,7 +237,6 @@ void qemu_spice_init(void)
|
||||
*x509_cert_file = NULL,
|
||||
*x509_cacert_file = NULL;
|
||||
int port, tls_port, len;
|
||||
- const char *jpeg, *zlib_glz;
|
||||
|
||||
if (!opts)
|
||||
return;
|
||||
@@ -301,6 +302,8 @@ void qemu_spice_init(void)
|
||||
/* TODO: make configurable via cmdline */
|
||||
spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
|
||||
|
||||
+#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
|
||||
+ const char *jpeg, *zlib_glz;
|
||||
jpeg = qemu_opt_get(opts, "jpeg");
|
||||
zlib_glz = qemu_opt_get(opts, "zlib-glz");
|
||||
|
||||
@@ -311,6 +314,7 @@ void qemu_spice_init(void)
|
||||
if (zlib_glz) {
|
||||
spice_server_set_zlib_glz_compression(spice_server, get_wan_compression_value(zlib_glz));
|
||||
}
|
||||
+#endif
|
||||
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
using_spice = 1;
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,27 +0,0 @@
|
||||
From 2165916a311108d39c7aa45e5189af26712234b8 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Wed, 14 Jul 2010 16:30:35 +0300
|
||||
Subject: [PATCH 28/39] spice-vmc: add counter to debug statements
|
||||
|
||||
---
|
||||
hw/spice-vmc.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 06e30e6..041f243 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -23,8 +23,9 @@
|
||||
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
+ static unsigned __dprintf_counter = 0; \
|
||||
if (_svc->debug >= _level) { \
|
||||
- fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
+ fprintf(stderr, "svc: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,53 +0,0 @@
|
||||
From f86c044ae075d142e658e866572eb0a37ecad2e1 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Thu, 22 Jul 2010 00:21:18 +0300
|
||||
Subject: [PATCH 29/39] spice-vmc: split vmc_write to max sized virtio_serial_write calls
|
||||
|
||||
workaround for current windows driver limitation (RHBZ 617000)
|
||||
---
|
||||
hw/spice-vmc.c | 21 ++++++++++++++++++---
|
||||
1 files changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 041f243..b9d64a2 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -21,6 +21,8 @@
|
||||
#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
#define VMC_DEVICE_NAME "spicevmc"
|
||||
|
||||
+#define VMC_MAX_HOST_WRITE 2048
|
||||
+
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
static unsigned __dprintf_counter = 0; \
|
||||
@@ -43,10 +45,23 @@ typedef struct SpiceVirtualChannel {
|
||||
static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
{
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- ssize_t out;
|
||||
+ ssize_t out = 0;
|
||||
+ ssize_t last_out;
|
||||
+ uint8_t* p = (uint8_t*)buf;
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ last_out = virtio_serial_write(&svc->port, p,
|
||||
+ MIN(len, VMC_MAX_HOST_WRITE));
|
||||
+ if (last_out > 0) {
|
||||
+ out += last_out;
|
||||
+ len -= last_out;
|
||||
+ p += last_out;
|
||||
+ } else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ dprintf(svc, 3, "%s: %lu/%zd\n", __func__, out, len + out);
|
||||
return out;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,24 +0,0 @@
|
||||
From be78cc4a136f8ec63dc6d7efd8356625c639a877 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Tue, 3 Aug 2010 11:37:51 +0300
|
||||
Subject: [PATCH 30/39] qxl: add 800x480 resolution to qxl_modes (n900 native)
|
||||
|
||||
---
|
||||
hw/qxl.c | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 7bd4467..86c0e03 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -64,6 +64,7 @@
|
||||
|
||||
static QXLMode qxl_modes[] = {
|
||||
QXL_MODE_EX(640, 480),
|
||||
+ QXL_MODE_EX(800, 480),
|
||||
QXL_MODE_EX(800, 600),
|
||||
QXL_MODE_EX(832, 624),
|
||||
QXL_MODE_EX(1024, 768),
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,259 +0,0 @@
|
||||
From e55e5fd43113a5b266efa6d17e44f0e9231a98ed Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 25 Aug 2010 16:08:37 +0000
|
||||
Subject: [PATCH 31/39] qxl: savevm fixes
|
||||
|
||||
---
|
||||
hw/qxl.c | 125 +++++++++++++++++++++++++++++++++++++++++++++----------------
|
||||
hw/qxl.h | 6 +++
|
||||
2 files changed, 98 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 86c0e03..4a15200 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1087,6 +1087,14 @@ static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
{
|
||||
PCIQXLDevice *qxl = opaque;
|
||||
qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
|
||||
+
|
||||
+ if (!running && qxl->mode == QXL_MODE_NATIVE) {
|
||||
+ /* dirty all vram (which holds surfaces) to make sure it is saved */
|
||||
+ /* FIXME #1: should go out during "live" stage */
|
||||
+ /* FIXME #2: we only need to save the areas which are actually used */
|
||||
+ ram_addr_t addr = qxl->vram_offset;
|
||||
+ qxl_set_dirty(addr, addr + qxl->vram_size);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* display change listener */
|
||||
@@ -1134,6 +1142,8 @@ static int qxl_init(PCIDevice *dev)
|
||||
qxl->id = device_id;
|
||||
qxl->mode = QXL_MODE_UNDEFINED;
|
||||
qxl->generation = 1;
|
||||
+ qxl->num_memslots = NUM_MEMSLOTS;
|
||||
+ qxl->num_surfaces = NUM_SURFACES;
|
||||
|
||||
switch (qxl->revision) {
|
||||
case 1: /* spice 0.4 -- qxl-1 */
|
||||
@@ -1183,7 +1193,8 @@ static int qxl_init(PCIDevice *dev)
|
||||
if (ram_size < 16 * 1024 * 1024)
|
||||
ram_size = 16 * 1024 * 1024;
|
||||
qxl->vga.vram_size = ram_size;
|
||||
- qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar0", qxl->vga.vram_size);
|
||||
+ qxl->vga.vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vgavram",
|
||||
+ qxl->vga.vram_size);
|
||||
qxl->vga.vram_ptr = qemu_get_ram_ptr(qxl->vga.vram_offset);
|
||||
|
||||
pci_config_set_class(config, PCI_CLASS_DISPLAY_OTHER);
|
||||
@@ -1195,14 +1206,14 @@ static int qxl_init(PCIDevice *dev)
|
||||
pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
|
||||
|
||||
qxl->rom_size = qxl_rom_size();
|
||||
- qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar2", qxl->rom_size);
|
||||
+ qxl->rom_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vrom", qxl->rom_size);
|
||||
init_qxl_rom(qxl);
|
||||
init_qxl_ram(qxl);
|
||||
|
||||
if (qxl->vram_size < 16 * 1024 * 1024)
|
||||
qxl->vram_size = 16 * 1024 * 1024;
|
||||
qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
|
||||
- qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "bar1", qxl->vram_size);
|
||||
+ qxl->vram_offset = qemu_ram_alloc(&qxl->pci.qdev, "qxl.vram", qxl->vram_size);
|
||||
|
||||
pci_register_bar(&qxl->pci, QXL_IO_RANGE_INDEX,
|
||||
msb_mask(QXL_IO_RANGE_SIZE * 2 - 1),
|
||||
@@ -1237,14 +1248,12 @@ static void qxl_pre_save(void *opaque)
|
||||
uint8_t *ram_start = d->vga.vram_ptr;
|
||||
|
||||
dprintf(d, 1, "%s:\n", __FUNCTION__);
|
||||
-#if 1 /* wanna zap this */
|
||||
if (d->last_release == NULL) {
|
||||
d->last_release_offset = 0;
|
||||
} else {
|
||||
d->last_release_offset = (uint8_t *)d->last_release - ram_start;
|
||||
}
|
||||
assert(d->last_release_offset < d->vga.vram_size);
|
||||
-#endif
|
||||
}
|
||||
|
||||
static int qxl_pre_load(void *opaque)
|
||||
@@ -1306,29 +1315,55 @@ static int qxl_post_load(void *opaque, int version)
|
||||
}
|
||||
dprintf(d, 1, "%s: done\n", __FUNCTION__);
|
||||
|
||||
-#if 1 /* wanna zap this */
|
||||
- if (d->last_release_offset >= d->vga.vram_size) {
|
||||
- dprintf(d, 1, "%s: invalid last_release_offset %u, ram_size %u\n",
|
||||
- __FUNCTION__, d->last_release_offset, d->vga.vram_size);
|
||||
- exit(-1);
|
||||
- }
|
||||
-
|
||||
+ assert(d->last_release_offset < d->vga.vram_size);
|
||||
if (d->last_release_offset == 0) {
|
||||
d->last_release = NULL;
|
||||
} else {
|
||||
d->last_release = (QXLReleaseInfo *)(ram_start + d->last_release_offset);
|
||||
}
|
||||
-#endif
|
||||
+
|
||||
+ /* spice 0.4 compatibility -- accept but ignore */
|
||||
+ free(d->worker_data);
|
||||
+ d->worker_data = NULL;
|
||||
+ d->worker_data_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-#define QXL_VER 1
|
||||
+#define QXL_SAVE_VERSION 20
|
||||
+
|
||||
+static bool qxl_test_worker_data(void *opaque, int version_id)
|
||||
+{
|
||||
+ PCIQXLDevice* d = opaque;
|
||||
+
|
||||
+ if (d->revision != 1) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!d->worker_data_size) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!d->worker_data) {
|
||||
+ d->worker_data = qemu_malloc(d->worker_data_size);
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool qxl_test_spice04(void *opaque, int version_id)
|
||||
+{
|
||||
+ PCIQXLDevice* d = opaque;
|
||||
+ return d->revision == 1;
|
||||
+}
|
||||
+
|
||||
+static bool qxl_test_spice06(void *opaque)
|
||||
+{
|
||||
+ PCIQXLDevice* d = opaque;
|
||||
+ return d->revision > 1;
|
||||
+}
|
||||
|
||||
static VMStateDescription qxl_memslot = {
|
||||
.name = "qxl-memslot",
|
||||
- .version_id = QXL_VER,
|
||||
- .minimum_version_id = QXL_VER,
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(slot.mem_start, struct guest_slots),
|
||||
VMSTATE_UINT64(slot.mem_end, struct guest_slots),
|
||||
@@ -1339,8 +1374,8 @@ static VMStateDescription qxl_memslot = {
|
||||
|
||||
static VMStateDescription qxl_surface = {
|
||||
.name = "qxl-surface",
|
||||
- .version_id = QXL_VER,
|
||||
- .minimum_version_id = QXL_VER,
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(width, QXLSurfaceCreate),
|
||||
VMSTATE_UINT32(height, QXLSurfaceCreate),
|
||||
@@ -1355,34 +1390,58 @@ static VMStateDescription qxl_surface = {
|
||||
}
|
||||
};
|
||||
|
||||
+static VMStateDescription qxl_vmstate_spice06 = {
|
||||
+ .name = "qxl/spice06",
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
+ .fields = (VMStateField []) {
|
||||
+ VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
|
||||
+ VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
|
||||
+ qxl_memslot, struct guest_slots),
|
||||
+ VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
|
||||
+ qxl_surface, QXLSurfaceCreate),
|
||||
+ VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
|
||||
+ VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
|
||||
+ vmstate_info_uint64, uint64_t),
|
||||
+ VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static VMStateDescription qxl_vmstate = {
|
||||
.name = "qxl",
|
||||
- .version_id = QXL_VER,
|
||||
- .minimum_version_id = QXL_VER,
|
||||
+ .version_id = QXL_SAVE_VERSION,
|
||||
+ .minimum_version_id = QXL_SAVE_VERSION,
|
||||
.pre_save = qxl_pre_save,
|
||||
.pre_load = qxl_pre_load,
|
||||
.post_load = qxl_post_load,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
|
||||
- VMSTATE_STRUCT(vga, PCIQXLDevice, QXL_VER, vmstate_vga_common, VGACommonState),
|
||||
+ VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
|
||||
VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
|
||||
-#if 1 /* wanna zap this */
|
||||
VMSTATE_UINT32(num_free_res, PCIQXLDevice),
|
||||
VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
|
||||
-#endif
|
||||
VMSTATE_UINT32(mode, PCIQXLDevice),
|
||||
VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
|
||||
-#if 1 /* new stuff */
|
||||
- VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, QXL_VER,
|
||||
- qxl_memslot, struct guest_slots),
|
||||
- VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, QXL_VER,
|
||||
- qxl_surface, QXLSurfaceCreate),
|
||||
- VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, QXL_VER,
|
||||
- vmstate_info_uint64, uint64_t),
|
||||
- VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
|
||||
-#endif
|
||||
+
|
||||
+ /* spice 0.4 sends/expects them */
|
||||
+ VMSTATE_VBUFFER_UINT32(vga.vram_ptr, PCIQXLDevice, 0, qxl_test_spice04, 0,
|
||||
+ vga.vram_size),
|
||||
+ VMSTATE_UINT32_TEST(worker_data_size, PCIQXLDevice, qxl_test_spice04),
|
||||
+ VMSTATE_VBUFFER_UINT32(worker_data, PCIQXLDevice, 0, qxl_test_worker_data, 0,
|
||||
+ worker_data_size),
|
||||
+
|
||||
VMSTATE_END_OF_LIST()
|
||||
- }
|
||||
+ },
|
||||
+ .subsections = (VMStateSubsection[]) {
|
||||
+ {
|
||||
+ /* additional spice 0.6 state */
|
||||
+ .vmsd = &qxl_vmstate_spice06,
|
||||
+ .needed = qxl_test_spice06,
|
||||
+ },{
|
||||
+ /* end of list */
|
||||
+ },
|
||||
+ },
|
||||
};
|
||||
|
||||
static PCIDeviceInfo qxl_info = {
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index 1216405..caf3684 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -24,6 +24,9 @@ typedef struct PCIQXLDevice {
|
||||
int generation;
|
||||
uint32_t revision;
|
||||
|
||||
+ int32_t num_memslots;
|
||||
+ int32_t num_surfaces;
|
||||
+
|
||||
struct guest_slots {
|
||||
QXLMemSlot slot;
|
||||
void *ptr;
|
||||
@@ -74,6 +77,9 @@ typedef struct PCIQXLDevice {
|
||||
/* io bar */
|
||||
uint32_t io_base;
|
||||
|
||||
+ /* spice 0.4 loadvm compatibility */
|
||||
+ void *worker_data;
|
||||
+ uint32_t worker_data_size;
|
||||
} PCIQXLDevice;
|
||||
|
||||
#define PANIC_ON(x) if ((x)) { \
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,53 +0,0 @@
|
||||
From f48f184b9d22bbd2e34fb4f3a7a760f0e98fae64 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:45:30 +0200
|
||||
Subject: [PATCH 32/39] Revert "spice-vmc: split vmc_write to max sized virtio_serial_write calls"
|
||||
|
||||
This reverts commit 380b75548db5116e538dc646e84bceb1c4b0e61b.
|
||||
---
|
||||
hw/spice-vmc.c | 21 +++------------------
|
||||
1 files changed, 3 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index b9d64a2..041f243 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -21,8 +21,6 @@
|
||||
#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
#define VMC_DEVICE_NAME "spicevmc"
|
||||
|
||||
-#define VMC_MAX_HOST_WRITE 2048
|
||||
-
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
static unsigned __dprintf_counter = 0; \
|
||||
@@ -45,23 +43,10 @@ typedef struct SpiceVirtualChannel {
|
||||
static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
{
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- ssize_t out = 0;
|
||||
- ssize_t last_out;
|
||||
- uint8_t* p = (uint8_t*)buf;
|
||||
-
|
||||
- while (len > 0) {
|
||||
- last_out = virtio_serial_write(&svc->port, p,
|
||||
- MIN(len, VMC_MAX_HOST_WRITE));
|
||||
- if (last_out > 0) {
|
||||
- out += last_out;
|
||||
- len -= last_out;
|
||||
- p += last_out;
|
||||
- } else {
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
+ ssize_t out;
|
||||
|
||||
- dprintf(svc, 3, "%s: %lu/%zd\n", __func__, out, len + out);
|
||||
+ out = virtio_serial_write(&svc->port, buf, len);
|
||||
+ dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
return out;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,28 +0,0 @@
|
||||
From a5d6e7e76bf5f5fb0e2c8232ddca2b850bfc1afa Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:45:49 +0200
|
||||
Subject: [PATCH 33/39] Revert "spice-vmc: add counter to debug statements"
|
||||
|
||||
This reverts commit f3ab5192a20ee9dc7776b13ec0ba75030bb52a20.
|
||||
---
|
||||
hw/spice-vmc.c | 3 +--
|
||||
1 files changed, 1 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 041f243..06e30e6 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -23,9 +23,8 @@
|
||||
|
||||
#define dprintf(_svc, _level, _fmt, ...) \
|
||||
do { \
|
||||
- static unsigned __dprintf_counter = 0; \
|
||||
if (_svc->debug >= _level) { \
|
||||
- fprintf(stderr, "svc: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
|
||||
+ fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,55 +0,0 @@
|
||||
From 84115ef1adf343c34eebfb1045cbc5c72892e3b2 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:46:18 +0200
|
||||
Subject: [PATCH 34/39] Revert "spice-vmc: two bugfixes in vmc_read"
|
||||
|
||||
This reverts commit 71983a37e30c68beab5e9056a4600d2958f77a04.
|
||||
---
|
||||
hw/spice-vmc.c | 13 +++++--------
|
||||
1 files changed, 5 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
index 06e30e6..3f6a2bb 100644
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -45,7 +45,7 @@ static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
ssize_t out;
|
||||
|
||||
out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 3, "%s: %lu/%d\n", __func__, out, len);
|
||||
+ dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -54,16 +54,13 @@ static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
int bytes = MIN(len, svc->datalen);
|
||||
|
||||
- dprintf(svc, 2, "%s: %p %d/%d/%zd\n", __func__, svc->datapos, len, bytes, svc->datalen);
|
||||
- if (bytes > 0) {
|
||||
+ dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
+ if (bytes) {
|
||||
memcpy(buf, svc->datapos, bytes);
|
||||
svc->datapos += bytes;
|
||||
svc->datalen -= bytes;
|
||||
- assert(svc->datalen >= 0);
|
||||
- if (svc->datalen == 0) {
|
||||
- svc->datapos = 0;
|
||||
+ if (0 == svc->datalen) {
|
||||
virtio_serial_throttle_port(&svc->port, false);
|
||||
- // ^^^ !!! may call vmc_have_data, so don't touch svc after it!
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
@@ -143,7 +140,7 @@ static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len
|
||||
SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
|
||||
dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
- assert(svc->datalen == 0);
|
||||
+ assert(svc->datapos == 0);
|
||||
if (svc->bufsize < len) {
|
||||
svc->bufsize = len;
|
||||
svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,181 +0,0 @@
|
||||
From 3e0d1b6ed5f8e8b871803337008e104398e4db0a Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:48:57 +0200
|
||||
Subject: [PATCH 35/39] Revert "spice: live migration (wip)."
|
||||
|
||||
This reverts commit 85b9db9ba993af737c9c402cf2f67db7b1b3cbce.
|
||||
|
||||
Conflicts:
|
||||
|
||||
spice.c
|
||||
---
|
||||
monitor.c | 1 -
|
||||
qemu-monitor.hx | 11 -------
|
||||
qemu-spice.h | 2 -
|
||||
spice.c | 87 -------------------------------------------------------
|
||||
4 files changed, 0 insertions(+), 101 deletions(-)
|
||||
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index 6674a8c..e51df62 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -57,7 +57,6 @@
|
||||
#include "osdep.h"
|
||||
#include "exec-all.h"
|
||||
#include "qemu-kvm.h"
|
||||
-#include "qemu-spice.h"
|
||||
|
||||
//#define DEBUG
|
||||
//#define DEBUG_COMPLETION
|
||||
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
|
||||
index c2570d9..da7b796 100644
|
||||
--- a/qemu-monitor.hx
|
||||
+++ b/qemu-monitor.hx
|
||||
@@ -2510,17 +2510,6 @@ ETEXI
|
||||
|
||||
HXCOMM DO NOT add new commands after 'info', move your addition before it!
|
||||
|
||||
-#if defined(CONFIG_SPICE)
|
||||
- {
|
||||
- .name = "spice_migrate_info",
|
||||
- .args_type = "hostname:s,port:i?,tls-port:i?,cert-subject:s?",
|
||||
- .params = "hostname port tls-port cert-subject",
|
||||
- .help = "send migration info to spice client",
|
||||
- .user_print = monitor_user_noop,
|
||||
- .mhandler.cmd_new = mon_spice_migrate,
|
||||
- },
|
||||
-#endif
|
||||
-
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
diff --git a/qemu-spice.h b/qemu-spice.h
|
||||
index 3c8e959..6f19ba7 100644
|
||||
--- a/qemu-spice.h
|
||||
+++ b/qemu-spice.h
|
||||
@@ -16,8 +16,6 @@ void qemu_spice_input_init(void);
|
||||
void qemu_spice_audio_init(void);
|
||||
void qemu_spice_display_init(DisplayState *ds);
|
||||
|
||||
-int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
-
|
||||
#else /* CONFIG_SPICE */
|
||||
|
||||
#define using_spice 0
|
||||
diff --git a/spice.c b/spice.c
|
||||
index 76e6ac1..e6f047d 100644
|
||||
--- a/spice.c
|
||||
+++ b/spice.c
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "qemu-queue.h"
|
||||
#include "qemu-x509.h"
|
||||
#include "monitor.h"
|
||||
-#include "hw/hw.h"
|
||||
|
||||
/* core bits */
|
||||
|
||||
@@ -123,90 +122,8 @@ static SpiceCoreInterface core_interface = {
|
||||
.watch_remove = watch_remove,
|
||||
};
|
||||
|
||||
-/* handle client migration */
|
||||
-
|
||||
-static int spice_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
|
||||
-{
|
||||
- static int last_stage;
|
||||
- static int migrate_client, client_connected;
|
||||
- int ret = 1;
|
||||
-
|
||||
- if (last_stage != stage) {
|
||||
- last_stage = stage;
|
||||
- fprintf(stderr, "%s: stage %d\n", __FUNCTION__, stage);
|
||||
- } else {
|
||||
- fprintf(stderr, ".");
|
||||
- }
|
||||
-
|
||||
- switch (stage) {
|
||||
- case 1:
|
||||
- migrate_client = 1;
|
||||
- client_connected = 0;
|
||||
- fprintf(stderr, "%s: start client migration\n", __FUNCTION__);
|
||||
- if (spice_server_migrate_start(spice_server) != 0) {
|
||||
- fprintf(stderr, "%s: fail -> no client migration\n", __FUNCTION__);
|
||||
- migrate_client = 0;
|
||||
- }
|
||||
- break;
|
||||
- case 2:
|
||||
- if (!migrate_client)
|
||||
- break;
|
||||
- switch (spice_server_migrate_client_state(spice_server)) {
|
||||
- case SPICE_MIGRATE_CLIENT_NONE:
|
||||
- fprintf(stderr, "%s: no client connected\n", __FUNCTION__);
|
||||
- migrate_client = 0;
|
||||
- break;
|
||||
- case SPICE_MIGRATE_CLIENT_WAITING:
|
||||
- ret = 0;
|
||||
- break;
|
||||
- case SPICE_MIGRATE_CLIENT_READY:
|
||||
- if (!client_connected) {
|
||||
- fprintf(stderr, "%s: client connected to target\n", __FUNCTION__);
|
||||
- client_connected = 1;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- break;
|
||||
- case 3:
|
||||
- if (migrate_client && client_connected) {
|
||||
- fprintf(stderr, "%s: finish client migration\n", __FUNCTION__);
|
||||
- spice_server_migrate_end(spice_server, 1);
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static void spice_save(QEMUFile *f, void *opaque)
|
||||
-{
|
||||
- fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
-}
|
||||
-
|
||||
-static int spice_load(QEMUFile *f, void *opaque, int version_id)
|
||||
-{
|
||||
- fprintf(stderr, "%s:\n", __FUNCTION__);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
/* functions for the rest of qemu */
|
||||
|
||||
-int mon_spice_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
-{
|
||||
- const char *hostname = qdict_get_str(qdict, "hostname");
|
||||
- const char *subject = qdict_get_try_str(qdict, "cert-subject");
|
||||
- int port = qdict_get_try_int(qdict, "port", -1);
|
||||
- int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
|
||||
-
|
||||
- if (!spice_server) {
|
||||
- qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* TODO: Convert to QError */
|
||||
- return spice_server_migrate_info(spice_server, hostname,
|
||||
- port, tls_port, subject);
|
||||
-}
|
||||
-
|
||||
#if defined(SPICE_SERVER_VERSION) && SPICE_SERVER_VERSION >= 0x000503
|
||||
static inline spice_wan_compression_t get_wan_compression_value(const char *str)
|
||||
{
|
||||
@@ -322,10 +239,6 @@ void qemu_spice_init(void)
|
||||
qemu_spice_input_init();
|
||||
qemu_spice_audio_init();
|
||||
|
||||
- register_savevm_live(NULL, "spice", -1, 1, NULL,
|
||||
- spice_live, spice_save, spice_load,
|
||||
- spice_server);
|
||||
-
|
||||
qemu_free(x509_key_file);
|
||||
qemu_free(x509_cert_file);
|
||||
qemu_free(x509_cacert_file);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,590 +0,0 @@
|
||||
From 7bad8970dd7db3e3e0e0b11626656c68f4238884 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:49:22 +0200
|
||||
Subject: [PATCH 36/39] Revert "spice: add pci vdi port backend (obsolete)."
|
||||
|
||||
This reverts commit b56a2ed131bdb4ce42db8f33f87603c416e7a60a.
|
||||
---
|
||||
Makefile.target | 2 +-
|
||||
hw/spice-vdi.c | 556 -------------------------------------------------------
|
||||
2 files changed, 1 insertions(+), 557 deletions(-)
|
||||
delete mode 100644 hw/spice-vdi.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 025bdb8..90544c5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,7 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
-obj-i386-$(CONFIG_SPICE) += spice-vmc.o spice-vdi.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vdi.c b/hw/spice-vdi.c
|
||||
deleted file mode 100644
|
||||
index 23cbbe1..0000000
|
||||
--- a/hw/spice-vdi.c
|
||||
+++ /dev/null
|
||||
@@ -1,556 +0,0 @@
|
||||
-#include <pthread.h>
|
||||
-#include <signal.h>
|
||||
-
|
||||
-#include "qemu-common.h"
|
||||
-#include "qemu-spice.h"
|
||||
-#include "hw/hw.h"
|
||||
-#include "hw/pc.h"
|
||||
-#include "hw/pci.h"
|
||||
-#include "console.h"
|
||||
-#include "hw/vga_int.h"
|
||||
-#include "qemu-timer.h"
|
||||
-#include "sysemu.h"
|
||||
-#include "console.h"
|
||||
-#include "pci.h"
|
||||
-#include "hw.h"
|
||||
-#include "cpu-common.h"
|
||||
-
|
||||
-#include <spice.h>
|
||||
-#include <spice-experimental.h>
|
||||
-#include <spice/ipc_ring.h>
|
||||
-#include <spice/barrier.h>
|
||||
-
|
||||
-#undef SPICE_RING_PROD_ITEM
|
||||
-#define SPICE_RING_PROD_ITEM(r, ret) { \
|
||||
- typeof(r) start = r; \
|
||||
- typeof(r) end = r + 1; \
|
||||
- uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
|
||||
- typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
|
||||
- if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
- abort(); \
|
||||
- } \
|
||||
- ret = &m_item->el; \
|
||||
- }
|
||||
-
|
||||
-#undef SPICE_RING_CONS_ITEM
|
||||
-#define SPICE_RING_CONS_ITEM(r, ret) { \
|
||||
- typeof(r) start = r; \
|
||||
- typeof(r) end = r + 1; \
|
||||
- uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
|
||||
- typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
|
||||
- if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||
- abort(); \
|
||||
- } \
|
||||
- ret = &m_item->el; \
|
||||
- }
|
||||
-
|
||||
-
|
||||
-#undef ALIGN
|
||||
-#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
|
||||
-
|
||||
-#define REDHAT_PCI_VENDOR_ID 0x1b36
|
||||
-#define VDI_PORT_DEVICE_ID 0x0105
|
||||
-#define VDI_PORT_REVISION 0x01
|
||||
-
|
||||
-#define VDI_PORT_INTERRUPT (1 << 0)
|
||||
-
|
||||
-#define VDI_PORT_MAGIC (*(uint32_t*)"VDIP")
|
||||
-
|
||||
-#define VDI_PORT_DEV_NAME "vdi_port"
|
||||
-#define VDI_PORT_SAVE_VERSION 20
|
||||
-
|
||||
-#include <spice/start-packed.h>
|
||||
-
|
||||
-typedef struct SPICE_ATTR_PACKED VDIPortPacket {
|
||||
- uint32_t gen;
|
||||
- uint32_t size;
|
||||
- uint8_t data[512 - 2 * sizeof(uint32_t)];
|
||||
-} VDIPortPacket;
|
||||
-
|
||||
-SPICE_RING_DECLARE(VDIPortRing, VDIPortPacket, 32);
|
||||
-
|
||||
-enum {
|
||||
- VDI_PORT_IO_RANGE_INDEX,
|
||||
- VDI_PORT_RAM_RANGE_INDEX,
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- VDI_PORT_IO_CONNECTION,
|
||||
- VDI_PORT_IO_NOTIFY = 4,
|
||||
- VDI_PORT_IO_UPDATE_IRQ = 8,
|
||||
-
|
||||
- VDI_PORT_IO_RANGE_SIZE = 12
|
||||
-};
|
||||
-
|
||||
-typedef struct SPICE_ATTR_PACKED VDIPortRam {
|
||||
- uint32_t magic;
|
||||
- uint32_t generation;
|
||||
- uint32_t int_pending;
|
||||
- uint32_t int_mask;
|
||||
- VDIPortRing input;
|
||||
- VDIPortRing output;
|
||||
- uint32_t reserv[32];
|
||||
-} VDIPortRam;
|
||||
-
|
||||
-#include <spice/end-packed.h>
|
||||
-
|
||||
-typedef struct PCIVDIPortDevice {
|
||||
- PCIDevice pci_dev;
|
||||
- uint32_t io_base;
|
||||
- uint64_t ram_offset;
|
||||
- uint32_t ram_size;
|
||||
- VDIPortRam *ram;
|
||||
- uint32_t connected;
|
||||
- int running;
|
||||
- int new_gen_on_resume;
|
||||
- int active_interface;
|
||||
- SpiceVDIPortInstance sin;
|
||||
- int plug_read_pos;
|
||||
-} PCIVDIPortDevice;
|
||||
-
|
||||
-static int debug = 1;
|
||||
-
|
||||
-static inline uint32_t msb_mask(uint32_t val)
|
||||
-{
|
||||
- uint32_t mask;
|
||||
-
|
||||
- do {
|
||||
- mask = ~(val - 1) & val;
|
||||
- val &= ~mask;
|
||||
- } while (mask < val);
|
||||
-
|
||||
- return mask;
|
||||
-}
|
||||
-
|
||||
-static inline void atomic_or(uint32_t *var, uint32_t add)
|
||||
-{
|
||||
- __asm__ __volatile__ ("lock; orl %1, %0" : "+m" (*var) : "r" (add) : "memory");
|
||||
-}
|
||||
-
|
||||
-static inline uint32_t atomic_exchange(uint32_t val, uint32_t *ptr)
|
||||
-{
|
||||
- __asm__ __volatile__("xchgl %0, %1" : "+q"(val), "+m" (*ptr) : : "memory");
|
||||
- return val;
|
||||
-}
|
||||
-
|
||||
-static void set_dirty(void *base, ram_addr_t offset, void *start, uint32_t length)
|
||||
-{
|
||||
- assert(start >= base);
|
||||
-
|
||||
- ram_addr_t addr = (ram_addr_t)((uint8_t*)start - (uint8_t*)base) + offset;
|
||||
- ram_addr_t end = ALIGN(addr + length, TARGET_PAGE_SIZE);
|
||||
-
|
||||
- do {
|
||||
- cpu_physical_memory_set_dirty(addr);
|
||||
- addr += TARGET_PAGE_SIZE;
|
||||
- } while ( addr < end );
|
||||
-}
|
||||
-
|
||||
-static inline void vdi_port_set_dirty(PCIVDIPortDevice *d, void *start, uint32_t length)
|
||||
-{
|
||||
- set_dirty(d->ram, d->ram_offset, start, length);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_new_gen(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- d->ram->generation = (d->ram->generation + 1 == 0) ? 1 : d->ram->generation + 1;
|
||||
- vdi_port_set_dirty(d, &d->ram->generation, sizeof(d->ram->generation));
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_irq_level(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- return !!(d->ram->int_pending & d->ram->int_mask);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_notify_guest(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- uint32_t events = VDI_PORT_INTERRUPT;
|
||||
- uint32_t old_pending;
|
||||
-
|
||||
- if (!d->connected) {
|
||||
- return;
|
||||
- }
|
||||
- old_pending = __sync_fetch_and_or(&d->ram->int_pending, events);
|
||||
- if ((old_pending & events) == events) {
|
||||
- return;
|
||||
- }
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
- vdi_port_set_dirty(d, &d->ram->int_pending, sizeof(d->ram->int_pending));
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_interface_write(SpiceVDIPortInstance *sin,
|
||||
- const uint8_t *buf, int len)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
- VDIPortRing *ring = &d->ram->output;
|
||||
- int do_notify = false;
|
||||
- int actual_write = 0;
|
||||
- int l = len;
|
||||
-
|
||||
- if (!d->running) {
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- while (len) {
|
||||
- VDIPortPacket *packet;
|
||||
- int notify;
|
||||
- int wait;
|
||||
-
|
||||
- SPICE_RING_PROD_WAIT(ring, wait);
|
||||
- if (wait) {
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- SPICE_RING_PROD_ITEM(ring, packet);
|
||||
- packet->gen = d->ram->generation;
|
||||
- packet->size = MIN(len, sizeof(packet->data));
|
||||
- memcpy(packet->data, buf, packet->size);
|
||||
- vdi_port_set_dirty(d, packet, sizeof(*packet) - (sizeof(packet->data) - packet->size));
|
||||
-
|
||||
- SPICE_RING_PUSH(ring, notify);
|
||||
- do_notify = do_notify || notify;
|
||||
- len -= packet->size;
|
||||
- buf += packet->size;
|
||||
- actual_write += packet->size;
|
||||
- }
|
||||
- vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
-
|
||||
- if (do_notify) {
|
||||
- vdi_port_notify_guest(d);
|
||||
- }
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_write, l);
|
||||
- }
|
||||
- return actual_write;
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_interface_read(SpiceVDIPortInstance *sin,
|
||||
- uint8_t *buf, int len)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
||||
- VDIPortRing *ring = &d->ram->input;
|
||||
- uint32_t gen = d->ram->generation;
|
||||
- VDIPortPacket *packet;
|
||||
- int do_notify = false;
|
||||
- int actual_read = 0;
|
||||
- int l = len;
|
||||
-
|
||||
- if (!d->running) {
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- while (!SPICE_RING_IS_EMPTY(ring)) {
|
||||
- int notify;
|
||||
-
|
||||
- SPICE_RING_CONS_ITEM(ring, packet);
|
||||
- if (packet->gen == gen) {
|
||||
- break;
|
||||
- }
|
||||
- SPICE_RING_POP(ring, notify);
|
||||
- do_notify = do_notify || notify;
|
||||
- }
|
||||
- while (len) {
|
||||
- VDIPortPacket *packet;
|
||||
- int wait;
|
||||
- int now;
|
||||
-
|
||||
- SPICE_RING_CONS_WAIT(ring, wait);
|
||||
-
|
||||
- if (wait) {
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- SPICE_RING_CONS_ITEM(ring, packet);
|
||||
- if (packet->size > sizeof(packet->data)) {
|
||||
- vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
- printf("%s: bad packet size\n", __FUNCTION__);
|
||||
- return 0;
|
||||
- }
|
||||
- now = MIN(len, packet->size - d->plug_read_pos);
|
||||
- memcpy(buf, packet->data + d->plug_read_pos, now);
|
||||
- len -= now;
|
||||
- buf += now;
|
||||
- actual_read += now;
|
||||
- if ((d->plug_read_pos += now) == packet->size) {
|
||||
- int notify;
|
||||
-
|
||||
- d->plug_read_pos = 0;
|
||||
- SPICE_RING_POP(ring, notify);
|
||||
- do_notify = do_notify || notify;
|
||||
- }
|
||||
- }
|
||||
- vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
||||
-
|
||||
- if (do_notify) {
|
||||
- vdi_port_notify_guest(d);
|
||||
- }
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_read, l);
|
||||
- }
|
||||
- return actual_read;
|
||||
-}
|
||||
-
|
||||
-static SpiceVDIPortInterface vdi_port_interface = {
|
||||
- .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
- .base.description = "vdi port",
|
||||
- .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
- .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
-
|
||||
- .write = vdi_port_interface_write,
|
||||
- .read = vdi_port_interface_read,
|
||||
-};
|
||||
-
|
||||
-static void vdi_port_register_interface(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (d->active_interface ) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
- }
|
||||
- d->sin.base.sif = &vdi_port_interface.base;
|
||||
- spice_server_add_interface(spice_server, &d->sin.base);
|
||||
- d->active_interface = true;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_unregister_interface(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (!d->active_interface ) {
|
||||
- return;
|
||||
- }
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
- }
|
||||
- spice_server_remove_interface(&d->sin.base);
|
||||
- d->active_interface = false;
|
||||
-}
|
||||
-
|
||||
-static uint32_t vdi_port_dev_connect(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (d->connected) {
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: already connected\n", __FUNCTION__);
|
||||
- }
|
||||
- return 0;
|
||||
- }
|
||||
- vdi_port_new_gen(d);
|
||||
- d->connected = true;
|
||||
- vdi_port_register_interface(d);
|
||||
- return d->ram->generation;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_dev_disconnect(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- if (!d->connected) {
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
- }
|
||||
- return;
|
||||
- }
|
||||
- d->connected = false;
|
||||
- vdi_port_unregister_interface(d);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_dev_notify(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- spice_server_vdi_port_wakeup(&d->sin);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_write_dword(void *opaque, uint32_t addr, uint32_t val)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = opaque;
|
||||
- uint32_t io_port = addr - d->io_base;
|
||||
-
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: addr 0x%x val 0x%x\n", __FUNCTION__, addr, val);
|
||||
- }
|
||||
- switch (io_port) {
|
||||
- case VDI_PORT_IO_NOTIFY:
|
||||
- if (!d->connected) {
|
||||
- fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
||||
- return;
|
||||
- }
|
||||
- vdi_port_dev_notify(d);
|
||||
- break;
|
||||
- case VDI_PORT_IO_UPDATE_IRQ:
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
- break;
|
||||
- case VDI_PORT_IO_CONNECTION:
|
||||
- vdi_port_dev_disconnect(d);
|
||||
- break;
|
||||
- default:
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: unexpected addr 0x%x val 0x%x\n",
|
||||
- __FUNCTION__, addr, val);
|
||||
- }
|
||||
- };
|
||||
-}
|
||||
-
|
||||
-static uint32_t vdi_port_read_dword(void *opaque, uint32_t addr)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = opaque;
|
||||
- uint32_t io_port = addr - d->io_base;
|
||||
-
|
||||
- if (debug > 1) {
|
||||
- fprintf(stderr, "%s: addr 0x%x\n", __FUNCTION__, addr);
|
||||
- }
|
||||
- if (io_port == VDI_PORT_IO_CONNECTION) {
|
||||
- return vdi_port_dev_connect(d);
|
||||
- } else {
|
||||
- fprintf(stderr, "%s: unexpected addr 0x%x\n", __FUNCTION__, addr);
|
||||
- }
|
||||
- return 0xffffffff;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_io_map(PCIDevice *pci_dev, int region_num,
|
||||
- pcibus_t addr, pcibus_t size, int type)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
-
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: base 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
- }
|
||||
- d->io_base = addr;
|
||||
- register_ioport_write(addr, size, 4, vdi_port_write_dword, pci_dev);
|
||||
- register_ioport_read(addr, size, 4, vdi_port_read_dword, pci_dev);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_ram_map(PCIDevice *pci_dev, int region_num,
|
||||
- pcibus_t addr, pcibus_t size, int type)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
||||
-
|
||||
- if (debug) {
|
||||
- fprintf(stderr, "%s: addr 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
||||
- }
|
||||
-
|
||||
- assert((addr & (size - 1)) == 0);
|
||||
- assert(size == d->ram_size);
|
||||
-
|
||||
- cpu_register_physical_memory(addr, size, d->ram_offset | IO_MEM_RAM);
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_reset(PCIVDIPortDevice *d)
|
||||
-{
|
||||
- memset(d->ram, 0, sizeof(*d->ram));
|
||||
- SPICE_RING_INIT(&d->ram->input);
|
||||
- SPICE_RING_INIT(&d->ram->output);
|
||||
- d->ram->magic = VDI_PORT_MAGIC;
|
||||
- d->ram->generation = 0;
|
||||
- d->ram->int_pending = 0;
|
||||
- d->ram->int_mask = 0;
|
||||
- d->connected = false;
|
||||
- d->plug_read_pos = 0;
|
||||
- vdi_port_set_dirty(d, d->ram, sizeof(*d->ram));
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_reset_handler(DeviceState *dev)
|
||||
-{
|
||||
- PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev.qdev, dev);
|
||||
-
|
||||
- if (d->connected) {
|
||||
- vdi_port_dev_disconnect(d);
|
||||
- }
|
||||
-
|
||||
- vdi_port_reset(d);
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_pre_load(void* opaque)
|
||||
-{
|
||||
- PCIVDIPortDevice* d = opaque;
|
||||
-
|
||||
- vdi_port_unregister_interface(d);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_post_load(void* opaque,int version_id)
|
||||
-{
|
||||
- PCIVDIPortDevice* d = opaque;
|
||||
-
|
||||
- if (d->connected) {
|
||||
- vdi_port_register_interface(d);
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void vdi_port_vm_change_state_handler(void *opaque, int running, int reason)
|
||||
-{
|
||||
- PCIVDIPortDevice* d = opaque;
|
||||
-
|
||||
- if (running) {
|
||||
- d->running = true;
|
||||
- if (d->new_gen_on_resume) {
|
||||
- d->new_gen_on_resume = false;
|
||||
- vdi_port_new_gen(d);
|
||||
- vdi_port_notify_guest(d);
|
||||
- }
|
||||
- qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
||||
- vdi_port_dev_notify(d);
|
||||
- } else {
|
||||
- d->running = false;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int vdi_port_init(PCIDevice *dev)
|
||||
-{
|
||||
- PCIVDIPortDevice *vdi = (PCIVDIPortDevice *)dev;
|
||||
- uint8_t* config = vdi->pci_dev.config;
|
||||
- uint32_t ram_size = msb_mask(sizeof(VDIPortRam) * 2 - 1);
|
||||
-
|
||||
- vdi->ram_offset = qemu_ram_alloc(&vdi->pci_dev.qdev, "bar1", ram_size);
|
||||
- vdi->ram = qemu_get_ram_ptr(vdi->ram_offset);
|
||||
- vdi_port_reset(vdi);
|
||||
- vdi->ram_size = ram_size;
|
||||
- vdi->new_gen_on_resume = false;
|
||||
- vdi->running = false;
|
||||
-
|
||||
- pci_config_set_vendor_id(config, REDHAT_PCI_VENDOR_ID);
|
||||
- pci_config_set_device_id(config, VDI_PORT_DEVICE_ID);
|
||||
- pci_config_set_class(config, PCI_CLASS_COMMUNICATION_OTHER);
|
||||
- pci_set_byte(&config[PCI_REVISION_ID], VDI_PORT_REVISION);
|
||||
- pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
|
||||
-
|
||||
- pci_register_bar(dev, VDI_PORT_IO_RANGE_INDEX,
|
||||
- msb_mask(VDI_PORT_IO_RANGE_SIZE * 2 - 1),
|
||||
- PCI_BASE_ADDRESS_SPACE_IO, vdi_port_io_map);
|
||||
-
|
||||
- pci_register_bar(dev, VDI_PORT_RAM_RANGE_INDEX,
|
||||
- vdi->ram_size , PCI_BASE_ADDRESS_SPACE_MEMORY,
|
||||
- vdi_port_ram_map);
|
||||
-
|
||||
- qemu_add_vm_change_state_handler(vdi_port_vm_change_state_handler, vdi);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static VMStateDescription vdi_port_vmstate = {
|
||||
- .name = VDI_PORT_DEV_NAME,
|
||||
- .version_id = VDI_PORT_SAVE_VERSION,
|
||||
- .minimum_version_id = VDI_PORT_SAVE_VERSION,
|
||||
- .pre_load = vdi_port_pre_load,
|
||||
- .post_load = vdi_port_post_load,
|
||||
- .fields = (VMStateField []) {
|
||||
- VMSTATE_PCI_DEVICE(pci_dev, PCIVDIPortDevice),
|
||||
- VMSTATE_UINT32(connected, PCIVDIPortDevice),
|
||||
- VMSTATE_END_OF_LIST()
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-static PCIDeviceInfo vdi_port_info = {
|
||||
- .qdev.name = VDI_PORT_DEV_NAME,
|
||||
- .qdev.desc = "spice virtual desktop port (obsolete)",
|
||||
- .qdev.size = sizeof(PCIVDIPortDevice),
|
||||
- .qdev.vmsd = &vdi_port_vmstate,
|
||||
- .qdev.reset = vdi_port_reset_handler,
|
||||
-
|
||||
- .init = vdi_port_init,
|
||||
-};
|
||||
-
|
||||
-static void vdi_port_register(void)
|
||||
-{
|
||||
- pci_qdev_register(&vdi_port_info);
|
||||
-}
|
||||
-
|
||||
-device_init(vdi_port_register);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,236 +0,0 @@
|
||||
From bebcc44cfe5da8a4881292fa564869a481eea4ae Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Sep 2010 11:49:40 +0200
|
||||
Subject: [PATCH 37/39] Revert "spice: add virtio-serial based vdi port backend."
|
||||
|
||||
This reverts commit ef9e975b1d34c1426867cef832ba6238a401b740.
|
||||
---
|
||||
Makefile.target | 1 -
|
||||
hw/spice-vmc.c | 203 -------------------------------------------------------
|
||||
2 files changed, 0 insertions(+), 204 deletions(-)
|
||||
delete mode 100644 hw/spice-vmc.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 90544c5..4da33b5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,7 +217,6 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
-obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
deleted file mode 100644
|
||||
index 3f6a2bb..0000000
|
||||
--- a/hw/spice-vmc.c
|
||||
+++ /dev/null
|
||||
@@ -1,203 +0,0 @@
|
||||
-/*
|
||||
-
|
||||
- Spice Virtual Machine Channel (VMC).
|
||||
-
|
||||
- A virtio-serial port used for spice to guest communication, over
|
||||
- which spice client and a daemon in the guest operating system
|
||||
- communicate.
|
||||
-
|
||||
- Replaces the old vdi_port PCI device.
|
||||
-
|
||||
-*/
|
||||
-
|
||||
-#include <stdio.h>
|
||||
-#include <stdbool.h>
|
||||
-#include <spice.h>
|
||||
-#include <spice-experimental.h>
|
||||
-
|
||||
-#include "virtio-serial.h"
|
||||
-#include "qemu-spice.h"
|
||||
-
|
||||
-#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
-#define VMC_DEVICE_NAME "spicevmc"
|
||||
-
|
||||
-#define dprintf(_svc, _level, _fmt, ...) \
|
||||
- do { \
|
||||
- if (_svc->debug >= _level) { \
|
||||
- fprintf(stderr, "svc: " _fmt, ## __VA_ARGS__); \
|
||||
- } \
|
||||
- } while (0)
|
||||
-
|
||||
-typedef struct SpiceVirtualChannel {
|
||||
- VirtIOSerialPort port;
|
||||
- VMChangeStateEntry *vmstate;
|
||||
- SpiceVDIPortInstance sin;
|
||||
- bool active;
|
||||
- uint8_t *buffer;
|
||||
- uint8_t *datapos;
|
||||
- ssize_t bufsize, datalen;
|
||||
- uint32_t debug;
|
||||
-} SpiceVirtualChannel;
|
||||
-
|
||||
-static int vmc_write(SpiceVDIPortInstance *sin, const uint8_t *buf, int len)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- ssize_t out;
|
||||
-
|
||||
- out = virtio_serial_write(&svc->port, buf, len);
|
||||
- dprintf(svc, 2, "%s: %lu/%d\n", __func__, out, len);
|
||||
- return out;
|
||||
-}
|
||||
-
|
||||
-static int vmc_read(SpiceVDIPortInstance *sin, uint8_t *buf, int len)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
- int bytes = MIN(len, svc->datalen);
|
||||
-
|
||||
- dprintf(svc, 2, "%s: %d/%zd\n", __func__, bytes, svc->datalen);
|
||||
- if (bytes) {
|
||||
- memcpy(buf, svc->datapos, bytes);
|
||||
- svc->datapos += bytes;
|
||||
- svc->datalen -= bytes;
|
||||
- if (0 == svc->datalen) {
|
||||
- virtio_serial_throttle_port(&svc->port, false);
|
||||
- }
|
||||
- }
|
||||
- return bytes;
|
||||
-}
|
||||
-
|
||||
-static SpiceVDIPortInterface vmc_interface = {
|
||||
- .base.type = SPICE_INTERFACE_VDI_PORT,
|
||||
- .base.description = "spice virtual channel vdi port",
|
||||
- .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
||||
- .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
||||
- .write = vmc_write,
|
||||
- .read = vmc_read,
|
||||
-};
|
||||
-
|
||||
-static void vmc_register_interface(SpiceVirtualChannel *svc)
|
||||
-{
|
||||
- if (svc->active) {
|
||||
- return;
|
||||
- }
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- svc->sin.base.sif = &vmc_interface.base;
|
||||
- spice_server_add_interface(spice_server, &svc->sin.base);
|
||||
- svc->active = true;
|
||||
-}
|
||||
-
|
||||
-static void vmc_unregister_interface(SpiceVirtualChannel *svc)
|
||||
-{
|
||||
- if (!svc->active) {
|
||||
- return;
|
||||
- }
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- spice_server_remove_interface(&svc->sin.base);
|
||||
- svc->active = false;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static void vmc_change_state_handler(void *opaque, int running, int reason)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = opaque;
|
||||
-
|
||||
- if (running && svc->active) {
|
||||
- spice_server_vdi_port_wakeup(&svc->sin);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * virtio-serial callbacks
|
||||
- */
|
||||
-
|
||||
-static void vmc_guest_open(VirtIOSerialPort *port)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- vmc_register_interface(svc);
|
||||
-}
|
||||
-
|
||||
-static void vmc_guest_close(VirtIOSerialPort *port)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- vmc_unregister_interface(svc);
|
||||
-}
|
||||
-
|
||||
-static void vmc_guest_ready(VirtIOSerialPort *port)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- if (svc->active)
|
||||
- spice_server_vdi_port_wakeup(&svc->sin);
|
||||
-}
|
||||
-
|
||||
-static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
-{
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
- assert(svc->datapos == 0);
|
||||
- if (svc->bufsize < len) {
|
||||
- svc->bufsize = len;
|
||||
- svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
- }
|
||||
- memcpy(svc->buffer, buf, len);
|
||||
- svc->datapos = svc->buffer;
|
||||
- svc->datalen = len;
|
||||
- virtio_serial_throttle_port(&svc->port, true);
|
||||
- spice_server_vdi_port_wakeup(&svc->sin);
|
||||
-}
|
||||
-
|
||||
-static int vmc_initfn(VirtIOSerialDevice *dev)
|
||||
-{
|
||||
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- if (!using_spice)
|
||||
- return -1;
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
|
||||
- svc->vmstate = qemu_add_vm_change_state_handler(
|
||||
- vmc_change_state_handler, svc);
|
||||
- virtio_serial_open(port);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int vmc_exitfn(VirtIOSerialDevice *dev)
|
||||
-{
|
||||
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
- SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
-
|
||||
- dprintf(svc, 1, "%s\n", __func__);
|
||||
- vmc_unregister_interface(svc);
|
||||
- qemu_del_vm_change_state_handler(svc->vmstate);
|
||||
- virtio_serial_close(port);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static VirtIOSerialPortInfo vmc_info = {
|
||||
- .qdev.name = VMC_DEVICE_NAME,
|
||||
- .qdev.size = sizeof(SpiceVirtualChannel),
|
||||
- .init = vmc_initfn,
|
||||
- .exit = vmc_exitfn,
|
||||
- .guest_open = vmc_guest_open,
|
||||
- .guest_close = vmc_guest_close,
|
||||
- .guest_ready = vmc_guest_ready,
|
||||
- .have_data = vmc_have_data,
|
||||
- .qdev.props = (Property[]) {
|
||||
- DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
- DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
|
||||
- DEFINE_PROP_END_OF_LIST(),
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-static void vmc_register(void)
|
||||
-{
|
||||
- virtio_serial_port_qdev_register(&vmc_info);
|
||||
-}
|
||||
-device_init(vmc_register)
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,297 +0,0 @@
|
||||
From 5bdc01e675a51a123a813d62a8ae837db9360b7f Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 20 Apr 2010 13:33:54 +0200
|
||||
Subject: [PATCH 38/39] spice: add virtio-serial based spice vmchannel backend.
|
||||
|
||||
Adds the spicevmc device. This is a communication channel between the
|
||||
spice client and the guest. It is used to send display information and
|
||||
mouse events from the spice clients to the guest.
|
||||
---
|
||||
Makefile.target | 1 +
|
||||
hw/spice-vmc.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 263 insertions(+), 0 deletions(-)
|
||||
create mode 100644 hw/spice-vmc.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
index 4da33b5..90544c5 100644
|
||||
--- a/Makefile.target
|
||||
+++ b/Makefile.target
|
||||
@@ -217,6 +217,7 @@ obj-i386-y += pc_piix.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
diff --git a/hw/spice-vmc.c b/hw/spice-vmc.c
|
||||
new file mode 100644
|
||||
index 0000000..b77fc60
|
||||
--- /dev/null
|
||||
+++ b/hw/spice-vmc.c
|
||||
@@ -0,0 +1,262 @@
|
||||
+/*
|
||||
+
|
||||
+ Spice Virtual Machine Channel (VMC).
|
||||
+
|
||||
+ A virtio-serial port used for spice to guest communication, over
|
||||
+ which spice client and a daemon in the guest operating system
|
||||
+ communicate.
|
||||
+
|
||||
+ Replaces the old vdi_port PCI device.
|
||||
+
|
||||
+*/
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <spice.h>
|
||||
+#include <spice-experimental.h>
|
||||
+
|
||||
+#include "virtio-serial.h"
|
||||
+#include "qemu-spice.h"
|
||||
+
|
||||
+#define VMC_GUEST_DEVICE_NAME "com.redhat.spice.0"
|
||||
+#define VMC_DEVICE_NAME "spicevmc"
|
||||
+
|
||||
+/* windows guest driver bug workaround */
|
||||
+#define VMC_MAX_HOST_WRITE 2048
|
||||
+
|
||||
+#define dprintf(_svc, _level, _fmt, ...) \
|
||||
+ do { \
|
||||
+ static unsigned __dprintf_counter = 0; \
|
||||
+ if (_svc->debug >= _level) { \
|
||||
+ fprintf(stderr, "svc: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
|
||||
+ } \
|
||||
+ } while (0)
|
||||
+
|
||||
+typedef struct SpiceVirtualChannel {
|
||||
+ VirtIOSerialPort port;
|
||||
+ VMChangeStateEntry *vmstate;
|
||||
+ SpiceCharDeviceInstance sin;
|
||||
+ char *subtype;
|
||||
+ bool active;
|
||||
+ uint8_t *buffer;
|
||||
+ uint8_t *datapos;
|
||||
+ ssize_t bufsize, datalen;
|
||||
+ uint32_t debug;
|
||||
+} SpiceVirtualChannel;
|
||||
+
|
||||
+static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ ssize_t out = 0;
|
||||
+ ssize_t last_out;
|
||||
+ uint8_t* p = (uint8_t*)buf;
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ last_out = virtio_serial_write(&svc->port, p,
|
||||
+ MIN(len, VMC_MAX_HOST_WRITE));
|
||||
+ if (last_out > 0) {
|
||||
+ out += last_out;
|
||||
+ len -= last_out;
|
||||
+ p += last_out;
|
||||
+ } else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dprintf(svc, 3, "%s: %lu/%zd\n", __func__, out, len + out);
|
||||
+ return out;
|
||||
+}
|
||||
+
|
||||
+static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = container_of(sin, SpiceVirtualChannel, sin);
|
||||
+ int bytes = MIN(len, svc->datalen);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %p %d/%d/%zd\n", __func__, svc->datapos, len, bytes, svc->datalen);
|
||||
+ if (bytes > 0) {
|
||||
+ memcpy(buf, svc->datapos, bytes);
|
||||
+ svc->datapos += bytes;
|
||||
+ svc->datalen -= bytes;
|
||||
+ assert(svc->datalen >= 0);
|
||||
+ if (svc->datalen == 0) {
|
||||
+ svc->datapos = 0;
|
||||
+ virtio_serial_throttle_port(&svc->port, false);
|
||||
+ // ^^^ !!! may call vmc_have_data, so don't touch svc after it!
|
||||
+ }
|
||||
+ }
|
||||
+ return bytes;
|
||||
+}
|
||||
+
|
||||
+static SpiceCharDeviceInterface vmc_interface = {
|
||||
+ .base.type = SPICE_INTERFACE_CHAR_DEVICE,
|
||||
+ .base.description = "spice virtual channel char device",
|
||||
+ .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
|
||||
+ .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
|
||||
+ .write = vmc_write,
|
||||
+ .read = vmc_read,
|
||||
+};
|
||||
+
|
||||
+static void vmc_register_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ svc->sin.base.sif = &vmc_interface.base;
|
||||
+ spice_server_add_interface(spice_server, &svc->sin.base);
|
||||
+ svc->active = true;
|
||||
+}
|
||||
+
|
||||
+static void vmc_unregister_interface(SpiceVirtualChannel *svc)
|
||||
+{
|
||||
+ if (!svc->active) {
|
||||
+ return;
|
||||
+ }
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ spice_server_remove_interface(&svc->sin.base);
|
||||
+ svc->active = false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void vmc_change_state_handler(void *opaque, int running, int reason)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = opaque;
|
||||
+
|
||||
+ if (running && svc->active) {
|
||||
+ spice_server_char_device_wakeup(&svc->sin);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * virtio-serial callbacks
|
||||
+ */
|
||||
+
|
||||
+static void vmc_guest_open(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_register_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_close(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+}
|
||||
+
|
||||
+static void vmc_guest_ready(VirtIOSerialPort *port)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ if (svc->active) {
|
||||
+ spice_server_char_device_wakeup(&svc->sin);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void vmc_have_data(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
+{
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 2, "%s: %zd\n", __func__, len);
|
||||
+ assert(svc->datalen == 0);
|
||||
+ if (svc->bufsize < len) {
|
||||
+ svc->bufsize = len;
|
||||
+ svc->buffer = qemu_realloc(svc->buffer, svc->bufsize);
|
||||
+ }
|
||||
+ memcpy(svc->buffer, buf, len);
|
||||
+ svc->datapos = svc->buffer;
|
||||
+ svc->datalen = len;
|
||||
+ virtio_serial_throttle_port(&svc->port, true);
|
||||
+ spice_server_char_device_wakeup(&svc->sin);
|
||||
+}
|
||||
+
|
||||
+static void vmc_print_optional_subtypes(void)
|
||||
+{
|
||||
+ const char** psubtype = spice_server_char_device_recognized_subtypes();
|
||||
+ int i;
|
||||
+
|
||||
+ fprintf(stderr, "supported subtypes: ");
|
||||
+ for(i=0; *psubtype != NULL; ++psubtype, ++i) {
|
||||
+ if (i == 0) {
|
||||
+ fprintf(stderr, *psubtype);
|
||||
+ } else {
|
||||
+ fprintf(stderr, ", %s", *psubtype);
|
||||
+ }
|
||||
+ }
|
||||
+ fprintf(stderr, "\n");
|
||||
+}
|
||||
+
|
||||
+static int vmc_initfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+ const char** psubtype = spice_server_char_device_recognized_subtypes();
|
||||
+ const char *subtype = NULL;
|
||||
+
|
||||
+ if (!using_spice) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+
|
||||
+ if (svc->subtype == NULL) {
|
||||
+ svc->subtype = strdup("vdagent");
|
||||
+ }
|
||||
+
|
||||
+ for(;*psubtype != NULL; ++psubtype) {
|
||||
+ if (strcmp(svc->subtype, *psubtype) == 0) {
|
||||
+ subtype = *psubtype;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (subtype == NULL) {
|
||||
+ fprintf(stderr, "spice-vmc: unsupported subtype\n");
|
||||
+ vmc_print_optional_subtypes();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ port->name = qemu_strdup(VMC_GUEST_DEVICE_NAME);
|
||||
+ svc->vmstate = qemu_add_vm_change_state_handler
|
||||
+ (vmc_change_state_handler, svc);
|
||||
+ svc->sin.subtype = svc->subtype;
|
||||
+ virtio_serial_open(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vmc_exitfn(VirtIOSerialDevice *dev)
|
||||
+{
|
||||
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
|
||||
+ SpiceVirtualChannel *svc = DO_UPCAST(SpiceVirtualChannel, port, port);
|
||||
+
|
||||
+ dprintf(svc, 1, "%s\n", __func__);
|
||||
+ vmc_unregister_interface(svc);
|
||||
+ qemu_del_vm_change_state_handler(svc->vmstate);
|
||||
+ virtio_serial_close(port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static VirtIOSerialPortInfo vmc_info = {
|
||||
+ .qdev.name = VMC_DEVICE_NAME,
|
||||
+ .qdev.size = sizeof(SpiceVirtualChannel),
|
||||
+ .init = vmc_initfn,
|
||||
+ .exit = vmc_exitfn,
|
||||
+ .guest_open = vmc_guest_open,
|
||||
+ .guest_close = vmc_guest_close,
|
||||
+ .guest_ready = vmc_guest_ready,
|
||||
+ .have_data = vmc_have_data,
|
||||
+ .qdev.props = (Property[]) {
|
||||
+ DEFINE_PROP_UINT32("nr", SpiceVirtualChannel, port.id, VIRTIO_CONSOLE_BAD_ID),
|
||||
+ DEFINE_PROP_UINT32("debug", SpiceVirtualChannel, debug, 1),
|
||||
+ DEFINE_PROP_STRING("subtype", SpiceVirtualChannel, subtype),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static void vmc_register(void)
|
||||
+{
|
||||
+ virtio_serial_port_qdev_register(&vmc_info);
|
||||
+}
|
||||
+device_init(vmc_register)
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 9394cbaab7701fe421d5c0168854d39d6a8ecfc2 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 7 Sep 2010 16:45:27 +0200
|
||||
Subject: [PATCH 39/39] qxl: fix release ring overrun
|
||||
|
||||
---
|
||||
hw/qxl.c | 6 +++---
|
||||
1 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 4a15200..8448893 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -377,10 +377,10 @@ static inline void qxl_push_free_res(PCIQXLDevice *d)
|
||||
QXLReleaseRing *ring = &d->ram->release_ring;
|
||||
uint64_t *item;
|
||||
|
||||
-#define QXL_FREE_BUNCH_SIZE 10
|
||||
+#define QXL_FREE_BUNCH_SIZE 32
|
||||
|
||||
- if (SPICE_RING_IS_EMPTY(ring) || (d->num_free_res == QXL_FREE_BUNCH_SIZE &&
|
||||
- ring->prod - ring->cons + 1 != ring->num_items)) {
|
||||
+ if (SPICE_RING_IS_EMPTY(ring) || (d->num_free_res >= QXL_FREE_BUNCH_SIZE &&
|
||||
+ ring->prod - ring->cons + 2 != ring->num_items)) {
|
||||
int notify;
|
||||
|
||||
SPICE_RING_PUSH(ring, notify);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,25 +0,0 @@
|
||||
From b0f3b268c79c532725ae23af56621ab2948ac480 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 16 Sep 2010 12:07:51 +0000
|
||||
Subject: [PATCH 40/40] qxl: flip default to stable pci revision.
|
||||
|
||||
---
|
||||
hw/qxl.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 8448893..d2a0c16 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1455,7 +1455,7 @@ static PCIDeviceInfo qxl_info = {
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
|
||||
DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024),
|
||||
- DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 3),
|
||||
+ DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2),
|
||||
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
|
||||
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,116 +0,0 @@
|
||||
From ff53b62094b009f34dd3312e32a637ca73c752e3 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 8 Oct 2010 00:30:13 +0000
|
||||
Subject: [PATCH 41/42] vmmouse: adapt to mouse handler changes.
|
||||
|
||||
This patch updates the vmmouse handler registration and activation.
|
||||
|
||||
Old behavior:
|
||||
vmmouse_read_id, vmmouse_request_relative and vmmouse_request_absolute
|
||||
unregister the handler and re-register it.
|
||||
|
||||
New behavior:
|
||||
vmmouse_request_relative and vmmouse_request_absolute will unregister
|
||||
the handler in case the mode did change. Then register and active the
|
||||
handler with current mode if needed.
|
||||
|
||||
Note that the old code never ever *activates* the handler, so the
|
||||
vmmouse doesn't receive events. This trips up Fedora 14 for example:
|
||||
Boot a default install without usb tablet, watch the X-Server activating
|
||||
the vmmouse then, enjoy a non-functional mouse.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/vmmouse.c | 31 +++++++++++++++++++++----------
|
||||
1 files changed, 21 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
|
||||
index f359304..2097119 100644
|
||||
--- a/hw/vmmouse.c
|
||||
+++ b/hw/vmmouse.c
|
||||
@@ -100,16 +100,29 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_
|
||||
i8042_isa_mouse_fake_event(s->ps2_mouse);
|
||||
}
|
||||
|
||||
-static void vmmouse_update_handler(VMMouseState *s)
|
||||
+static void vmmouse_remove_handler(VMMouseState *s)
|
||||
{
|
||||
if (s->entry) {
|
||||
qemu_remove_mouse_event_handler(s->entry);
|
||||
s->entry = NULL;
|
||||
}
|
||||
- if (s->status == 0)
|
||||
+}
|
||||
+
|
||||
+static void vmmouse_update_handler(VMMouseState *s, int absolute)
|
||||
+{
|
||||
+ if (s->status != 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (s->absolute != absolute) {
|
||||
+ s->absolute = absolute;
|
||||
+ vmmouse_remove_handler(s);
|
||||
+ }
|
||||
+ if (s->entry == NULL) {
|
||||
s->entry = qemu_add_mouse_event_handler(vmmouse_mouse_event,
|
||||
s, s->absolute,
|
||||
"vmmouse");
|
||||
+ qemu_activate_mouse_event_handler(s->entry);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void vmmouse_read_id(VMMouseState *s)
|
||||
@@ -121,28 +134,25 @@ static void vmmouse_read_id(VMMouseState *s)
|
||||
|
||||
s->queue[s->nb_queue++] = VMMOUSE_VERSION;
|
||||
s->status = 0;
|
||||
- vmmouse_update_handler(s);
|
||||
}
|
||||
|
||||
static void vmmouse_request_relative(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_request_relative()\n");
|
||||
- s->absolute = 0;
|
||||
- vmmouse_update_handler(s);
|
||||
+ vmmouse_update_handler(s, 0);
|
||||
}
|
||||
|
||||
static void vmmouse_request_absolute(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_request_absolute()\n");
|
||||
- s->absolute = 1;
|
||||
- vmmouse_update_handler(s);
|
||||
+ vmmouse_update_handler(s, 1);
|
||||
}
|
||||
|
||||
static void vmmouse_disable(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_disable()\n");
|
||||
s->status = 0xffff;
|
||||
- vmmouse_update_handler(s);
|
||||
+ vmmouse_remove_handler(s);
|
||||
}
|
||||
|
||||
static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
|
||||
@@ -154,7 +164,7 @@ static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
|
||||
if (size == 0 || size > 6 || size > s->nb_queue) {
|
||||
printf("vmmouse: driver requested too much data %d\n", size);
|
||||
s->status = 0xffff;
|
||||
- vmmouse_update_handler(s);
|
||||
+ vmmouse_remove_handler(s);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -239,7 +249,8 @@ static int vmmouse_post_load(void *opaque, int version_id)
|
||||
{
|
||||
VMMouseState *s = opaque;
|
||||
|
||||
- vmmouse_update_handler(s);
|
||||
+ vmmouse_remove_handler(s);
|
||||
+ vmmouse_update_handler(s, s->absolute);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1,316 +0,0 @@
|
||||
From 2ed38f61f1054e188838bae9244fc1c327f8cda4 Mon Sep 17 00:00:00 2001
|
||||
From: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
Date: Mon, 18 Oct 2010 16:17:00 -0200
|
||||
Subject: [PATCH 42/42] vhost-net patches for qemu-0.13.0 tarball
|
||||
|
||||
Justin,
|
||||
|
||||
Attached are the patches to fix vhost-net on the 0.13.0 tarball.
|
||||
Untested.
|
||||
|
||||
commit f76cfc6f0882f227101f21d5a5b80804710b88cb
|
||||
Author: Michael S. Tsirkin <mst@redhat.com>
|
||||
Date: Wed Oct 6 07:22:00 2010 +0200
|
||||
|
||||
vhost: fix up irqfd support
|
||||
|
||||
vhost irqfd support: case where many vqs are
|
||||
mapped to a single msix vector is currently broken.
|
||||
Fix it up.
|
||||
|
||||
Includes this patch from qemu.git:
|
||||
|
||||
virtio: change set guest notifier to per-device
|
||||
|
||||
When using irqfd with vhost-net to inject interrupts,
|
||||
a single evenfd might inject multiple interrupts.
|
||||
Implementing this is much easier with a single
|
||||
per-device callback to set guest notifiers.
|
||||
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
hw/msix.c | 82 +++++++++++++++++++++++++++++++-----------------------
|
||||
hw/msix.h | 4 +-
|
||||
hw/pci.h | 3 +-
|
||||
hw/virtio-pci.c | 56 +++++++++++++++++++++++++++++++------
|
||||
4 files changed, 97 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/hw/msix.c b/hw/msix.c
|
||||
index 3dd0456..c0c6b50 100644
|
||||
--- a/hw/msix.c
|
||||
+++ b/hw/msix.c
|
||||
@@ -300,10 +300,8 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
|
||||
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
|
||||
}
|
||||
- if (was_masked != msix_is_masked(dev, vector) &&
|
||||
- dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
|
||||
+ if (was_masked != msix_is_masked(dev, vector) && dev->msix_mask_notifier) {
|
||||
int r = dev->msix_mask_notifier(dev, vector,
|
||||
- dev->msix_mask_notifier_opaque[vector],
|
||||
msix_is_masked(dev, vector));
|
||||
assert(r >= 0);
|
||||
}
|
||||
@@ -351,9 +349,8 @@ static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
|
||||
int was_masked = msix_is_masked(dev, vector);
|
||||
dev->msix_table_page[offset] |= MSIX_VECTOR_MASK;
|
||||
if (was_masked != msix_is_masked(dev, vector) &&
|
||||
- dev->msix_mask_notifier && dev->msix_mask_notifier_opaque[vector]) {
|
||||
+ dev->msix_mask_notifier) {
|
||||
r = dev->msix_mask_notifier(dev, vector,
|
||||
- dev->msix_mask_notifier_opaque[vector],
|
||||
msix_is_masked(dev, vector));
|
||||
assert(r >= 0);
|
||||
}
|
||||
@@ -379,8 +376,6 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
|
||||
sizeof *dev->msix_irq_entries);
|
||||
}
|
||||
#endif
|
||||
- dev->msix_mask_notifier_opaque =
|
||||
- qemu_mallocz(nentries * sizeof *dev->msix_mask_notifier_opaque);
|
||||
dev->msix_mask_notifier = NULL;
|
||||
dev->msix_entry_used = qemu_mallocz(MSIX_MAX_ENTRIES *
|
||||
sizeof *dev->msix_entry_used);
|
||||
@@ -444,8 +439,6 @@ int msix_uninit(PCIDevice *dev)
|
||||
dev->msix_entry_used = NULL;
|
||||
qemu_free(dev->msix_irq_entries);
|
||||
dev->msix_irq_entries = NULL;
|
||||
- qemu_free(dev->msix_mask_notifier_opaque);
|
||||
- dev->msix_mask_notifier_opaque = NULL;
|
||||
dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
|
||||
return 0;
|
||||
}
|
||||
@@ -590,46 +583,65 @@ void msix_unuse_all_vectors(PCIDevice *dev)
|
||||
msix_free_irq_entries(dev);
|
||||
}
|
||||
|
||||
-int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque)
|
||||
+/* Invoke the notifier if vector entry is used and unmasked. */
|
||||
+static int msix_notify_if_unmasked(PCIDevice *dev, unsigned vector, int masked)
|
||||
{
|
||||
- int r = 0;
|
||||
- if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
|
||||
+ assert(dev->msix_mask_notifier);
|
||||
+ if (!dev->msix_entry_used[vector] || msix_is_masked(dev, vector)) {
|
||||
return 0;
|
||||
+ }
|
||||
+ return dev->msix_mask_notifier(dev, vector, masked);
|
||||
+}
|
||||
|
||||
- assert(dev->msix_mask_notifier);
|
||||
- assert(opaque);
|
||||
- assert(!dev->msix_mask_notifier_opaque[vector]);
|
||||
+static int msix_set_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
|
||||
+{
|
||||
+ /* Notifier has been set. Invoke it on unmasked vectors. */
|
||||
+ return msix_notify_if_unmasked(dev, vector, 0);
|
||||
+}
|
||||
+
|
||||
+static int msix_unset_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
|
||||
+{
|
||||
+ /* Notifier will be unset. Invoke it to mask unmasked entries. */
|
||||
+ return msix_notify_if_unmasked(dev, vector, 1);
|
||||
+}
|
||||
|
||||
- /* Unmask the new notifier unless vector is masked. */
|
||||
- if (!msix_is_masked(dev, vector)) {
|
||||
- r = dev->msix_mask_notifier(dev, vector, opaque, false);
|
||||
+int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func f)
|
||||
+{
|
||||
+ int r, n;
|
||||
+ assert(!dev->msix_mask_notifier);
|
||||
+ dev->msix_mask_notifier = f;
|
||||
+ for (n = 0; n < dev->msix_entries_nr; ++n) {
|
||||
+ r = msix_set_mask_notifier_for_vector(dev, n);
|
||||
if (r < 0) {
|
||||
- return r;
|
||||
+ goto undo;
|
||||
}
|
||||
}
|
||||
- dev->msix_mask_notifier_opaque[vector] = opaque;
|
||||
+ return 0;
|
||||
+
|
||||
+undo:
|
||||
+ while (--n >= 0) {
|
||||
+ msix_unset_mask_notifier_for_vector(dev, n);
|
||||
+ }
|
||||
+ dev->msix_mask_notifier = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
-int msix_unset_mask_notifier(PCIDevice *dev, unsigned vector)
|
||||
+int msix_unset_mask_notifier(PCIDevice *dev)
|
||||
{
|
||||
- int r = 0;
|
||||
- void *opaque;
|
||||
- if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
|
||||
- return 0;
|
||||
-
|
||||
- opaque = dev->msix_mask_notifier_opaque[vector];
|
||||
-
|
||||
+ int r, n;
|
||||
assert(dev->msix_mask_notifier);
|
||||
- assert(opaque);
|
||||
-
|
||||
- /* Mask the old notifier unless it is already masked. */
|
||||
- if (!msix_is_masked(dev, vector)) {
|
||||
- r = dev->msix_mask_notifier(dev, vector, opaque, true);
|
||||
+ for (n = 0; n < dev->msix_entries_nr; ++n) {
|
||||
+ r = msix_unset_mask_notifier_for_vector(dev, n);
|
||||
if (r < 0) {
|
||||
- return r;
|
||||
+ goto undo;
|
||||
}
|
||||
}
|
||||
- dev->msix_mask_notifier_opaque[vector] = NULL;
|
||||
+ dev->msix_mask_notifier = NULL;
|
||||
+ return 0;
|
||||
+
|
||||
+undo:
|
||||
+ while (--n >= 0) {
|
||||
+ msix_set_mask_notifier_for_vector(dev, n);
|
||||
+ }
|
||||
return r;
|
||||
}
|
||||
diff --git a/hw/msix.h b/hw/msix.h
|
||||
index 6b21ffb..5a81df5 100644
|
||||
--- a/hw/msix.h
|
||||
+++ b/hw/msix.h
|
||||
@@ -33,6 +33,6 @@ void msix_reset(PCIDevice *dev);
|
||||
|
||||
extern int msix_supported;
|
||||
|
||||
-int msix_set_mask_notifier(PCIDevice *dev, unsigned vector, void *opaque);
|
||||
-int msix_unset_mask_notifier(PCIDevice *dev, unsigned vector);
|
||||
+int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func);
|
||||
+int msix_unset_mask_notifier(PCIDevice *dev);
|
||||
#endif
|
||||
diff --git a/hw/pci.h b/hw/pci.h
|
||||
index ccb99d0..a40dc14 100644
|
||||
--- a/hw/pci.h
|
||||
+++ b/hw/pci.h
|
||||
@@ -131,7 +131,7 @@ enum {
|
||||
#define PCI_CAPABILITY_CONFIG_MSIX_LENGTH 0x10
|
||||
|
||||
typedef int (*msix_mask_notifier_func)(PCIDevice *, unsigned vector,
|
||||
- void *opaque, int masked);
|
||||
+ int masked);
|
||||
|
||||
struct PCIDevice {
|
||||
DeviceState qdev;
|
||||
@@ -198,7 +198,6 @@ struct PCIDevice {
|
||||
|
||||
struct kvm_irq_routing_entry *msix_irq_entries;
|
||||
|
||||
- void **msix_mask_notifier_opaque;
|
||||
msix_mask_notifier_func msix_mask_notifier;
|
||||
|
||||
/* Device capability configuration space */
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index 83b7871..72bc80e 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -427,11 +427,10 @@ static void virtio_pci_guest_notifier_read(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
-static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
- void *opaque, int masked)
|
||||
+static int virtio_pci_mask_vq(PCIDevice *dev, unsigned vector,
|
||||
+ VirtQueue *vq, int masked)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
- VirtQueue *vq = opaque;
|
||||
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
|
||||
int r = kvm_set_irqfd(dev->msix_irq_entries[vector].gsi,
|
||||
event_notifier_get_fd(notifier),
|
||||
@@ -452,6 +451,34 @@ static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
#endif
|
||||
}
|
||||
|
||||
+static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
|
||||
+ int masked)
|
||||
+{
|
||||
+ VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
|
||||
+ VirtIODevice *vdev = proxy->vdev;
|
||||
+ int r, n;
|
||||
+
|
||||
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
||||
+ if (!virtio_queue_get_num(vdev, n)) {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (virtio_queue_vector(vdev, n) != vector) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ r = virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), masked);
|
||||
+ if (r < 0) {
|
||||
+ goto undo;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+undo:
|
||||
+ while (--n >= 0) {
|
||||
+ virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), !masked);
|
||||
+ }
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
|
||||
{
|
||||
VirtIOPCIProxy *proxy = opaque;
|
||||
@@ -465,11 +492,7 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
|
||||
}
|
||||
qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
virtio_pci_guest_notifier_read, NULL, vq);
|
||||
- msix_set_mask_notifier(&proxy->pci_dev,
|
||||
- virtio_queue_vector(proxy->vdev, n), vq);
|
||||
} else {
|
||||
- msix_unset_mask_notifier(&proxy->pci_dev,
|
||||
- virtio_queue_vector(proxy->vdev, n));
|
||||
qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
NULL, NULL, NULL);
|
||||
/* Test and clear notifier before closing it,
|
||||
@@ -487,6 +510,13 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
||||
VirtIODevice *vdev = proxy->vdev;
|
||||
int r, n;
|
||||
|
||||
+ /* Must unset mask notifier while guest notifier
|
||||
+ * is still assigned */
|
||||
+ if (!assign) {
|
||||
+ r = msix_unset_mask_notifier(&proxy->pci_dev);
|
||||
+ assert(r >= 0);
|
||||
+ }
|
||||
+
|
||||
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
|
||||
if (!virtio_queue_get_num(vdev, n)) {
|
||||
break;
|
||||
@@ -498,6 +528,16 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Must set mask notifier after guest notifier
|
||||
+ * has been assigned */
|
||||
+ if (assign) {
|
||||
+ r = msix_set_mask_notifier(&proxy->pci_dev,
|
||||
+ virtio_pci_mask_notifier);
|
||||
+ if (r < 0) {
|
||||
+ goto assign_error;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
assign_error:
|
||||
@@ -583,8 +623,6 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
|
||||
|
||||
proxy->pci_dev.config_write = virtio_write_config;
|
||||
|
||||
- proxy->pci_dev.msix_mask_notifier = virtio_pci_mask_notifier;
|
||||
-
|
||||
size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
|
||||
if (size & (size-1))
|
||||
size = 1 << qemu_fls(size);
|
||||
--
|
||||
1.7.2.3
|
||||
|
@ -1 +0,0 @@
|
||||
KERNEL=="kvm", GROUP="kvm", MODE="0666"
|
12
95-kvm-ppc64-memlock.conf
Normal file
12
95-kvm-ppc64-memlock.conf
Normal file
@ -0,0 +1,12 @@
|
||||
# The KVM HV implementation on Power can require a significant amount
|
||||
# of unswappable memory (about half of which also needs to be host
|
||||
# physically contiguous) to hold the guest's Hash Page Table (HPT) -
|
||||
# roughly 1/64th of the guest's RAM size, minimum 16MiB.
|
||||
#
|
||||
# These limits allow unprivileged users to start smallish VMs, such as
|
||||
# those used by libguestfs.
|
||||
#
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1293024
|
||||
#
|
||||
* hard memlock 65536
|
||||
* soft memlock 65536
|
2
99-qemu-guest-agent.rules
Normal file
2
99-qemu-guest-agent.rules
Normal file
@ -0,0 +1,2 @@
|
||||
SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \
|
||||
TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service"
|
@ -1,34 +0,0 @@
|
||||
commit d35b261c7a94be9e2fcad5484343544d58ff99be
|
||||
Author: Richard Henderson <rth@twiddle.net>
|
||||
Date: Fri Jun 4 12:14:10 2010 -0700
|
||||
|
||||
s390x: Avoid _llseek.
|
||||
|
||||
There's no _llseek on s390x either. Replace the existing
|
||||
test for __x86_64__ with a functional test for __NR_llseek.
|
||||
|
||||
Signed-off-by: Richard Henderson <rth@twiddle.net>
|
||||
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index 8222cb9..e94f1ee 100644
|
||||
--- a/linux-user/syscall.c
|
||||
+++ b/linux-user/syscall.c
|
||||
@@ -208,7 +208,7 @@ _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count)
|
||||
_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
|
||||
#endif
|
||||
_syscall2(int, sys_getpriority, int, which, int, who);
|
||||
-#if defined(TARGET_NR__llseek) && !defined (__x86_64__)
|
||||
+#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
|
||||
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
|
||||
loff_t *, res, uint, wh);
|
||||
#endif
|
||||
@@ -5933,7 +5933,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef TARGET_NR__llseek /* Not on alpha */
|
||||
case TARGET_NR__llseek:
|
||||
{
|
||||
-#if defined (__x86_64__)
|
||||
+#if !defined(__NR_llseek)
|
||||
ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
|
||||
if (put_user_s64(ret, arg4))
|
||||
goto efault;
|
@ -1,63 +0,0 @@
|
||||
From e69a45b96be09d25429175fa8f0f85e3d7fab5a8 Mon Sep 17 00:00:00 2001
|
||||
Message-Id: <e69a45b96be09d25429175fa8f0f85e3d7fab5a8.1277191832.git.amit.shah@redhat.com>
|
||||
From: Kirill A. Shutemov <kirill@shutemov.name>
|
||||
Date: Wed, 20 Jan 2010 00:56:14 +0100
|
||||
Subject: [PATCH] block/vvfat.c: fix warnings with _FORTIFY_SOURCE
|
||||
|
||||
CC block/vvfat.o
|
||||
cc1: warnings being treated as errors
|
||||
block/vvfat.c: In function 'commit_one_file':
|
||||
block/vvfat.c:2259: error: ignoring return value of 'ftruncate', declared with attribute warn_unused_result
|
||||
make: *** [block/vvfat.o] Error 1
|
||||
CC block/vvfat.o
|
||||
In file included from /usr/include/stdio.h:912,
|
||||
from ./qemu-common.h:19,
|
||||
from block/vvfat.c:27:
|
||||
In function 'snprintf',
|
||||
inlined from 'init_directories' at block/vvfat.c:871,
|
||||
inlined from 'vvfat_open' at block/vvfat.c:1068:
|
||||
/usr/include/bits/stdio2.h:65: error: call to __builtin___snprintf_chk will always overflow destination buffer
|
||||
make: *** [block/vvfat.o] Error 1
|
||||
|
||||
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
|
||||
Signed-off-by: Juan Quintela <quintela@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
(cherry picked from commit 2dedf83ef0cc3463783d6b71bf1b25476f691f3a)
|
||||
|
||||
This fixes Fedora bug 605202.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
block/vvfat.c | 9 +++++++--
|
||||
1 files changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/vvfat.c b/block/vvfat.c
|
||||
index c1acb35..592d6e6 100644
|
||||
--- a/block/vvfat.c
|
||||
+++ b/block/vvfat.c
|
||||
@@ -868,7 +868,8 @@ static int init_directories(BDRVVVFATState* s,
|
||||
{
|
||||
direntry_t* entry=array_get_next(&(s->directory));
|
||||
entry->attributes=0x28; /* archive | volume label */
|
||||
- snprintf((char*)entry->name,11,"QEMU VVFAT");
|
||||
+ memcpy(entry->name,"QEMU VVF",8);
|
||||
+ memcpy(entry->extension,"AT ",3);
|
||||
}
|
||||
|
||||
/* Now build FAT, and write back information into directory */
|
||||
@@ -2256,7 +2257,11 @@ static int commit_one_file(BDRVVVFATState* s,
|
||||
c = c1;
|
||||
}
|
||||
|
||||
- ftruncate(fd, size);
|
||||
+ if (ftruncate(fd, size)) {
|
||||
+ perror("ftruncate()");
|
||||
+ close(fd);
|
||||
+ return -4;
|
||||
+ }
|
||||
close(fd);
|
||||
|
||||
return commit_mappings(s, first_cluster, dir_index);
|
||||
--
|
||||
1.7.0.1
|
||||
|
1
bridge.conf
Normal file
1
bridge.conf
Normal file
@ -0,0 +1 @@
|
||||
allow virbr0
|
104
ksm.init
104
ksm.init
@ -1,104 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# ksm Kernel Samepage Merging
|
||||
#
|
||||
# Author: Dan Kenigsberg <danken@redhat.com>
|
||||
#
|
||||
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
|
||||
# Released under the GPL
|
||||
#
|
||||
# chkconfig: 345 84 16
|
||||
# description: The KSM init script starts and stops the ksm kernel thread.
|
||||
# config: /etc/sysconfig/ksm
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: ksm
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Should-Start:
|
||||
# Default-Start: 3 4 5
|
||||
# Short-Description: start and stop ksm
|
||||
# Description: The KSM init script starts and stops the ksm kernel thread.
|
||||
### END INIT INFO
|
||||
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
if [ -f /etc/sysconfig/ksm ]; then
|
||||
. /etc/sysconfig/ksm
|
||||
fi
|
||||
|
||||
prog=ksm
|
||||
RETVAL=0
|
||||
|
||||
# unless KSM_MAX_KERNEL_PAGES is set, let ksm munch up to half of total memory.
|
||||
default_max_kernel_pages () {
|
||||
local total pagesize
|
||||
total=`awk '/^MemTotal:/ {print $2}' /proc/meminfo`
|
||||
pagesize=`getconf PAGESIZE`
|
||||
echo $[total * 1024 / pagesize / 2]
|
||||
}
|
||||
|
||||
start() {
|
||||
echo -n $"Starting $prog: "
|
||||
if [ -f /sys/kernel/mm/ksm/max_kernel_pages ]; then
|
||||
KSM_MAX_KERNEL_PAGES=${KSM_MAX_KERNEL_PAGES:-`default_max_kernel_pages`}
|
||||
echo $KSM_MAX_KERNEL_PAGES > /sys/kernel/mm/ksm/max_kernel_pages
|
||||
fi
|
||||
echo 1 > /sys/kernel/mm/ksm/run
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && success $"$prog startup" || failure $"$prog startup"
|
||||
echo
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping $prog: "
|
||||
echo 0 > /sys/kernel/mm/ksm/run
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && success $"$prog shutdown" || failure $"$prog shutdown"
|
||||
echo
|
||||
}
|
||||
|
||||
status() {
|
||||
if [ ! -f /sys/kernel/mm/ksm/run ] ; then
|
||||
echo $"$prog not supported"
|
||||
RETVAL=1
|
||||
else if [ "$(cat /sys/kernel/mm/ksm/run 2>/dev/null)" != "1" ]; then
|
||||
echo $"$prog is not running"
|
||||
RETVAL=1
|
||||
else
|
||||
echo $"$prog is running"
|
||||
RETVAL=0
|
||||
fi; fi
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
condrestart|try-restart)
|
||||
status >/dev/null 2>&1 || exit 0
|
||||
restart
|
||||
;;
|
||||
force-reload)
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $prog {start|stop|restart|force-reload|condrestart|try-restart|status|help}"
|
||||
RETVAL=2
|
||||
esac
|
||||
|
||||
exit $RETVAL
|
@ -1,4 +0,0 @@
|
||||
# The maximum number of unswappable kernel pages
|
||||
# which may be allocated by ksm (0 for unlimited)
|
||||
# If unset, defaults to half of total memory
|
||||
# KSM_MAX_KERNEL_PAGES=
|
137
ksmtuned
137
ksmtuned
@ -1,137 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
|
||||
# Released under the GPL
|
||||
#
|
||||
# Author: Dan Kenigsberg <danken@redhat.com>
|
||||
#
|
||||
# ksmtuned - a simple script that controls whether (and with what vigor) ksm
|
||||
# should search for duplicated pages.
|
||||
#
|
||||
# starts ksm when memory commited to qemu processes exceeds a threshold, and
|
||||
# make ksm work harder and harder untill memory load falls below that
|
||||
# threshold.
|
||||
#
|
||||
# send SIGUSR1 to this process right after a new qemu process is started, or
|
||||
# following its death, to retune ksm accordingly
|
||||
#
|
||||
# needs testing and ironing. contact danken@redhat.com if something breaks.
|
||||
|
||||
if [ -f /etc/ksmtuned.conf ]; then
|
||||
. /etc/ksmtuned.conf
|
||||
fi
|
||||
|
||||
debug() {
|
||||
if [ -n "$DEBUG" ]; then
|
||||
s="`/bin/date`: $*"
|
||||
[ -n "$LOGFILE" ] && echo "$s" >> "$LOGFILE" || echo "$s"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
KSM_MONITOR_INTERVAL=${KSM_MONITOR_INTERVAL:-60}
|
||||
KSM_NPAGES_BOOST=${KSM_NPAGES_BOOST:-300}
|
||||
KSM_NPAGES_DECAY=${KSM_NPAGES_DECAY:--50}
|
||||
|
||||
KSM_NPAGES_MIN=${KSM_NPAGES_MIN:-64}
|
||||
KSM_NPAGES_MAX=${KSM_NPAGES_MAX:-1250}
|
||||
# millisecond sleep between ksm scans for 16Gb server. Smaller servers sleep
|
||||
# more, bigger sleep less.
|
||||
KSM_SLEEP_MSEC=${KSM_SLEEP_MSEC:-10}
|
||||
|
||||
KSM_THRES_COEF=${KSM_THRES_COEF:-20}
|
||||
KSM_THRES_CONST=${KSM_THRES_CONST:-2048}
|
||||
|
||||
total=`awk '/^MemTotal:/ {print $2}' /proc/meminfo`
|
||||
debug total $total
|
||||
|
||||
npages=0
|
||||
sleep=$[KSM_SLEEP_MSEC * 16 * 1024 * 1024 / total]
|
||||
[ $sleep -le 10 ] && sleep=10
|
||||
debug sleep $sleep
|
||||
thres=$[total * KSM_THRES_COEF / 100]
|
||||
if [ $KSM_THRES_CONST -gt $thres ]; then
|
||||
thres=$KSM_THRES_CONST
|
||||
fi
|
||||
debug thres $thres
|
||||
|
||||
KSMCTL () {
|
||||
case x$1 in
|
||||
xstop)
|
||||
echo 0 > /sys/kernel/mm/ksm/run
|
||||
;;
|
||||
xstart)
|
||||
echo $2 > /sys/kernel/mm/ksm/pages_to_scan
|
||||
echo $3 > /sys/kernel/mm/ksm/sleep_millisecs
|
||||
echo 1 > /sys/kernel/mm/ksm/run
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
committed_memory () {
|
||||
# calculate how much memory is committed to running qemu processes
|
||||
local progname
|
||||
progname=${1:-qemu-kvm}
|
||||
ps -C "$progname" -o rsz | awk '{ sum += $1 }; END { print sum }'
|
||||
}
|
||||
|
||||
free_memory () {
|
||||
awk '/^(MemFree|Buffers|Cached):/ {free += $2}; END {print free}' \
|
||||
/proc/meminfo
|
||||
}
|
||||
|
||||
increase_npages() {
|
||||
local delta
|
||||
delta=${1:-0}
|
||||
npages=$[npages + delta]
|
||||
if [ $npages -lt $KSM_NPAGES_MIN ]; then
|
||||
npages=$KSM_NPAGES_MIN
|
||||
elif [ $npages -gt $KSM_NPAGES_MAX ]; then
|
||||
npages=$KSM_NPAGES_MAX
|
||||
fi
|
||||
echo $npages
|
||||
}
|
||||
|
||||
|
||||
adjust () {
|
||||
local free committed
|
||||
free=`free_memory`
|
||||
committed=`committed_memory`
|
||||
debug committed $committed free $free
|
||||
if [ $[committed + thres] -lt $total -a $free -gt $thres ]; then
|
||||
KSMCTL stop
|
||||
debug "$[committed + thres] < $total and free > $thres, stop ksm"
|
||||
return 1
|
||||
fi
|
||||
debug "$[committed + thres] > $total, start ksm"
|
||||
if [ $free -lt $thres ]; then
|
||||
npages=`increase_npages $KSM_NPAGES_BOOST`
|
||||
debug "$free < $thres, boost"
|
||||
else
|
||||
npages=`increase_npages $KSM_NPAGES_DECAY`
|
||||
debug "$free > $thres, decay"
|
||||
fi
|
||||
KSMCTL start $npages $sleep
|
||||
debug "KSMCTL start $npages $sleep"
|
||||
return 0
|
||||
}
|
||||
|
||||
function nothing () {
|
||||
:
|
||||
}
|
||||
|
||||
loop () {
|
||||
trap nothing SIGUSR1
|
||||
while true
|
||||
do
|
||||
sleep $KSM_MONITOR_INTERVAL &
|
||||
wait $!
|
||||
adjust
|
||||
done
|
||||
}
|
||||
|
||||
PIDFILE=${PIDFILE-/var/run/ksmtune.pid}
|
||||
if touch "$PIDFILE"; then
|
||||
loop &
|
||||
echo $! > "$PIDFILE"
|
||||
fi
|
@ -1,21 +0,0 @@
|
||||
# Configuration file for ksmtuned.
|
||||
|
||||
# How long ksmtuned should sleep between tuning adjustments
|
||||
# KSM_MONITOR_INTERVAL=60
|
||||
|
||||
# Millisecond sleep between ksm scans for 16Gb server.
|
||||
# Smaller servers sleep more, bigger sleep less.
|
||||
# KSM_SLEEP_MSEC=10
|
||||
|
||||
# KSM_NPAGES_BOOST=300
|
||||
# KSM_NPAGES_DECAY=-50
|
||||
# KSM_NPAGES_MIN=64
|
||||
# KSM_NPAGES_MAX=1250
|
||||
|
||||
# KSM_THRES_COEF=20
|
||||
# KSM_THRES_CONST=2048
|
||||
|
||||
# uncomment the following if you want ksmtuned debug info
|
||||
|
||||
# LOGFILE=/var/log/ksmtuned
|
||||
# DEBUG=1
|
@ -1,94 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# ksmtuned Kernel Samepage Merging (KSM) Tuning Daemon
|
||||
#
|
||||
# Author: Dan Kenigsberg <danken@redhat.com>
|
||||
#
|
||||
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
|
||||
# Released under the GPL
|
||||
#
|
||||
# chkconfig: 345 85 15
|
||||
# description: The KSM tuning daemon controls whether (and with what vigor) \
|
||||
# ksm should ksm search duplicated pages.
|
||||
# processname: ksmtuned
|
||||
# config: /etc/ksmtuned.conf
|
||||
# pidfile: /var/run/ksmtuned.pid
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: ksmtuned
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Should-Start:
|
||||
# Default-Start: 3 4 5
|
||||
# Short-Description: tune the speed of ksm
|
||||
# Description: The Kernel Samepage Merging control Daemon is a simple script
|
||||
# that controls whether (and with what vigor) should ksm search duplicated
|
||||
# memory pages.
|
||||
# needs testing and ironing. contact danken@redhat.com if something breaks.
|
||||
### END INIT INFO
|
||||
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
prog=ksmtuned
|
||||
ksmtuned=/usr/sbin/ksmtuned
|
||||
pidfile=${PIDFILE-/var/run/ksmtune.pid}
|
||||
RETVAL=0
|
||||
|
||||
start() {
|
||||
echo -n $"Starting $prog: "
|
||||
daemon --pidfile=${pidfile} $ksmtuned
|
||||
RETVAL=$?
|
||||
echo
|
||||
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping $prog: "
|
||||
killproc -p ${pidfile}
|
||||
RETVAL=$?
|
||||
echo
|
||||
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
condrestart() {
|
||||
[ -e /var/lock/subsys/$prog ] && restart || :
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
status)
|
||||
status -p ${pidfile} $prog
|
||||
RETVAL=$?
|
||||
;;
|
||||
restart|force-reload)
|
||||
restart
|
||||
;;
|
||||
condrestart|try-restart)
|
||||
condrestart
|
||||
;;
|
||||
retune)
|
||||
pid=`cat ${pidfile} 2> /dev/null`
|
||||
RETVAL=$?
|
||||
if [ -z "$pid" ]; then
|
||||
echo $"Cannot retune, service is not running."
|
||||
else
|
||||
kill -SIGUSR1 $pid
|
||||
RETVAL=$?
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $prog {start|stop|restart|force-reload|condrestart|try-restart|status|retune|help}"
|
||||
RETVAL=2
|
||||
esac
|
||||
|
||||
exit $RETVAL
|
11
kvm-x86.modprobe.conf
Normal file
11
kvm-x86.modprobe.conf
Normal file
@ -0,0 +1,11 @@
|
||||
###
|
||||
### This configuration file was provided by the qemu package.
|
||||
### Feel free to update as needed.
|
||||
###
|
||||
|
||||
###
|
||||
### Set these options to enable nested virtualization
|
||||
###
|
||||
|
||||
#options kvm_intel nested=1
|
||||
#options kvm_amd nested=1
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $(grep -c vmx /proc/cpuinfo) -ne 0 ]; then
|
||||
modprobe -b kvm-intel >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [ $(grep -c svm /proc/cpuinfo) -ne 0 ]; then
|
||||
modprobe -b kvm-amd >/dev/null 2>&1
|
||||
fi
|
@ -1,37 +0,0 @@
|
||||
From: Justin M. Forbes <jforbes@redhat.com>
|
||||
Date: Thu, Aug 19 09:13:45 2010 -0500
|
||||
Subject: pc: Add a Fedora-13 machine type for backwards compatibility.
|
||||
|
||||
In Fedora 13 a fedora-13 machine type was added as default to allow
|
||||
interaction with upstream stable qemu which did not support the same
|
||||
feature set. As a result we need to support this machine type through
|
||||
the Fedora 15 release.
|
||||
|
||||
|
||||
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
|
||||
index 9e4bac8..eb1ed05 100644
|
||||
--- a/hw/pc_piix.c
|
||||
+++ b/hw/pc_piix.c
|
||||
@@ -237,6 +237,14 @@ static QEMUMachine pc_machine = {
|
||||
.is_default = 1,
|
||||
};
|
||||
|
||||
+static QEMUMachine pc_machine_f13 = {
|
||||
+ .name = "fedora-13",
|
||||
+ .desc = "Standard PC",
|
||||
+ .init = pc_init_pci,
|
||||
+ .max_cpus = 255,
|
||||
+ .is_default = 0,
|
||||
+};
|
||||
+
|
||||
static QEMUMachine pc_machine_v0_12 = {
|
||||
.name = "pc-0.12",
|
||||
.desc = "Standard PC",
|
||||
@@ -348,6 +356,7 @@ static QEMUMachine isapc_machine = {
|
||||
static void pc_machine_init(void)
|
||||
{
|
||||
qemu_register_machine(&pc_machine);
|
||||
+ qemu_register_machine(&pc_machine_f13);
|
||||
qemu_register_machine(&pc_machine_v0_12);
|
||||
qemu_register_machine(&pc_machine_v0_11);
|
||||
qemu_register_machine(&pc_machine_v0_10);
|
19
qemu-ga.sysconfig
Normal file
19
qemu-ga.sysconfig
Normal file
@ -0,0 +1,19 @@
|
||||
# This is a systemd environment file, not a shell script.
|
||||
# It provides settings for "/lib/systemd/system/qemu-guest-agent.service".
|
||||
|
||||
# Comma-separated blacklist of RPCs to disable, or empty list to enable all.
|
||||
#
|
||||
# You can get the list of RPC commands using "qemu-ga --blacklist='?'".
|
||||
# There should be no spaces between commas and commands in the blacklist.
|
||||
#BLACKLIST_RPC=guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush,guest-exec,guest-exec-status
|
||||
|
||||
# Fsfreeze hook script specification.
|
||||
#
|
||||
# FSFREEZE_HOOK_PATHNAME=/dev/null : disables the feature.
|
||||
#
|
||||
# FSFREEZE_HOOK_PATHNAME=/path/to/executable : enables the feature with the
|
||||
# specified binary or shell script.
|
||||
#
|
||||
# FSFREEZE_HOOK_PATHNAME= : enables the feature with the
|
||||
# default value (invoke "qemu-ga --help" to interrogate).
|
||||
FSFREEZE_HOOK_PATHNAME=/etc/qemu-ga/fsfreeze-hook
|
19
qemu-guest-agent.service
Normal file
19
qemu-guest-agent.service
Normal file
@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=QEMU Guest Agent
|
||||
BindsTo=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
||||
After=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
||||
IgnoreOnIsolate=True
|
||||
|
||||
[Service]
|
||||
UMask=0077
|
||||
EnvironmentFile=/etc/sysconfig/qemu-ga
|
||||
ExecStart=/usr/bin/qemu-ga \
|
||||
--method=virtio-serial \
|
||||
--path=/dev/virtio-ports/org.qemu.guest_agent.0 \
|
||||
--blacklist=${BLACKLIST_RPC} \
|
||||
-F${FSFREEZE_HOOK_PATHNAME}
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
|
||||
[Install]
|
||||
WantedBy=dev-virtio\x2dports-org.qemu.guest_agent.0.device
|
10
qemu-kvm.sh
Normal file
10
qemu-kvm.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Libvirt introspects the binary using -M none. In that case, don't try
|
||||
# to init KVM, which will fail and be noisy if the host has kvm disabled
|
||||
opts="-machine accel=kvm"
|
||||
if echo "$@" | grep -q " -M none "; then
|
||||
opts=
|
||||
fi
|
||||
|
||||
exec /usr/bin/qemu-system-x86_64 $opts "$@"
|
102
qemu.init
102
qemu.init
@ -1,102 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# qemu Allow users to run non-native Linux programs by just clicking on them
|
||||
# (or typing ./file.exe)
|
||||
#
|
||||
# chkconfig: 2345 35 98
|
||||
# description: Allow users to run non-native Linux programs by just clicking \
|
||||
# on them (or typing ./file.exe)
|
||||
|
||||
. /etc/rc.d/init.d/functions
|
||||
RETVAL=0
|
||||
QEMU=/usr/bin
|
||||
|
||||
start() {
|
||||
cpu=`uname -m`
|
||||
case "$cpu" in
|
||||
i386|i486|i586|i686|i86pc|BePC)
|
||||
cpu="i386"
|
||||
;;
|
||||
"Power Macintosh"|ppc|ppc64)
|
||||
cpu="ppc"
|
||||
;;
|
||||
armv4l|armv5l)
|
||||
cpu="arm"
|
||||
;;
|
||||
sh4)
|
||||
cpu="sh4"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -n $"Registering binary handler for qemu applications"
|
||||
/sbin/modprobe binfmt_misc &>/dev/null
|
||||
if [ "$cpu" != i386 -a -x $QEMU/qemu-i386 -a -d /usr/qemu-i386 ] ; then
|
||||
echo ":qemu-i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-i386:" > /proc/sys/fs/binfmt_misc/register
|
||||
echo ":qemu-i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-i386:" > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ "$cpu" != arm -a -x $QEMU/qemu-arm -a -d /usr/qemu-arm ] ; then
|
||||
echo ":qemu-arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-arm:" > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ "$cpu" != ppc -a -x $QEMU/qemu-ppc -a -d /usr/qemu-ppc ] ; then
|
||||
echo ":ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-ppc:" > /proc/sys/fs/binfmt_misc/register
|
||||
echo do ppc
|
||||
fi
|
||||
if [ "$cpu" != sparc -a -x $QEMU/qemu-sparc -a -d /usr/qemu-sparc ] ; then
|
||||
echo ":qemu-sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-sparc:" > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ "$cpu" != sh4 -a -x $QEMU/qemu-sh4 -a -d /usr/qemu-sh4 ] ; then
|
||||
echo ":qemu-sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xff\xff\xff:$QEMU/qemu-sh4:" > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Unregistering binary handler for qemu applications"
|
||||
for a in i386 i486 ppc arm sparc sh4 ] ; do
|
||||
[ -r /proc/sys/fs/binfmt_misc/qemu-$a ] && echo "-1" >/proc/sys/fs/binfmt_misc/qemu-$a
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
reload() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
qemu_status() {
|
||||
if ls /proc/sys/fs/binfmt_misc/qemu-* &>/dev/null; then
|
||||
echo $"qemu binary format handlers are registered."
|
||||
return 0
|
||||
else
|
||||
echo $"qemu binary format handlers are not registered."
|
||||
return 3
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
status)
|
||||
qemu_status
|
||||
RETVAL=$?
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
condrestart)
|
||||
if qemu_status &>/dev/null; then
|
||||
stop
|
||||
start
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $prog {start|stop|status|restart|condrestart}"
|
||||
exit 1
|
||||
esac
|
||||
exit $RETVAL
|
||||
|
Loading…
Reference in New Issue
Block a user