Compare commits
458 Commits
pull-input
...
pull-gtk-3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bda66028b | ||
|
|
298526fe92 | ||
|
|
881249c792 | ||
|
|
f4b11eee2f | ||
|
|
6fffa26244 | ||
|
|
e638308097 | ||
|
|
9c749e4dbe | ||
|
|
379e21c258 | ||
|
|
a00f66ab9b | ||
|
|
69df1c3c9d | ||
|
|
6d4adef48d | ||
|
|
3b163b0165 | ||
|
|
f214530f56 | ||
|
|
9d5614d582 | ||
|
|
39d16d29c8 | ||
|
|
cc13eead53 | ||
|
|
86c3b20a5f | ||
|
|
6d585ca559 | ||
|
|
dfb3804d47 | ||
|
|
4191d0eb41 | ||
|
|
03d51428e2 | ||
|
|
582ab779c5 | ||
|
|
8678b71ce6 | ||
|
|
1fcc9ddfb3 | ||
|
|
c6e929e784 | ||
|
|
b3c56df769 | ||
|
|
ed7a0aa8bc | ||
|
|
04ce397b33 | ||
|
|
14b155ddc4 | ||
|
|
e029f29385 | ||
|
|
90f1cd9138 | ||
|
|
7d11fc7c2b | ||
|
|
096c46c0ff | ||
|
|
df9351e372 | ||
|
|
50573c66eb | ||
|
|
46dea4160d | ||
|
|
dc668ded10 | ||
|
|
1e8ece0db3 | ||
|
|
4a41a2d68a | ||
|
|
62e466e845 | ||
|
|
c3adb58fe0 | ||
|
|
aa7a6a399f | ||
|
|
2e323f03bf | ||
|
|
22956a3755 | ||
|
|
5d92c74f8a | ||
|
|
b19fc63cad | ||
|
|
90c5d39cb8 | ||
|
|
01c22f2cdd | ||
|
|
cb201b4872 | ||
|
|
f33f991185 | ||
|
|
be21c33616 | ||
|
|
8bf0975902 | ||
|
|
7effdaa321 | ||
|
|
d44229c54f | ||
|
|
d0b2542574 | ||
|
|
4c1410d59c | ||
|
|
bbbd67f0cc | ||
|
|
2ef1f68d4f | ||
|
|
0c591eb0a9 | ||
|
|
00c8cb0a36 | ||
|
|
31b030d4ab | ||
|
|
0063ebd6ac | ||
|
|
0dd106c5f0 | ||
|
|
a47dddd734 | ||
|
|
d7f0a59ff0 | ||
|
|
bb0e627a84 | ||
|
|
baea4fae7b | ||
|
|
0ea8cb8895 | ||
|
|
b3310ab338 | ||
|
|
75a34036d4 | ||
|
|
d0e39c5d70 | ||
|
|
611d4f996f | ||
|
|
648f034c6c | ||
|
|
90b40a696a | ||
|
|
239c51a54f | ||
|
|
74f10515d1 | ||
|
|
3f38f309b2 | ||
|
|
5638d180d6 | ||
|
|
d5a11fefef | ||
|
|
f0c3c505a8 | ||
|
|
ff4700b05c | ||
|
|
0429a97195 | ||
|
|
27103424c4 | ||
|
|
6f03bef0ff | ||
|
|
8cd70437f3 | ||
|
|
28ecfd7a62 | ||
|
|
efee734004 | ||
|
|
99df7dce8a | ||
|
|
93afeade09 | ||
|
|
7510454e3e | ||
|
|
7372c2b926 | ||
|
|
9262685b81 | ||
|
|
1590bbcb02 | ||
|
|
247bf011f6 | ||
|
|
433ac7a968 | ||
|
|
db5d39f786 | ||
|
|
94a444b295 | ||
|
|
d940ee9b78 | ||
|
|
500050d1e0 | ||
|
|
ef02ef5f45 | ||
|
|
8fb4f821e9 | ||
|
|
5fcca9ff3b | ||
|
|
74f54bc4ba | ||
|
|
9576de7573 | ||
|
|
285f025d2c | ||
|
|
c080e30ec8 | ||
|
|
8c2e1b0093 | ||
|
|
1cf5ccbca8 | ||
|
|
62864712b3 | ||
|
|
2fad1112db | ||
|
|
2efc6be2ea | ||
|
|
33276f1b9c | ||
|
|
19d6ca16d9 | ||
|
|
70d74660e7 | ||
|
|
d2810ffd34 | ||
|
|
9d111183d5 | ||
|
|
4a9a1f49c5 | ||
|
|
57fac92c2d | ||
|
|
41975b269c | ||
|
|
57ed25b1b0 | ||
|
|
cc28c6aa46 | ||
|
|
18fa1c42a3 | ||
|
|
d3f4984583 | ||
|
|
7af803d4f8 | ||
|
|
f988388025 | ||
|
|
9562f69cfd | ||
|
|
27eb6c097c | ||
|
|
d475e5acd2 | ||
|
|
dc3dd0d2be | ||
|
|
88eb7c29e4 | ||
|
|
48ff269272 | ||
|
|
6e4a876b43 | ||
|
|
7d1de46448 | ||
|
|
be8d853766 | ||
|
|
98563fc3ec | ||
|
|
2da61b671e | ||
|
|
11f590b1a2 | ||
|
|
b5042a3622 | ||
|
|
98d39e34fe | ||
|
|
938789ea92 | ||
|
|
dba2855572 | ||
|
|
3456a8d185 | ||
|
|
26d49c4675 | ||
|
|
be86c53c05 | ||
|
|
c8d146aecc | ||
|
|
0100f42550 | ||
|
|
ac1b84dd1e | ||
|
|
295d51aa6a | ||
|
|
c6ba42f6bc | ||
|
|
fb0e843a11 | ||
|
|
8f3babb74d | ||
|
|
7a1a4dac94 | ||
|
|
602a3921ff | ||
|
|
f8762027a3 | ||
|
|
d2f69df746 | ||
|
|
5c21ce77d7 | ||
|
|
02e7f85dac | ||
|
|
04e9a20b49 | ||
|
|
2ef66625f3 | ||
|
|
0399a3819b | ||
|
|
6e8114a065 | ||
|
|
aa97405e32 | ||
|
|
26c9a015ef | ||
|
|
b6f46f02f4 | ||
|
|
02063aaa65 | ||
|
|
c7a59bed62 | ||
|
|
83bb0b2ffd | ||
|
|
dc06cbd286 | ||
|
|
0056ae24bc | ||
|
|
261747f176 | ||
|
|
36d20cb2b3 | ||
|
|
49649f23db | ||
|
|
a3d7cbc139 | ||
|
|
1b8601b0ea | ||
|
|
cdccf7d7e7 | ||
|
|
1f760d5f2b | ||
|
|
7c77b654c5 | ||
|
|
5ef4a1c304 | ||
|
|
d43269dddc | ||
|
|
1a7d9ee6dd | ||
|
|
a01aedc8d3 | ||
|
|
7b0309490c | ||
|
|
267a3264cd | ||
|
|
2b81b35f8f | ||
|
|
750036a848 | ||
|
|
2f23e9ae2c | ||
|
|
21143b615a | ||
|
|
fd3ece2533 | ||
|
|
a822837d12 | ||
|
|
01ac27ce7f | ||
|
|
84f3fe1b07 | ||
|
|
2c3445bb85 | ||
|
|
7602e3e4a3 | ||
|
|
613c12ec28 | ||
|
|
d58b912271 | ||
|
|
7f5e07d9b3 | ||
|
|
dc9528fdf9 | ||
|
|
68e5ec6400 | ||
|
|
5c1e1890bf | ||
|
|
c2804ee6c0 | ||
|
|
16c358e96e | ||
|
|
be813ef02d | ||
|
|
2396187076 | ||
|
|
01207d0b78 | ||
|
|
0ca540dbae | ||
|
|
2a7a1a56d1 | ||
|
|
5d371f41b4 | ||
|
|
5223070c47 | ||
|
|
59ca664ef8 | ||
|
|
bceae7697f | ||
|
|
b0b58195e4 | ||
|
|
6299659f54 | ||
|
|
b86b05ed60 | ||
|
|
515b943a91 | ||
|
|
4b35991a3b | ||
|
|
dad1fcab91 | ||
|
|
ed9b103d3e | ||
|
|
c57ec3249e | ||
|
|
13f65b2e10 | ||
|
|
b4e5a4bffd | ||
|
|
263cf4367f | ||
|
|
dc65540465 | ||
|
|
ac41881b48 | ||
|
|
fe6c53b4bb | ||
|
|
b0f15a5d56 | ||
|
|
118760dfc9 | ||
|
|
b304bf0021 | ||
|
|
3f1506704e | ||
|
|
0c126db27c | ||
|
|
72c1d3af6e | ||
|
|
2b194951c5 | ||
|
|
c8f8f9fb2b | ||
|
|
d2f41a1169 | ||
|
|
43a32ed68f | ||
|
|
b29c8f115d | ||
|
|
0624976f61 | ||
|
|
7c2cb42b50 | ||
|
|
af5199347a | ||
|
|
c9dd4074df | ||
|
|
9b74d0d598 | ||
|
|
4b87dc4c97 | ||
|
|
dbb2a1326a | ||
|
|
c3aa84b68f | ||
|
|
e9d818b8b1 | ||
|
|
cbc14e6f28 | ||
|
|
16513b1b45 | ||
|
|
e22492d332 | ||
|
|
919372251c | ||
|
|
863d7c9105 | ||
|
|
12b316d4c1 | ||
|
|
6cd859aa8a | ||
|
|
b4c85ddcec | ||
|
|
38ee14f4f3 | ||
|
|
e3c1adf16e | ||
|
|
2e7bcdb99a | ||
|
|
5264917bcf | ||
|
|
98bc3ab0f2 | ||
|
|
220c8ed536 | ||
|
|
f1b7e0e498 | ||
|
|
175f099b30 | ||
|
|
15d914b18d | ||
|
|
262f6f5140 | ||
|
|
4a4fcdf6df | ||
|
|
4900116e6f | ||
|
|
8f480de0c9 | ||
|
|
5d12f961c6 | ||
|
|
6e1f0a55a1 | ||
|
|
8e46bbf362 | ||
|
|
ddfa83ea06 | ||
|
|
6cb46e1e90 | ||
|
|
8dcf525abc | ||
|
|
f8e2484389 | ||
|
|
523fdc08cc | ||
|
|
017a86f7ad | ||
|
|
2e796c7621 | ||
|
|
8d8db193f2 | ||
|
|
a51a6b6ad5 | ||
|
|
f029341494 | ||
|
|
7763ffa017 | ||
|
|
3353d0dcc3 | ||
|
|
82295d8a2d | ||
|
|
464400f6a5 | ||
|
|
4fed9421e9 | ||
|
|
ac4df4e608 | ||
|
|
fd8cec932c | ||
|
|
f53f3d0a00 | ||
|
|
d7c698af8a | ||
|
|
6570025e53 | ||
|
|
80aaa0741f | ||
|
|
6fc0303b95 | ||
|
|
bb2b045034 | ||
|
|
c3f8d28e45 | ||
|
|
4089f7c6a0 | ||
|
|
2c02f88780 | ||
|
|
4c288acbd6 | ||
|
|
9c83ffd859 | ||
|
|
eb909c7f72 | ||
|
|
c75203c8d3 | ||
|
|
c6e0bd9b70 | ||
|
|
8ae8e904fc | ||
|
|
d5546c5e77 | ||
|
|
7dc74db88b | ||
|
|
464d9f641d | ||
|
|
078896a9ee | ||
|
|
cd5d031e75 | ||
|
|
50c75136be | ||
|
|
90ce8a061b | ||
|
|
47ea2de2d6 | ||
|
|
f47c3f5a80 | ||
|
|
2fa4c042bc | ||
|
|
64bb01aa35 | ||
|
|
b1f7d84fd2 | ||
|
|
85c09bc016 | ||
|
|
7e7494627f | ||
|
|
0f20ba62c3 | ||
|
|
0ce470cd4c | ||
|
|
a0fcac9c21 | ||
|
|
c138593380 | ||
|
|
3f94170be3 | ||
|
|
7c43bca004 | ||
|
|
f3c75d42ad | ||
|
|
3707cd62db | ||
|
|
7dff9abe63 | ||
|
|
3c3b0ddefa | ||
|
|
e5d7d2b0f5 | ||
|
|
0a61f3b478 | ||
|
|
ac174549b7 | ||
|
|
57354f8f12 | ||
|
|
557d52fa69 | ||
|
|
e8f7b27b99 | ||
|
|
b8476fc7c6 | ||
|
|
f1064f612c | ||
|
|
6f3dab41fb | ||
|
|
4d82038e41 | ||
|
|
b41da4ebb2 | ||
|
|
2fdf78e649 | ||
|
|
818692ff95 | ||
|
|
e0ffe77f27 | ||
|
|
4430e07663 | ||
|
|
024215b242 | ||
|
|
8203e31b54 | ||
|
|
e13500b3c3 | ||
|
|
f293f04ab5 | ||
|
|
953f0f5842 | ||
|
|
63be09365a | ||
|
|
aa9e930c88 | ||
|
|
56eabc7508 | ||
|
|
111c5f54a1 | ||
|
|
a737d3ebc8 | ||
|
|
50f5fc0cf2 | ||
|
|
5dffff5a47 | ||
|
|
9b47bb490c | ||
|
|
bb5275338d | ||
|
|
32ea54ab5f | ||
|
|
27b95bfe62 | ||
|
|
9c294d5ab3 | ||
|
|
84cab1e2f5 | ||
|
|
e0498daab5 | ||
|
|
71a8c019c4 | ||
|
|
38a853375e | ||
|
|
52a4984d97 | ||
|
|
60511041d6 | ||
|
|
94840e0700 | ||
|
|
f5bc1bfa35 | ||
|
|
3f34cf910c | ||
|
|
61de36761b | ||
|
|
5736245c80 | ||
|
|
3b66da82ce | ||
|
|
18674b2678 | ||
|
|
6a2331d12e | ||
|
|
133e70ee88 | ||
|
|
eb1e7c3e51 | ||
|
|
b36f100e17 | ||
|
|
0658aa9cba | ||
|
|
69b31b907b | ||
|
|
66c3e32841 | ||
|
|
ce8ca30b39 | ||
|
|
6d41d146c9 | ||
|
|
da29cb7bc7 | ||
|
|
29a0e4e9a1 | ||
|
|
c73860803f | ||
|
|
28288b48a8 | ||
|
|
fab7fe426f | ||
|
|
1b0bd0029f | ||
|
|
587c51f74b | ||
|
|
5c77a786e2 | ||
|
|
1fa6c53304 | ||
|
|
a98eb9e99d | ||
|
|
6a4fda3358 | ||
|
|
e44259b6d4 | ||
|
|
98d1eb2748 | ||
|
|
a824bc191a | ||
|
|
86ba37edcb | ||
|
|
7ee19fb9d6 | ||
|
|
3d1140bf3e | ||
|
|
097ec5d850 | ||
|
|
f5c0f7f981 | ||
|
|
67a33f3727 | ||
|
|
74698350ca | ||
|
|
f53f81e08b | ||
|
|
968e76bcab | ||
|
|
cea4e57473 | ||
|
|
2c0c52ae62 | ||
|
|
b24d0b472b | ||
|
|
ab9408a2d1 | ||
|
|
3fd0aadfc1 | ||
|
|
e16a626b82 | ||
|
|
f026da7830 | ||
|
|
cac7f0ba4a | ||
|
|
e072fe796e | ||
|
|
dbcc48fa8f | ||
|
|
88e33d08c9 | ||
|
|
5177d2ca93 | ||
|
|
ed8ac5686a | ||
|
|
354a6decf1 | ||
|
|
959e9c9d1e | ||
|
|
4f17e9c738 | ||
|
|
595c6eefb7 | ||
|
|
5cb151acb1 | ||
|
|
bc80838f86 | ||
|
|
d3f9df8fb8 | ||
|
|
d32404fe42 | ||
|
|
2009227fbe | ||
|
|
4b98eeef50 | ||
|
|
5e591d8812 | ||
|
|
ee6e02c0ac | ||
|
|
3c3cbbdc84 | ||
|
|
59800ec8e5 | ||
|
|
4e38181979 | ||
|
|
3052f0d594 | ||
|
|
09aa9a526a | ||
|
|
6cd8712c5f | ||
|
|
7a7c05d77d | ||
|
|
363248e8c9 | ||
|
|
0dc083fe10 | ||
|
|
ca480de664 | ||
|
|
135a129a1c | ||
|
|
9c06a1f79f | ||
|
|
88ccd23a0c | ||
|
|
401949176c | ||
|
|
0bfe9299da | ||
|
|
81d2fb4dfd | ||
|
|
6475c9f05c | ||
|
|
a5100e752b | ||
|
|
993c91a0e9 | ||
|
|
b51910baf2 | ||
|
|
974a196d7f | ||
|
|
f19e00d776 | ||
|
|
76ca310a19 | ||
| cd98d390ae | |||
|
|
8a3ae9109e | ||
|
|
4cf2348026 | ||
|
|
4fa4ce7107 | ||
|
|
fae0864573 | ||
|
|
75b7931ec6 | ||
|
|
f9a49dfa02 | ||
|
|
9ba3cf540f | ||
|
|
d77f7779b4 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,6 +21,7 @@
|
|||||||
libdis*
|
libdis*
|
||||||
libuser
|
libuser
|
||||||
/linux-headers/asm
|
/linux-headers/asm
|
||||||
|
/qga/qapi-generated
|
||||||
/qapi-generated
|
/qapi-generated
|
||||||
/qapi-types.[ch]
|
/qapi-types.[ch]
|
||||||
/qapi-visit.[ch]
|
/qapi-visit.[ch]
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -13,6 +13,9 @@
|
|||||||
[submodule "roms/openbios"]
|
[submodule "roms/openbios"]
|
||||||
path = roms/openbios
|
path = roms/openbios
|
||||||
url = git://git.qemu-project.org/openbios.git
|
url = git://git.qemu-project.org/openbios.git
|
||||||
|
[submodule "roms/openhackware"]
|
||||||
|
path = roms/openhackware
|
||||||
|
url = git://git.qemu-project.org/openhackware.git
|
||||||
[submodule "roms/qemu-palcode"]
|
[submodule "roms/qemu-palcode"]
|
||||||
path = roms/qemu-palcode
|
path = roms/qemu-palcode
|
||||||
url = git://github.com/rth7680/qemu-palcode.git
|
url = git://github.com/rth7680/qemu-palcode.git
|
||||||
|
|||||||
19
.travis.yml
19
.travis.yml
@@ -4,6 +4,12 @@ python:
|
|||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
|
notifications:
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
- "irc.oftc.net#qemu"
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- TEST_CMD="make check"
|
- TEST_CMD="make check"
|
||||||
@@ -46,6 +52,10 @@ matrix:
|
|||||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
|
EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter"
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
|
# All the extra -dev packages
|
||||||
|
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
|
EXTRA_PKGS="libaio-dev libcap-ng-dev libattr1-dev libbrlapi-dev uuid-dev libusb-1.0.0-dev"
|
||||||
|
compiler: gcc
|
||||||
# Currently configure doesn't force --disable-pie
|
# Currently configure doesn't force --disable-pie
|
||||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
|
EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie"
|
||||||
@@ -65,8 +75,7 @@ matrix:
|
|||||||
EXTRA_CONFIG="--enable-trace-backend=ftrace"
|
EXTRA_CONFIG="--enable-trace-backend=ftrace"
|
||||||
TEST_CMD=""
|
TEST_CMD=""
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
# This disabled make check for the ftrace backend which needs more setting up
|
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
# Currently broken on 12.04 due to mis-packaged liburcu and changed API, will be pulled.
|
EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
||||||
#- env: TARGETS=i386-softmmu,x86_64-softmmu
|
EXTRA_CONFIG="--enable-trace-backend=ust"
|
||||||
# EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
compiler: gcc
|
||||||
# EXTRA_CONFIG="--enable-trace-backend=ust"
|
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ Guest CPU Cores (KVM):
|
|||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Overall
|
Overall
|
||||||
M: Gleb Natapov <gleb@redhat.com>
|
|
||||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
L: kvm@vger.kernel.org
|
L: kvm@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
@@ -176,12 +175,14 @@ S: Maintained
|
|||||||
F: target-ppc/kvm.c
|
F: target-ppc/kvm.c
|
||||||
|
|
||||||
S390
|
S390
|
||||||
|
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||||
|
M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-s390x/kvm.c
|
F: target-s390x/kvm.c
|
||||||
|
F: hw/intc/s390_flic.[hc]
|
||||||
|
|
||||||
X86
|
X86
|
||||||
M: Gleb Natapov <gleb@redhat.com>
|
|
||||||
M: Marcelo Tosatti <mtosatti@redhat.com>
|
M: Marcelo Tosatti <mtosatti@redhat.com>
|
||||||
L: kvm@vger.kernel.org
|
L: kvm@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
@@ -495,10 +496,13 @@ F: hw/s390x/s390-*.c
|
|||||||
|
|
||||||
S390 Virtio-ccw
|
S390 Virtio-ccw
|
||||||
M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
|
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: hw/s390x/s390-virtio-ccw.c
|
F: hw/s390x/s390-virtio-ccw.c
|
||||||
F: hw/s390x/css.[hc]
|
F: hw/s390x/css.[hc]
|
||||||
|
F: hw/s390x/sclp*.[hc]
|
||||||
|
F: hw/s390x/ipl*.[hc]
|
||||||
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
|
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
|
||||||
|
|
||||||
UniCore32 Machines
|
UniCore32 Machines
|
||||||
@@ -629,6 +633,7 @@ F: hw/block/virtio-blk.c
|
|||||||
|
|
||||||
virtio-ccw
|
virtio-ccw
|
||||||
M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
|
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: hw/s390x/virtio-ccw.[hc]
|
F: hw/s390x/virtio-ccw.[hc]
|
||||||
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
|
T: git git://github.com/cohuck/qemu virtio-ccw-upstr
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -265,10 +265,7 @@ clean:
|
|||||||
# avoid old build problems by removing potentially incorrect old files
|
# avoid old build problems by removing potentially incorrect old files
|
||||||
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
||||||
rm -f qemu-options.def
|
rm -f qemu-options.def
|
||||||
find . -name '*.[oda]' -type f -exec rm -f {} +
|
find . \( -name '*.l[oa]' -o -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
|
||||||
find . -name '*.l[oa]' -type f -exec rm -f {} +
|
|
||||||
find . -name '*$(DSOSUF)' -type f -exec rm -f {} +
|
|
||||||
find . -name '*.mo' -type f -exec rm -f {} +
|
|
||||||
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
|
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
|
||||||
rm -f fsdev/*.pod
|
rm -f fsdev/*.pod
|
||||||
rm -rf .libs */.libs
|
rm -rf .libs */.libs
|
||||||
@@ -399,7 +396,7 @@ endif
|
|||||||
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
|
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
|
||||||
done
|
done
|
||||||
for d in $(TARGET_DIRS); do \
|
for d in $(TARGET_DIRS); do \
|
||||||
$(MAKE) -C $$d $@ || exit 1 ; \
|
$(MAKE) $(SUBDIR_MAKEFLAGS) TARGET_DIR=$$d/ -C $$d $@ || exit 1 ; \
|
||||||
done
|
done
|
||||||
|
|
||||||
# various test targets
|
# various test targets
|
||||||
|
|||||||
@@ -21,11 +21,6 @@ block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
|
|||||||
|
|
||||||
block-obj-m = block/
|
block-obj-m = block/
|
||||||
|
|
||||||
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
|
|
||||||
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
|
|
||||||
# only pull in the actual virtio-9p device if we also enabled virtio.
|
|
||||||
CONFIG_REALLY_VIRTFS=y
|
|
||||||
endif
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# smartcard
|
# smartcard
|
||||||
@@ -44,6 +39,7 @@ libcacard-y += libcacard/vcardt.o
|
|||||||
|
|
||||||
ifeq ($(CONFIG_SOFTMMU),y)
|
ifeq ($(CONFIG_SOFTMMU),y)
|
||||||
common-obj-y = blockdev.o blockdev-nbd.o block/
|
common-obj-y = blockdev.o blockdev-nbd.o block/
|
||||||
|
common-obj-y += iothread.o
|
||||||
common-obj-y += net/
|
common-obj-y += net/
|
||||||
common-obj-y += qdev-monitor.o device-hotplug.o
|
common-obj-y += qdev-monitor.o device-hotplug.o
|
||||||
common-obj-$(CONFIG_WIN32) += os-win32.o
|
common-obj-$(CONFIG_WIN32) += os-win32.o
|
||||||
|
|||||||
52
arch_init.c
52
arch_init.c
@@ -164,8 +164,9 @@ static struct {
|
|||||||
uint8_t *encoded_buf;
|
uint8_t *encoded_buf;
|
||||||
/* buffer for storing page content */
|
/* buffer for storing page content */
|
||||||
uint8_t *current_buf;
|
uint8_t *current_buf;
|
||||||
/* Cache for XBZRLE */
|
/* Cache for XBZRLE, Protected by lock. */
|
||||||
PageCache *cache;
|
PageCache *cache;
|
||||||
|
QemuMutex lock;
|
||||||
} XBZRLE = {
|
} XBZRLE = {
|
||||||
.encoded_buf = NULL,
|
.encoded_buf = NULL,
|
||||||
.current_buf = NULL,
|
.current_buf = NULL,
|
||||||
@@ -174,16 +175,52 @@ static struct {
|
|||||||
/* buffer used for XBZRLE decoding */
|
/* buffer used for XBZRLE decoding */
|
||||||
static uint8_t *xbzrle_decoded_buf;
|
static uint8_t *xbzrle_decoded_buf;
|
||||||
|
|
||||||
|
static void XBZRLE_cache_lock(void)
|
||||||
|
{
|
||||||
|
if (migrate_use_xbzrle())
|
||||||
|
qemu_mutex_lock(&XBZRLE.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void XBZRLE_cache_unlock(void)
|
||||||
|
{
|
||||||
|
if (migrate_use_xbzrle())
|
||||||
|
qemu_mutex_unlock(&XBZRLE.lock);
|
||||||
|
}
|
||||||
|
|
||||||
int64_t xbzrle_cache_resize(int64_t new_size)
|
int64_t xbzrle_cache_resize(int64_t new_size)
|
||||||
{
|
{
|
||||||
|
PageCache *new_cache, *cache_to_free;
|
||||||
|
|
||||||
if (new_size < TARGET_PAGE_SIZE) {
|
if (new_size < TARGET_PAGE_SIZE) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* no need to lock, the current thread holds qemu big lock */
|
||||||
if (XBZRLE.cache != NULL) {
|
if (XBZRLE.cache != NULL) {
|
||||||
return cache_resize(XBZRLE.cache, new_size / TARGET_PAGE_SIZE) *
|
/* check XBZRLE.cache again later */
|
||||||
TARGET_PAGE_SIZE;
|
if (pow2floor(new_size) == migrate_xbzrle_cache_size()) {
|
||||||
|
return pow2floor(new_size);
|
||||||
}
|
}
|
||||||
|
new_cache = cache_init(new_size / TARGET_PAGE_SIZE,
|
||||||
|
TARGET_PAGE_SIZE);
|
||||||
|
if (!new_cache) {
|
||||||
|
DPRINTF("Error creating cache\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
XBZRLE_cache_lock();
|
||||||
|
/* the XBZRLE.cache may have be destroyed, check it again */
|
||||||
|
if (XBZRLE.cache != NULL) {
|
||||||
|
cache_to_free = XBZRLE.cache;
|
||||||
|
XBZRLE.cache = new_cache;
|
||||||
|
} else {
|
||||||
|
cache_to_free = new_cache;
|
||||||
|
}
|
||||||
|
XBZRLE_cache_unlock();
|
||||||
|
|
||||||
|
cache_fini(cache_to_free);
|
||||||
|
}
|
||||||
|
|
||||||
return pow2floor(new_size);
|
return pow2floor(new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,6 +576,8 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
|
|||||||
ret = ram_control_save_page(f, block->offset,
|
ret = ram_control_save_page(f, block->offset,
|
||||||
offset, TARGET_PAGE_SIZE, &bytes_sent);
|
offset, TARGET_PAGE_SIZE, &bytes_sent);
|
||||||
|
|
||||||
|
XBZRLE_cache_lock();
|
||||||
|
|
||||||
current_addr = block->offset + offset;
|
current_addr = block->offset + offset;
|
||||||
if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
|
if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
|
||||||
if (ret != RAM_SAVE_CONTROL_DELAYED) {
|
if (ret != RAM_SAVE_CONTROL_DELAYED) {
|
||||||
@@ -587,6 +626,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
|
|||||||
acct_info.norm_pages++;
|
acct_info.norm_pages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XBZRLE_cache_unlock();
|
||||||
/* if page is unmodified, continue to the next */
|
/* if page is unmodified, continue to the next */
|
||||||
if (bytes_sent > 0) {
|
if (bytes_sent > 0) {
|
||||||
last_sent_block = block;
|
last_sent_block = block;
|
||||||
@@ -654,6 +694,7 @@ static void migration_end(void)
|
|||||||
migration_bitmap = NULL;
|
migration_bitmap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XBZRLE_cache_lock();
|
||||||
if (XBZRLE.cache) {
|
if (XBZRLE.cache) {
|
||||||
cache_fini(XBZRLE.cache);
|
cache_fini(XBZRLE.cache);
|
||||||
g_free(XBZRLE.cache);
|
g_free(XBZRLE.cache);
|
||||||
@@ -663,6 +704,7 @@ static void migration_end(void)
|
|||||||
XBZRLE.encoded_buf = NULL;
|
XBZRLE.encoded_buf = NULL;
|
||||||
XBZRLE.current_buf = NULL;
|
XBZRLE.current_buf = NULL;
|
||||||
}
|
}
|
||||||
|
XBZRLE_cache_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ram_migration_cancel(void *opaque)
|
static void ram_migration_cancel(void *opaque)
|
||||||
@@ -693,13 +735,17 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
|
|||||||
dirty_rate_high_cnt = 0;
|
dirty_rate_high_cnt = 0;
|
||||||
|
|
||||||
if (migrate_use_xbzrle()) {
|
if (migrate_use_xbzrle()) {
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
|
XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
|
||||||
TARGET_PAGE_SIZE,
|
TARGET_PAGE_SIZE,
|
||||||
TARGET_PAGE_SIZE);
|
TARGET_PAGE_SIZE);
|
||||||
if (!XBZRLE.cache) {
|
if (!XBZRLE.cache) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
DPRINTF("Error creating cache\n");
|
DPRINTF("Error creating cache\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
qemu_mutex_init(&XBZRLE.lock);
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
/* We prefer not to abort if there is no memory */
|
/* We prefer not to abort if there is no memory */
|
||||||
XBZRLE.encoded_buf = g_try_malloc0(TARGET_PAGE_SIZE);
|
XBZRLE.encoded_buf = g_try_malloc0(TARGET_PAGE_SIZE);
|
||||||
|
|||||||
18
async.c
18
async.c
@@ -214,6 +214,7 @@ aio_ctx_finalize(GSource *source)
|
|||||||
thread_pool_free(ctx->thread_pool);
|
thread_pool_free(ctx->thread_pool);
|
||||||
aio_set_event_notifier(ctx, &ctx->notifier, NULL);
|
aio_set_event_notifier(ctx, &ctx->notifier, NULL);
|
||||||
event_notifier_cleanup(&ctx->notifier);
|
event_notifier_cleanup(&ctx->notifier);
|
||||||
|
rfifolock_destroy(&ctx->lock);
|
||||||
qemu_mutex_destroy(&ctx->bh_lock);
|
qemu_mutex_destroy(&ctx->bh_lock);
|
||||||
g_array_free(ctx->pollfds, TRUE);
|
g_array_free(ctx->pollfds, TRUE);
|
||||||
timerlistgroup_deinit(&ctx->tlg);
|
timerlistgroup_deinit(&ctx->tlg);
|
||||||
@@ -250,6 +251,12 @@ static void aio_timerlist_notify(void *opaque)
|
|||||||
aio_notify(opaque);
|
aio_notify(opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void aio_rfifolock_cb(void *opaque)
|
||||||
|
{
|
||||||
|
/* Kick owner thread in case they are blocked in aio_poll() */
|
||||||
|
aio_notify(opaque);
|
||||||
|
}
|
||||||
|
|
||||||
AioContext *aio_context_new(void)
|
AioContext *aio_context_new(void)
|
||||||
{
|
{
|
||||||
AioContext *ctx;
|
AioContext *ctx;
|
||||||
@@ -257,6 +264,7 @@ AioContext *aio_context_new(void)
|
|||||||
ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
|
ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
|
||||||
ctx->thread_pool = NULL;
|
ctx->thread_pool = NULL;
|
||||||
qemu_mutex_init(&ctx->bh_lock);
|
qemu_mutex_init(&ctx->bh_lock);
|
||||||
|
rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx);
|
||||||
event_notifier_init(&ctx->notifier, false);
|
event_notifier_init(&ctx->notifier, false);
|
||||||
aio_set_event_notifier(ctx, &ctx->notifier,
|
aio_set_event_notifier(ctx, &ctx->notifier,
|
||||||
(EventNotifierHandler *)
|
(EventNotifierHandler *)
|
||||||
@@ -275,3 +283,13 @@ void aio_context_unref(AioContext *ctx)
|
|||||||
{
|
{
|
||||||
g_source_unref(&ctx->source);
|
g_source_unref(&ctx->source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_context_acquire(AioContext *ctx)
|
||||||
|
{
|
||||||
|
rfifolock_lock(&ctx->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void aio_context_release(AioContext *ctx)
|
||||||
|
{
|
||||||
|
rfifolock_unlock(&ctx->lock);
|
||||||
|
}
|
||||||
|
|||||||
112
block.c
112
block.c
@@ -935,7 +935,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
|
|
||||||
bdrv_refresh_limits(bs);
|
bdrv_refresh_limits(bs);
|
||||||
assert(bdrv_opt_mem_align(bs) != 0);
|
assert(bdrv_opt_mem_align(bs) != 0);
|
||||||
assert(bs->request_alignment != 0);
|
assert((bs->request_alignment != 0) || bs->sg);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (bs->is_temporary) {
|
if (bs->is_temporary) {
|
||||||
@@ -1017,7 +1017,12 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!drv->bdrv_needs_filename) {
|
||||||
qdict_del(*options, "filename");
|
qdict_del(*options, "filename");
|
||||||
|
} else {
|
||||||
|
filename = qdict_get_str(*options, "filename");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drv->bdrv_file_open) {
|
if (!drv->bdrv_file_open) {
|
||||||
@@ -1229,6 +1234,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
ret = bdrv_file_open(bs, filename, &options, flags & ~BDRV_O_PROTOCOL,
|
ret = bdrv_file_open(bs, filename, &options, flags & ~BDRV_O_PROTOCOL,
|
||||||
&local_err);
|
&local_err);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
drv = bs->drv;
|
||||||
goto done;
|
goto done;
|
||||||
} else if (bs->drv) {
|
} else if (bs->drv) {
|
||||||
goto close_and_fail;
|
goto close_and_fail;
|
||||||
@@ -1315,7 +1321,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
bdrv_open_flags(bs, flags | BDRV_O_UNMAP) |
|
bdrv_open_flags(bs, flags | BDRV_O_UNMAP) |
|
||||||
BDRV_O_PROTOCOL, true, &local_err);
|
BDRV_O_PROTOCOL, true, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto unlink_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the right image format driver */
|
/* Find the right image format driver */
|
||||||
@@ -1382,12 +1388,19 @@ done:
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto close_and_fail;
|
goto close_and_fail;
|
||||||
}
|
}
|
||||||
QDECREF(options);
|
|
||||||
|
|
||||||
if (!bdrv_key_required(bs)) {
|
if (!bdrv_key_required(bs)) {
|
||||||
bdrv_dev_change_media_cb(bs, true);
|
bdrv_dev_change_media_cb(bs, true);
|
||||||
|
} else if (!runstate_check(RUN_STATE_PRELAUNCH)
|
||||||
|
&& !runstate_check(RUN_STATE_INMIGRATE)
|
||||||
|
&& !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
|
||||||
|
error_setg(errp,
|
||||||
|
"Guest must be stopped for opening of encrypted image");
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto close_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDECREF(options);
|
||||||
*pbs = bs;
|
*pbs = bs;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -1847,11 +1860,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
|
|||||||
pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
|
pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
|
||||||
bs_src->device_name);
|
bs_src->device_name);
|
||||||
bs_dest->device_list = bs_src->device_list;
|
bs_dest->device_list = bs_src->device_list;
|
||||||
|
|
||||||
/* keep the same entry in graph_bdrv_states
|
|
||||||
* We do want to swap name but don't want to swap linked list entries
|
|
||||||
*/
|
|
||||||
bs_dest->node_list = bs_src->node_list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1870,6 +1878,17 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
|
|||||||
{
|
{
|
||||||
BlockDriverState tmp;
|
BlockDriverState tmp;
|
||||||
|
|
||||||
|
/* The code needs to swap the node_name but simply swapping node_list won't
|
||||||
|
* work so first remove the nodes from the graph list, do the swap then
|
||||||
|
* insert them back if needed.
|
||||||
|
*/
|
||||||
|
if (bs_new->node_name[0] != '\0') {
|
||||||
|
QTAILQ_REMOVE(&graph_bdrv_states, bs_new, node_list);
|
||||||
|
}
|
||||||
|
if (bs_old->node_name[0] != '\0') {
|
||||||
|
QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
|
||||||
|
}
|
||||||
|
|
||||||
/* bs_new must be anonymous and shouldn't have anything fancy enabled */
|
/* bs_new must be anonymous and shouldn't have anything fancy enabled */
|
||||||
assert(bs_new->device_name[0] == '\0');
|
assert(bs_new->device_name[0] == '\0');
|
||||||
assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
|
assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
|
||||||
@@ -1898,6 +1917,14 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
|
|||||||
assert(bs_new->io_limits_enabled == false);
|
assert(bs_new->io_limits_enabled == false);
|
||||||
assert(!throttle_have_timer(&bs_new->throttle_state));
|
assert(!throttle_have_timer(&bs_new->throttle_state));
|
||||||
|
|
||||||
|
/* insert the nodes back into the graph node list if needed */
|
||||||
|
if (bs_new->node_name[0] != '\0') {
|
||||||
|
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_new, node_list);
|
||||||
|
}
|
||||||
|
if (bs_old->node_name[0] != '\0') {
|
||||||
|
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_old, node_list);
|
||||||
|
}
|
||||||
|
|
||||||
bdrv_rebind(bs_new);
|
bdrv_rebind(bs_new);
|
||||||
bdrv_rebind(bs_old);
|
bdrv_rebind(bs_old);
|
||||||
}
|
}
|
||||||
@@ -4035,7 +4062,7 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)
|
|||||||
|
|
||||||
int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
|
int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
|
||||||
{
|
{
|
||||||
while (bs && bs->drv && !bs->drv->bdrv_debug_resume) {
|
while (bs && (!bs->drv || !bs->drv->bdrv_debug_resume)) {
|
||||||
bs = bs->file;
|
bs = bs->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4756,9 +4783,17 @@ flush_parent:
|
|||||||
|
|
||||||
void bdrv_invalidate_cache(BlockDriverState *bs)
|
void bdrv_invalidate_cache(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
if (bs->drv && bs->drv->bdrv_invalidate_cache) {
|
if (!bs->drv) {
|
||||||
bs->drv->bdrv_invalidate_cache(bs);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bs->drv->bdrv_invalidate_cache) {
|
||||||
|
bs->drv->bdrv_invalidate_cache(bs);
|
||||||
|
} else if (bs->file) {
|
||||||
|
bdrv_invalidate_cache(bs->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh_total_sectors(bs, bs->total_sectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bdrv_invalidate_cache_all(void)
|
void bdrv_invalidate_cache_all(void)
|
||||||
@@ -5370,43 +5405,37 @@ int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options)
|
|||||||
return bs->drv->bdrv_amend_options(bs, options);
|
return bs->drv->bdrv_amend_options(bs, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to recurse on single child block filters.
|
/* This function will be called by the bdrv_recurse_is_first_non_filter method
|
||||||
* Single child block filter will store their child in bs->file.
|
* of block filter and by bdrv_is_first_non_filter.
|
||||||
|
* It is used to test if the given bs is the candidate or recurse more in the
|
||||||
|
* node graph.
|
||||||
*/
|
*/
|
||||||
bool bdrv_generic_is_first_non_filter(BlockDriverState *bs,
|
|
||||||
BlockDriverState *candidate)
|
|
||||||
{
|
|
||||||
if (!bs->drv) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bs->drv->authorizations[BS_IS_A_FILTER]) {
|
|
||||||
if (bs == candidate) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bs->drv->authorizations[BS_FILTER_PASS_DOWN]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bs->file) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bdrv_recurse_is_first_non_filter(bs->file, candidate);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
|
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
|
||||||
BlockDriverState *candidate)
|
BlockDriverState *candidate)
|
||||||
{
|
{
|
||||||
if (bs->drv && bs->drv->bdrv_recurse_is_first_non_filter) {
|
/* return false if basic checks fails */
|
||||||
|
if (!bs || !bs->drv) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the code reached a non block filter driver -> check if the bs is
|
||||||
|
* the same as the candidate. It's the recursion termination condition.
|
||||||
|
*/
|
||||||
|
if (!bs->drv->is_filter) {
|
||||||
|
return bs == candidate;
|
||||||
|
}
|
||||||
|
/* Down this path the driver is a block filter driver */
|
||||||
|
|
||||||
|
/* If the block filter recursion method is defined use it to recurse down
|
||||||
|
* the node graph.
|
||||||
|
*/
|
||||||
|
if (bs->drv->bdrv_recurse_is_first_non_filter) {
|
||||||
return bs->drv->bdrv_recurse_is_first_non_filter(bs, candidate);
|
return bs->drv->bdrv_recurse_is_first_non_filter(bs, candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bdrv_generic_is_first_non_filter(bs, candidate);
|
/* the driver is a block filter but don't allow to recurse -> return false
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function checks if the candidate is the first non filter bs down it's
|
/* This function checks if the candidate is the first non filter bs down it's
|
||||||
@@ -5421,6 +5450,7 @@ bool bdrv_is_first_non_filter(BlockDriverState *candidate)
|
|||||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||||
bool perm;
|
bool perm;
|
||||||
|
|
||||||
|
/* try to recurse in this top level bs */
|
||||||
perm = bdrv_recurse_is_first_non_filter(bs, candidate);
|
perm = bdrv_recurse_is_first_non_filter(bs, candidate);
|
||||||
|
|
||||||
/* candidate is the first non filter */
|
/* candidate is the first non filter */
|
||||||
|
|||||||
@@ -288,6 +288,20 @@ static BlockDriverAIOCB *blkverify_aio_flush(BlockDriverState *bs,
|
|||||||
return bdrv_aio_flush(s->test_file, cb, opaque);
|
return bdrv_aio_flush(s->test_file, cb, opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
|
||||||
|
BlockDriverState *candidate)
|
||||||
|
{
|
||||||
|
BDRVBlkverifyState *s = bs->opaque;
|
||||||
|
|
||||||
|
bool perm = bdrv_recurse_is_first_non_filter(bs->file, candidate);
|
||||||
|
|
||||||
|
if (perm) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bdrv_recurse_is_first_non_filter(s->test_file, candidate);
|
||||||
|
}
|
||||||
|
|
||||||
static BlockDriver bdrv_blkverify = {
|
static BlockDriver bdrv_blkverify = {
|
||||||
.format_name = "blkverify",
|
.format_name = "blkverify",
|
||||||
.protocol_name = "blkverify",
|
.protocol_name = "blkverify",
|
||||||
@@ -302,7 +316,8 @@ static BlockDriver bdrv_blkverify = {
|
|||||||
.bdrv_aio_writev = blkverify_aio_writev,
|
.bdrv_aio_writev = blkverify_aio_writev,
|
||||||
.bdrv_aio_flush = blkverify_aio_flush,
|
.bdrv_aio_flush = blkverify_aio_flush,
|
||||||
|
|
||||||
.authorizations = { true, false },
|
.is_filter = true,
|
||||||
|
.bdrv_recurse_is_first_non_filter = blkverify_recurse_is_first_non_filter,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bdrv_blkverify_init(void)
|
static void bdrv_blkverify_init(void)
|
||||||
|
|||||||
@@ -3,21 +3,12 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
|
* Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
|
||||||
*
|
*
|
||||||
* Pipe handling mechanism in AIO implementation is derived from
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
* block/rbd.c. Hence,
|
* See the COPYING file in the top-level directory.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2011 Christian Brunner <chb@muc.de>,
|
|
||||||
* Josh Durgin <josh.durgin@dreamhost.com>
|
|
||||||
*
|
|
||||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
||||||
* the COPYING file in the top-level directory.
|
|
||||||
*
|
|
||||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
|
||||||
* GNU GPL, version 2 or (at your option) any later version.
|
|
||||||
*/
|
*/
|
||||||
#include <glusterfs/api/glfs.h>
|
#include <glusterfs/api/glfs.h>
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "qemu/sockets.h"
|
|
||||||
#include "qemu/uri.h"
|
#include "qemu/uri.h"
|
||||||
|
|
||||||
typedef struct GlusterAIOCB {
|
typedef struct GlusterAIOCB {
|
||||||
@@ -32,9 +23,6 @@ typedef struct BDRVGlusterState {
|
|||||||
struct glfs_fd *fd;
|
struct glfs_fd *fd;
|
||||||
} BDRVGlusterState;
|
} BDRVGlusterState;
|
||||||
|
|
||||||
#define GLUSTER_FD_READ 0
|
|
||||||
#define GLUSTER_FD_WRITE 1
|
|
||||||
|
|
||||||
typedef struct GlusterConf {
|
typedef struct GlusterConf {
|
||||||
char *server;
|
char *server;
|
||||||
int port;
|
int port;
|
||||||
|
|||||||
@@ -1231,12 +1231,11 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
|
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
|
||||||
bs->request_alignment = iscsilun->block_size;
|
bs->request_alignment = iscsilun->block_size;
|
||||||
|
|
||||||
/* Medium changer or tape. We dont have any emulation for this so this must
|
/* We don't have any emulation for devices other than disks and CD-ROMs, so
|
||||||
* be sg ioctl compatible. We force it to be sg, otherwise qemu will try
|
* this must be sg ioctl compatible. We force it to be sg, otherwise qemu
|
||||||
* to read from the device to guess the image format.
|
* will try to read from the device to guess the image format.
|
||||||
*/
|
*/
|
||||||
if (iscsilun->type == TYPE_MEDIUM_CHANGER ||
|
if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) {
|
||||||
iscsilun->type == TYPE_TAPE) {
|
|
||||||
bs->sg = 1;
|
bs->sg = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -520,9 +520,6 @@ static void mirror_complete(BlockJob *job, Error **errp)
|
|||||||
|
|
||||||
ret = bdrv_open_backing_file(s->target, NULL, &local_err);
|
ret = bdrv_open_backing_file(s->target, NULL, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
char backing_filename[PATH_MAX];
|
|
||||||
bdrv_get_full_backing_filename(s->target, backing_filename,
|
|
||||||
sizeof(backing_filename));
|
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,17 @@ static void nbd_recv_coroutines_enter_all(NbdClientSession *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nbd_teardown_connection(NbdClientSession *client)
|
||||||
|
{
|
||||||
|
/* finish any pending coroutines */
|
||||||
|
shutdown(client->sock, 2);
|
||||||
|
nbd_recv_coroutines_enter_all(client);
|
||||||
|
|
||||||
|
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
||||||
|
closesocket(client->sock);
|
||||||
|
client->sock = -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void nbd_reply_ready(void *opaque)
|
static void nbd_reply_ready(void *opaque)
|
||||||
{
|
{
|
||||||
NbdClientSession *s = opaque;
|
NbdClientSession *s = opaque;
|
||||||
@@ -78,7 +89,7 @@ static void nbd_reply_ready(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
nbd_recv_coroutines_enter_all(s);
|
nbd_teardown_connection(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nbd_restart_write(void *opaque)
|
static void nbd_restart_write(void *opaque)
|
||||||
@@ -324,7 +335,7 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nbd_teardown_connection(NbdClientSession *client)
|
void nbd_client_session_close(NbdClientSession *client)
|
||||||
{
|
{
|
||||||
struct nbd_request request = {
|
struct nbd_request request = {
|
||||||
.type = NBD_CMD_DISC,
|
.type = NBD_CMD_DISC,
|
||||||
@@ -332,22 +343,14 @@ static void nbd_teardown_connection(NbdClientSession *client)
|
|||||||
.len = 0
|
.len = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
nbd_send_request(client->sock, &request);
|
|
||||||
|
|
||||||
/* finish any pending coroutines */
|
|
||||||
shutdown(client->sock, 2);
|
|
||||||
nbd_recv_coroutines_enter_all(client);
|
|
||||||
|
|
||||||
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
|
||||||
closesocket(client->sock);
|
|
||||||
client->sock = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nbd_client_session_close(NbdClientSession *client)
|
|
||||||
{
|
|
||||||
if (!client->bs) {
|
if (!client->bs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (client->sock == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbd_send_request(client->sock, &request);
|
||||||
|
|
||||||
nbd_teardown_connection(client);
|
nbd_teardown_connection(client);
|
||||||
client->bs = NULL;
|
client->bs = NULL;
|
||||||
|
|||||||
@@ -380,6 +380,10 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
|
|||||||
|
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
|
BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
|
||||||
|
|
||||||
|
if (!bs->drv) {
|
||||||
|
return -ENOMEDIUM;
|
||||||
|
}
|
||||||
|
|
||||||
/* Call .bdrv_co_readv() directly instead of using the public block-layer
|
/* Call .bdrv_co_readv() directly instead of using the public block-layer
|
||||||
* interface. This avoids double I/O throttling and request tracking,
|
* interface. This avoids double I/O throttling and request tracking,
|
||||||
* which can lead to deadlock when block layer copy-on-read is enabled.
|
* which can lead to deadlock when block layer copy-on-read is enabled.
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
|
|||||||
refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
|
refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
|
||||||
if (refcount_table_index >= s->refcount_table_size)
|
if (refcount_table_index >= s->refcount_table_size)
|
||||||
return 0;
|
return 0;
|
||||||
refcount_block_offset = s->refcount_table[refcount_table_index];
|
refcount_block_offset =
|
||||||
|
s->refcount_table[refcount_table_index] & REFT_OFFSET_MASK;
|
||||||
if (!refcount_block_offset)
|
if (!refcount_block_offset)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -644,7 +644,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Clear unknown autoclear feature bits */
|
/* Clear unknown autoclear feature bits */
|
||||||
if (!bs->read_only && s->autoclear_features != 0) {
|
if (!bs->read_only && !(flags & BDRV_O_INCOMING) && s->autoclear_features) {
|
||||||
s->autoclear_features = 0;
|
s->autoclear_features = 0;
|
||||||
ret = qcow2_update_header(bs);
|
ret = qcow2_update_header(bs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -657,7 +657,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
qemu_co_mutex_init(&s->lock);
|
qemu_co_mutex_init(&s->lock);
|
||||||
|
|
||||||
/* Repair image if dirty */
|
/* Repair image if dirty */
|
||||||
if (!(flags & BDRV_O_CHECK) && !bs->read_only &&
|
if (!(flags & (BDRV_O_CHECK | BDRV_O_INCOMING)) && !bs->read_only &&
|
||||||
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
|
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
|
||||||
BdrvCheckResult result = {0};
|
BdrvCheckResult result = {0};
|
||||||
|
|
||||||
@@ -1137,10 +1137,12 @@ static void qcow2_close(BlockDriverState *bs)
|
|||||||
/* else pre-write overlap checks in cache_destroy may crash */
|
/* else pre-write overlap checks in cache_destroy may crash */
|
||||||
s->l1_table = NULL;
|
s->l1_table = NULL;
|
||||||
|
|
||||||
|
if (!(bs->open_flags & BDRV_O_INCOMING)) {
|
||||||
qcow2_cache_flush(bs, s->l2_table_cache);
|
qcow2_cache_flush(bs, s->l2_table_cache);
|
||||||
qcow2_cache_flush(bs, s->refcount_block_cache);
|
qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||||
|
|
||||||
qcow2_mark_clean(bs);
|
qcow2_mark_clean(bs);
|
||||||
|
}
|
||||||
|
|
||||||
qcow2_cache_destroy(bs, s->l2_table_cache);
|
qcow2_cache_destroy(bs, s->l2_table_cache);
|
||||||
qcow2_cache_destroy(bs, s->refcount_block_cache);
|
qcow2_cache_destroy(bs, s->refcount_block_cache);
|
||||||
@@ -1176,11 +1178,10 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
|
|||||||
|
|
||||||
qcow2_close(bs);
|
qcow2_close(bs);
|
||||||
|
|
||||||
options = qdict_new();
|
bdrv_invalidate_cache(bs->file);
|
||||||
qdict_put(options, QCOW2_OPT_LAZY_REFCOUNTS,
|
|
||||||
qbool_from_int(s->use_lazy_refcounts));
|
|
||||||
|
|
||||||
memset(s, 0, sizeof(BDRVQcowState));
|
memset(s, 0, sizeof(BDRVQcowState));
|
||||||
|
options = qdict_clone_shallow(bs->options);
|
||||||
qcow2_open(bs, options, flags, NULL);
|
qcow2_open(bs, options, flags, NULL);
|
||||||
|
|
||||||
QDECREF(options);
|
QDECREF(options);
|
||||||
|
|||||||
@@ -1563,6 +1563,9 @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs)
|
|||||||
BDRVQEDState *s = bs->opaque;
|
BDRVQEDState *s = bs->opaque;
|
||||||
|
|
||||||
bdrv_qed_close(bs);
|
bdrv_qed_close(bs);
|
||||||
|
|
||||||
|
bdrv_invalidate_cache(bs->file);
|
||||||
|
|
||||||
memset(s, 0, sizeof(BDRVQEDState));
|
memset(s, 0, sizeof(BDRVQEDState));
|
||||||
bdrv_qed_open(bs, NULL, bs->open_flags, NULL);
|
bdrv_qed_open(bs, NULL, bs->open_flags, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -852,8 +852,6 @@ static BlockDriver bdrv_quorum = {
|
|||||||
.bdrv_file_open = quorum_open,
|
.bdrv_file_open = quorum_open,
|
||||||
.bdrv_close = quorum_close,
|
.bdrv_close = quorum_close,
|
||||||
|
|
||||||
.authorizations = { true, true },
|
|
||||||
|
|
||||||
.bdrv_co_flush_to_disk = quorum_co_flush,
|
.bdrv_co_flush_to_disk = quorum_co_flush,
|
||||||
|
|
||||||
.bdrv_getlength = quorum_getlength,
|
.bdrv_getlength = quorum_getlength,
|
||||||
@@ -862,6 +860,7 @@ static BlockDriver bdrv_quorum = {
|
|||||||
.bdrv_aio_writev = quorum_aio_writev,
|
.bdrv_aio_writev = quorum_aio_writev,
|
||||||
.bdrv_invalidate_cache = quorum_invalidate_cache,
|
.bdrv_invalidate_cache = quorum_invalidate_cache,
|
||||||
|
|
||||||
|
.is_filter = true,
|
||||||
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -336,6 +336,17 @@ error:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void raw_parse_filename(const char *filename, QDict *options,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
/* The filename does not have to be prefixed by the protocol name, since
|
||||||
|
* "file" is the default protocol; therefore, the return value of this
|
||||||
|
* function call can be ignored. */
|
||||||
|
strstart(filename, "file:", &filename);
|
||||||
|
|
||||||
|
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
|
||||||
|
}
|
||||||
|
|
||||||
static QemuOptsList raw_runtime_opts = {
|
static QemuOptsList raw_runtime_opts = {
|
||||||
.name = "raw",
|
.name = "raw",
|
||||||
.head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
|
.head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
|
||||||
@@ -1230,6 +1241,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
int64_t total_size = 0;
|
int64_t total_size = 0;
|
||||||
|
|
||||||
|
strstart(filename, "file:", &filename);
|
||||||
|
|
||||||
/* Read out options */
|
/* Read out options */
|
||||||
while (options && options->name) {
|
while (options && options->name) {
|
||||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||||
@@ -1412,6 +1425,7 @@ static BlockDriver bdrv_file = {
|
|||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_needs_filename = true,
|
.bdrv_needs_filename = true,
|
||||||
.bdrv_probe = NULL, /* no probe for protocols */
|
.bdrv_probe = NULL, /* no probe for protocols */
|
||||||
|
.bdrv_parse_filename = raw_parse_filename,
|
||||||
.bdrv_file_open = raw_open,
|
.bdrv_file_open = raw_open,
|
||||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||||
.bdrv_reopen_commit = raw_reopen_commit,
|
.bdrv_reopen_commit = raw_reopen_commit,
|
||||||
@@ -1547,6 +1561,15 @@ static int check_hdev_writable(BDRVRawState *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hdev_parse_filename(const char *filename, QDict *options,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
/* The prefix is optional, just as for "file". */
|
||||||
|
strstart(filename, "host_device:", &filename);
|
||||||
|
|
||||||
|
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
|
||||||
|
}
|
||||||
|
|
||||||
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@@ -1753,6 +1776,18 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
int64_t total_size = 0;
|
int64_t total_size = 0;
|
||||||
|
bool has_prefix;
|
||||||
|
|
||||||
|
/* This function is used by all three protocol block drivers and therefore
|
||||||
|
* any of these three prefixes may be given.
|
||||||
|
* The return value has to be stored somewhere, otherwise this is an error
|
||||||
|
* due to -Werror=unused-value. */
|
||||||
|
has_prefix =
|
||||||
|
strstart(filename, "host_device:", &filename) ||
|
||||||
|
strstart(filename, "host_cdrom:" , &filename) ||
|
||||||
|
strstart(filename, "host_floppy:", &filename);
|
||||||
|
|
||||||
|
(void)has_prefix;
|
||||||
|
|
||||||
/* Read out options */
|
/* Read out options */
|
||||||
while (options && options->name) {
|
while (options && options->name) {
|
||||||
@@ -1791,6 +1826,7 @@ static BlockDriver bdrv_host_device = {
|
|||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_needs_filename = true,
|
.bdrv_needs_filename = true,
|
||||||
.bdrv_probe_device = hdev_probe_device,
|
.bdrv_probe_device = hdev_probe_device,
|
||||||
|
.bdrv_parse_filename = hdev_parse_filename,
|
||||||
.bdrv_file_open = hdev_open,
|
.bdrv_file_open = hdev_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||||
@@ -1820,6 +1856,15 @@ static BlockDriver bdrv_host_device = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
static void floppy_parse_filename(const char *filename, QDict *options,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
/* The prefix is optional, just as for "file". */
|
||||||
|
strstart(filename, "host_floppy:", &filename);
|
||||||
|
|
||||||
|
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
|
||||||
|
}
|
||||||
|
|
||||||
static int floppy_open(BlockDriverState *bs, QDict *options, int flags,
|
static int floppy_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@@ -1925,6 +1970,7 @@ static BlockDriver bdrv_host_floppy = {
|
|||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_needs_filename = true,
|
.bdrv_needs_filename = true,
|
||||||
.bdrv_probe_device = floppy_probe_device,
|
.bdrv_probe_device = floppy_probe_device,
|
||||||
|
.bdrv_parse_filename = floppy_parse_filename,
|
||||||
.bdrv_file_open = floppy_open,
|
.bdrv_file_open = floppy_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||||
@@ -1949,7 +1995,20 @@ static BlockDriver bdrv_host_floppy = {
|
|||||||
.bdrv_media_changed = floppy_media_changed,
|
.bdrv_media_changed = floppy_media_changed,
|
||||||
.bdrv_eject = floppy_eject,
|
.bdrv_eject = floppy_eject,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
static void cdrom_parse_filename(const char *filename, QDict *options,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
/* The prefix is optional, just as for "file". */
|
||||||
|
strstart(filename, "host_cdrom:", &filename);
|
||||||
|
|
||||||
|
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
static int cdrom_open(BlockDriverState *bs, QDict *options, int flags,
|
static int cdrom_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@@ -2036,6 +2095,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_needs_filename = true,
|
.bdrv_needs_filename = true,
|
||||||
.bdrv_probe_device = cdrom_probe_device,
|
.bdrv_probe_device = cdrom_probe_device,
|
||||||
|
.bdrv_parse_filename = cdrom_parse_filename,
|
||||||
.bdrv_file_open = cdrom_open,
|
.bdrv_file_open = cdrom_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||||
@@ -2166,6 +2226,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_needs_filename = true,
|
.bdrv_needs_filename = true,
|
||||||
.bdrv_probe_device = cdrom_probe_device,
|
.bdrv_probe_device = cdrom_probe_device,
|
||||||
|
.bdrv_parse_filename = cdrom_parse_filename,
|
||||||
.bdrv_file_open = cdrom_open,
|
.bdrv_file_open = cdrom_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||||
|
|||||||
@@ -251,6 +251,17 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void raw_parse_filename(const char *filename, QDict *options,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
/* The filename does not have to be prefixed by the protocol name, since
|
||||||
|
* "file" is the default protocol; therefore, the return value of this
|
||||||
|
* function call can be ignored. */
|
||||||
|
strstart(filename, "file:", &filename);
|
||||||
|
|
||||||
|
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
|
||||||
|
}
|
||||||
|
|
||||||
static QemuOptsList raw_runtime_opts = {
|
static QemuOptsList raw_runtime_opts = {
|
||||||
.name = "raw",
|
.name = "raw",
|
||||||
.head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
|
.head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head),
|
||||||
@@ -470,6 +481,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
int fd;
|
int fd;
|
||||||
int64_t total_size = 0;
|
int64_t total_size = 0;
|
||||||
|
|
||||||
|
strstart(filename, "file:", &filename);
|
||||||
|
|
||||||
/* Read out options */
|
/* Read out options */
|
||||||
while (options && options->name) {
|
while (options && options->name) {
|
||||||
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
|
||||||
@@ -504,6 +517,7 @@ static BlockDriver bdrv_file = {
|
|||||||
.protocol_name = "file",
|
.protocol_name = "file",
|
||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_needs_filename = true,
|
.bdrv_needs_filename = true,
|
||||||
|
.bdrv_parse_filename = raw_parse_filename,
|
||||||
.bdrv_file_open = raw_open,
|
.bdrv_file_open = raw_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = raw_create,
|
.bdrv_create = raw_create,
|
||||||
@@ -579,6 +593,15 @@ static int hdev_probe_device(const char *filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hdev_parse_filename(const char *filename, QDict *options,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
/* The prefix is optional, just as for "file". */
|
||||||
|
strstart(filename, "host_device:", &filename);
|
||||||
|
|
||||||
|
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
|
||||||
|
}
|
||||||
|
|
||||||
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@@ -649,6 +672,7 @@ static BlockDriver bdrv_host_device = {
|
|||||||
.protocol_name = "host_device",
|
.protocol_name = "host_device",
|
||||||
.instance_size = sizeof(BDRVRawState),
|
.instance_size = sizeof(BDRVRawState),
|
||||||
.bdrv_needs_filename = true,
|
.bdrv_needs_filename = true,
|
||||||
|
.bdrv_parse_filename = hdev_parse_filename,
|
||||||
.bdrv_probe_device = hdev_probe_device,
|
.bdrv_probe_device = hdev_probe_device,
|
||||||
.bdrv_file_open = hdev_open,
|
.bdrv_file_open = hdev_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
/* These structures are ones that are defined in the VHDX specification
|
/* These structures are ones that are defined in the VHDX specification
|
||||||
* document */
|
* document */
|
||||||
|
|
||||||
#define VHDX_FILE_SIGNATURE 0x656C696678646876 /* "vhdxfile" in ASCII */
|
#define VHDX_FILE_SIGNATURE 0x656C696678646876ULL /* "vhdxfile" in ASCII */
|
||||||
typedef struct VHDXFileIdentifier {
|
typedef struct VHDXFileIdentifier {
|
||||||
uint64_t signature; /* "vhdxfile" in ASCII */
|
uint64_t signature; /* "vhdxfile" in ASCII */
|
||||||
uint16_t creator[256]; /* optional; utf-16 string to identify
|
uint16_t creator[256]; /* optional; utf-16 string to identify
|
||||||
@@ -238,7 +238,7 @@ typedef struct QEMU_PACKED VHDXLogDataSector {
|
|||||||
/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
|
/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
|
||||||
other bits are reserved */
|
other bits are reserved */
|
||||||
#define VHDX_BAT_STATE_BIT_MASK 0x07
|
#define VHDX_BAT_STATE_BIT_MASK 0x07
|
||||||
#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000 /* upper 44 bits */
|
#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000ULL /* upper 44 bits */
|
||||||
typedef uint64_t VHDXBatEntry;
|
typedef uint64_t VHDXBatEntry;
|
||||||
|
|
||||||
/* ---- METADATA REGION STRUCTURES ---- */
|
/* ---- METADATA REGION STRUCTURES ---- */
|
||||||
@@ -247,7 +247,7 @@ typedef uint64_t VHDXBatEntry;
|
|||||||
#define VHDX_METADATA_MAX_ENTRIES 2047 /* not including the header */
|
#define VHDX_METADATA_MAX_ENTRIES 2047 /* not including the header */
|
||||||
#define VHDX_METADATA_TABLE_MAX_SIZE \
|
#define VHDX_METADATA_TABLE_MAX_SIZE \
|
||||||
(VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
|
(VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
|
||||||
#define VHDX_METADATA_SIGNATURE 0x617461646174656D /* "metadata" in ASCII */
|
#define VHDX_METADATA_SIGNATURE 0x617461646174656DULL /* "metadata" in ASCII */
|
||||||
typedef struct QEMU_PACKED VHDXMetadataTableHeader {
|
typedef struct QEMU_PACKED VHDXMetadataTableHeader {
|
||||||
uint64_t signature; /* "metadata" in ASCII */
|
uint64_t signature; /* "metadata" in ASCII */
|
||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
|
|||||||
15
blockdev.c
15
blockdev.c
@@ -2266,6 +2266,7 @@ void qmp_block_job_complete(const char *device, Error **errp)
|
|||||||
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||||
{
|
{
|
||||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||||
|
DriveInfo *dinfo;
|
||||||
QObject *obj;
|
QObject *obj;
|
||||||
QDict *qdict;
|
QDict *qdict;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@@ -2282,8 +2283,10 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
|||||||
*
|
*
|
||||||
* For now, simply forbidding the combination for all drivers will do. */
|
* For now, simply forbidding the combination for all drivers will do. */
|
||||||
if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
|
if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
|
||||||
bool direct = options->cache->has_direct && options->cache->direct;
|
bool direct = options->has_cache &&
|
||||||
if (!options->has_cache && !direct) {
|
options->cache->has_direct &&
|
||||||
|
options->cache->direct;
|
||||||
|
if (!direct) {
|
||||||
error_setg(errp, "aio=native requires cache.direct=true");
|
error_setg(errp, "aio=native requires cache.direct=true");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -2301,12 +2304,18 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
|||||||
|
|
||||||
qdict_flatten(qdict);
|
qdict_flatten(qdict);
|
||||||
|
|
||||||
blockdev_init(NULL, qdict, &local_err);
|
dinfo = blockdev_init(NULL, qdict, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bdrv_key_required(dinfo->bdrv)) {
|
||||||
|
drive_uninit(dinfo);
|
||||||
|
error_setg(errp, "blockdev-add doesn't support encrypted devices");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
qmp_output_visitor_cleanup(ov);
|
qmp_output_visitor_cleanup(ov);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1000,7 +1000,7 @@ int main(int argc, char **argv)
|
|||||||
memset(ts, 0, sizeof(TaskState));
|
memset(ts, 0, sizeof(TaskState));
|
||||||
init_task_state(ts);
|
init_task_state(ts);
|
||||||
ts->info = info;
|
ts->info = info;
|
||||||
env->opaque = ts;
|
cpu->opaque = ts;
|
||||||
|
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
cpu_x86_set_cpl(env, 3);
|
cpu_x86_set_cpl(env, 3);
|
||||||
|
|||||||
119
configure
vendored
119
configure
vendored
@@ -14,13 +14,14 @@ fi
|
|||||||
TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
|
TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
|
||||||
TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}"
|
TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}"
|
||||||
TMPO="${TMPDIR1}/${TMPB}.o"
|
TMPO="${TMPDIR1}/${TMPB}.o"
|
||||||
|
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
|
||||||
TMPL="${TMPDIR1}/${TMPB}.lo"
|
TMPL="${TMPDIR1}/${TMPB}.lo"
|
||||||
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
||||||
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
|
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
|
||||||
|
|
||||||
# NB: do not call "exit" in the trap handler; this is buggy with some shells;
|
# NB: do not call "exit" in the trap handler; this is buggy with some shells;
|
||||||
# see <1285349658-3122-1-git-send-email-loic.minier@linaro.org>
|
# see <1285349658-3122-1-git-send-email-loic.minier@linaro.org>
|
||||||
trap "rm -f $TMPC $TMPO $TMPE" EXIT INT QUIT TERM
|
trap "rm -f $TMPC $TMPO $TMPCXX $TMPE" EXIT INT QUIT TERM
|
||||||
rm -f config.log
|
rm -f config.log
|
||||||
|
|
||||||
# Print a helpful header at the top of config.log
|
# Print a helpful header at the top of config.log
|
||||||
@@ -30,19 +31,6 @@ printf " '%s'" "$0" "$@" >> config.log
|
|||||||
echo >> config.log
|
echo >> config.log
|
||||||
echo "#" >> config.log
|
echo "#" >> config.log
|
||||||
|
|
||||||
# Save the configure command line for later reuse.
|
|
||||||
cat <<EOD >config.status
|
|
||||||
#!/bin/sh
|
|
||||||
# Generated by configure.
|
|
||||||
# Run this file to recreate the current configuration.
|
|
||||||
# Compiler output produced by configure, useful for debugging
|
|
||||||
# configure, is in config.log if it exists.
|
|
||||||
EOD
|
|
||||||
printf "exec" >>config.status
|
|
||||||
printf " '%s'" "$0" "$@" >>config.status
|
|
||||||
echo >>config.status
|
|
||||||
chmod +x config.status
|
|
||||||
|
|
||||||
error_exit() {
|
error_exit() {
|
||||||
echo
|
echo
|
||||||
echo "ERROR: $1"
|
echo "ERROR: $1"
|
||||||
@@ -54,10 +42,13 @@ error_exit() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
do_cc() {
|
do_compiler() {
|
||||||
# Run the compiler, capturing its output to the log.
|
# Run the compiler, capturing its output to the log. First argument
|
||||||
echo $cc "$@" >> config.log
|
# is compiler binary to execute.
|
||||||
$cc "$@" >> config.log 2>&1 || return $?
|
local compiler="$1"
|
||||||
|
shift
|
||||||
|
echo $compiler "$@" >> config.log
|
||||||
|
$compiler "$@" >> config.log 2>&1 || return $?
|
||||||
# Test passed. If this is an --enable-werror build, rerun
|
# Test passed. If this is an --enable-werror build, rerun
|
||||||
# the test with -Werror and bail out if it fails. This
|
# the test with -Werror and bail out if it fails. This
|
||||||
# makes warning-generating-errors in configure test code
|
# makes warning-generating-errors in configure test code
|
||||||
@@ -71,14 +62,39 @@ do_cc() {
|
|||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo $cc -Werror "$@" >> config.log
|
echo $compiler -Werror "$@" >> config.log
|
||||||
$cc -Werror "$@" >> config.log 2>&1 && return $?
|
$compiler -Werror "$@" >> config.log 2>&1 && return $?
|
||||||
error_exit "configure test passed without -Werror but failed with -Werror." \
|
error_exit "configure test passed without -Werror but failed with -Werror." \
|
||||||
"This is probably a bug in the configure script. The failing command" \
|
"This is probably a bug in the configure script. The failing command" \
|
||||||
"will be at the bottom of config.log." \
|
"will be at the bottom of config.log." \
|
||||||
"You can run configure with --disable-werror to bypass this check."
|
"You can run configure with --disable-werror to bypass this check."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do_cc() {
|
||||||
|
do_compiler "$cc" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_cxx() {
|
||||||
|
do_compiler "$cxx" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_cxxflags() {
|
||||||
|
# Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those
|
||||||
|
# options which some versions of GCC's C++ compiler complain about
|
||||||
|
# because they only make sense for C programs.
|
||||||
|
QEMU_CXXFLAGS=
|
||||||
|
for arg in $QEMU_CFLAGS; do
|
||||||
|
case $arg in
|
||||||
|
-Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\
|
||||||
|
-Wold-style-declaration|-Wold-style-definition|-Wredundant-decls)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
compile_object() {
|
compile_object() {
|
||||||
do_cc $QEMU_CFLAGS -c -o $TMPO $TMPC
|
do_cc $QEMU_CFLAGS -c -o $TMPO $TMPC
|
||||||
}
|
}
|
||||||
@@ -373,7 +389,7 @@ sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}"
|
|||||||
ARFLAGS="${ARFLAGS-rv}"
|
ARFLAGS="${ARFLAGS-rv}"
|
||||||
|
|
||||||
# default flags for all hosts
|
# default flags for all hosts
|
||||||
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
|
QEMU_CFLAGS="-fno-strict-aliasing -fno-common $QEMU_CFLAGS"
|
||||||
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
|
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
|
||||||
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
|
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
|
||||||
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
|
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
|
||||||
@@ -1340,6 +1356,19 @@ if test "$ARCH" = "unknown"; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Consult white-list to determine whether to enable werror
|
||||||
|
# by default. Only enable by default for git builds
|
||||||
|
z_version=`cut -f3 -d. $source_path/VERSION`
|
||||||
|
|
||||||
|
if test -z "$werror" ; then
|
||||||
|
if test -d "$source_path/.git" -a \
|
||||||
|
"$linux" = "yes" ; then
|
||||||
|
werror="yes"
|
||||||
|
else
|
||||||
|
werror="no"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# check that the C compiler works.
|
# check that the C compiler works.
|
||||||
cat > $TMPC <<EOF
|
cat > $TMPC <<EOF
|
||||||
int main(void) { return 0; }
|
int main(void) { return 0; }
|
||||||
@@ -1360,14 +1389,16 @@ EOF
|
|||||||
|
|
||||||
compile_object
|
compile_object
|
||||||
|
|
||||||
cat > $TMPC <<EOF
|
cat > $TMPCXX <<EOF
|
||||||
extern "C" {
|
extern "C" {
|
||||||
int c_function(void);
|
int c_function(void);
|
||||||
}
|
}
|
||||||
int c_function(void) { return 42; }
|
int c_function(void) { return 42; }
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
if (cc=$cxx do_cc $QEMU_CFLAGS -o $TMPE $TMPC $TMPO $LDFLAGS); then
|
update_cxxflags
|
||||||
|
|
||||||
|
if do_cxx $QEMU_CXXFLAGS -o $TMPE $TMPCXX $TMPO $LDFLAGS; then
|
||||||
# C++ compiler $cxx works ok with C compiler $cc
|
# C++ compiler $cxx works ok with C compiler $cc
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
@@ -1380,19 +1411,6 @@ else
|
|||||||
cxx=
|
cxx=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Consult white-list to determine whether to enable werror
|
|
||||||
# by default. Only enable by default for git builds
|
|
||||||
z_version=`cut -f3 -d. $source_path/VERSION`
|
|
||||||
|
|
||||||
if test -z "$werror" ; then
|
|
||||||
if test -d "$source_path/.git" -a \
|
|
||||||
"$linux" = "yes" ; then
|
|
||||||
werror="yes"
|
|
||||||
else
|
|
||||||
werror="no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
|
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
|
||||||
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
|
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
|
||||||
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
|
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
|
||||||
@@ -3804,6 +3822,11 @@ fi
|
|||||||
|
|
||||||
int128=no
|
int128=no
|
||||||
cat > $TMPC << EOF
|
cat > $TMPC << EOF
|
||||||
|
#if defined(__clang_major__) && defined(__clang_minor__)
|
||||||
|
# if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2))
|
||||||
|
# error __int128_t does not work in CLANG before 3.2
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
__int128_t a;
|
__int128_t a;
|
||||||
__uint128_t b;
|
__uint128_t b;
|
||||||
int main (void) {
|
int main (void) {
|
||||||
@@ -4076,7 +4099,11 @@ echo "vhost-net support $vhost_net"
|
|||||||
echo "vhost-scsi support $vhost_scsi"
|
echo "vhost-scsi support $vhost_scsi"
|
||||||
echo "Trace backend $trace_backend"
|
echo "Trace backend $trace_backend"
|
||||||
echo "Trace output file $trace_file-<pid>"
|
echo "Trace output file $trace_file-<pid>"
|
||||||
|
if test "$spice" = "yes"; then
|
||||||
echo "spice support $spice ($spice_protocol_version/$spice_server_version)"
|
echo "spice support $spice ($spice_protocol_version/$spice_server_version)"
|
||||||
|
else
|
||||||
|
echo "spice support $spice"
|
||||||
|
fi
|
||||||
echo "rbd support $rbd"
|
echo "rbd support $rbd"
|
||||||
echo "xfsctl support $xfs"
|
echo "xfsctl support $xfs"
|
||||||
echo "nss used $smartcard_nss"
|
echo "nss used $smartcard_nss"
|
||||||
@@ -4937,6 +4964,12 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
|
|||||||
echo "CONFIG_ALPHA_DIS=y" >> $config_target_mak
|
echo "CONFIG_ALPHA_DIS=y" >> $config_target_mak
|
||||||
echo "CONFIG_ALPHA_DIS=y" >> config-all-disas.mak
|
echo "CONFIG_ALPHA_DIS=y" >> config-all-disas.mak
|
||||||
;;
|
;;
|
||||||
|
aarch64)
|
||||||
|
if test -n "${cxx}"; then
|
||||||
|
echo "CONFIG_ARM_A64_DIS=y" >> $config_target_mak
|
||||||
|
echo "CONFIG_ARM_A64_DIS=y" >> config-all-disas.mak
|
||||||
|
fi
|
||||||
|
;;
|
||||||
arm)
|
arm)
|
||||||
echo "CONFIG_ARM_DIS=y" >> $config_target_mak
|
echo "CONFIG_ARM_DIS=y" >> $config_target_mak
|
||||||
echo "CONFIG_ARM_DIS=y" >> config-all-disas.mak
|
echo "CONFIG_ARM_DIS=y" >> config-all-disas.mak
|
||||||
@@ -5105,3 +5138,17 @@ done
|
|||||||
if test "$docs" = "yes" ; then
|
if test "$docs" = "yes" ; then
|
||||||
mkdir -p QMP
|
mkdir -p QMP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Save the configure command line for later reuse.
|
||||||
|
cat <<EOD >config.status
|
||||||
|
#!/bin/sh
|
||||||
|
# Generated by configure.
|
||||||
|
# Run this file to recreate the current configuration.
|
||||||
|
# Compiler output produced by configure, useful for debugging
|
||||||
|
# configure, is in config.log if it exists.
|
||||||
|
EOD
|
||||||
|
printf "exec" >>config.status
|
||||||
|
printf " '%s'" "$0" "$@" >>config.status
|
||||||
|
echo >>config.status
|
||||||
|
chmod +x config.status
|
||||||
|
|
||||||
|
|||||||
106
cpu-exec.c
106
cpu-exec.c
@@ -23,29 +23,22 @@
|
|||||||
#include "qemu/atomic.h"
|
#include "qemu/atomic.h"
|
||||||
#include "sysemu/qtest.h"
|
#include "sysemu/qtest.h"
|
||||||
|
|
||||||
bool qemu_cpu_has_work(CPUState *cpu)
|
void cpu_loop_exit(CPUState *cpu)
|
||||||
{
|
{
|
||||||
return cpu_has_work(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cpu_loop_exit(CPUArchState *env)
|
|
||||||
{
|
|
||||||
CPUState *cpu = ENV_GET_CPU(env);
|
|
||||||
|
|
||||||
cpu->current_tb = NULL;
|
cpu->current_tb = NULL;
|
||||||
siglongjmp(env->jmp_env, 1);
|
siglongjmp(cpu->jmp_env, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exit the current TB from a signal handler. The host registers are
|
/* exit the current TB from a signal handler. The host registers are
|
||||||
restored in a state compatible with the CPU emulator
|
restored in a state compatible with the CPU emulator
|
||||||
*/
|
*/
|
||||||
#if defined(CONFIG_SOFTMMU)
|
#if defined(CONFIG_SOFTMMU)
|
||||||
void cpu_resume_from_signal(CPUArchState *env, void *puc)
|
void cpu_resume_from_signal(CPUState *cpu, void *puc)
|
||||||
{
|
{
|
||||||
/* XXX: restore cpu registers saved in host registers */
|
/* XXX: restore cpu registers saved in host registers */
|
||||||
|
|
||||||
env->exception_index = -1;
|
cpu->exception_index = -1;
|
||||||
siglongjmp(env->jmp_env, 1);
|
siglongjmp(cpu->jmp_env, 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -108,7 +101,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
|
|||||||
if (max_cycles > CF_COUNT_MASK)
|
if (max_cycles > CF_COUNT_MASK)
|
||||||
max_cycles = CF_COUNT_MASK;
|
max_cycles = CF_COUNT_MASK;
|
||||||
|
|
||||||
tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
|
tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
|
||||||
max_cycles);
|
max_cycles);
|
||||||
cpu->current_tb = tb;
|
cpu->current_tb = tb;
|
||||||
/* execute the generated code */
|
/* execute the generated code */
|
||||||
@@ -123,6 +116,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
|
|||||||
target_ulong cs_base,
|
target_ulong cs_base,
|
||||||
uint64_t flags)
|
uint64_t flags)
|
||||||
{
|
{
|
||||||
|
CPUState *cpu = ENV_GET_CPU(env);
|
||||||
TranslationBlock *tb, **ptb1;
|
TranslationBlock *tb, **ptb1;
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
tb_page_addr_t phys_pc, phys_page1;
|
tb_page_addr_t phys_pc, phys_page1;
|
||||||
@@ -160,7 +154,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
|
|||||||
}
|
}
|
||||||
not_found:
|
not_found:
|
||||||
/* if no translated code available, then translate it now */
|
/* if no translated code available, then translate it now */
|
||||||
tb = tb_gen_code(env, pc, cs_base, flags, 0);
|
tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
|
||||||
|
|
||||||
found:
|
found:
|
||||||
/* Move the last found TB to the head of the list */
|
/* Move the last found TB to the head of the list */
|
||||||
@@ -170,12 +164,13 @@ static TranslationBlock *tb_find_slow(CPUArchState *env,
|
|||||||
tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
|
tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
|
||||||
}
|
}
|
||||||
/* we add the TB in the virtual pc hash table */
|
/* we add the TB in the virtual pc hash table */
|
||||||
env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
|
cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline TranslationBlock *tb_find_fast(CPUArchState *env)
|
static inline TranslationBlock *tb_find_fast(CPUArchState *env)
|
||||||
{
|
{
|
||||||
|
CPUState *cpu = ENV_GET_CPU(env);
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
target_ulong cs_base, pc;
|
target_ulong cs_base, pc;
|
||||||
int flags;
|
int flags;
|
||||||
@@ -184,7 +179,7 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env)
|
|||||||
always be the same before a given translated block
|
always be the same before a given translated block
|
||||||
is executed. */
|
is executed. */
|
||||||
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
|
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
|
||||||
tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
|
tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
|
||||||
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
|
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
|
||||||
tb->flags != flags)) {
|
tb->flags != flags)) {
|
||||||
tb = tb_find_slow(env, pc, cs_base, flags);
|
tb = tb_find_slow(env, pc, cs_base, flags);
|
||||||
@@ -201,10 +196,11 @@ void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
|
|||||||
|
|
||||||
static void cpu_handle_debug_exception(CPUArchState *env)
|
static void cpu_handle_debug_exception(CPUArchState *env)
|
||||||
{
|
{
|
||||||
|
CPUState *cpu = ENV_GET_CPU(env);
|
||||||
CPUWatchpoint *wp;
|
CPUWatchpoint *wp;
|
||||||
|
|
||||||
if (!env->watchpoint_hit) {
|
if (!cpu->watchpoint_hit) {
|
||||||
QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
|
QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
|
||||||
wp->flags &= ~BP_WATCHPOINT_HIT;
|
wp->flags &= ~BP_WATCHPOINT_HIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,16 +279,16 @@ int cpu_exec(CPUArchState *env)
|
|||||||
#else
|
#else
|
||||||
#error unsupported target CPU
|
#error unsupported target CPU
|
||||||
#endif
|
#endif
|
||||||
env->exception_index = -1;
|
cpu->exception_index = -1;
|
||||||
|
|
||||||
/* prepare setjmp context for exception handling */
|
/* prepare setjmp context for exception handling */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (sigsetjmp(env->jmp_env, 0) == 0) {
|
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
|
||||||
/* if an exception is pending, we execute it here */
|
/* if an exception is pending, we execute it here */
|
||||||
if (env->exception_index >= 0) {
|
if (cpu->exception_index >= 0) {
|
||||||
if (env->exception_index >= EXCP_INTERRUPT) {
|
if (cpu->exception_index >= EXCP_INTERRUPT) {
|
||||||
/* exit request from the cpu execution loop */
|
/* exit request from the cpu execution loop */
|
||||||
ret = env->exception_index;
|
ret = cpu->exception_index;
|
||||||
if (ret == EXCP_DEBUG) {
|
if (ret == EXCP_DEBUG) {
|
||||||
cpu_handle_debug_exception(env);
|
cpu_handle_debug_exception(env);
|
||||||
}
|
}
|
||||||
@@ -305,11 +301,11 @@ int cpu_exec(CPUArchState *env)
|
|||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
#endif
|
#endif
|
||||||
ret = env->exception_index;
|
ret = cpu->exception_index;
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
env->exception_index = -1;
|
cpu->exception_index = -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,8 +320,8 @@ int cpu_exec(CPUArchState *env)
|
|||||||
}
|
}
|
||||||
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
|
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
|
||||||
cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
|
cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
|
||||||
env->exception_index = EXCP_DEBUG;
|
cpu->exception_index = EXCP_DEBUG;
|
||||||
cpu_loop_exit(env);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
|
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
|
||||||
defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
|
defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
|
||||||
@@ -333,8 +329,8 @@ int cpu_exec(CPUArchState *env)
|
|||||||
if (interrupt_request & CPU_INTERRUPT_HALT) {
|
if (interrupt_request & CPU_INTERRUPT_HALT) {
|
||||||
cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
|
cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
|
||||||
cpu->halted = 1;
|
cpu->halted = 1;
|
||||||
env->exception_index = EXCP_HLT;
|
cpu->exception_index = EXCP_HLT;
|
||||||
cpu_loop_exit(env);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
@@ -348,8 +344,8 @@ int cpu_exec(CPUArchState *env)
|
|||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
|
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
|
||||||
0);
|
0);
|
||||||
do_cpu_init(x86_cpu);
|
do_cpu_init(x86_cpu);
|
||||||
env->exception_index = EXCP_HALTED;
|
cpu->exception_index = EXCP_HALTED;
|
||||||
cpu_loop_exit(env);
|
cpu_loop_exit(cpu);
|
||||||
} else if (interrupt_request & CPU_INTERRUPT_SIPI) {
|
} else if (interrupt_request & CPU_INTERRUPT_SIPI) {
|
||||||
do_cpu_sipi(x86_cpu);
|
do_cpu_sipi(x86_cpu);
|
||||||
} else if (env->hflags2 & HF2_GIF_MASK) {
|
} else if (env->hflags2 & HF2_GIF_MASK) {
|
||||||
@@ -420,7 +416,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
#elif defined(TARGET_LM32)
|
#elif defined(TARGET_LM32)
|
||||||
if ((interrupt_request & CPU_INTERRUPT_HARD)
|
if ((interrupt_request & CPU_INTERRUPT_HARD)
|
||||||
&& (env->ie & IE_IE)) {
|
&& (env->ie & IE_IE)) {
|
||||||
env->exception_index = EXCP_IRQ;
|
cpu->exception_index = EXCP_IRQ;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -429,7 +425,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
&& (env->sregs[SR_MSR] & MSR_IE)
|
&& (env->sregs[SR_MSR] & MSR_IE)
|
||||||
&& !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
|
&& !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
|
||||||
&& !(env->iflags & (D_FLAG | IMM_FLAG))) {
|
&& !(env->iflags & (D_FLAG | IMM_FLAG))) {
|
||||||
env->exception_index = EXCP_IRQ;
|
cpu->exception_index = EXCP_IRQ;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -437,7 +433,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
cpu_mips_hw_interrupts_pending(env)) {
|
cpu_mips_hw_interrupts_pending(env)) {
|
||||||
/* Raise it */
|
/* Raise it */
|
||||||
env->exception_index = EXCP_EXT_INTERRUPT;
|
cpu->exception_index = EXCP_EXT_INTERRUPT;
|
||||||
env->error_code = 0;
|
env->error_code = 0;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
@@ -454,7 +450,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
idx = EXCP_TICK;
|
idx = EXCP_TICK;
|
||||||
}
|
}
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
env->exception_index = idx;
|
cpu->exception_index = idx;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -469,7 +465,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
if (((type == TT_EXTINT) &&
|
if (((type == TT_EXTINT) &&
|
||||||
cpu_pil_allowed(env, pil)) ||
|
cpu_pil_allowed(env, pil)) ||
|
||||||
type != TT_EXTINT) {
|
type != TT_EXTINT) {
|
||||||
env->exception_index = env->interrupt_index;
|
cpu->exception_index = env->interrupt_index;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -478,7 +474,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
#elif defined(TARGET_ARM)
|
#elif defined(TARGET_ARM)
|
||||||
if (interrupt_request & CPU_INTERRUPT_FIQ
|
if (interrupt_request & CPU_INTERRUPT_FIQ
|
||||||
&& !(env->daif & PSTATE_F)) {
|
&& !(env->daif & PSTATE_F)) {
|
||||||
env->exception_index = EXCP_FIQ;
|
cpu->exception_index = EXCP_FIQ;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -494,14 +490,14 @@ int cpu_exec(CPUArchState *env)
|
|||||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||||
&& ((IS_M(env) && env->regs[15] < 0xfffffff0)
|
&& ((IS_M(env) && env->regs[15] < 0xfffffff0)
|
||||||
|| !(env->daif & PSTATE_I))) {
|
|| !(env->daif & PSTATE_I))) {
|
||||||
env->exception_index = EXCP_IRQ;
|
cpu->exception_index = EXCP_IRQ;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_UNICORE32)
|
#elif defined(TARGET_UNICORE32)
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||||
&& !(env->uncached_asr & ASR_I)) {
|
&& !(env->uncached_asr & ASR_I)) {
|
||||||
env->exception_index = UC32_EXCP_INTR;
|
cpu->exception_index = UC32_EXCP_INTR;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -536,7 +532,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
env->exception_index = idx;
|
cpu->exception_index = idx;
|
||||||
env->error_code = 0;
|
env->error_code = 0;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
@@ -546,7 +542,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||||
&& (env->pregs[PR_CCS] & I_FLAG)
|
&& (env->pregs[PR_CCS] & I_FLAG)
|
||||||
&& !env->locked_irq) {
|
&& !env->locked_irq) {
|
||||||
env->exception_index = EXCP_IRQ;
|
cpu->exception_index = EXCP_IRQ;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -558,7 +554,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
m_flag_archval = M_FLAG_V32;
|
m_flag_archval = M_FLAG_V32;
|
||||||
}
|
}
|
||||||
if ((env->pregs[PR_CCS] & m_flag_archval)) {
|
if ((env->pregs[PR_CCS] & m_flag_archval)) {
|
||||||
env->exception_index = EXCP_NMI;
|
cpu->exception_index = EXCP_NMI;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -572,7 +568,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
hardware doesn't rely on this, so we
|
hardware doesn't rely on this, so we
|
||||||
provide/save the vector when the interrupt is
|
provide/save the vector when the interrupt is
|
||||||
first signalled. */
|
first signalled. */
|
||||||
env->exception_index = env->pending_vector;
|
cpu->exception_index = env->pending_vector;
|
||||||
do_interrupt_m68k_hardirq(env);
|
do_interrupt_m68k_hardirq(env);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -584,7 +580,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
}
|
}
|
||||||
#elif defined(TARGET_XTENSA)
|
#elif defined(TARGET_XTENSA)
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||||
env->exception_index = EXC_IRQ;
|
cpu->exception_index = EXC_IRQ;
|
||||||
cc->do_interrupt(cpu);
|
cc->do_interrupt(cpu);
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
@@ -600,8 +596,8 @@ int cpu_exec(CPUArchState *env)
|
|||||||
}
|
}
|
||||||
if (unlikely(cpu->exit_request)) {
|
if (unlikely(cpu->exit_request)) {
|
||||||
cpu->exit_request = 0;
|
cpu->exit_request = 0;
|
||||||
env->exception_index = EXCP_INTERRUPT;
|
cpu->exception_index = EXCP_INTERRUPT;
|
||||||
cpu_loop_exit(env);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
spin_lock(&tcg_ctx.tb_ctx.tb_lock);
|
spin_lock(&tcg_ctx.tb_ctx.tb_lock);
|
||||||
tb = tb_find_fast(env);
|
tb = tb_find_fast(env);
|
||||||
@@ -654,25 +650,25 @@ int cpu_exec(CPUArchState *env)
|
|||||||
/* Instruction counter expired. */
|
/* Instruction counter expired. */
|
||||||
int insns_left;
|
int insns_left;
|
||||||
tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
|
tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
|
||||||
insns_left = env->icount_decr.u32;
|
insns_left = cpu->icount_decr.u32;
|
||||||
if (env->icount_extra && insns_left >= 0) {
|
if (cpu->icount_extra && insns_left >= 0) {
|
||||||
/* Refill decrementer and continue execution. */
|
/* Refill decrementer and continue execution. */
|
||||||
env->icount_extra += insns_left;
|
cpu->icount_extra += insns_left;
|
||||||
if (env->icount_extra > 0xffff) {
|
if (cpu->icount_extra > 0xffff) {
|
||||||
insns_left = 0xffff;
|
insns_left = 0xffff;
|
||||||
} else {
|
} else {
|
||||||
insns_left = env->icount_extra;
|
insns_left = cpu->icount_extra;
|
||||||
}
|
}
|
||||||
env->icount_extra -= insns_left;
|
cpu->icount_extra -= insns_left;
|
||||||
env->icount_decr.u16.low = insns_left;
|
cpu->icount_decr.u16.low = insns_left;
|
||||||
} else {
|
} else {
|
||||||
if (insns_left > 0) {
|
if (insns_left > 0) {
|
||||||
/* Execute remaining instructions. */
|
/* Execute remaining instructions. */
|
||||||
cpu_exec_nocache(env, insns_left, tb);
|
cpu_exec_nocache(env, insns_left, tb);
|
||||||
}
|
}
|
||||||
env->exception_index = EXCP_INTERRUPT;
|
cpu->exception_index = EXCP_INTERRUPT;
|
||||||
next_tb = 0;
|
next_tb = 0;
|
||||||
cpu_loop_exit(env);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
50
cpus.c
50
cpus.c
@@ -76,7 +76,7 @@ static bool cpu_thread_is_idle(CPUState *cpu)
|
|||||||
if (cpu_is_stopped(cpu)) {
|
if (cpu_is_stopped(cpu)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!cpu->halted || qemu_cpu_has_work(cpu) ||
|
if (!cpu->halted || cpu_has_work(cpu) ||
|
||||||
kvm_halt_in_kernel()) {
|
kvm_halt_in_kernel()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -139,11 +139,10 @@ static int64_t cpu_get_icount_locked(void)
|
|||||||
|
|
||||||
icount = qemu_icount;
|
icount = qemu_icount;
|
||||||
if (cpu) {
|
if (cpu) {
|
||||||
CPUArchState *env = cpu->env_ptr;
|
if (!cpu_can_do_io(cpu)) {
|
||||||
if (!can_do_io(env)) {
|
|
||||||
fprintf(stderr, "Bad clock read\n");
|
fprintf(stderr, "Bad clock read\n");
|
||||||
}
|
}
|
||||||
icount -= (env->icount_decr.u16.low + env->icount_extra);
|
icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
|
||||||
}
|
}
|
||||||
return qemu_icount_bias + (icount << icount_time_shift);
|
return qemu_icount_bias + (icount << icount_time_shift);
|
||||||
}
|
}
|
||||||
@@ -1117,8 +1116,13 @@ void resume_all_vcpus(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For temporary buffers for forming a name */
|
||||||
|
#define VCPU_THREAD_NAME_SIZE 16
|
||||||
|
|
||||||
static void qemu_tcg_init_vcpu(CPUState *cpu)
|
static void qemu_tcg_init_vcpu(CPUState *cpu)
|
||||||
{
|
{
|
||||||
|
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||||
|
|
||||||
tcg_cpu_address_space_init(cpu, cpu->as);
|
tcg_cpu_address_space_init(cpu, cpu->as);
|
||||||
|
|
||||||
/* share a single thread for all cpus with TCG */
|
/* share a single thread for all cpus with TCG */
|
||||||
@@ -1127,8 +1131,10 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
|
|||||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||||
qemu_cond_init(cpu->halt_cond);
|
qemu_cond_init(cpu->halt_cond);
|
||||||
tcg_halt_cond = cpu->halt_cond;
|
tcg_halt_cond = cpu->halt_cond;
|
||||||
qemu_thread_create(cpu->thread, qemu_tcg_cpu_thread_fn, cpu,
|
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
|
||||||
QEMU_THREAD_JOINABLE);
|
cpu->cpu_index);
|
||||||
|
qemu_thread_create(cpu->thread, thread_name, qemu_tcg_cpu_thread_fn,
|
||||||
|
cpu, QEMU_THREAD_JOINABLE);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
cpu->hThread = qemu_thread_get_handle(cpu->thread);
|
cpu->hThread = qemu_thread_get_handle(cpu->thread);
|
||||||
#endif
|
#endif
|
||||||
@@ -1144,11 +1150,15 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
|
|||||||
|
|
||||||
static void qemu_kvm_start_vcpu(CPUState *cpu)
|
static void qemu_kvm_start_vcpu(CPUState *cpu)
|
||||||
{
|
{
|
||||||
|
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||||
|
|
||||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||||
qemu_cond_init(cpu->halt_cond);
|
qemu_cond_init(cpu->halt_cond);
|
||||||
qemu_thread_create(cpu->thread, qemu_kvm_cpu_thread_fn, cpu,
|
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
|
||||||
QEMU_THREAD_JOINABLE);
|
cpu->cpu_index);
|
||||||
|
qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
|
||||||
|
cpu, QEMU_THREAD_JOINABLE);
|
||||||
while (!cpu->created) {
|
while (!cpu->created) {
|
||||||
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
||||||
}
|
}
|
||||||
@@ -1156,10 +1166,14 @@ static void qemu_kvm_start_vcpu(CPUState *cpu)
|
|||||||
|
|
||||||
static void qemu_dummy_start_vcpu(CPUState *cpu)
|
static void qemu_dummy_start_vcpu(CPUState *cpu)
|
||||||
{
|
{
|
||||||
|
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||||
|
|
||||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||||
qemu_cond_init(cpu->halt_cond);
|
qemu_cond_init(cpu->halt_cond);
|
||||||
qemu_thread_create(cpu->thread, qemu_dummy_cpu_thread_fn, cpu,
|
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY",
|
||||||
|
cpu->cpu_index);
|
||||||
|
qemu_thread_create(cpu->thread, thread_name, qemu_dummy_cpu_thread_fn, cpu,
|
||||||
QEMU_THREAD_JOINABLE);
|
QEMU_THREAD_JOINABLE);
|
||||||
while (!cpu->created) {
|
while (!cpu->created) {
|
||||||
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
||||||
@@ -1221,6 +1235,7 @@ int vm_stop_force_state(RunState state)
|
|||||||
|
|
||||||
static int tcg_cpu_exec(CPUArchState *env)
|
static int tcg_cpu_exec(CPUArchState *env)
|
||||||
{
|
{
|
||||||
|
CPUState *cpu = ENV_GET_CPU(env);
|
||||||
int ret;
|
int ret;
|
||||||
#ifdef CONFIG_PROFILER
|
#ifdef CONFIG_PROFILER
|
||||||
int64_t ti;
|
int64_t ti;
|
||||||
@@ -1233,9 +1248,9 @@ static int tcg_cpu_exec(CPUArchState *env)
|
|||||||
int64_t count;
|
int64_t count;
|
||||||
int64_t deadline;
|
int64_t deadline;
|
||||||
int decr;
|
int decr;
|
||||||
qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
|
qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
|
||||||
env->icount_decr.u16.low = 0;
|
cpu->icount_decr.u16.low = 0;
|
||||||
env->icount_extra = 0;
|
cpu->icount_extra = 0;
|
||||||
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
||||||
|
|
||||||
/* Maintain prior (possibly buggy) behaviour where if no deadline
|
/* Maintain prior (possibly buggy) behaviour where if no deadline
|
||||||
@@ -1251,8 +1266,8 @@ static int tcg_cpu_exec(CPUArchState *env)
|
|||||||
qemu_icount += count;
|
qemu_icount += count;
|
||||||
decr = (count > 0xffff) ? 0xffff : count;
|
decr = (count > 0xffff) ? 0xffff : count;
|
||||||
count -= decr;
|
count -= decr;
|
||||||
env->icount_decr.u16.low = decr;
|
cpu->icount_decr.u16.low = decr;
|
||||||
env->icount_extra = count;
|
cpu->icount_extra = count;
|
||||||
}
|
}
|
||||||
ret = cpu_exec(env);
|
ret = cpu_exec(env);
|
||||||
#ifdef CONFIG_PROFILER
|
#ifdef CONFIG_PROFILER
|
||||||
@@ -1261,10 +1276,9 @@ static int tcg_cpu_exec(CPUArchState *env)
|
|||||||
if (use_icount) {
|
if (use_icount) {
|
||||||
/* Fold pending instructions back into the
|
/* Fold pending instructions back into the
|
||||||
instruction counter, and clear the interrupt flag. */
|
instruction counter, and clear the interrupt flag. */
|
||||||
qemu_icount -= (env->icount_decr.u16.low
|
qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
|
||||||
+ env->icount_extra);
|
cpu->icount_decr.u32 = 0;
|
||||||
env->icount_decr.u32 = 0;
|
cpu->icount_extra = 0;
|
||||||
env->icount_extra = 0;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
24
cputlb.c
24
cputlb.c
@@ -46,9 +46,9 @@ int tlb_flush_count;
|
|||||||
* entries from the TLB at any time, so flushing more entries than
|
* entries from the TLB at any time, so flushing more entries than
|
||||||
* required is only an efficiency issue, not a correctness issue.
|
* required is only an efficiency issue, not a correctness issue.
|
||||||
*/
|
*/
|
||||||
void tlb_flush(CPUArchState *env, int flush_global)
|
void tlb_flush(CPUState *cpu, int flush_global)
|
||||||
{
|
{
|
||||||
CPUState *cpu = ENV_GET_CPU(env);
|
CPUArchState *env = cpu->env_ptr;
|
||||||
|
|
||||||
#if defined(DEBUG_TLB)
|
#if defined(DEBUG_TLB)
|
||||||
printf("tlb_flush:\n");
|
printf("tlb_flush:\n");
|
||||||
@@ -58,7 +58,7 @@ void tlb_flush(CPUArchState *env, int flush_global)
|
|||||||
cpu->current_tb = NULL;
|
cpu->current_tb = NULL;
|
||||||
|
|
||||||
memset(env->tlb_table, -1, sizeof(env->tlb_table));
|
memset(env->tlb_table, -1, sizeof(env->tlb_table));
|
||||||
memset(env->tb_jmp_cache, 0, sizeof(env->tb_jmp_cache));
|
memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
|
||||||
|
|
||||||
env->tlb_flush_addr = -1;
|
env->tlb_flush_addr = -1;
|
||||||
env->tlb_flush_mask = 0;
|
env->tlb_flush_mask = 0;
|
||||||
@@ -77,9 +77,9 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tlb_flush_page(CPUArchState *env, target_ulong addr)
|
void tlb_flush_page(CPUState *cpu, target_ulong addr)
|
||||||
{
|
{
|
||||||
CPUState *cpu = ENV_GET_CPU(env);
|
CPUArchState *env = cpu->env_ptr;
|
||||||
int i;
|
int i;
|
||||||
int mmu_idx;
|
int mmu_idx;
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr)
|
|||||||
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
|
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
|
||||||
env->tlb_flush_addr, env->tlb_flush_mask);
|
env->tlb_flush_addr, env->tlb_flush_mask);
|
||||||
#endif
|
#endif
|
||||||
tlb_flush(env, 1);
|
tlb_flush(cpu, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* must reset current TB so that interrupts cannot modify the
|
/* must reset current TB so that interrupts cannot modify the
|
||||||
@@ -106,7 +106,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr)
|
|||||||
tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
|
tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
tb_flush_jmp_cache(env, addr);
|
tb_flush_jmp_cache(cpu, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update the TLBs so that writes to code in the virtual page 'addr'
|
/* update the TLBs so that writes to code in the virtual page 'addr'
|
||||||
@@ -119,7 +119,7 @@ void tlb_protect_code(ram_addr_t ram_addr)
|
|||||||
|
|
||||||
/* update the TLB so that writes in physical page 'phys_addr' are no longer
|
/* update the TLB so that writes in physical page 'phys_addr' are no longer
|
||||||
tested for self modifying code */
|
tested for self modifying code */
|
||||||
void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
|
void tlb_unprotect_code_phys(CPUState *cpu, ram_addr_t ram_addr,
|
||||||
target_ulong vaddr)
|
target_ulong vaddr)
|
||||||
{
|
{
|
||||||
cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE);
|
cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE);
|
||||||
@@ -221,10 +221,11 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
|
|||||||
/* Add a new TLB entry. At most one entry for a given virtual address
|
/* Add a new TLB entry. At most one entry for a given virtual address
|
||||||
is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
|
is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
|
||||||
supplied size is only used by tlb_flush_page. */
|
supplied size is only used by tlb_flush_page. */
|
||||||
void tlb_set_page(CPUArchState *env, target_ulong vaddr,
|
void tlb_set_page(CPUState *cpu, target_ulong vaddr,
|
||||||
hwaddr paddr, int prot,
|
hwaddr paddr, int prot,
|
||||||
int mmu_idx, target_ulong size)
|
int mmu_idx, target_ulong size)
|
||||||
{
|
{
|
||||||
|
CPUArchState *env = cpu->env_ptr;
|
||||||
MemoryRegionSection *section;
|
MemoryRegionSection *section;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
target_ulong address;
|
target_ulong address;
|
||||||
@@ -232,7 +233,6 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
|
|||||||
uintptr_t addend;
|
uintptr_t addend;
|
||||||
CPUTLBEntry *te;
|
CPUTLBEntry *te;
|
||||||
hwaddr iotlb, xlat, sz;
|
hwaddr iotlb, xlat, sz;
|
||||||
CPUState *cpu = ENV_GET_CPU(env);
|
|
||||||
|
|
||||||
assert(size >= TARGET_PAGE_SIZE);
|
assert(size >= TARGET_PAGE_SIZE);
|
||||||
if (size != TARGET_PAGE_SIZE) {
|
if (size != TARGET_PAGE_SIZE) {
|
||||||
@@ -261,7 +261,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
code_address = address;
|
code_address = address;
|
||||||
iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, xlat,
|
iotlb = memory_region_section_get_iotlb(cpu, section, vaddr, paddr, xlat,
|
||||||
prot, &address);
|
prot, &address);
|
||||||
|
|
||||||
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
@@ -322,7 +322,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
|||||||
if (cc->do_unassigned_access) {
|
if (cc->do_unassigned_access) {
|
||||||
cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
|
cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
|
||||||
} else {
|
} else {
|
||||||
cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x"
|
cpu_abort(cpu, "Trying to execute code outside RAM or ROM at 0x"
|
||||||
TARGET_FMT_lx "\n", addr);
|
TARGET_FMT_lx "\n", addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,4 +47,5 @@ CONFIG_E500=y
|
|||||||
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
|
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
|
||||||
# For PReP
|
# For PReP
|
||||||
CONFIG_MC146818RTC=y
|
CONFIG_MC146818RTC=y
|
||||||
|
CONFIG_ETSEC=y
|
||||||
CONFIG_ISA_TESTDEV=y
|
CONFIG_ISA_TESTDEV=y
|
||||||
|
|||||||
@@ -33,12 +33,14 @@ DriveInfo *add_init_drive(const char *optstr)
|
|||||||
{
|
{
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
|
MachineClass *mc;
|
||||||
|
|
||||||
opts = drive_def(optstr);
|
opts = drive_def(optstr);
|
||||||
if (!opts)
|
if (!opts)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dinfo = drive_init(opts, current_machine->block_default_type);
|
mc = MACHINE_GET_CLASS(current_machine);
|
||||||
|
dinfo = drive_init(opts, mc->qemu_machine->block_default_type);
|
||||||
if (!dinfo) {
|
if (!dinfo) {
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1342,7 +1342,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||||||
ASSERT(format[5] == 'L');
|
ASSERT(format[5] == 'L');
|
||||||
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
|
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
|
||||||
if (instr->ShiftMoveWide() > 0) {
|
if (instr->ShiftMoveWide() > 0) {
|
||||||
AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
|
AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 8;
|
return 8;
|
||||||
@@ -1391,7 +1391,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||||||
}
|
}
|
||||||
case 'F': { // IFPSingle, IFPDouble or IFPFBits.
|
case 'F': { // IFPSingle, IFPDouble or IFPFBits.
|
||||||
if (format[3] == 'F') { // IFPFbits.
|
if (format[3] == 'F') { // IFPFbits.
|
||||||
AppendToOutput("#%d", 64 - instr->FPScale());
|
AppendToOutput("#%" PRId64, 64 - instr->FPScale());
|
||||||
return 8;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
|
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
|
||||||
@@ -1412,23 +1412,23 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
case 'P': { // IP - Conditional compare.
|
case 'P': { // IP - Conditional compare.
|
||||||
AppendToOutput("#%d", instr->ImmCondCmp());
|
AppendToOutput("#%" PRId64, instr->ImmCondCmp());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
case 'B': { // Bitfields.
|
case 'B': { // Bitfields.
|
||||||
return SubstituteBitfieldImmediateField(instr, format);
|
return SubstituteBitfieldImmediateField(instr, format);
|
||||||
}
|
}
|
||||||
case 'E': { // IExtract.
|
case 'E': { // IExtract.
|
||||||
AppendToOutput("#%d", instr->ImmS());
|
AppendToOutput("#%" PRId64, instr->ImmS());
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
case 'S': { // IS - Test and branch bit.
|
case 'S': { // IS - Test and branch bit.
|
||||||
AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
|
AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) |
|
||||||
instr->ImmTestBranchBit40());
|
instr->ImmTestBranchBit40());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
case 'D': { // IDebug - HLT and BRK instructions.
|
case 'D': { // IDebug - HLT and BRK instructions.
|
||||||
AppendToOutput("#0x%x", instr->ImmException());
|
AppendToOutput("#0x%" PRIx64, instr->ImmException());
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -1598,12 +1598,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
|
|||||||
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
|
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
|
||||||
(instr->ExtendMode() == UXTX))) {
|
(instr->ExtendMode() == UXTX))) {
|
||||||
if (instr->ImmExtendShift() > 0) {
|
if (instr->ImmExtendShift() > 0) {
|
||||||
AppendToOutput(", lsl #%d", instr->ImmExtendShift());
|
AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
|
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
|
||||||
if (instr->ImmExtendShift() > 0) {
|
if (instr->ImmExtendShift() > 0) {
|
||||||
AppendToOutput(" #%d", instr->ImmExtendShift());
|
AppendToOutput(" #%" PRId64, instr->ImmExtendShift());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 3;
|
return 3;
|
||||||
@@ -1632,7 +1632,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
|||||||
if (!((ext == UXTX) && (shift == 0))) {
|
if (!((ext == UXTX) && (shift == 0))) {
|
||||||
AppendToOutput(", %s", extend_mode[ext]);
|
AppendToOutput(", %s", extend_mode[ext]);
|
||||||
if (shift != 0) {
|
if (shift != 0) {
|
||||||
AppendToOutput(" #%d", instr->SizeLS());
|
AppendToOutput(" #%" PRId64, instr->SizeLS());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 9;
|
return 9;
|
||||||
|
|||||||
@@ -123,11 +123,12 @@ And it looks like this on the wire:
|
|||||||
|
|
||||||
Flat union types avoid the nesting on the wire. They are used whenever a
|
Flat union types avoid the nesting on the wire. They are used whenever a
|
||||||
specific field of the base type is declared as the discriminator ('type' is
|
specific field of the base type is declared as the discriminator ('type' is
|
||||||
then no longer generated). The discriminator must always be a string field.
|
then no longer generated). The discriminator must be of enumeration type.
|
||||||
The above example can then be modified as follows:
|
The above example can then be modified as follows:
|
||||||
|
|
||||||
|
{ 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] }
|
||||||
{ 'type': 'BlockdevCommonOptions',
|
{ 'type': 'BlockdevCommonOptions',
|
||||||
'data': { 'driver': 'str', 'readonly': 'bool' } }
|
'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } }
|
||||||
{ 'union': 'BlockdevOptions',
|
{ 'union': 'BlockdevOptions',
|
||||||
'base': 'BlockdevCommonOptions',
|
'base': 'BlockdevCommonOptions',
|
||||||
'discriminator': 'driver',
|
'discriminator': 'driver',
|
||||||
|
|||||||
@@ -11,99 +11,92 @@
|
|||||||
; (Com+Lpt)" from the list. Click "Have a disk". Select this file.
|
; (Com+Lpt)" from the list. Click "Have a disk". Select this file.
|
||||||
; Procedure may vary a bit depending on the windows version.
|
; Procedure may vary a bit depending on the windows version.
|
||||||
|
|
||||||
; FIXME: This file covers the single port version only.
|
; This file covers all options: pci-serial, pci-serial-2x, pci-serial-4x
|
||||||
|
; for both 32 and 64 bit platforms.
|
||||||
|
|
||||||
[Version]
|
[Version]
|
||||||
Signature="$CHICAGO$"
|
Signature="$Windows NT$"
|
||||||
Class=Ports
|
Class=MultiFunction
|
||||||
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
|
ClassGUID={4d36e971-e325-11ce-bfc1-08002be10318}
|
||||||
Provider=%QEMU%
|
Provider=%QEMU%
|
||||||
DriverVer=09/24/2012,1.3.0
|
DriverVer=12/29/2013,1.3.0
|
||||||
|
[ControlFlags]
|
||||||
[SourceDisksNames]
|
ExcludeFromSelect=*
|
||||||
3426=windows cd
|
|
||||||
|
|
||||||
[SourceDisksFiles]
|
|
||||||
serial.sys = 3426
|
|
||||||
serenum.sys = 3426
|
|
||||||
|
|
||||||
[DestinationDirs]
|
|
||||||
DefaultDestDir = 11 ;LDID_SYS
|
|
||||||
ComPort.NT.Copy = 12 ;DIRID_DRIVERS
|
|
||||||
SerialEnumerator.NT.Copy=12 ;DIRID_DRIVERS
|
|
||||||
|
|
||||||
; Drivers
|
|
||||||
;----------------------------------------------------------
|
|
||||||
[Manufacturer]
|
[Manufacturer]
|
||||||
%QEMU%=QEMU,NTx86
|
%QEMU%=QEMU,NTx86,NTAMD64
|
||||||
|
|
||||||
[QEMU.NTx86]
|
[QEMU.NTx86]
|
||||||
%QEMU-PCI_SERIAL.DeviceDesc% = ComPort, "PCI\VEN_1b36&DEV_0002&CC_0700"
|
%QEMU-PCI_SERIAL_1_PORT%=ComPort_inst1, PCI\VEN_1B36&DEV_0002
|
||||||
|
%QEMU-PCI_SERIAL_2_PORT%=ComPort_inst2, PCI\VEN_1B36&DEV_0003
|
||||||
|
%QEMU-PCI_SERIAL_4_PORT%=ComPort_inst4, PCI\VEN_1B36&DEV_0004
|
||||||
|
|
||||||
; COM sections
|
[QEMU.NTAMD64]
|
||||||
;----------------------------------------------------------
|
%QEMU-PCI_SERIAL_1_PORT%=ComPort_inst1, PCI\VEN_1B36&DEV_0002
|
||||||
[ComPort.AddReg]
|
%QEMU-PCI_SERIAL_2_PORT%=ComPort_inst2, PCI\VEN_1B36&DEV_0003
|
||||||
HKR,,PortSubClass,1,01
|
%QEMU-PCI_SERIAL_4_PORT%=ComPort_inst4, PCI\VEN_1B36&DEV_0004
|
||||||
|
|
||||||
[ComPort.NT]
|
[ComPort_inst1]
|
||||||
AddReg=ComPort.AddReg, ComPort.NT.AddReg
|
Include=mf.inf
|
||||||
LogConfig=caa
|
Needs=MFINSTALL.mf
|
||||||
SyssetupPnPFlags = 1
|
|
||||||
|
|
||||||
[ComPort.NT.HW]
|
[ComPort_inst2]
|
||||||
AddReg=ComPort.NT.HW.AddReg
|
Include=mf.inf
|
||||||
|
Needs=MFINSTALL.mf
|
||||||
|
|
||||||
[ComPort.NT.AddReg]
|
[ComPort_inst4]
|
||||||
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
|
Include=mf.inf
|
||||||
|
Needs=MFINSTALL.mf
|
||||||
|
|
||||||
[ComPort.NT.HW.AddReg]
|
[ComPort_inst1.HW]
|
||||||
HKR,,"UpperFilters",0x00010000,"serenum"
|
AddReg=ComPort_inst1.RegHW
|
||||||
|
|
||||||
;-------------- Service installation
|
[ComPort_inst2.HW]
|
||||||
; Port Driver (function driver for this device)
|
AddReg=ComPort_inst2.RegHW
|
||||||
[ComPort.NT.Services]
|
|
||||||
AddService = Serial, 0x00000002, Serial_Service_Inst, Serial_EventLog_Inst
|
|
||||||
AddService = Serenum,,Serenum_Service_Inst
|
|
||||||
|
|
||||||
; -------------- Serial Port Driver install sections
|
[ComPort_inst4.HW]
|
||||||
[Serial_Service_Inst]
|
AddReg=ComPort_inst4.RegHW
|
||||||
DisplayName = %Serial.SVCDESC%
|
|
||||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
|
||||||
StartType = 1 ; SERVICE_SYSTEM_START (this driver may do detection)
|
|
||||||
ErrorControl = 0 ; SERVICE_ERROR_IGNORE
|
|
||||||
ServiceBinary = %12%\serial.sys
|
|
||||||
LoadOrderGroup = Extended base
|
|
||||||
|
|
||||||
; -------------- Serenum Driver install section
|
[ComPort_inst1.Services]
|
||||||
[Serenum_Service_Inst]
|
Include=mf.inf
|
||||||
DisplayName = %Serenum.SVCDESC%
|
Needs=MFINSTALL.mf.Services
|
||||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
|
||||||
StartType = 3 ; SERVICE_DEMAND_START
|
|
||||||
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
|
|
||||||
ServiceBinary = %12%\serenum.sys
|
|
||||||
LoadOrderGroup = PNP Filter
|
|
||||||
|
|
||||||
[Serial_EventLog_Inst]
|
[ComPort_inst2.Services]
|
||||||
AddReg = Serial_EventLog_AddReg
|
Include=mf.inf
|
||||||
|
Needs=MFINSTALL.mf.Services
|
||||||
|
|
||||||
[Serial_EventLog_AddReg]
|
[ComPort_inst4.Services]
|
||||||
HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\serial.sys"
|
Include=mf.inf
|
||||||
HKR,,TypesSupported,0x00010001,7
|
Needs=MFINSTALL.mf.Services
|
||||||
|
|
||||||
; The following sections are COM port resource configs.
|
[ComPort_inst1.RegHW]
|
||||||
; Section name format means:
|
HKR,Child0000,HardwareID,,*PNP0501
|
||||||
; Char 1 = c (COM port)
|
HKR,Child0000,VaryingResourceMap,1,00, 00,00,00,00, 08,00,00,00
|
||||||
; Char 2 = I/O config: 1 (3f8), 2 (2f8), 3 (3e8), 4 (2e8), a (any)
|
HKR,Child0000,ResourceMap,1,02
|
||||||
; Char 3 = IRQ config: #, a (any)
|
|
||||||
|
|
||||||
[caa] ; Any base, any IRQ
|
[ComPort_inst2.RegHW]
|
||||||
ConfigPriority=HARDRECONFIG
|
HKR,Child0000,HardwareID,,*PNP0501
|
||||||
IOConfig=8@100-ffff%fff8(3ff::)
|
HKR,Child0000,VaryingResourceMap,1,00, 00,00,00,00, 08,00,00,00
|
||||||
IRQConfig=S:3,4,5,7,9,10,11,12,14,15
|
HKR,Child0000,ResourceMap,1,02
|
||||||
|
HKR,Child0001,HardwareID,,*PNP0501
|
||||||
|
HKR,Child0001,VaryingResourceMap,1,00, 08,00,00,00, 08,00,00,00
|
||||||
|
HKR,Child0001,ResourceMap,1,02
|
||||||
|
|
||||||
|
[ComPort_inst4.RegHW]
|
||||||
|
HKR,Child0000,HardwareID,,*PNP0501
|
||||||
|
HKR,Child0000,VaryingResourceMap,1,00, 00,00,00,00, 08,00,00,00
|
||||||
|
HKR,Child0000,ResourceMap,1,02
|
||||||
|
HKR,Child0001,HardwareID,,*PNP0501
|
||||||
|
HKR,Child0001,VaryingResourceMap,1,00, 08,00,00,00, 08,00,00,00
|
||||||
|
HKR,Child0001,ResourceMap,1,02
|
||||||
|
HKR,Child0002,HardwareID,,*PNP0501
|
||||||
|
HKR,Child0002,VaryingResourceMap,1,00, 10,00,00,00, 08,00,00,00
|
||||||
|
HKR,Child0002,ResourceMap,1,02
|
||||||
|
HKR,Child0003,HardwareID,,*PNP0501
|
||||||
|
HKR,Child0003,VaryingResourceMap,1,00, 18,00,00,00, 08,00,00,00
|
||||||
|
HKR,Child0003,ResourceMap,1,02
|
||||||
|
|
||||||
[Strings]
|
[Strings]
|
||||||
QEMU="QEMU"
|
QEMU="QEMU"
|
||||||
QEMU-PCI_SERIAL.DeviceDesc="QEMU Serial PCI Card"
|
QEMU-PCI_SERIAL_1_PORT="1x QEMU PCI Serial Card"
|
||||||
|
QEMU-PCI_SERIAL_2_PORT="2x QEMU PCI Serial Card"
|
||||||
Serial.SVCDESC = "Serial port driver"
|
QEMU-PCI_SERIAL_4_PORT="4x QEMU PCI Serial Card"
|
||||||
Serenum.SVCDESC = "Serenum Filter Driver"
|
|
||||||
|
|||||||
132
exec.c
132
exec.c
@@ -33,6 +33,7 @@
|
|||||||
#include "hw/xen/xen.h"
|
#include "hw/xen/xen.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
#include "sysemu/dma.h"
|
#include "sysemu/dma.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
@@ -484,8 +485,8 @@ void cpu_exec_init(CPUArchState *env)
|
|||||||
}
|
}
|
||||||
cpu->cpu_index = cpu_index;
|
cpu->cpu_index = cpu_index;
|
||||||
cpu->numa_node = 0;
|
cpu->numa_node = 0;
|
||||||
QTAILQ_INIT(&env->breakpoints);
|
QTAILQ_INIT(&cpu->breakpoints);
|
||||||
QTAILQ_INIT(&env->watchpoints);
|
QTAILQ_INIT(&cpu->watchpoints);
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
cpu->as = &address_space_memory;
|
cpu->as = &address_space_memory;
|
||||||
cpu->thread_id = qemu_get_thread_id();
|
cpu->thread_id = qemu_get_thread_id();
|
||||||
@@ -527,29 +528,29 @@ static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
|||||||
#endif /* TARGET_HAS_ICE */
|
#endif /* TARGET_HAS_ICE */
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
|
void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
|
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
|
||||||
int flags, CPUWatchpoint **watchpoint)
|
int flags, CPUWatchpoint **watchpoint)
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Add a watchpoint. */
|
/* Add a watchpoint. */
|
||||||
int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
|
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
|
||||||
int flags, CPUWatchpoint **watchpoint)
|
int flags, CPUWatchpoint **watchpoint)
|
||||||
{
|
{
|
||||||
target_ulong len_mask = ~(len - 1);
|
vaddr len_mask = ~(len - 1);
|
||||||
CPUWatchpoint *wp;
|
CPUWatchpoint *wp;
|
||||||
|
|
||||||
/* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
|
/* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
|
||||||
if ((len & (len - 1)) || (addr & ~len_mask) ||
|
if ((len & (len - 1)) || (addr & ~len_mask) ||
|
||||||
len == 0 || len > TARGET_PAGE_SIZE) {
|
len == 0 || len > TARGET_PAGE_SIZE) {
|
||||||
fprintf(stderr, "qemu: tried to set invalid watchpoint at "
|
error_report("tried to set invalid watchpoint at %"
|
||||||
TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
|
VADDR_PRIx ", len=%" VADDR_PRIu, addr, len);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
wp = g_malloc(sizeof(*wp));
|
wp = g_malloc(sizeof(*wp));
|
||||||
@@ -559,12 +560,13 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len
|
|||||||
wp->flags = flags;
|
wp->flags = flags;
|
||||||
|
|
||||||
/* keep all GDB-injected watchpoints in front */
|
/* keep all GDB-injected watchpoints in front */
|
||||||
if (flags & BP_GDB)
|
if (flags & BP_GDB) {
|
||||||
QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
|
QTAILQ_INSERT_HEAD(&cpu->watchpoints, wp, entry);
|
||||||
else
|
} else {
|
||||||
QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
|
QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry);
|
||||||
|
}
|
||||||
|
|
||||||
tlb_flush_page(env, addr);
|
tlb_flush_page(cpu, addr);
|
||||||
|
|
||||||
if (watchpoint)
|
if (watchpoint)
|
||||||
*watchpoint = wp;
|
*watchpoint = wp;
|
||||||
@@ -572,16 +574,16 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Remove a specific watchpoint. */
|
/* Remove a specific watchpoint. */
|
||||||
int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
|
int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
target_ulong len_mask = ~(len - 1);
|
vaddr len_mask = ~(len - 1);
|
||||||
CPUWatchpoint *wp;
|
CPUWatchpoint *wp;
|
||||||
|
|
||||||
QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
|
QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
|
||||||
if (addr == wp->vaddr && len_mask == wp->len_mask
|
if (addr == wp->vaddr && len_mask == wp->len_mask
|
||||||
&& flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
|
&& flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
|
||||||
cpu_watchpoint_remove_by_ref(env, wp);
|
cpu_watchpoint_remove_by_ref(cpu, wp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,29 +591,30 @@ int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Remove a specific watchpoint by reference. */
|
/* Remove a specific watchpoint by reference. */
|
||||||
void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
|
void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint)
|
||||||
{
|
{
|
||||||
QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
|
QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry);
|
||||||
|
|
||||||
tlb_flush_page(env, watchpoint->vaddr);
|
tlb_flush_page(cpu, watchpoint->vaddr);
|
||||||
|
|
||||||
g_free(watchpoint);
|
g_free(watchpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove all matching watchpoints. */
|
/* Remove all matching watchpoints. */
|
||||||
void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
|
void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
|
||||||
{
|
{
|
||||||
CPUWatchpoint *wp, *next;
|
CPUWatchpoint *wp, *next;
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
|
QTAILQ_FOREACH_SAFE(wp, &cpu->watchpoints, entry, next) {
|
||||||
if (wp->flags & mask)
|
if (wp->flags & mask) {
|
||||||
cpu_watchpoint_remove_by_ref(env, wp);
|
cpu_watchpoint_remove_by_ref(cpu, wp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Add a breakpoint. */
|
/* Add a breakpoint. */
|
||||||
int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
|
int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
|
||||||
CPUBreakpoint **breakpoint)
|
CPUBreakpoint **breakpoint)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_HAS_ICE)
|
#if defined(TARGET_HAS_ICE)
|
||||||
@@ -624,12 +627,12 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
|
|||||||
|
|
||||||
/* keep all GDB-injected breakpoints in front */
|
/* keep all GDB-injected breakpoints in front */
|
||||||
if (flags & BP_GDB) {
|
if (flags & BP_GDB) {
|
||||||
QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
|
QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry);
|
||||||
} else {
|
} else {
|
||||||
QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
|
QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
breakpoint_invalidate(ENV_GET_CPU(env), pc);
|
breakpoint_invalidate(cpu, pc);
|
||||||
|
|
||||||
if (breakpoint) {
|
if (breakpoint) {
|
||||||
*breakpoint = bp;
|
*breakpoint = bp;
|
||||||
@@ -641,14 +644,14 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Remove a specific breakpoint. */
|
/* Remove a specific breakpoint. */
|
||||||
int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
|
int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_HAS_ICE)
|
#if defined(TARGET_HAS_ICE)
|
||||||
CPUBreakpoint *bp;
|
CPUBreakpoint *bp;
|
||||||
|
|
||||||
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
|
||||||
if (bp->pc == pc && bp->flags == flags) {
|
if (bp->pc == pc && bp->flags == flags) {
|
||||||
cpu_breakpoint_remove_by_ref(env, bp);
|
cpu_breakpoint_remove_by_ref(cpu, bp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -659,26 +662,27 @@ int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Remove a specific breakpoint by reference. */
|
/* Remove a specific breakpoint by reference. */
|
||||||
void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
|
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_HAS_ICE)
|
#if defined(TARGET_HAS_ICE)
|
||||||
QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
|
QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry);
|
||||||
|
|
||||||
breakpoint_invalidate(ENV_GET_CPU(env), breakpoint->pc);
|
breakpoint_invalidate(cpu, breakpoint->pc);
|
||||||
|
|
||||||
g_free(breakpoint);
|
g_free(breakpoint);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove all matching breakpoints. */
|
/* Remove all matching breakpoints. */
|
||||||
void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
|
void cpu_breakpoint_remove_all(CPUState *cpu, int mask)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_HAS_ICE)
|
#if defined(TARGET_HAS_ICE)
|
||||||
CPUBreakpoint *bp, *next;
|
CPUBreakpoint *bp, *next;
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
|
QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) {
|
||||||
if (bp->flags & mask)
|
if (bp->flags & mask) {
|
||||||
cpu_breakpoint_remove_by_ref(env, bp);
|
cpu_breakpoint_remove_by_ref(cpu, bp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -702,9 +706,8 @@ void cpu_single_step(CPUState *cpu, int enabled)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_abort(CPUArchState *env, const char *fmt, ...)
|
void cpu_abort(CPUState *cpu, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
CPUState *cpu = ENV_GET_CPU(env);
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_list ap2;
|
va_list ap2;
|
||||||
|
|
||||||
@@ -792,7 +795,7 @@ static void cpu_physical_memory_set_dirty_tracking(bool enable)
|
|||||||
in_migration = enable;
|
in_migration = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
hwaddr memory_region_section_get_iotlb(CPUState *cpu,
|
||||||
MemoryRegionSection *section,
|
MemoryRegionSection *section,
|
||||||
target_ulong vaddr,
|
target_ulong vaddr,
|
||||||
hwaddr paddr, hwaddr xlat,
|
hwaddr paddr, hwaddr xlat,
|
||||||
@@ -818,7 +821,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
|||||||
|
|
||||||
/* Make accesses to pages with watchpoints go via the
|
/* Make accesses to pages with watchpoints go via the
|
||||||
watchpoint trap routines. */
|
watchpoint trap routines. */
|
||||||
QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
|
QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
|
||||||
if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
|
if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
|
||||||
/* Avoid trapping reads of pages with a write breakpoint. */
|
/* Avoid trapping reads of pages with a write breakpoint. */
|
||||||
if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) {
|
if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) {
|
||||||
@@ -1029,7 +1032,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
|
|
||||||
hpagesize = gethugepagesize(path);
|
hpagesize = gethugepagesize(path);
|
||||||
if (!hpagesize) {
|
if (!hpagesize) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memory < hpagesize) {
|
if (memory < hpagesize) {
|
||||||
@@ -1038,7 +1041,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
|
|
||||||
if (kvm_enabled() && !kvm_has_sync_mmu()) {
|
if (kvm_enabled() && !kvm_has_sync_mmu()) {
|
||||||
fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
|
fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make name safe to use with mkstemp by replacing '/' with '_'. */
|
/* Make name safe to use with mkstemp by replacing '/' with '_'. */
|
||||||
@@ -1056,7 +1059,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("unable to create backing store for hugepages");
|
perror("unable to create backing store for hugepages");
|
||||||
g_free(filename);
|
g_free(filename);
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
g_free(filename);
|
g_free(filename);
|
||||||
@@ -1076,7 +1079,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
if (area == MAP_FAILED) {
|
if (area == MAP_FAILED) {
|
||||||
perror("file_ram_alloc: can't mmap RAM pages");
|
perror("file_ram_alloc: can't mmap RAM pages");
|
||||||
close(fd);
|
close(fd);
|
||||||
return (NULL);
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_prealloc) {
|
if (mem_prealloc) {
|
||||||
@@ -1120,6 +1123,12 @@ static void *file_ram_alloc(RAMBlock *block,
|
|||||||
|
|
||||||
block->fd = fd;
|
block->fd = fd;
|
||||||
return area;
|
return area;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (mem_prealloc) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void *file_ram_alloc(RAMBlock *block,
|
static void *file_ram_alloc(RAMBlock *block,
|
||||||
@@ -1547,7 +1556,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
|
|||||||
flushed */
|
flushed */
|
||||||
if (!cpu_physical_memory_is_clean(ram_addr)) {
|
if (!cpu_physical_memory_is_clean(ram_addr)) {
|
||||||
CPUArchState *env = current_cpu->env_ptr;
|
CPUArchState *env = current_cpu->env_ptr;
|
||||||
tlb_set_dirty(env, env->mem_io_vaddr);
|
tlb_set_dirty(env, current_cpu->mem_io_vaddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1566,34 +1575,35 @@ static const MemoryRegionOps notdirty_mem_ops = {
|
|||||||
/* Generate a debug exception if a watchpoint has been hit. */
|
/* Generate a debug exception if a watchpoint has been hit. */
|
||||||
static void check_watchpoint(int offset, int len_mask, int flags)
|
static void check_watchpoint(int offset, int len_mask, int flags)
|
||||||
{
|
{
|
||||||
CPUArchState *env = current_cpu->env_ptr;
|
CPUState *cpu = current_cpu;
|
||||||
|
CPUArchState *env = cpu->env_ptr;
|
||||||
target_ulong pc, cs_base;
|
target_ulong pc, cs_base;
|
||||||
target_ulong vaddr;
|
target_ulong vaddr;
|
||||||
CPUWatchpoint *wp;
|
CPUWatchpoint *wp;
|
||||||
int cpu_flags;
|
int cpu_flags;
|
||||||
|
|
||||||
if (env->watchpoint_hit) {
|
if (cpu->watchpoint_hit) {
|
||||||
/* We re-entered the check after replacing the TB. Now raise
|
/* We re-entered the check after replacing the TB. Now raise
|
||||||
* the debug interrupt so that is will trigger after the
|
* the debug interrupt so that is will trigger after the
|
||||||
* current instruction. */
|
* current instruction. */
|
||||||
cpu_interrupt(ENV_GET_CPU(env), CPU_INTERRUPT_DEBUG);
|
cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
|
vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
|
||||||
QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
|
QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
|
||||||
if ((vaddr == (wp->vaddr & len_mask) ||
|
if ((vaddr == (wp->vaddr & len_mask) ||
|
||||||
(vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
|
(vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
|
||||||
wp->flags |= BP_WATCHPOINT_HIT;
|
wp->flags |= BP_WATCHPOINT_HIT;
|
||||||
if (!env->watchpoint_hit) {
|
if (!cpu->watchpoint_hit) {
|
||||||
env->watchpoint_hit = wp;
|
cpu->watchpoint_hit = wp;
|
||||||
tb_check_watchpoint(env);
|
tb_check_watchpoint(cpu);
|
||||||
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
|
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
|
||||||
env->exception_index = EXCP_DEBUG;
|
cpu->exception_index = EXCP_DEBUG;
|
||||||
cpu_loop_exit(env);
|
cpu_loop_exit(cpu);
|
||||||
} else {
|
} else {
|
||||||
cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
|
cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
|
||||||
tb_gen_code(env, pc, cs_base, cpu_flags, 1);
|
tb_gen_code(cpu, pc, cs_base, cpu_flags, 1);
|
||||||
cpu_resume_from_signal(env, NULL);
|
cpu_resume_from_signal(cpu, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1824,14 +1834,12 @@ static void tcg_commit(MemoryListener *listener)
|
|||||||
reset the modified entries */
|
reset the modified entries */
|
||||||
/* XXX: slow ! */
|
/* XXX: slow ! */
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
CPUArchState *env = cpu->env_ptr;
|
|
||||||
|
|
||||||
/* FIXME: Disentangle the cpu.h circular files deps so we can
|
/* FIXME: Disentangle the cpu.h circular files deps so we can
|
||||||
directly get the right CPU from listener. */
|
directly get the right CPU from listener. */
|
||||||
if (cpu->tcg_as_listener != listener) {
|
if (cpu->tcg_as_listener != listener) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tlb_flush(env, 1);
|
tlb_flush(cpu, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
ifeq ($(CONFIG_REALLY_VIRTFS),y)
|
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
|
||||||
|
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
|
||||||
|
# only pull in the actual virtio-9p device if we also enabled virtio.
|
||||||
common-obj-y = qemu-fsdev.o virtio-9p-marshal.o
|
common-obj-y = qemu-fsdev.o virtio-9p-marshal.o
|
||||||
else
|
else
|
||||||
common-obj-y = qemu-fsdev-dummy.o
|
common-obj-y = qemu-fsdev-dummy.o
|
||||||
|
|||||||
@@ -595,7 +595,7 @@ static int do_readlink(struct iovec *iovec, struct iovec *out_iovec)
|
|||||||
}
|
}
|
||||||
buffer = g_malloc(size);
|
buffer = g_malloc(size);
|
||||||
v9fs_string_init(&target);
|
v9fs_string_init(&target);
|
||||||
retval = readlink(path.data, buffer, size);
|
retval = readlink(path.data, buffer, size - 1);
|
||||||
if (retval > 0) {
|
if (retval > 0) {
|
||||||
buffer[retval] = '\0';
|
buffer[retval] = '\0';
|
||||||
v9fs_string_sprintf(&target, "%s", buffer);
|
v9fs_string_sprintf(&target, "%s", buffer);
|
||||||
|
|||||||
46
gdbstub.c
46
gdbstub.c
@@ -635,7 +635,6 @@ static const int xlat_gdb_type[] = {
|
|||||||
static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
|
static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
|
||||||
{
|
{
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
CPUArchState *env;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
@@ -646,19 +645,18 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
|
|||||||
case GDB_BREAKPOINT_SW:
|
case GDB_BREAKPOINT_SW:
|
||||||
case GDB_BREAKPOINT_HW:
|
case GDB_BREAKPOINT_HW:
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
env = cpu->env_ptr;
|
err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL);
|
||||||
err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
|
if (err) {
|
||||||
if (err)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
case GDB_WATCHPOINT_WRITE:
|
case GDB_WATCHPOINT_WRITE:
|
||||||
case GDB_WATCHPOINT_READ:
|
case GDB_WATCHPOINT_READ:
|
||||||
case GDB_WATCHPOINT_ACCESS:
|
case GDB_WATCHPOINT_ACCESS:
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
env = cpu->env_ptr;
|
err = cpu_watchpoint_insert(cpu, addr, len, xlat_gdb_type[type],
|
||||||
err = cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type],
|
|
||||||
NULL);
|
NULL);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
@@ -673,7 +671,6 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
|
|||||||
static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
|
static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
|
||||||
{
|
{
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
CPUArchState *env;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
@@ -684,19 +681,18 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
|
|||||||
case GDB_BREAKPOINT_SW:
|
case GDB_BREAKPOINT_SW:
|
||||||
case GDB_BREAKPOINT_HW:
|
case GDB_BREAKPOINT_HW:
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
env = cpu->env_ptr;
|
err = cpu_breakpoint_remove(cpu, addr, BP_GDB);
|
||||||
err = cpu_breakpoint_remove(env, addr, BP_GDB);
|
if (err) {
|
||||||
if (err)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
case GDB_WATCHPOINT_WRITE:
|
case GDB_WATCHPOINT_WRITE:
|
||||||
case GDB_WATCHPOINT_READ:
|
case GDB_WATCHPOINT_READ:
|
||||||
case GDB_WATCHPOINT_ACCESS:
|
case GDB_WATCHPOINT_ACCESS:
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
env = cpu->env_ptr;
|
err = cpu_watchpoint_remove(cpu, addr, len, xlat_gdb_type[type]);
|
||||||
err = cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]);
|
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -710,7 +706,6 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
|
|||||||
static void gdb_breakpoint_remove_all(void)
|
static void gdb_breakpoint_remove_all(void)
|
||||||
{
|
{
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
CPUArchState *env;
|
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
|
kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
|
||||||
@@ -718,10 +713,9 @@ static void gdb_breakpoint_remove_all(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CPU_FOREACH(cpu) {
|
CPU_FOREACH(cpu) {
|
||||||
env = cpu->env_ptr;
|
cpu_breakpoint_remove_all(cpu, BP_GDB);
|
||||||
cpu_breakpoint_remove_all(env, BP_GDB);
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
cpu_watchpoint_remove_all(env, BP_GDB);
|
cpu_watchpoint_remove_all(cpu, BP_GDB);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1086,8 +1080,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
|||||||
}
|
}
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
else if (strncmp(p, "Offsets", 7) == 0) {
|
else if (strncmp(p, "Offsets", 7) == 0) {
|
||||||
CPUArchState *env = s->c_cpu->env_ptr;
|
TaskState *ts = s->c_cpu->opaque;
|
||||||
TaskState *ts = env->opaque;
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
snprintf(buf, sizeof(buf),
|
||||||
"Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
|
"Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
|
||||||
@@ -1205,8 +1198,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
|
|||||||
}
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case RUN_STATE_DEBUG:
|
case RUN_STATE_DEBUG:
|
||||||
if (env->watchpoint_hit) {
|
if (cpu->watchpoint_hit) {
|
||||||
switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
|
switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) {
|
||||||
case BP_MEM_READ:
|
case BP_MEM_READ:
|
||||||
type = "r";
|
type = "r";
|
||||||
break;
|
break;
|
||||||
@@ -1220,8 +1213,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
|
|||||||
snprintf(buf, sizeof(buf),
|
snprintf(buf, sizeof(buf),
|
||||||
"T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
|
"T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
|
||||||
GDB_SIGNAL_TRAP, cpu_index(cpu), type,
|
GDB_SIGNAL_TRAP, cpu_index(cpu), type,
|
||||||
env->watchpoint_hit->vaddr);
|
(target_ulong)cpu->watchpoint_hit->vaddr);
|
||||||
env->watchpoint_hit = NULL;
|
cpu->watchpoint_hit = NULL;
|
||||||
goto send_packet;
|
goto send_packet;
|
||||||
}
|
}
|
||||||
tb_flush(env);
|
tb_flush(env);
|
||||||
@@ -1594,13 +1587,16 @@ int gdbserver_start(int port)
|
|||||||
/* Disable gdb stub for child processes. */
|
/* Disable gdb stub for child processes. */
|
||||||
void gdbserver_fork(CPUArchState *env)
|
void gdbserver_fork(CPUArchState *env)
|
||||||
{
|
{
|
||||||
|
CPUState *cpu = ENV_GET_CPU(env);
|
||||||
GDBState *s = gdbserver_state;
|
GDBState *s = gdbserver_state;
|
||||||
if (gdbserver_fd < 0 || s->fd < 0)
|
|
||||||
|
if (gdbserver_fd < 0 || s->fd < 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
close(s->fd);
|
close(s->fd);
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
cpu_breakpoint_remove_all(env, BP_GDB);
|
cpu_breakpoint_remove_all(cpu, BP_GDB);
|
||||||
cpu_watchpoint_remove_all(env, BP_GDB);
|
cpu_watchpoint_remove_all(cpu, BP_GDB);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int gdb_chr_can_receive(void *opaque)
|
static int gdb_chr_can_receive(void *opaque)
|
||||||
|
|||||||
@@ -17,35 +17,55 @@
|
|||||||
#include "block/coroutine.h"
|
#include "block/coroutine.h"
|
||||||
#include "virtio-9p-coth.h"
|
#include "virtio-9p-coth.h"
|
||||||
|
|
||||||
|
static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
|
||||||
|
{
|
||||||
|
ssize_t len, maxlen = PATH_MAX;
|
||||||
|
|
||||||
|
buf->data = g_malloc(PATH_MAX);
|
||||||
|
for(;;) {
|
||||||
|
len = s->ops->readlink(&s->ctx, path, buf->data, maxlen);
|
||||||
|
if (len < 0) {
|
||||||
|
g_free(buf->data);
|
||||||
|
buf->data = NULL;
|
||||||
|
buf->size = 0;
|
||||||
|
break;
|
||||||
|
} else if (len == maxlen) {
|
||||||
|
/*
|
||||||
|
* We dodn't have space to put the NULL or we have more
|
||||||
|
* to read. Increase the size and try again
|
||||||
|
*/
|
||||||
|
maxlen *= 2;
|
||||||
|
g_free(buf->data);
|
||||||
|
buf->data = g_malloc(maxlen);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Null terminate the readlink output
|
||||||
|
*/
|
||||||
|
buf->data[len] = '\0';
|
||||||
|
buf->size = len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
|
int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
ssize_t len;
|
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
|
|
||||||
if (v9fs_request_cancelled(pdu)) {
|
if (v9fs_request_cancelled(pdu)) {
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
buf->data = g_malloc(PATH_MAX);
|
|
||||||
v9fs_path_read_lock(s);
|
v9fs_path_read_lock(s);
|
||||||
v9fs_co_run_in_worker(
|
v9fs_co_run_in_worker(
|
||||||
{
|
{
|
||||||
len = s->ops->readlink(&s->ctx, path,
|
err = __readlink(s, path, buf);
|
||||||
buf->data, PATH_MAX - 1);
|
if (err < 0) {
|
||||||
if (len > -1) {
|
|
||||||
buf->size = len;
|
|
||||||
buf->data[len] = 0;
|
|
||||||
err = 0;
|
|
||||||
} else {
|
|
||||||
err = -errno;
|
err = -errno;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
v9fs_path_unlock(s);
|
v9fs_path_unlock(s);
|
||||||
if (err) {
|
|
||||||
g_free(buf->data);
|
|
||||||
buf->data = NULL;
|
|
||||||
buf->size = 0;
|
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -498,7 +498,7 @@ static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
|
|||||||
static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
|
static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
|
||||||
const char *name, V9fsPath *target)
|
const char *name, V9fsPath *target)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
struct file_handle *fh;
|
struct file_handle *fh;
|
||||||
int dirfd, ret, mnt_id;
|
int dirfd, ret, mnt_id;
|
||||||
struct handle_data *data = (struct handle_data *)ctx->private;
|
struct handle_data *data = (struct handle_data *)ctx->private;
|
||||||
@@ -513,7 +513,9 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
|
|||||||
dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
|
dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
|
||||||
} else {
|
} else {
|
||||||
/* relative to export root */
|
/* relative to export root */
|
||||||
dirfd = open(rpath(ctx, ".", buffer), O_DIRECTORY);
|
buffer = rpath(ctx, ".");
|
||||||
|
dirfd = open(buffer, O_DIRECTORY);
|
||||||
|
g_free(buffer);
|
||||||
}
|
}
|
||||||
if (dirfd < 0) {
|
if (dirfd < 0) {
|
||||||
return dirfd;
|
return dirfd;
|
||||||
@@ -521,7 +523,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
|
|||||||
fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
|
fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
|
||||||
fh->handle_bytes = data->handle_bytes;
|
fh->handle_bytes = data->handle_bytes;
|
||||||
/* add a "./" at the beginning of the path */
|
/* add a "./" at the beginning of the path */
|
||||||
snprintf(buffer, PATH_MAX, "./%s", name);
|
buffer = g_strdup_printf("./%s", name);
|
||||||
/* flag = 0 imply don't follow symlink */
|
/* flag = 0 imply don't follow symlink */
|
||||||
ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
|
ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
@@ -531,6 +533,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
|
|||||||
g_free(fh);
|
g_free(fh);
|
||||||
}
|
}
|
||||||
close(dirfd);
|
close(dirfd);
|
||||||
|
g_free(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,18 +42,18 @@
|
|||||||
|
|
||||||
#define VIRTFS_META_DIR ".virtfs_metadata"
|
#define VIRTFS_META_DIR ".virtfs_metadata"
|
||||||
|
|
||||||
static const char *local_mapped_attr_path(FsContext *ctx,
|
static char *local_mapped_attr_path(FsContext *ctx, const char *path)
|
||||||
const char *path, char *buffer)
|
|
||||||
{
|
{
|
||||||
char *dir_name;
|
char *dir_name;
|
||||||
char *tmp_path = g_strdup(path);
|
char *tmp_path = g_strdup(path);
|
||||||
char *base_name = basename(tmp_path);
|
char *base_name = basename(tmp_path);
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
/* NULL terminate the directory */
|
/* NULL terminate the directory */
|
||||||
dir_name = tmp_path;
|
dir_name = tmp_path;
|
||||||
*(base_name - 1) = '\0';
|
*(base_name - 1) = '\0';
|
||||||
|
|
||||||
snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
|
buffer = g_strdup_printf("%s/%s/%s/%s",
|
||||||
ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
|
ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
|
||||||
g_free(tmp_path);
|
g_free(tmp_path);
|
||||||
return buffer;
|
return buffer;
|
||||||
@@ -92,10 +92,11 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
|
|||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[ATTR_MAX];
|
char buf[ATTR_MAX];
|
||||||
char attr_path[PATH_MAX];
|
char *attr_path;
|
||||||
|
|
||||||
local_mapped_attr_path(ctx, path, attr_path);
|
attr_path = local_mapped_attr_path(ctx, path);
|
||||||
fp = local_fopen(attr_path, "r");
|
fp = local_fopen(attr_path, "r");
|
||||||
|
g_free(attr_path);
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -118,12 +119,13 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
|
|||||||
static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
|
static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
err = lstat(rpath(fs_ctx, path, buffer), stbuf);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
err = lstat(buffer, stbuf);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
goto err_out;
|
||||||
}
|
}
|
||||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
/* Actual credentials are part of extended attrs */
|
/* Actual credentials are part of extended attrs */
|
||||||
@@ -131,41 +133,42 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
|
|||||||
gid_t tmp_gid;
|
gid_t tmp_gid;
|
||||||
mode_t tmp_mode;
|
mode_t tmp_mode;
|
||||||
dev_t tmp_dev;
|
dev_t tmp_dev;
|
||||||
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
|
if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
|
||||||
sizeof(uid_t)) > 0) {
|
|
||||||
stbuf->st_uid = tmp_uid;
|
stbuf->st_uid = tmp_uid;
|
||||||
}
|
}
|
||||||
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
|
if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
|
||||||
sizeof(gid_t)) > 0) {
|
|
||||||
stbuf->st_gid = tmp_gid;
|
stbuf->st_gid = tmp_gid;
|
||||||
}
|
}
|
||||||
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
|
if (getxattr(buffer, "user.virtfs.mode",
|
||||||
&tmp_mode, sizeof(mode_t)) > 0) {
|
&tmp_mode, sizeof(mode_t)) > 0) {
|
||||||
stbuf->st_mode = tmp_mode;
|
stbuf->st_mode = tmp_mode;
|
||||||
}
|
}
|
||||||
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
|
if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
|
||||||
sizeof(dev_t)) > 0) {
|
|
||||||
stbuf->st_rdev = tmp_dev;
|
stbuf->st_rdev = tmp_dev;
|
||||||
}
|
}
|
||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
local_mapped_file_attr(fs_ctx, path, stbuf);
|
local_mapped_file_attr(fs_ctx, path, stbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
g_free(buffer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
|
static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char attr_dir[PATH_MAX];
|
char *attr_dir;
|
||||||
char *tmp_path = g_strdup(path);
|
char *tmp_path = g_strdup(path);
|
||||||
|
|
||||||
snprintf(attr_dir, PATH_MAX, "%s/%s/%s",
|
attr_dir = g_strdup_printf("%s/%s/%s",
|
||||||
ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
|
ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
|
||||||
|
|
||||||
err = mkdir(attr_dir, 0700);
|
err = mkdir(attr_dir, 0700);
|
||||||
if (err < 0 && errno == EEXIST) {
|
if (err < 0 && errno == EEXIST) {
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
g_free(attr_dir);
|
||||||
g_free(tmp_path);
|
g_free(tmp_path);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -176,10 +179,11 @@ static int local_set_mapped_file_attr(FsContext *ctx,
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char buf[ATTR_MAX];
|
char buf[ATTR_MAX];
|
||||||
char attr_path[PATH_MAX];
|
char *attr_path;
|
||||||
int uid = -1, gid = -1, mode = -1, rdev = -1;
|
int uid = -1, gid = -1, mode = -1, rdev = -1;
|
||||||
|
|
||||||
fp = local_fopen(local_mapped_attr_path(ctx, path, attr_path), "r");
|
attr_path = local_mapped_attr_path(ctx, path);
|
||||||
|
fp = local_fopen(attr_path, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
goto create_map_file;
|
goto create_map_file;
|
||||||
}
|
}
|
||||||
@@ -241,6 +245,7 @@ update_map_file:
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
g_free(attr_path);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,36 +287,43 @@ static int local_set_xattr(const char *path, FsCred *credp)
|
|||||||
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
|
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
|
||||||
FsCred *credp)
|
FsCred *credp)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
|
||||||
if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
|
buffer = rpath(fs_ctx, path);
|
||||||
credp->fc_gid) < 0) {
|
if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) {
|
||||||
/*
|
/*
|
||||||
* If we fail to change ownership and if we are
|
* If we fail to change ownership and if we are
|
||||||
* using security model none. Ignore the error
|
* using security model none. Ignore the error
|
||||||
*/
|
*/
|
||||||
if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
|
if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
|
if (chmod(buffer, credp->fc_mode & 07777) < 0) {
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
|
err:
|
||||||
|
g_free(buffer);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
|
static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
|
||||||
char *buf, size_t bufsz)
|
char *buf, size_t bufsz)
|
||||||
{
|
{
|
||||||
ssize_t tsize = -1;
|
ssize_t tsize = -1;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
|
if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
|
(fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
|
||||||
int fd;
|
int fd;
|
||||||
fd = open(rpath(fs_ctx, path, buffer), O_RDONLY | O_NOFOLLOW);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
fd = open(buffer, O_RDONLY | O_NOFOLLOW);
|
||||||
|
g_free(buffer);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -322,7 +334,9 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
|
|||||||
return tsize;
|
return tsize;
|
||||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||||
tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
tsize = readlink(buffer, buf, bufsz);
|
||||||
|
g_free(buffer);
|
||||||
}
|
}
|
||||||
return tsize;
|
return tsize;
|
||||||
}
|
}
|
||||||
@@ -340,20 +354,24 @@ static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
|
|||||||
static int local_open(FsContext *ctx, V9fsPath *fs_path,
|
static int local_open(FsContext *ctx, V9fsPath *fs_path,
|
||||||
int flags, V9fsFidOpenState *fs)
|
int flags, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
fs->fd = open(rpath(ctx, path, buffer), flags | O_NOFOLLOW);
|
buffer = rpath(ctx, path);
|
||||||
|
fs->fd = open(buffer, flags | O_NOFOLLOW);
|
||||||
|
g_free(buffer);
|
||||||
return fs->fd;
|
return fs->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_opendir(FsContext *ctx,
|
static int local_opendir(FsContext *ctx,
|
||||||
V9fsPath *fs_path, V9fsFidOpenState *fs)
|
V9fsPath *fs_path, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
fs->dir = opendir(rpath(ctx, path, buffer));
|
buffer = rpath(ctx, path);
|
||||||
|
fs->dir = opendir(buffer);
|
||||||
|
g_free(buffer);
|
||||||
if (!fs->dir) {
|
if (!fs->dir) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -441,18 +459,23 @@ static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
|
|||||||
|
|
||||||
static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
int ret = -1;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
ret = local_set_xattr(buffer, credp);
|
||||||
|
g_free(buffer);
|
||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
return local_set_mapped_file_attr(fs_ctx, path, credp);
|
return local_set_mapped_file_attr(fs_ctx, path, credp);
|
||||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||||
return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
ret = chmod(buffer, credp->fc_mode);
|
||||||
|
g_free(buffer);
|
||||||
}
|
}
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
||||||
@@ -462,7 +485,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
int err = -1;
|
int err = -1;
|
||||||
int serrno = 0;
|
int serrno = 0;
|
||||||
V9fsString fullname;
|
V9fsString fullname;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
|
||||||
v9fs_string_init(&fullname);
|
v9fs_string_init(&fullname);
|
||||||
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
|
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
|
||||||
@@ -470,21 +493,23 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
|
|
||||||
/* Determine the security model */
|
/* Determine the security model */
|
||||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
err = mknod(rpath(fs_ctx, path, buffer),
|
buffer = rpath(fs_ctx, path);
|
||||||
SM_LOCAL_MODE_BITS|S_IFREG, 0);
|
err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
|
g_free(buffer);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
|
err = local_set_xattr(buffer, credp);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
goto err_end;
|
goto err_end;
|
||||||
}
|
}
|
||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
|
|
||||||
err = mknod(rpath(fs_ctx, path, buffer),
|
buffer = rpath(fs_ctx, path);
|
||||||
SM_LOCAL_MODE_BITS|S_IFREG, 0);
|
err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
|
g_free(buffer);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err = local_set_mapped_file_attr(fs_ctx, path, credp);
|
err = local_set_mapped_file_attr(fs_ctx, path, credp);
|
||||||
@@ -494,9 +519,10 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
}
|
}
|
||||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||||
err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
|
buffer = rpath(fs_ctx, path);
|
||||||
credp->fc_rdev);
|
err = mknod(buffer, credp->fc_mode, credp->fc_rdev);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
|
g_free(buffer);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err = local_post_create_passthrough(fs_ctx, path, credp);
|
err = local_post_create_passthrough(fs_ctx, path, credp);
|
||||||
@@ -508,8 +534,9 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err_end:
|
err_end:
|
||||||
remove(rpath(fs_ctx, path, buffer));
|
remove(buffer);
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
|
g_free(buffer);
|
||||||
out:
|
out:
|
||||||
v9fs_string_free(&fullname);
|
v9fs_string_free(&fullname);
|
||||||
return err;
|
return err;
|
||||||
@@ -522,7 +549,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
int err = -1;
|
int err = -1;
|
||||||
int serrno = 0;
|
int serrno = 0;
|
||||||
V9fsString fullname;
|
V9fsString fullname;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
|
||||||
v9fs_string_init(&fullname);
|
v9fs_string_init(&fullname);
|
||||||
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
|
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
|
||||||
@@ -530,19 +557,23 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
|
|
||||||
/* Determine the security model */
|
/* Determine the security model */
|
||||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
|
g_free(buffer);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
credp->fc_mode = credp->fc_mode|S_IFDIR;
|
credp->fc_mode = credp->fc_mode|S_IFDIR;
|
||||||
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
|
err = local_set_xattr(buffer, credp);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
goto err_end;
|
goto err_end;
|
||||||
}
|
}
|
||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
|
g_free(buffer);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
credp->fc_mode = credp->fc_mode|S_IFDIR;
|
credp->fc_mode = credp->fc_mode|S_IFDIR;
|
||||||
@@ -553,8 +584,10 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
}
|
}
|
||||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||||
err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
err = mkdir(buffer, credp->fc_mode);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
|
g_free(buffer);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err = local_post_create_passthrough(fs_ctx, path, credp);
|
err = local_post_create_passthrough(fs_ctx, path, credp);
|
||||||
@@ -566,8 +599,9 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err_end:
|
err_end:
|
||||||
remove(rpath(fs_ctx, path, buffer));
|
remove(buffer);
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
|
g_free(buffer);
|
||||||
out:
|
out:
|
||||||
v9fs_string_free(&fullname);
|
v9fs_string_free(&fullname);
|
||||||
return err;
|
return err;
|
||||||
@@ -626,7 +660,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
|
|||||||
int err = -1;
|
int err = -1;
|
||||||
int serrno = 0;
|
int serrno = 0;
|
||||||
V9fsString fullname;
|
V9fsString fullname;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark all the open to not follow symlinks
|
* Mark all the open to not follow symlinks
|
||||||
@@ -639,21 +673,25 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
|
|||||||
|
|
||||||
/* Determine the security model */
|
/* Determine the security model */
|
||||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
g_free(buffer);
|
||||||
err = fd;
|
err = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
credp->fc_mode = credp->fc_mode|S_IFREG;
|
credp->fc_mode = credp->fc_mode|S_IFREG;
|
||||||
/* Set cleint credentials in xattr */
|
/* Set cleint credentials in xattr */
|
||||||
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
|
err = local_set_xattr(buffer, credp);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
goto err_end;
|
goto err_end;
|
||||||
}
|
}
|
||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
g_free(buffer);
|
||||||
err = fd;
|
err = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -666,8 +704,10 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
|
|||||||
}
|
}
|
||||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||||
fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
fd = open(buffer, flags, credp->fc_mode);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
g_free(buffer);
|
||||||
err = fd;
|
err = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -683,8 +723,9 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
|
|||||||
|
|
||||||
err_end:
|
err_end:
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(rpath(fs_ctx, path, buffer));
|
remove(buffer);
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
|
g_free(buffer);
|
||||||
out:
|
out:
|
||||||
v9fs_string_free(&fullname);
|
v9fs_string_free(&fullname);
|
||||||
return err;
|
return err;
|
||||||
@@ -698,7 +739,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||||||
int serrno = 0;
|
int serrno = 0;
|
||||||
char *newpath;
|
char *newpath;
|
||||||
V9fsString fullname;
|
V9fsString fullname;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
|
||||||
v9fs_string_init(&fullname);
|
v9fs_string_init(&fullname);
|
||||||
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
|
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
|
||||||
@@ -708,10 +749,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
int fd;
|
int fd;
|
||||||
ssize_t oldpath_size, write_size;
|
ssize_t oldpath_size, write_size;
|
||||||
fd = open(rpath(fs_ctx, newpath, buffer),
|
buffer = rpath(fs_ctx, newpath);
|
||||||
O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
|
fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
|
||||||
SM_LOCAL_MODE_BITS);
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
g_free(buffer);
|
||||||
err = fd;
|
err = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -730,7 +771,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||||||
close(fd);
|
close(fd);
|
||||||
/* Set cleint credentials in symlink's xattr */
|
/* Set cleint credentials in symlink's xattr */
|
||||||
credp->fc_mode = credp->fc_mode|S_IFLNK;
|
credp->fc_mode = credp->fc_mode|S_IFLNK;
|
||||||
err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
|
err = local_set_xattr(buffer, credp);
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
goto err_end;
|
goto err_end;
|
||||||
@@ -738,10 +779,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
int fd;
|
int fd;
|
||||||
ssize_t oldpath_size, write_size;
|
ssize_t oldpath_size, write_size;
|
||||||
fd = open(rpath(fs_ctx, newpath, buffer),
|
buffer = rpath(fs_ctx, newpath);
|
||||||
O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
|
fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
|
||||||
SM_LOCAL_MODE_BITS);
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
g_free(buffer);
|
||||||
err = fd;
|
err = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -767,12 +808,13 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||||||
}
|
}
|
||||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||||
err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
|
buffer = rpath(fs_ctx, newpath);
|
||||||
|
err = symlink(oldpath, buffer);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
g_free(buffer);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
|
err = lchown(buffer, credp->fc_uid, credp->fc_gid);
|
||||||
credp->fc_gid);
|
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
/*
|
/*
|
||||||
* If we fail to change ownership and if we are
|
* If we fail to change ownership and if we are
|
||||||
@@ -788,8 +830,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err_end:
|
err_end:
|
||||||
remove(rpath(fs_ctx, newpath, buffer));
|
remove(buffer);
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
|
g_free(buffer);
|
||||||
out:
|
out:
|
||||||
v9fs_string_free(&fullname);
|
v9fs_string_free(&fullname);
|
||||||
return err;
|
return err;
|
||||||
@@ -800,13 +843,16 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
V9fsString newpath;
|
V9fsString newpath;
|
||||||
char buffer[PATH_MAX], buffer1[PATH_MAX];
|
char *buffer, *buffer1;
|
||||||
|
|
||||||
v9fs_string_init(&newpath);
|
v9fs_string_init(&newpath);
|
||||||
v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
|
v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
|
||||||
|
|
||||||
ret = link(rpath(ctx, oldpath->data, buffer),
|
buffer = rpath(ctx, oldpath->data);
|
||||||
rpath(ctx, newpath.data, buffer1));
|
buffer1 = rpath(ctx, newpath.data);
|
||||||
|
ret = link(buffer, buffer1);
|
||||||
|
g_free(buffer);
|
||||||
|
g_free(buffer1);
|
||||||
|
|
||||||
/* now link the virtfs_metadata files */
|
/* now link the virtfs_metadata files */
|
||||||
if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
|
if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
|
||||||
@@ -815,8 +861,11 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
|
buffer = local_mapped_attr_path(ctx, oldpath->data);
|
||||||
local_mapped_attr_path(ctx, newpath.data, buffer1));
|
buffer1 = local_mapped_attr_path(ctx, newpath.data);
|
||||||
|
ret = link(buffer, buffer1);
|
||||||
|
g_free(buffer);
|
||||||
|
g_free(buffer1);
|
||||||
if (ret < 0 && errno != ENOENT) {
|
if (ret < 0 && errno != ENOENT) {
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@@ -828,17 +877,21 @@ err_out:
|
|||||||
|
|
||||||
static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
|
static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
int ret;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
return truncate(rpath(ctx, path, buffer), size);
|
buffer = rpath(ctx, path);
|
||||||
|
ret = truncate(buffer, size);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_rename(FsContext *ctx, const char *oldpath,
|
static int local_rename(FsContext *ctx, const char *oldpath,
|
||||||
const char *newpath)
|
const char *newpath)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char buffer[PATH_MAX], buffer1[PATH_MAX];
|
char *buffer, *buffer1;
|
||||||
|
|
||||||
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
err = local_create_mapped_attr_dir(ctx, newpath);
|
err = local_create_mapped_attr_dir(ctx, newpath);
|
||||||
@@ -846,50 +899,69 @@ static int local_rename(FsContext *ctx, const char *oldpath,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
/* rename the .virtfs_metadata files */
|
/* rename the .virtfs_metadata files */
|
||||||
err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
|
buffer = local_mapped_attr_path(ctx, oldpath);
|
||||||
local_mapped_attr_path(ctx, newpath, buffer1));
|
buffer1 = local_mapped_attr_path(ctx, newpath);
|
||||||
|
err = rename(buffer, buffer1);
|
||||||
|
g_free(buffer);
|
||||||
|
g_free(buffer1);
|
||||||
if (err < 0 && errno != ENOENT) {
|
if (err < 0 && errno != ENOENT) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
|
|
||||||
|
buffer = rpath(ctx, oldpath);
|
||||||
|
buffer1 = rpath(ctx, newpath);
|
||||||
|
err = rename(buffer, buffer1);
|
||||||
|
g_free(buffer);
|
||||||
|
g_free(buffer1);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
int ret = -1;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
|
if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
(fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||||
return lchown(rpath(fs_ctx, path, buffer),
|
buffer = rpath(fs_ctx, path);
|
||||||
credp->fc_uid, credp->fc_gid);
|
ret = lchown(buffer, credp->fc_uid, credp->fc_gid);
|
||||||
|
g_free(buffer);
|
||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
|
buffer = rpath(fs_ctx, path);
|
||||||
|
ret = local_set_xattr(buffer, credp);
|
||||||
|
g_free(buffer);
|
||||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
return local_set_mapped_file_attr(fs_ctx, path, credp);
|
return local_set_mapped_file_attr(fs_ctx, path, credp);
|
||||||
}
|
}
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_utimensat(FsContext *s, V9fsPath *fs_path,
|
static int local_utimensat(FsContext *s, V9fsPath *fs_path,
|
||||||
const struct timespec *buf)
|
const struct timespec *buf)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
int ret;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
return qemu_utimens(rpath(s, path, buffer), buf);
|
buffer = rpath(s, path);
|
||||||
|
ret = qemu_utimens(buffer, buf);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_remove(FsContext *ctx, const char *path)
|
static int local_remove(FsContext *ctx, const char *path)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
|
||||||
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
err = lstat(rpath(ctx, path, buffer), &stbuf);
|
buffer = rpath(ctx, path);
|
||||||
|
err = lstat(buffer, &stbuf);
|
||||||
|
g_free(buffer);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@@ -898,8 +970,10 @@ static int local_remove(FsContext *ctx, const char *path)
|
|||||||
* directory
|
* directory
|
||||||
*/
|
*/
|
||||||
if (S_ISDIR(stbuf.st_mode)) {
|
if (S_ISDIR(stbuf.st_mode)) {
|
||||||
sprintf(buffer, "%s/%s/%s", ctx->fs_root, path, VIRTFS_META_DIR);
|
buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
|
||||||
|
path, VIRTFS_META_DIR);
|
||||||
err = remove(buffer);
|
err = remove(buffer);
|
||||||
|
g_free(buffer);
|
||||||
if (err < 0 && errno != ENOENT) {
|
if (err < 0 && errno != ENOENT) {
|
||||||
/*
|
/*
|
||||||
* We didn't had the .virtfs_metadata file. May be file created
|
* We didn't had the .virtfs_metadata file. May be file created
|
||||||
@@ -912,7 +986,9 @@ static int local_remove(FsContext *ctx, const char *path)
|
|||||||
* Now remove the name from parent directory
|
* Now remove the name from parent directory
|
||||||
* .virtfs_metadata directory
|
* .virtfs_metadata directory
|
||||||
*/
|
*/
|
||||||
err = remove(local_mapped_attr_path(ctx, path, buffer));
|
buffer = local_mapped_attr_path(ctx, path);
|
||||||
|
err = remove(buffer);
|
||||||
|
g_free(buffer);
|
||||||
if (err < 0 && errno != ENOENT) {
|
if (err < 0 && errno != ENOENT) {
|
||||||
/*
|
/*
|
||||||
* We didn't had the .virtfs_metadata file. May be file created
|
* We didn't had the .virtfs_metadata file. May be file created
|
||||||
@@ -921,7 +997,10 @@ static int local_remove(FsContext *ctx, const char *path)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return remove(rpath(ctx, path, buffer));
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
err = remove(buffer);
|
||||||
|
g_free(buffer);
|
||||||
err_out:
|
err_out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -946,10 +1025,14 @@ static int local_fsync(FsContext *ctx, int fid_type,
|
|||||||
|
|
||||||
static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
|
static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
int ret;
|
||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
return statfs(rpath(s, path, buffer), stbuf);
|
buffer = rpath(s, path);
|
||||||
|
ret = statfs(buffer, stbuf);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
|
static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
|
||||||
@@ -1022,7 +1105,7 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
V9fsString fullname;
|
V9fsString fullname;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
|
||||||
v9fs_string_init(&fullname);
|
v9fs_string_init(&fullname);
|
||||||
|
|
||||||
@@ -1033,9 +1116,10 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||||||
* If directory remove .virtfs_metadata contained in the
|
* If directory remove .virtfs_metadata contained in the
|
||||||
* directory
|
* directory
|
||||||
*/
|
*/
|
||||||
sprintf(buffer, "%s/%s/%s", ctx->fs_root,
|
buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
|
||||||
fullname.data, VIRTFS_META_DIR);
|
fullname.data, VIRTFS_META_DIR);
|
||||||
ret = remove(buffer);
|
ret = remove(buffer);
|
||||||
|
g_free(buffer);
|
||||||
if (ret < 0 && errno != ENOENT) {
|
if (ret < 0 && errno != ENOENT) {
|
||||||
/*
|
/*
|
||||||
* We didn't had the .virtfs_metadata file. May be file created
|
* We didn't had the .virtfs_metadata file. May be file created
|
||||||
@@ -1048,7 +1132,9 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||||||
* Now remove the name from parent directory
|
* Now remove the name from parent directory
|
||||||
* .virtfs_metadata directory.
|
* .virtfs_metadata directory.
|
||||||
*/
|
*/
|
||||||
ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
|
buffer = local_mapped_attr_path(ctx, fullname.data);
|
||||||
|
ret = remove(buffer);
|
||||||
|
g_free(buffer);
|
||||||
if (ret < 0 && errno != ENOENT) {
|
if (ret < 0 && errno != ENOENT) {
|
||||||
/*
|
/*
|
||||||
* We didn't had the .virtfs_metadata file. May be file created
|
* We didn't had the .virtfs_metadata file. May be file created
|
||||||
@@ -1058,10 +1144,12 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Remove the name finally */
|
/* Remove the name finally */
|
||||||
ret = remove(rpath(ctx, fullname.data, buffer));
|
buffer = rpath(ctx, fullname.data);
|
||||||
v9fs_string_free(&fullname);
|
ret = remove(buffer);
|
||||||
|
g_free(buffer);
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
v9fs_string_free(&fullname);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,13 @@
|
|||||||
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value, size_t size)
|
const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size);
|
ssize_t ret;
|
||||||
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
|
||||||
@@ -52,17 +57,23 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
|
|||||||
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
void *value, size_t size, int flags)
|
void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value,
|
int ret;
|
||||||
size, flags);
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_pacl_removexattr(FsContext *ctx,
|
static int mp_pacl_removexattr(FsContext *ctx,
|
||||||
const char *path, const char *name)
|
const char *path, const char *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS);
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lremovexattr(buffer, MAP_ACL_ACCESS);
|
||||||
if (ret == -1 && errno == ENODATA) {
|
if (ret == -1 && errno == ENODATA) {
|
||||||
/*
|
/*
|
||||||
* We don't get ENODATA error when trying to remove a
|
* We don't get ENODATA error when trying to remove a
|
||||||
@@ -72,14 +83,20 @@ static int mp_pacl_removexattr(FsContext *ctx,
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
g_free(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value, size_t size)
|
const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size);
|
ssize_t ret;
|
||||||
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
|
||||||
@@ -104,17 +121,23 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
|
|||||||
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
void *value, size_t size, int flags)
|
void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value,
|
int ret;
|
||||||
size, flags);
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_dacl_removexattr(FsContext *ctx,
|
static int mp_dacl_removexattr(FsContext *ctx,
|
||||||
const char *path, const char *name)
|
const char *path, const char *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT);
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lremovexattr(buffer, MAP_ACL_DEFAULT);
|
||||||
if (ret == -1 && errno == ENODATA) {
|
if (ret == -1 && errno == ENODATA) {
|
||||||
/*
|
/*
|
||||||
* We don't get ENODATA error when trying to remove a
|
* We don't get ENODATA error when trying to remove a
|
||||||
@@ -124,6 +147,7 @@ static int mp_dacl_removexattr(FsContext *ctx,
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
g_free(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value, size_t size)
|
const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
||||||
/*
|
/*
|
||||||
* Don't allow fetch of user.virtfs namesapce
|
* Don't allow fetch of user.virtfs namesapce
|
||||||
@@ -30,7 +32,10 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
|
|||||||
errno = ENOATTR;
|
errno = ENOATTR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return lgetxattr(rpath(ctx, path, buffer), name, value, size);
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lgetxattr(buffer, name, value, size);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
|
||||||
@@ -69,7 +74,9 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
|
|||||||
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
|
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
void *value, size_t size, int flags)
|
void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
||||||
/*
|
/*
|
||||||
* Don't allow fetch of user.virtfs namesapce
|
* Don't allow fetch of user.virtfs namesapce
|
||||||
@@ -78,13 +85,18 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
|
|||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lsetxattr(buffer, name, value, size, flags);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_user_removexattr(FsContext *ctx,
|
static int mp_user_removexattr(FsContext *ctx,
|
||||||
const char *path, const char *name)
|
const char *path, const char *name)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
||||||
/*
|
/*
|
||||||
* Don't allow fetch of user.virtfs namesapce
|
* Don't allow fetch of user.virtfs namesapce
|
||||||
@@ -93,7 +105,10 @@ static int mp_user_removexattr(FsContext *ctx,
|
|||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return lremovexattr(rpath(ctx, path, buffer), name);
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lremovexattr(buffer, name);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
XattrOperations mapped_user_xattr = {
|
XattrOperations mapped_user_xattr = {
|
||||||
|
|||||||
@@ -67,21 +67,24 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
|
|||||||
void *value, size_t vsize)
|
void *value, size_t vsize)
|
||||||
{
|
{
|
||||||
ssize_t size = 0;
|
ssize_t size = 0;
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
void *ovalue = value;
|
void *ovalue = value;
|
||||||
XattrOperations *xops;
|
XattrOperations *xops;
|
||||||
char *orig_value, *orig_value_start;
|
char *orig_value, *orig_value_start;
|
||||||
ssize_t xattr_len, parsed_len = 0, attr_len;
|
ssize_t xattr_len, parsed_len = 0, attr_len;
|
||||||
|
|
||||||
/* Get the actual len */
|
/* Get the actual len */
|
||||||
xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0);
|
buffer = rpath(ctx, path);
|
||||||
|
xattr_len = llistxattr(buffer, value, 0);
|
||||||
if (xattr_len <= 0) {
|
if (xattr_len <= 0) {
|
||||||
|
g_free(buffer);
|
||||||
return xattr_len;
|
return xattr_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now fetch the xattr and find the actual size */
|
/* Now fetch the xattr and find the actual size */
|
||||||
orig_value = g_malloc(xattr_len);
|
orig_value = g_malloc(xattr_len);
|
||||||
xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len);
|
xattr_len = llistxattr(buffer, orig_value, xattr_len);
|
||||||
|
g_free(buffer);
|
||||||
|
|
||||||
/* store the orig pointer */
|
/* store the orig pointer */
|
||||||
orig_value_start = orig_value;
|
orig_value_start = orig_value;
|
||||||
|
|||||||
@@ -54,23 +54,38 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
|
|||||||
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
|
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value, size_t size)
|
const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
return lgetxattr(rpath(ctx, path, buffer), name, value, size);
|
ssize_t ret;
|
||||||
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lgetxattr(buffer, name, value, size);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int pt_setxattr(FsContext *ctx, const char *path,
|
static inline int pt_setxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value,
|
const char *name, void *value,
|
||||||
size_t size, int flags)
|
size_t size, int flags)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
|
int ret;
|
||||||
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lsetxattr(buffer, name, value, size, flags);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int pt_removexattr(FsContext *ctx,
|
static inline int pt_removexattr(FsContext *ctx,
|
||||||
const char *path, const char *name)
|
const char *path, const char *name)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char *buffer;
|
||||||
return lremovexattr(rpath(ctx, path, buffer), name);
|
int ret;
|
||||||
|
|
||||||
|
buffer = rpath(ctx, path);
|
||||||
|
ret = lremovexattr(path, name);
|
||||||
|
g_free(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
|
static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <glib.h>
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
#include "fsdev/file-op-9p.h"
|
#include "fsdev/file-op-9p.h"
|
||||||
#include "fsdev/virtio-9p-marshal.h"
|
#include "fsdev/virtio-9p-marshal.h"
|
||||||
@@ -112,10 +113,9 @@ enum p9_proto_version {
|
|||||||
|
|
||||||
#define FID_REFERENCED 0x1
|
#define FID_REFERENCED 0x1
|
||||||
#define FID_NON_RECLAIMABLE 0x2
|
#define FID_NON_RECLAIMABLE 0x2
|
||||||
static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
|
static inline char *rpath(FsContext *ctx, const char *path)
|
||||||
{
|
{
|
||||||
snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
|
return g_strdup_printf("%s/%s", ctx->fs_root, path);
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
devices-dirs-$(CONFIG_REALLY_VIRTFS) += 9pfs/
|
devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/
|
||||||
devices-dirs-$(CONFIG_ACPI) += acpi/
|
devices-dirs-$(CONFIG_ACPI) += acpi/
|
||||||
devices-dirs-$(CONFIG_SOFTMMU) += audio/
|
devices-dirs-$(CONFIG_SOFTMMU) += audio/
|
||||||
devices-dirs-$(CONFIG_SOFTMMU) += block/
|
devices-dirs-$(CONFIG_SOFTMMU) += block/
|
||||||
|
|||||||
@@ -110,10 +110,10 @@
|
|||||||
#define MP_PHY_88E3015 0x01410E20
|
#define MP_PHY_88E3015 0x01410E20
|
||||||
|
|
||||||
/* TX descriptor status */
|
/* TX descriptor status */
|
||||||
#define MP_ETH_TX_OWN (1 << 31)
|
#define MP_ETH_TX_OWN (1U << 31)
|
||||||
|
|
||||||
/* RX descriptor status */
|
/* RX descriptor status */
|
||||||
#define MP_ETH_RX_OWN (1 << 31)
|
#define MP_ETH_RX_OWN (1U << 31)
|
||||||
|
|
||||||
/* Interrupt cause/mask bits */
|
/* Interrupt cause/mask bits */
|
||||||
#define MP_ETH_IRQ_RX_BIT 0
|
#define MP_ETH_IRQ_RX_BIT 0
|
||||||
|
|||||||
@@ -809,22 +809,26 @@ static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
|
|||||||
uint32_t diff, uint32_t value)
|
uint32_t diff, uint32_t value)
|
||||||
{
|
{
|
||||||
if (s->compat1509) {
|
if (s->compat1509) {
|
||||||
if (diff & (1 << 31)) /* MCBSP3_CLK_HIZ_DI */
|
if (diff & (1U << 31)) {
|
||||||
omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
|
/* MCBSP3_CLK_HIZ_DI */
|
||||||
(value >> 31) & 1);
|
omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"), (value >> 31) & 1);
|
||||||
if (diff & (1 << 1)) /* CLK32K */
|
}
|
||||||
omap_clk_onoff(omap_findclk(s, "clk32k_out"),
|
if (diff & (1 << 1)) {
|
||||||
(~value >> 1) & 1);
|
/* CLK32K */
|
||||||
|
omap_clk_onoff(omap_findclk(s, "clk32k_out"), (~value >> 1) & 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
|
static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
|
||||||
uint32_t diff, uint32_t value)
|
uint32_t diff, uint32_t value)
|
||||||
{
|
{
|
||||||
if (diff & (1 << 31)) /* CONF_MOD_UART3_CLK_MODE_R */
|
if (diff & (1U << 31)) {
|
||||||
|
/* CONF_MOD_UART3_CLK_MODE_R */
|
||||||
omap_clk_reparent(omap_findclk(s, "uart3_ck"),
|
omap_clk_reparent(omap_findclk(s, "uart3_ck"),
|
||||||
omap_findclk(s, ((value >> 31) & 1) ?
|
omap_findclk(s, ((value >> 31) & 1) ?
|
||||||
"ck_48m" : "armper_ck"));
|
"ck_48m" : "armper_ck"));
|
||||||
|
}
|
||||||
if (diff & (1 << 30)) /* CONF_MOD_UART2_CLK_MODE_R */
|
if (diff & (1 << 30)) /* CONF_MOD_UART2_CLK_MODE_R */
|
||||||
omap_clk_reparent(omap_findclk(s, "uart2_ck"),
|
omap_clk_reparent(omap_findclk(s, "uart2_ck"),
|
||||||
omap_findclk(s, ((value >> 30) & 1) ?
|
omap_findclk(s, ((value >> 30) & 1) ?
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
/* Idle */
|
/* Idle */
|
||||||
if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
|
if (!(s->cm_regs[CCCR >> 2] & (1U << 31))) { /* CPDIS */
|
||||||
cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
|
cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -496,7 +496,7 @@ typedef struct {
|
|||||||
#define SSCR0_SSE (1 << 7)
|
#define SSCR0_SSE (1 << 7)
|
||||||
#define SSCR0_RIM (1 << 22)
|
#define SSCR0_RIM (1 << 22)
|
||||||
#define SSCR0_TIM (1 << 23)
|
#define SSCR0_TIM (1 << 23)
|
||||||
#define SSCR0_MOD (1 << 31)
|
#define SSCR0_MOD (1U << 31)
|
||||||
#define SSCR0_DSS(x) (((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
|
#define SSCR0_DSS(x) (((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
|
||||||
#define SSCR1_RIE (1 << 0)
|
#define SSCR1_RIE (1 << 0)
|
||||||
#define SSCR1_TIE (1 << 1)
|
#define SSCR1_TIE (1 << 1)
|
||||||
@@ -1006,7 +1006,7 @@ static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
|
|||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case RTTR:
|
case RTTR:
|
||||||
if (!(s->rttr & (1 << 31))) {
|
if (!(s->rttr & (1U << 31))) {
|
||||||
pxa2xx_rtc_hzupdate(s);
|
pxa2xx_rtc_hzupdate(s);
|
||||||
s->rttr = value;
|
s->rttr = value;
|
||||||
pxa2xx_rtc_alarm_update(s, s->rtsr);
|
pxa2xx_rtc_alarm_update(s, s->rtsr);
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bank = line >> 5;
|
bank = line >> 5;
|
||||||
mask = 1 << (line & 31);
|
mask = 1U << (line & 31);
|
||||||
|
|
||||||
if (level) {
|
if (level) {
|
||||||
s->status[bank] |= s->rising[bank] & mask &
|
s->status[bank] |= s->rising[bank] & mask &
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
|
|||||||
|
|
||||||
for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
|
for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
|
||||||
irq = s->priority[i] & 0x3f;
|
irq = s->priority[i] & 0x3f;
|
||||||
if ((s->priority[i] & (1 << 31)) && irq < PXA2XX_PIC_SRCS) {
|
if ((s->priority[i] & (1U << 31)) && irq < PXA2XX_PIC_SRCS) {
|
||||||
/* Source peripheral ID is valid. */
|
/* Source peripheral ID is valid. */
|
||||||
bit = 1 << (irq & 31);
|
bit = 1 << (irq & 31);
|
||||||
int_set = (irq >= 32);
|
int_set = (irq >= 32);
|
||||||
@@ -119,7 +119,7 @@ static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
|
|||||||
if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
|
if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
|
||||||
/* IRQ asserted */
|
/* IRQ asserted */
|
||||||
ichp &= 0x0000ffff;
|
ichp &= 0x0000ffff;
|
||||||
ichp |= (1 << 31) | (irq << 16);
|
ichp |= (1U << 31) | (irq << 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -658,14 +658,15 @@ static void spitz_adc_temp_on(void *opaque, int line, int level)
|
|||||||
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
|
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int corgi_ssp_init(SSISlave *dev)
|
static int corgi_ssp_init(SSISlave *d)
|
||||||
{
|
{
|
||||||
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
|
DeviceState *dev = DEVICE(d);
|
||||||
|
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, d);
|
||||||
|
|
||||||
qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3);
|
qdev_init_gpio_in(dev, corgi_ssp_gpio_cs, 3);
|
||||||
s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0");
|
s->bus[0] = ssi_create_bus(dev, "ssi0");
|
||||||
s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
|
s->bus[1] = ssi_create_bus(dev, "ssi1");
|
||||||
s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
|
s->bus[2] = ssi_create_bus(dev, "ssi2");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,13 +223,13 @@ static void *cur_chip = NULL; /* current chip point */
|
|||||||
/* static OPLSAMPLE *bufL,*bufR; */
|
/* static OPLSAMPLE *bufL,*bufR; */
|
||||||
static OPL_CH *S_CH;
|
static OPL_CH *S_CH;
|
||||||
static OPL_CH *E_CH;
|
static OPL_CH *E_CH;
|
||||||
OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
|
static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
|
||||||
|
|
||||||
static INT32 outd[1];
|
static INT32 outd[1];
|
||||||
static INT32 ams;
|
static INT32 ams;
|
||||||
static INT32 vib;
|
static INT32 vib;
|
||||||
INT32 *ams_table;
|
static INT32 *ams_table;
|
||||||
INT32 *vib_table;
|
static INT32 *vib_table;
|
||||||
static INT32 amsIncr;
|
static INT32 amsIncr;
|
||||||
static INT32 vibIncr;
|
static INT32 vibIncr;
|
||||||
static INT32 feedback2; /* connect for SLOT 2 */
|
static INT32 feedback2; /* connect for SLOT 2 */
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "virtio-blk.h"
|
#include "virtio-blk.h"
|
||||||
#include "block/aio.h"
|
#include "block/aio.h"
|
||||||
#include "hw/virtio/virtio-bus.h"
|
#include "hw/virtio/virtio-bus.h"
|
||||||
|
#include "monitor/monitor.h" /* for object_add() */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SEG_MAX = 126, /* maximum number of I/O segments */
|
SEG_MAX = 126, /* maximum number of I/O segments */
|
||||||
@@ -44,8 +45,6 @@ struct VirtIOBlockDataPlane {
|
|||||||
bool started;
|
bool started;
|
||||||
bool starting;
|
bool starting;
|
||||||
bool stopping;
|
bool stopping;
|
||||||
QEMUBH *start_bh;
|
|
||||||
QemuThread thread;
|
|
||||||
|
|
||||||
VirtIOBlkConf *blk;
|
VirtIOBlkConf *blk;
|
||||||
int fd; /* image file descriptor */
|
int fd; /* image file descriptor */
|
||||||
@@ -59,12 +58,14 @@ struct VirtIOBlockDataPlane {
|
|||||||
* (because you don't own the file descriptor or handle; you just
|
* (because you don't own the file descriptor or handle; you just
|
||||||
* use it).
|
* use it).
|
||||||
*/
|
*/
|
||||||
|
IOThread *iothread;
|
||||||
|
bool internal_iothread;
|
||||||
AioContext *ctx;
|
AioContext *ctx;
|
||||||
EventNotifier io_notifier; /* Linux AIO completion */
|
EventNotifier io_notifier; /* Linux AIO completion */
|
||||||
EventNotifier host_notifier; /* doorbell */
|
EventNotifier host_notifier; /* doorbell */
|
||||||
|
|
||||||
IOQueue ioqueue; /* Linux AIO queue (should really be per
|
IOQueue ioqueue; /* Linux AIO queue (should really be per
|
||||||
dataplane thread) */
|
IOThread) */
|
||||||
VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the
|
VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the
|
||||||
queue */
|
queue */
|
||||||
|
|
||||||
@@ -342,26 +343,7 @@ static void handle_io(EventNotifier *e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *data_plane_thread(void *opaque)
|
/* Context: QEMU global mutex held */
|
||||||
{
|
|
||||||
VirtIOBlockDataPlane *s = opaque;
|
|
||||||
|
|
||||||
while (!s->stopping || s->num_reqs > 0) {
|
|
||||||
aio_poll(s->ctx, true);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void start_data_plane_bh(void *opaque)
|
|
||||||
{
|
|
||||||
VirtIOBlockDataPlane *s = opaque;
|
|
||||||
|
|
||||||
qemu_bh_delete(s->start_bh);
|
|
||||||
s->start_bh = NULL;
|
|
||||||
qemu_thread_create(&s->thread, data_plane_thread,
|
|
||||||
s, QEMU_THREAD_JOINABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
||||||
VirtIOBlockDataPlane **dataplane,
|
VirtIOBlockDataPlane **dataplane,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
@@ -408,12 +390,33 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
|||||||
s->fd = fd;
|
s->fd = fd;
|
||||||
s->blk = blk;
|
s->blk = blk;
|
||||||
|
|
||||||
|
if (blk->iothread) {
|
||||||
|
s->internal_iothread = false;
|
||||||
|
s->iothread = blk->iothread;
|
||||||
|
object_ref(OBJECT(s->iothread));
|
||||||
|
} else {
|
||||||
|
/* Create per-device IOThread if none specified */
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
s->internal_iothread = true;
|
||||||
|
object_add(TYPE_IOTHREAD, vdev->name, NULL, NULL, &local_err);
|
||||||
|
if (error_is_set(&local_err)) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
g_free(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->iothread = iothread_find(vdev->name);
|
||||||
|
assert(s->iothread);
|
||||||
|
}
|
||||||
|
s->ctx = iothread_get_aio_context(s->iothread);
|
||||||
|
|
||||||
/* Prevent block operations that conflict with data plane thread */
|
/* Prevent block operations that conflict with data plane thread */
|
||||||
bdrv_set_in_use(blk->conf.bs, 1);
|
bdrv_set_in_use(blk->conf.bs, 1);
|
||||||
|
|
||||||
*dataplane = s;
|
*dataplane = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Context: QEMU global mutex held */
|
||||||
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
||||||
{
|
{
|
||||||
if (!s) {
|
if (!s) {
|
||||||
@@ -422,9 +425,14 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
|||||||
|
|
||||||
virtio_blk_data_plane_stop(s);
|
virtio_blk_data_plane_stop(s);
|
||||||
bdrv_set_in_use(s->blk->conf.bs, 0);
|
bdrv_set_in_use(s->blk->conf.bs, 0);
|
||||||
|
object_unref(OBJECT(s->iothread));
|
||||||
|
if (s->internal_iothread) {
|
||||||
|
object_unparent(OBJECT(s->iothread));
|
||||||
|
}
|
||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Context: QEMU global mutex held */
|
||||||
void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
||||||
{
|
{
|
||||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
|
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
|
||||||
@@ -448,8 +456,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->ctx = aio_context_new();
|
|
||||||
|
|
||||||
/* Set up guest notifier (irq) */
|
/* Set up guest notifier (irq) */
|
||||||
if (k->set_guest_notifiers(qbus->parent, 1, true) != 0) {
|
if (k->set_guest_notifiers(qbus->parent, 1, true) != 0) {
|
||||||
fprintf(stderr, "virtio-blk failed to set guest notifier, "
|
fprintf(stderr, "virtio-blk failed to set guest notifier, "
|
||||||
@@ -464,7 +470,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
s->host_notifier = *virtio_queue_get_host_notifier(vq);
|
s->host_notifier = *virtio_queue_get_host_notifier(vq);
|
||||||
aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify);
|
|
||||||
|
|
||||||
/* Set up ioqueue */
|
/* Set up ioqueue */
|
||||||
ioq_init(&s->ioqueue, s->fd, REQ_MAX);
|
ioq_init(&s->ioqueue, s->fd, REQ_MAX);
|
||||||
@@ -472,7 +477,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
|||||||
ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
|
ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
|
||||||
}
|
}
|
||||||
s->io_notifier = *ioq_get_notifier(&s->ioqueue);
|
s->io_notifier = *ioq_get_notifier(&s->ioqueue);
|
||||||
aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io);
|
|
||||||
|
|
||||||
s->starting = false;
|
s->starting = false;
|
||||||
s->started = true;
|
s->started = true;
|
||||||
@@ -481,11 +485,14 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
|||||||
/* Kick right away to begin processing requests already in vring */
|
/* Kick right away to begin processing requests already in vring */
|
||||||
event_notifier_set(virtio_queue_get_host_notifier(vq));
|
event_notifier_set(virtio_queue_get_host_notifier(vq));
|
||||||
|
|
||||||
/* Spawn thread in BH so it inherits iothread cpusets */
|
/* Get this show started by hooking up our callbacks */
|
||||||
s->start_bh = qemu_bh_new(start_data_plane_bh, s);
|
aio_context_acquire(s->ctx);
|
||||||
qemu_bh_schedule(s->start_bh);
|
aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify);
|
||||||
|
aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io);
|
||||||
|
aio_context_release(s->ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Context: QEMU global mutex held */
|
||||||
void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
|
void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
|
||||||
{
|
{
|
||||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
|
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
|
||||||
@@ -496,27 +503,32 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
|
|||||||
s->stopping = true;
|
s->stopping = true;
|
||||||
trace_virtio_blk_data_plane_stop(s);
|
trace_virtio_blk_data_plane_stop(s);
|
||||||
|
|
||||||
/* Stop thread or cancel pending thread creation BH */
|
aio_context_acquire(s->ctx);
|
||||||
if (s->start_bh) {
|
|
||||||
qemu_bh_delete(s->start_bh);
|
/* Stop notifications for new requests from guest */
|
||||||
s->start_bh = NULL;
|
aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
|
||||||
} else {
|
|
||||||
aio_notify(s->ctx);
|
/* Complete pending requests */
|
||||||
qemu_thread_join(&s->thread);
|
while (s->num_reqs > 0) {
|
||||||
|
aio_poll(s->ctx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Stop ioq callbacks (there are no pending requests left) */
|
||||||
aio_set_event_notifier(s->ctx, &s->io_notifier, NULL);
|
aio_set_event_notifier(s->ctx, &s->io_notifier, NULL);
|
||||||
|
|
||||||
|
aio_context_release(s->ctx);
|
||||||
|
|
||||||
|
/* Sync vring state back to virtqueue so that non-dataplane request
|
||||||
|
* processing can continue when we disable the host notifier below.
|
||||||
|
*/
|
||||||
|
vring_teardown(&s->vring, s->vdev, 0);
|
||||||
|
|
||||||
ioq_cleanup(&s->ioqueue);
|
ioq_cleanup(&s->ioqueue);
|
||||||
|
|
||||||
aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
|
|
||||||
k->set_host_notifier(qbus->parent, 0, false);
|
k->set_host_notifier(qbus->parent, 0, false);
|
||||||
|
|
||||||
aio_context_unref(s->ctx);
|
|
||||||
|
|
||||||
/* Clean up guest notifier (irq) */
|
/* Clean up guest notifier (irq) */
|
||||||
k->set_guest_notifiers(qbus->parent, 1, false);
|
k->set_guest_notifiers(qbus->parent, 1, false);
|
||||||
|
|
||||||
vring_teardown(&s->vring, s->vdev, 0);
|
|
||||||
s->started = false;
|
s->started = false;
|
||||||
s->stopping = false;
|
s->stopping = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,7 +241,8 @@ typedef enum {
|
|||||||
} CMDState;
|
} CMDState;
|
||||||
|
|
||||||
typedef struct Flash {
|
typedef struct Flash {
|
||||||
SSISlave ssidev;
|
SSISlave parent_obj;
|
||||||
|
|
||||||
uint32_t r;
|
uint32_t r;
|
||||||
|
|
||||||
BlockDriverState *bdrv;
|
BlockDriverState *bdrv;
|
||||||
@@ -545,7 +546,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
|
|||||||
|
|
||||||
static int m25p80_cs(SSISlave *ss, bool select)
|
static int m25p80_cs(SSISlave *ss, bool select)
|
||||||
{
|
{
|
||||||
Flash *s = FROM_SSI_SLAVE(Flash, ss);
|
Flash *s = M25P80(ss);
|
||||||
|
|
||||||
if (select) {
|
if (select) {
|
||||||
s->len = 0;
|
s->len = 0;
|
||||||
@@ -561,7 +562,7 @@ static int m25p80_cs(SSISlave *ss, bool select)
|
|||||||
|
|
||||||
static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
|
static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
|
||||||
{
|
{
|
||||||
Flash *s = FROM_SSI_SLAVE(Flash, ss);
|
Flash *s = M25P80(ss);
|
||||||
uint32_t r = 0;
|
uint32_t r = 0;
|
||||||
|
|
||||||
switch (s->state) {
|
switch (s->state) {
|
||||||
@@ -610,7 +611,7 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
|
|||||||
static int m25p80_init(SSISlave *ss)
|
static int m25p80_init(SSISlave *ss)
|
||||||
{
|
{
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
Flash *s = FROM_SSI_SLAVE(Flash, ss);
|
Flash *s = M25P80(ss);
|
||||||
M25P80Class *mc = M25P80_GET_CLASS(s);
|
M25P80Class *mc = M25P80_GET_CLASS(s);
|
||||||
|
|
||||||
s->pi = mc->pi;
|
s->pi = mc->pi;
|
||||||
|
|||||||
@@ -15,8 +15,13 @@
|
|||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "hw/virtio/virtio-serial.h"
|
#include "hw/virtio/virtio-serial.h"
|
||||||
|
|
||||||
|
#define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport"
|
||||||
|
#define VIRTIO_CONSOLE(obj) \
|
||||||
|
OBJECT_CHECK(VirtConsole, (obj), TYPE_VIRTIO_CONSOLE_SERIAL_PORT)
|
||||||
|
|
||||||
typedef struct VirtConsole {
|
typedef struct VirtConsole {
|
||||||
VirtIOSerialPort port;
|
VirtIOSerialPort parent_obj;
|
||||||
|
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
guint watch;
|
guint watch;
|
||||||
} VirtConsole;
|
} VirtConsole;
|
||||||
@@ -31,7 +36,7 @@ static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond,
|
|||||||
VirtConsole *vcon = opaque;
|
VirtConsole *vcon = opaque;
|
||||||
|
|
||||||
vcon->watch = 0;
|
vcon->watch = 0;
|
||||||
virtio_serial_throttle_port(&vcon->port, false);
|
virtio_serial_throttle_port(VIRTIO_SERIAL_PORT(vcon), false);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +44,7 @@ static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond,
|
|||||||
static ssize_t flush_buf(VirtIOSerialPort *port,
|
static ssize_t flush_buf(VirtIOSerialPort *port,
|
||||||
const uint8_t *buf, ssize_t len)
|
const uint8_t *buf, ssize_t len)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
VirtConsole *vcon = VIRTIO_CONSOLE(port);
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
if (!vcon->chr) {
|
if (!vcon->chr) {
|
||||||
@@ -75,7 +80,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
|
|||||||
/* Callback function that's called when the guest opens/closes the port */
|
/* Callback function that's called when the guest opens/closes the port */
|
||||||
static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
|
static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
VirtConsole *vcon = VIRTIO_CONSOLE(port);
|
||||||
|
|
||||||
if (!vcon->chr) {
|
if (!vcon->chr) {
|
||||||
return;
|
return;
|
||||||
@@ -88,45 +93,49 @@ static int chr_can_read(void *opaque)
|
|||||||
{
|
{
|
||||||
VirtConsole *vcon = opaque;
|
VirtConsole *vcon = opaque;
|
||||||
|
|
||||||
return virtio_serial_guest_ready(&vcon->port);
|
return virtio_serial_guest_ready(VIRTIO_SERIAL_PORT(vcon));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send data from a char device over to the guest */
|
/* Send data from a char device over to the guest */
|
||||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = opaque;
|
VirtConsole *vcon = opaque;
|
||||||
|
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
|
||||||
|
|
||||||
trace_virtio_console_chr_read(vcon->port.id, size);
|
trace_virtio_console_chr_read(port->id, size);
|
||||||
virtio_serial_write(&vcon->port, buf, size);
|
virtio_serial_write(port, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chr_event(void *opaque, int event)
|
static void chr_event(void *opaque, int event)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = opaque;
|
VirtConsole *vcon = opaque;
|
||||||
|
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
|
||||||
|
|
||||||
trace_virtio_console_chr_event(vcon->port.id, event);
|
trace_virtio_console_chr_event(port->id, event);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case CHR_EVENT_OPENED:
|
case CHR_EVENT_OPENED:
|
||||||
virtio_serial_open(&vcon->port);
|
virtio_serial_open(port);
|
||||||
break;
|
break;
|
||||||
case CHR_EVENT_CLOSED:
|
case CHR_EVENT_CLOSED:
|
||||||
if (vcon->watch) {
|
if (vcon->watch) {
|
||||||
g_source_remove(vcon->watch);
|
g_source_remove(vcon->watch);
|
||||||
vcon->watch = 0;
|
vcon->watch = 0;
|
||||||
}
|
}
|
||||||
virtio_serial_close(&vcon->port);
|
virtio_serial_close(port);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtconsole_initfn(VirtIOSerialPort *port)
|
static void virtconsole_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
|
||||||
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
|
VirtConsole *vcon = VIRTIO_CONSOLE(dev);
|
||||||
|
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
|
||||||
|
|
||||||
if (port->id == 0 && !k->is_console) {
|
if (port->id == 0 && !k->is_console) {
|
||||||
error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
|
error_setg(errp, "Port number 0 on virtio-serial devices reserved "
|
||||||
return -1;
|
"for virtconsole devices for backward compatibility.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vcon->chr) {
|
if (vcon->chr) {
|
||||||
@@ -134,43 +143,27 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
|
|||||||
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
||||||
vcon);
|
vcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtconsole_exitfn(VirtIOSerialPort *port)
|
static void virtconsole_unrealize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
VirtConsole *vcon = VIRTIO_CONSOLE(dev);
|
||||||
|
|
||||||
if (vcon->watch) {
|
if (vcon->watch) {
|
||||||
g_source_remove(vcon->watch);
|
g_source_remove(vcon->watch);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property virtconsole_properties[] = {
|
|
||||||
DEFINE_PROP_CHR("chardev", VirtConsole, chr),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void virtconsole_class_init(ObjectClass *klass, void *data)
|
static void virtconsole_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
||||||
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
|
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
|
||||||
|
|
||||||
k->is_console = true;
|
k->is_console = true;
|
||||||
k->init = virtconsole_initfn;
|
|
||||||
k->exit = virtconsole_exitfn;
|
|
||||||
k->have_data = flush_buf;
|
|
||||||
k->set_guest_connected = set_guest_connected;
|
|
||||||
dc->props = virtconsole_properties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtconsole_info = {
|
static const TypeInfo virtconsole_info = {
|
||||||
.name = "virtconsole",
|
.name = "virtconsole",
|
||||||
.parent = TYPE_VIRTIO_SERIAL_PORT,
|
.parent = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
|
||||||
.instance_size = sizeof(VirtConsole),
|
|
||||||
.class_init = virtconsole_class_init,
|
.class_init = virtconsole_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -184,15 +177,15 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
|
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
|
||||||
|
|
||||||
k->init = virtconsole_initfn;
|
k->realize = virtconsole_realize;
|
||||||
k->exit = virtconsole_exitfn;
|
k->unrealize = virtconsole_unrealize;
|
||||||
k->have_data = flush_buf;
|
k->have_data = flush_buf;
|
||||||
k->set_guest_connected = set_guest_connected;
|
k->set_guest_connected = set_guest_connected;
|
||||||
dc->props = virtserialport_properties;
|
dc->props = virtserialport_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtserialport_info = {
|
static const TypeInfo virtserialport_info = {
|
||||||
.name = "virtserialport",
|
.name = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
|
||||||
.parent = TYPE_VIRTIO_SERIAL_PORT,
|
.parent = TYPE_VIRTIO_SERIAL_PORT,
|
||||||
.instance_size = sizeof(VirtConsole),
|
.instance_size = sizeof(VirtConsole),
|
||||||
.class_init = virtserialport_class_init,
|
.class_init = virtserialport_class_init,
|
||||||
@@ -200,8 +193,8 @@ static const TypeInfo virtserialport_info = {
|
|||||||
|
|
||||||
static void virtconsole_register_types(void)
|
static void virtconsole_register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&virtconsole_info);
|
|
||||||
type_register_static(&virtserialport_info);
|
type_register_static(&virtserialport_info);
|
||||||
|
type_register_static(&virtconsole_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(virtconsole_register_types)
|
type_init(virtconsole_register_types)
|
||||||
|
|||||||
@@ -808,13 +808,14 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id)
|
|||||||
send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1);
|
send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtser_port_qdev_init(DeviceState *qdev)
|
static void virtser_port_device_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
|
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
|
||||||
VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
|
VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
|
||||||
VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus);
|
VirtIOSerialBus *bus = VIRTIO_SERIAL_BUS(qdev_get_parent_bus(dev));
|
||||||
int ret, max_nr_ports;
|
int max_nr_ports;
|
||||||
bool plugging_port0;
|
bool plugging_port0;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
port->vser = bus->vser;
|
port->vser = bus->vser;
|
||||||
port->bh = qemu_bh_new(flush_queued_data_bh, port);
|
port->bh = qemu_bh_new(flush_queued_data_bh, port);
|
||||||
@@ -829,9 +830,9 @@ static int virtser_port_qdev_init(DeviceState *qdev)
|
|||||||
plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0);
|
plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0);
|
||||||
|
|
||||||
if (find_port_by_id(port->vser, port->id)) {
|
if (find_port_by_id(port->vser, port->id)) {
|
||||||
error_report("virtio-serial-bus: A port already exists at id %u",
|
error_setg(errp, "virtio-serial-bus: A port already exists at id %u",
|
||||||
port->id);
|
port->id);
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->id == VIRTIO_CONSOLE_BAD_ID) {
|
if (port->id == VIRTIO_CONSOLE_BAD_ID) {
|
||||||
@@ -840,22 +841,24 @@ static int virtser_port_qdev_init(DeviceState *qdev)
|
|||||||
} else {
|
} else {
|
||||||
port->id = find_free_port_id(port->vser);
|
port->id = find_free_port_id(port->vser);
|
||||||
if (port->id == VIRTIO_CONSOLE_BAD_ID) {
|
if (port->id == VIRTIO_CONSOLE_BAD_ID) {
|
||||||
error_report("virtio-serial-bus: Maximum port limit for this device reached");
|
error_setg(errp, "virtio-serial-bus: Maximum port limit for "
|
||||||
return -1;
|
"this device reached");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
max_nr_ports = tswap32(port->vser->config.max_nr_ports);
|
max_nr_ports = tswap32(port->vser->config.max_nr_ports);
|
||||||
if (port->id >= max_nr_ports) {
|
if (port->id >= max_nr_ports) {
|
||||||
error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u",
|
error_setg(errp, "virtio-serial-bus: Out-of-range port id specified, "
|
||||||
max_nr_ports - 1);
|
"max. allowed: %u", max_nr_ports - 1);
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = vsc->init(port);
|
vsc->realize(dev, &err);
|
||||||
if (ret) {
|
if (err != NULL) {
|
||||||
return ret;
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
port->elem.out_num = 0;
|
port->elem.out_num = 0;
|
||||||
@@ -868,14 +871,12 @@ static int virtser_port_qdev_init(DeviceState *qdev)
|
|||||||
|
|
||||||
/* Send an update to the guest about this new port added */
|
/* Send an update to the guest about this new port added */
|
||||||
virtio_notify_config(VIRTIO_DEVICE(port->vser));
|
virtio_notify_config(VIRTIO_DEVICE(port->vser));
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtser_port_qdev_exit(DeviceState *qdev)
|
static void virtser_port_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
|
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
|
||||||
VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
|
VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
|
||||||
VirtIOSerial *vser = port->vser;
|
VirtIOSerial *vser = port->vser;
|
||||||
|
|
||||||
qemu_bh_delete(port->bh);
|
qemu_bh_delete(port->bh);
|
||||||
@@ -883,10 +884,9 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
|
|||||||
|
|
||||||
QTAILQ_REMOVE(&vser->ports, port, next);
|
QTAILQ_REMOVE(&vser->ports, port, next);
|
||||||
|
|
||||||
if (vsc->exit) {
|
if (vsc->unrealize) {
|
||||||
vsc->exit(port);
|
vsc->unrealize(dev, errp);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
|
static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
|
||||||
@@ -971,10 +971,11 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
|
|||||||
static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
|
static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *k = DEVICE_CLASS(klass);
|
DeviceClass *k = DEVICE_CLASS(klass);
|
||||||
k->init = virtser_port_qdev_init;
|
|
||||||
set_bit(DEVICE_CATEGORY_INPUT, k->categories);
|
set_bit(DEVICE_CATEGORY_INPUT, k->categories);
|
||||||
k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
|
k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
|
||||||
k->exit = virtser_port_qdev_exit;
|
k->realize = virtser_port_device_realize;
|
||||||
|
k->unrealize = virtser_port_device_unrealize;
|
||||||
k->unplug = qdev_simple_unplug_cb;
|
k->unplug = qdev_simple_unplug_cb;
|
||||||
k->props = virtser_props;
|
k->props = virtser_props;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
|
|||||||
common-obj-$(CONFIG_XILINX_AXI) += stream.o
|
common-obj-$(CONFIG_XILINX_AXI) += stream.o
|
||||||
common-obj-$(CONFIG_PTIMER) += ptimer.o
|
common-obj-$(CONFIG_PTIMER) += ptimer.o
|
||||||
common-obj-$(CONFIG_SOFTMMU) += sysbus.o
|
common-obj-$(CONFIG_SOFTMMU) += sysbus.o
|
||||||
|
common-obj-$(CONFIG_SOFTMMU) += machine.o
|
||||||
common-obj-$(CONFIG_SOFTMMU) += null-machine.o
|
common-obj-$(CONFIG_SOFTMMU) += null-machine.o
|
||||||
common-obj-$(CONFIG_SOFTMMU) += loader.o
|
common-obj-$(CONFIG_SOFTMMU) += loader.o
|
||||||
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
|
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,8 @@
|
|||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
bool rom_file_in_ram = true;
|
bool option_rom_has_mr = false;
|
||||||
|
bool rom_file_has_mr = true;
|
||||||
|
|
||||||
static int roms_loaded;
|
static int roms_loaded;
|
||||||
|
|
||||||
@@ -284,12 +285,30 @@ static void *load_at(int fd, int offset, int size)
|
|||||||
#define SZ 64
|
#define SZ 64
|
||||||
#include "hw/elf_ops.h"
|
#include "hw/elf_ops.h"
|
||||||
|
|
||||||
|
const char *load_elf_strerror(int error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
case 0:
|
||||||
|
return "No error";
|
||||||
|
case ELF_LOAD_FAILED:
|
||||||
|
return "Failed to load ELF";
|
||||||
|
case ELF_LOAD_NOT_ELF:
|
||||||
|
return "The image is not ELF";
|
||||||
|
case ELF_LOAD_WRONG_ARCH:
|
||||||
|
return "The image is from incompatible architecture";
|
||||||
|
case ELF_LOAD_WRONG_ENDIAN:
|
||||||
|
return "The image has incorrect endianness";
|
||||||
|
default:
|
||||||
|
return "Unknown error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* return < 0 if error, otherwise the number of bytes loaded in memory */
|
/* return < 0 if error, otherwise the number of bytes loaded in memory */
|
||||||
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
|
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
|
||||||
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
|
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
|
||||||
uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
|
uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
|
||||||
{
|
{
|
||||||
int fd, data_order, target_data_order, must_swab, ret;
|
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
|
||||||
uint8_t e_ident[EI_NIDENT];
|
uint8_t e_ident[EI_NIDENT];
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY | O_BINARY);
|
fd = open(filename, O_RDONLY | O_BINARY);
|
||||||
@@ -302,8 +321,10 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
|
|||||||
if (e_ident[0] != ELFMAG0 ||
|
if (e_ident[0] != ELFMAG0 ||
|
||||||
e_ident[1] != ELFMAG1 ||
|
e_ident[1] != ELFMAG1 ||
|
||||||
e_ident[2] != ELFMAG2 ||
|
e_ident[2] != ELFMAG2 ||
|
||||||
e_ident[3] != ELFMAG3)
|
e_ident[3] != ELFMAG3) {
|
||||||
|
ret = ELF_LOAD_NOT_ELF;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
#ifdef HOST_WORDS_BIGENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
data_order = ELFDATA2MSB;
|
data_order = ELFDATA2MSB;
|
||||||
#else
|
#else
|
||||||
@@ -317,6 +338,7 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (target_data_order != e_ident[EI_DATA]) {
|
if (target_data_order != e_ident[EI_DATA]) {
|
||||||
|
ret = ELF_LOAD_WRONG_ENDIAN;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,12 +351,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
|
|||||||
pentry, lowaddr, highaddr, elf_machine, clear_lsb);
|
pentry, lowaddr, highaddr, elf_machine, clear_lsb);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bswap_uboot_header(uboot_image_header_t *hdr)
|
static void bswap_uboot_header(uboot_image_header_t *hdr)
|
||||||
@@ -624,7 +643,8 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int rom_add_file(const char *file, const char *fw_dir,
|
int rom_add_file(const char *file, const char *fw_dir,
|
||||||
hwaddr addr, int32_t bootindex)
|
hwaddr addr, int32_t bootindex,
|
||||||
|
bool option_rom)
|
||||||
{
|
{
|
||||||
Rom *rom;
|
Rom *rom;
|
||||||
int rc, fd = -1;
|
int rc, fd = -1;
|
||||||
@@ -676,7 +696,7 @@ int rom_add_file(const char *file, const char *fw_dir,
|
|||||||
basename);
|
basename);
|
||||||
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
|
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
|
||||||
|
|
||||||
if (rom_file_in_ram) {
|
if ((!option_rom || option_rom_has_mr) && rom_file_has_mr) {
|
||||||
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
|
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
|
||||||
} else {
|
} else {
|
||||||
data = rom->data;
|
data = rom->data;
|
||||||
@@ -720,7 +740,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
|
|||||||
|
|
||||||
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
|
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
|
||||||
|
|
||||||
if (rom_file_in_ram) {
|
if (rom_file_has_mr) {
|
||||||
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
|
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
|
||||||
} else {
|
} else {
|
||||||
data = rom->data;
|
data = rom->data;
|
||||||
@@ -755,12 +775,12 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
|
|||||||
|
|
||||||
int rom_add_vga(const char *file)
|
int rom_add_vga(const char *file)
|
||||||
{
|
{
|
||||||
return rom_add_file(file, "vgaroms", 0, -1);
|
return rom_add_file(file, "vgaroms", 0, -1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rom_add_option(const char *file, int32_t bootindex)
|
int rom_add_option(const char *file, int32_t bootindex)
|
||||||
{
|
{
|
||||||
return rom_add_file(file, "genroms", 0, bootindex);
|
return rom_add_file(file, "genroms", 0, bootindex, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rom_reset(void *unused)
|
static void rom_reset(void *unused)
|
||||||
|
|||||||
28
hw/core/machine.c
Normal file
28
hw/core/machine.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Machine
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Red Hat Inc
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Marcel Apfelbaum <marcel.a@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hw/boards.h"
|
||||||
|
|
||||||
|
static const TypeInfo machine_info = {
|
||||||
|
.name = TYPE_MACHINE,
|
||||||
|
.parent = TYPE_OBJECT,
|
||||||
|
.abstract = true,
|
||||||
|
.class_size = sizeof(MachineClass),
|
||||||
|
.instance_size = sizeof(MachineState),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void machine_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&machine_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(machine_register_types)
|
||||||
@@ -18,17 +18,19 @@
|
|||||||
#include "net/hub.h"
|
#include "net/hub.h"
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
#include "sysemu/char.h"
|
#include "sysemu/char.h"
|
||||||
|
#include "sysemu/iothread.h"
|
||||||
|
|
||||||
static void get_pointer(Object *obj, Visitor *v, Property *prop,
|
static void get_pointer(Object *obj, Visitor *v, Property *prop,
|
||||||
const char *(*print)(void *ptr),
|
char *(*print)(void *ptr),
|
||||||
const char *name, Error **errp)
|
const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = (char *) (*ptr ? print(*ptr) : "");
|
p = *ptr ? print(*ptr) : g_strdup("");
|
||||||
visit_type_str(v, &p, name, errp);
|
visit_type_str(v, &p, name, errp);
|
||||||
|
g_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_pointer(Object *obj, Visitor *v, Property *prop,
|
static void set_pointer(Object *obj, Visitor *v, Property *prop,
|
||||||
@@ -91,9 +93,9 @@ static void release_drive(Object *obj, const char *name, void *opaque)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *print_drive(void *ptr)
|
static char *print_drive(void *ptr)
|
||||||
{
|
{
|
||||||
return bdrv_get_device_name(ptr);
|
return g_strdup(bdrv_get_device_name(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_drive(Object *obj, Visitor *v, void *opaque,
|
static void get_drive(Object *obj, Visitor *v, void *opaque,
|
||||||
@@ -145,11 +147,12 @@ static void release_chr(Object *obj, const char *name, void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *print_chr(void *ptr)
|
static char *print_chr(void *ptr)
|
||||||
{
|
{
|
||||||
CharDriverState *chr = ptr;
|
CharDriverState *chr = ptr;
|
||||||
|
const char *val = chr->label ? chr->label : "";
|
||||||
|
|
||||||
return chr->label ? chr->label : "";
|
return g_strdup(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_chr(Object *obj, Visitor *v, void *opaque,
|
static void get_chr(Object *obj, Visitor *v, void *opaque,
|
||||||
@@ -224,11 +227,12 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *print_netdev(void *ptr)
|
static char *print_netdev(void *ptr)
|
||||||
{
|
{
|
||||||
NetClientState *netdev = ptr;
|
NetClientState *netdev = ptr;
|
||||||
|
const char *val = netdev->name ? netdev->name : "";
|
||||||
|
|
||||||
return netdev->name ? netdev->name : "";
|
return g_strdup(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_netdev(Object *obj, Visitor *v, void *opaque,
|
static void get_netdev(Object *obj, Visitor *v, void *opaque,
|
||||||
@@ -382,6 +386,56 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
|||||||
nd->instantiated = 1;
|
nd->instantiated = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- iothread --- */
|
||||||
|
|
||||||
|
static char *print_iothread(void *ptr)
|
||||||
|
{
|
||||||
|
return iothread_get_id(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_iothread(DeviceState *dev, const char *str, void **ptr)
|
||||||
|
{
|
||||||
|
IOThread *iothread;
|
||||||
|
|
||||||
|
iothread = iothread_find(str);
|
||||||
|
if (!iothread) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
object_ref(OBJECT(iothread));
|
||||||
|
*ptr = iothread;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_iothread(Object *obj, struct Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
get_pointer(obj, v, opaque, print_iothread, name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_iothread(Object *obj, struct Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
set_pointer(obj, v, opaque, parse_iothread, name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void release_iothread(Object *obj, const char *name, void *opaque)
|
||||||
|
{
|
||||||
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
Property *prop = opaque;
|
||||||
|
IOThread **ptr = qdev_get_prop_ptr(dev, prop);
|
||||||
|
|
||||||
|
if (*ptr) {
|
||||||
|
object_unref(OBJECT(*ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyInfo qdev_prop_iothread = {
|
||||||
|
.name = "iothread",
|
||||||
|
.get = get_iothread,
|
||||||
|
.set = set_iothread,
|
||||||
|
.release = release_iothread,
|
||||||
|
};
|
||||||
|
|
||||||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
||||||
{
|
{
|
||||||
GlobalProperty *g;
|
GlobalProperty *g;
|
||||||
|
|||||||
107
hw/core/qdev.c
107
hw/core/qdev.c
@@ -440,27 +440,33 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
|
|||||||
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
|
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
|
||||||
{
|
{
|
||||||
const char *typename = object_get_typename(OBJECT(bus));
|
const char *typename = object_get_typename(OBJECT(bus));
|
||||||
|
BusClass *bc;
|
||||||
char *buf;
|
char *buf;
|
||||||
int i,len;
|
int i, len, bus_id;
|
||||||
|
|
||||||
bus->parent = parent;
|
bus->parent = parent;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
bus->name = g_strdup(name);
|
bus->name = g_strdup(name);
|
||||||
} else if (bus->parent && bus->parent->id) {
|
} else if (bus->parent && bus->parent->id) {
|
||||||
/* parent device has id -> use it for bus name */
|
/* parent device has id -> use it plus parent-bus-id for bus name */
|
||||||
|
bus_id = bus->parent->num_child_bus;
|
||||||
|
|
||||||
len = strlen(bus->parent->id) + 16;
|
len = strlen(bus->parent->id) + 16;
|
||||||
buf = g_malloc(len);
|
buf = g_malloc(len);
|
||||||
snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
|
snprintf(buf, len, "%s.%d", bus->parent->id, bus_id);
|
||||||
bus->name = buf;
|
bus->name = buf;
|
||||||
} else {
|
} else {
|
||||||
/* no id -> use lowercase bus type for bus name */
|
/* no id -> use lowercase bus type plus global bus-id for bus name */
|
||||||
|
bc = BUS_GET_CLASS(bus);
|
||||||
|
bus_id = bc->automatic_ids++;
|
||||||
|
|
||||||
len = strlen(typename) + 16;
|
len = strlen(typename) + 16;
|
||||||
buf = g_malloc(len);
|
buf = g_malloc(len);
|
||||||
len = snprintf(buf, len, "%s.%d", typename,
|
len = snprintf(buf, len, "%s.%d", typename, bus_id);
|
||||||
bus->parent ? bus->parent->num_child_bus : 0);
|
for (i = 0; i < len; i++) {
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
buf[i] = qemu_tolower(buf[i]);
|
buf[i] = qemu_tolower(buf[i]);
|
||||||
|
}
|
||||||
bus->name = buf;
|
bus->name = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,6 +501,45 @@ static void bus_unparent(Object *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool bus_get_realized(Object *obj, Error **err)
|
||||||
|
{
|
||||||
|
BusState *bus = BUS(obj);
|
||||||
|
|
||||||
|
return bus->realized;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bus_set_realized(Object *obj, bool value, Error **err)
|
||||||
|
{
|
||||||
|
BusState *bus = BUS(obj);
|
||||||
|
BusClass *bc = BUS_GET_CLASS(bus);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (value && !bus->realized) {
|
||||||
|
if (bc->realize) {
|
||||||
|
bc->realize(bus, &local_err);
|
||||||
|
|
||||||
|
if (local_err != NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (!value && bus->realized) {
|
||||||
|
if (bc->unrealize) {
|
||||||
|
bc->unrealize(bus, &local_err);
|
||||||
|
|
||||||
|
if (local_err != NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bus->realized = value;
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
error_propagate(err, local_err);
|
||||||
|
}
|
||||||
|
|
||||||
void qbus_create_inplace(void *bus, size_t size, const char *typename,
|
void qbus_create_inplace(void *bus, size_t size, const char *typename,
|
||||||
DeviceState *parent, const char *name)
|
DeviceState *parent, const char *name)
|
||||||
{
|
{
|
||||||
@@ -671,6 +716,7 @@ static void device_set_realized(Object *obj, bool value, Error **err)
|
|||||||
{
|
{
|
||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
DeviceClass *dc = DEVICE_GET_CLASS(dev);
|
DeviceClass *dc = DEVICE_GET_CLASS(dev);
|
||||||
|
BusState *bus;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (dev->hotplugged && !dc->hotpluggable) {
|
if (dev->hotplugged && !dc->hotpluggable) {
|
||||||
@@ -704,14 +750,30 @@ static void device_set_realized(Object *obj, bool value, Error **err)
|
|||||||
dev->instance_id_alias,
|
dev->instance_id_alias,
|
||||||
dev->alias_required_for_version);
|
dev->alias_required_for_version);
|
||||||
}
|
}
|
||||||
|
if (local_err == NULL) {
|
||||||
|
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||||
|
object_property_set_bool(OBJECT(bus), true, "realized",
|
||||||
|
&local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (dev->hotplugged && local_err == NULL) {
|
if (dev->hotplugged && local_err == NULL) {
|
||||||
device_reset(dev);
|
device_reset(dev);
|
||||||
}
|
}
|
||||||
} else if (!value && dev->realized) {
|
} else if (!value && dev->realized) {
|
||||||
if (qdev_get_vmsd(dev)) {
|
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||||
|
object_property_set_bool(OBJECT(bus), false, "realized",
|
||||||
|
&local_err);
|
||||||
|
if (local_err != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (qdev_get_vmsd(dev) && local_err == NULL) {
|
||||||
vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
|
vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
|
||||||
}
|
}
|
||||||
if (dc->unrealize) {
|
if (dc->unrealize && local_err == NULL) {
|
||||||
dc->unrealize(dev, &local_err);
|
dc->unrealize(dev, &local_err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,7 +791,8 @@ static bool device_get_hotpluggable(Object *obj, Error **err)
|
|||||||
DeviceClass *dc = DEVICE_GET_CLASS(obj);
|
DeviceClass *dc = DEVICE_GET_CLASS(obj);
|
||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
|
||||||
return dc->hotpluggable && dev->parent_bus->allow_hotplug;
|
return dc->hotpluggable && (dev->parent_bus == NULL ||
|
||||||
|
dev->parent_bus->allow_hotplug);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_initfn(Object *obj)
|
static void device_initfn(Object *obj)
|
||||||
@@ -786,14 +849,6 @@ static void device_class_base_init(ObjectClass *class, void *data)
|
|||||||
* so do not propagate them to the subclasses.
|
* so do not propagate them to the subclasses.
|
||||||
*/
|
*/
|
||||||
klass->props = NULL;
|
klass->props = NULL;
|
||||||
|
|
||||||
/* by default all devices were considered as hotpluggable,
|
|
||||||
* so with intent to check it in generic qdev_unplug() /
|
|
||||||
* device_set_realized() functions make every device
|
|
||||||
* hotpluggable. Devices that shouldn't be hotpluggable,
|
|
||||||
* should override it in their class_init()
|
|
||||||
*/
|
|
||||||
klass->hotpluggable = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_unparent(Object *obj)
|
static void device_unparent(Object *obj)
|
||||||
@@ -803,13 +858,13 @@ static void device_unparent(Object *obj)
|
|||||||
QObject *event_data;
|
QObject *event_data;
|
||||||
bool have_realized = dev->realized;
|
bool have_realized = dev->realized;
|
||||||
|
|
||||||
|
if (dev->realized) {
|
||||||
|
object_property_set_bool(obj, false, "realized", NULL);
|
||||||
|
}
|
||||||
while (dev->num_child_bus) {
|
while (dev->num_child_bus) {
|
||||||
bus = QLIST_FIRST(&dev->child_bus);
|
bus = QLIST_FIRST(&dev->child_bus);
|
||||||
object_unparent(OBJECT(bus));
|
object_unparent(OBJECT(bus));
|
||||||
}
|
}
|
||||||
if (dev->realized) {
|
|
||||||
object_property_set_bool(obj, false, "realized", NULL);
|
|
||||||
}
|
|
||||||
if (dev->parent_bus) {
|
if (dev->parent_bus) {
|
||||||
bus_remove_child(dev->parent_bus, dev);
|
bus_remove_child(dev->parent_bus, dev);
|
||||||
object_unref(OBJECT(dev->parent_bus));
|
object_unref(OBJECT(dev->parent_bus));
|
||||||
@@ -839,6 +894,14 @@ static void device_class_init(ObjectClass *class, void *data)
|
|||||||
class->unparent = device_unparent;
|
class->unparent = device_unparent;
|
||||||
dc->realize = device_realize;
|
dc->realize = device_realize;
|
||||||
dc->unrealize = device_unrealize;
|
dc->unrealize = device_unrealize;
|
||||||
|
|
||||||
|
/* by default all devices were considered as hotpluggable,
|
||||||
|
* so with intent to check it in generic qdev_unplug() /
|
||||||
|
* device_set_realized() functions make every device
|
||||||
|
* hotpluggable. Devices that shouldn't be hotpluggable,
|
||||||
|
* should override it in their class_init()
|
||||||
|
*/
|
||||||
|
dc->hotpluggable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_reset(DeviceState *dev)
|
void device_reset(DeviceState *dev)
|
||||||
@@ -882,6 +945,8 @@ static void qbus_initfn(Object *obj)
|
|||||||
object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
|
object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
|
||||||
TYPE_HOTPLUG_HANDLER,
|
TYPE_HOTPLUG_HANDLER,
|
||||||
(Object **)&bus->hotplug_handler, NULL);
|
(Object **)&bus->hotplug_handler, NULL);
|
||||||
|
object_property_add_bool(obj, "realized",
|
||||||
|
bus_get_realized, bus_set_realized, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *default_bus_get_fw_dev_path(DeviceState *dev)
|
static char *default_bus_get_fw_dev_path(DeviceState *dev)
|
||||||
|
|||||||
@@ -133,11 +133,12 @@ static const VMStateDescription vmstate_ads7846 = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ads7846_init(SSISlave *dev)
|
static int ads7846_init(SSISlave *d)
|
||||||
{
|
{
|
||||||
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev);
|
DeviceState *dev = DEVICE(d);
|
||||||
|
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, d);
|
||||||
|
|
||||||
qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1);
|
qdev_init_gpio_out(dev, &s->interrupt, 1);
|
||||||
|
|
||||||
s->input[0] = ADS_TEMP0; /* TEMP0 */
|
s->input[0] = ADS_TEMP0; /* TEMP0 */
|
||||||
s->input[2] = ADS_VBAT; /* VBAT */
|
s->input[2] = ADS_VBAT; /* VBAT */
|
||||||
|
|||||||
@@ -336,18 +336,19 @@ static const GraphicHwOps ssd0323_ops = {
|
|||||||
.gfx_update = ssd0323_update_display,
|
.gfx_update = ssd0323_update_display,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ssd0323_init(SSISlave *dev)
|
static int ssd0323_init(SSISlave *d)
|
||||||
{
|
{
|
||||||
ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev);
|
DeviceState *dev = DEVICE(d);
|
||||||
|
ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, d);
|
||||||
|
|
||||||
s->col_end = 63;
|
s->col_end = 63;
|
||||||
s->row_end = 79;
|
s->row_end = 79;
|
||||||
s->con = graphic_console_init(DEVICE(dev), 0, &ssd0323_ops, s);
|
s->con = graphic_console_init(dev, 0, &ssd0323_ops, s);
|
||||||
qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
|
qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
|
||||||
|
|
||||||
qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
|
qdev_init_gpio_in(dev, ssd0323_cd, 1);
|
||||||
|
|
||||||
register_savevm(&dev->qdev, "ssd0323_oled", -1, 1,
|
register_savevm(dev, "ssd0323_oled", -1, 1,
|
||||||
ssd0323_save, ssd0323_load, s);
|
ssd0323_save, ssd0323_load, s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -992,7 +992,7 @@ wait_more:
|
|||||||
|
|
||||||
/* vfb */
|
/* vfb */
|
||||||
fb = container_of(xfb, struct XenFB, c.xendev);
|
fb = container_of(xfb, struct XenFB, c.xendev);
|
||||||
fb->c.con = graphic_console_init(NULL, &xenfb_ops, fb);
|
fb->c.con = graphic_console_init(NULL, 0, &xenfb_ops, fb);
|
||||||
fb->have_console = 1;
|
fb->have_console = 1;
|
||||||
|
|
||||||
/* vkbd */
|
/* vkbd */
|
||||||
|
|||||||
@@ -466,9 +466,15 @@ static void acpi_align_size(GArray *blob, unsigned align)
|
|||||||
g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
|
g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get pointer within table in a safe manner */
|
/* Set a value within table in a safe manner */
|
||||||
#define ACPI_BUILD_PTR(table, size, off, type) \
|
#define ACPI_BUILD_SET_LE(table, size, off, bits, val) \
|
||||||
((type *)(acpi_data_get_ptr(table, size, off, sizeof(type))))
|
do { \
|
||||||
|
uint64_t ACPI_BUILD_SET_LE_val = cpu_to_le64(val); \
|
||||||
|
memcpy(acpi_data_get_ptr(table, size, off, \
|
||||||
|
(bits) / BITS_PER_BYTE), \
|
||||||
|
&ACPI_BUILD_SET_LE_val, \
|
||||||
|
(bits) / BITS_PER_BYTE); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size,
|
static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size,
|
||||||
unsigned off, unsigned size)
|
unsigned off, unsigned size)
|
||||||
@@ -643,6 +649,21 @@ static inline char acpi_get_hex(uint32_t val)
|
|||||||
#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
|
#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
|
||||||
#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
|
#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
|
||||||
|
|
||||||
|
#define ACPI_PCINOHP_OFFSET_HEX (*ssdt_pcinohp_name - *ssdt_pcinohp_start + 1)
|
||||||
|
#define ACPI_PCINOHP_OFFSET_ADR (*ssdt_pcinohp_adr - *ssdt_pcinohp_start)
|
||||||
|
#define ACPI_PCINOHP_SIZEOF (*ssdt_pcinohp_end - *ssdt_pcinohp_start)
|
||||||
|
#define ACPI_PCINOHP_AML (ssdp_pcihp_aml + *ssdt_pcinohp_start)
|
||||||
|
|
||||||
|
#define ACPI_PCIVGA_OFFSET_HEX (*ssdt_pcivga_name - *ssdt_pcivga_start + 1)
|
||||||
|
#define ACPI_PCIVGA_OFFSET_ADR (*ssdt_pcivga_adr - *ssdt_pcivga_start)
|
||||||
|
#define ACPI_PCIVGA_SIZEOF (*ssdt_pcivga_end - *ssdt_pcivga_start)
|
||||||
|
#define ACPI_PCIVGA_AML (ssdp_pcihp_aml + *ssdt_pcivga_start)
|
||||||
|
|
||||||
|
#define ACPI_PCIQXL_OFFSET_HEX (*ssdt_pciqxl_name - *ssdt_pciqxl_start + 1)
|
||||||
|
#define ACPI_PCIQXL_OFFSET_ADR (*ssdt_pciqxl_adr - *ssdt_pciqxl_start)
|
||||||
|
#define ACPI_PCIQXL_SIZEOF (*ssdt_pciqxl_end - *ssdt_pciqxl_start)
|
||||||
|
#define ACPI_PCIQXL_AML (ssdp_pcihp_aml + *ssdt_pciqxl_start)
|
||||||
|
|
||||||
#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
|
#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
|
||||||
#define ACPI_SSDT_HEADER_LENGTH 36
|
#define ACPI_SSDT_HEADER_LENGTH 36
|
||||||
|
|
||||||
@@ -677,6 +698,33 @@ static void patch_pcihp(int slot, uint8_t *ssdt_ptr)
|
|||||||
ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
|
ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void patch_pcinohp(int slot, uint8_t *ssdt_ptr)
|
||||||
|
{
|
||||||
|
unsigned devfn = PCI_DEVFN(slot, 0);
|
||||||
|
|
||||||
|
ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
|
||||||
|
ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX + 1] = acpi_get_hex(devfn);
|
||||||
|
ssdt_ptr[ACPI_PCINOHP_OFFSET_ADR + 2] = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void patch_pcivga(int slot, uint8_t *ssdt_ptr)
|
||||||
|
{
|
||||||
|
unsigned devfn = PCI_DEVFN(slot, 0);
|
||||||
|
|
||||||
|
ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
|
||||||
|
ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX + 1] = acpi_get_hex(devfn);
|
||||||
|
ssdt_ptr[ACPI_PCIVGA_OFFSET_ADR + 2] = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void patch_pciqxl(int slot, uint8_t *ssdt_ptr)
|
||||||
|
{
|
||||||
|
unsigned devfn = PCI_DEVFN(slot, 0);
|
||||||
|
|
||||||
|
ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX] = acpi_get_hex(devfn >> 4);
|
||||||
|
ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX + 1] = acpi_get_hex(devfn);
|
||||||
|
ssdt_ptr[ACPI_PCIQXL_OFFSET_ADR + 2] = slot;
|
||||||
|
}
|
||||||
|
|
||||||
/* Assign BSEL property to all buses. In the future, this can be changed
|
/* Assign BSEL property to all buses. In the future, this can be changed
|
||||||
* to only assign to buses that support hotplug.
|
* to only assign to buses that support hotplug.
|
||||||
*/
|
*/
|
||||||
@@ -737,6 +785,10 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
|
|||||||
AcpiBuildPciBusHotplugState *parent = child->parent;
|
AcpiBuildPciBusHotplugState *parent = child->parent;
|
||||||
GArray *bus_table = build_alloc_array();
|
GArray *bus_table = build_alloc_array();
|
||||||
DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
|
DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
|
||||||
|
DECLARE_BITMAP(slot_device_present, PCI_SLOT_MAX);
|
||||||
|
DECLARE_BITMAP(slot_device_system, PCI_SLOT_MAX);
|
||||||
|
DECLARE_BITMAP(slot_device_vga, PCI_SLOT_MAX);
|
||||||
|
DECLARE_BITMAP(slot_device_qxl, PCI_SLOT_MAX);
|
||||||
uint8_t op;
|
uint8_t op;
|
||||||
int i;
|
int i;
|
||||||
QObject *bsel;
|
QObject *bsel;
|
||||||
@@ -764,40 +816,82 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
|
|||||||
build_append_byte(bus_table, 0x08); /* NameOp */
|
build_append_byte(bus_table, 0x08); /* NameOp */
|
||||||
build_append_nameseg(bus_table, "BSEL");
|
build_append_nameseg(bus_table, "BSEL");
|
||||||
build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel)));
|
build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel)));
|
||||||
|
|
||||||
memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);
|
memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);
|
||||||
|
} else {
|
||||||
|
/* No bsel - no slots are hot-pluggable */
|
||||||
|
memset(slot_hotplug_enable, 0x00, sizeof slot_hotplug_enable);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
|
memset(slot_device_present, 0x00, sizeof slot_device_present);
|
||||||
|
memset(slot_device_system, 0x00, sizeof slot_device_present);
|
||||||
|
memset(slot_device_vga, 0x00, sizeof slot_device_vga);
|
||||||
|
memset(slot_device_qxl, 0x00, sizeof slot_device_qxl);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
|
||||||
DeviceClass *dc;
|
DeviceClass *dc;
|
||||||
PCIDeviceClass *pc;
|
PCIDeviceClass *pc;
|
||||||
PCIDevice *pdev = bus->devices[i];
|
PCIDevice *pdev = bus->devices[i];
|
||||||
|
int slot = PCI_SLOT(i);
|
||||||
|
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_bit(slot, slot_device_present);
|
||||||
pc = PCI_DEVICE_GET_CLASS(pdev);
|
pc = PCI_DEVICE_GET_CLASS(pdev);
|
||||||
dc = DEVICE_GET_CLASS(pdev);
|
dc = DEVICE_GET_CLASS(pdev);
|
||||||
|
|
||||||
if (!dc->hotpluggable || pc->is_bridge) {
|
if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
|
||||||
int slot = PCI_SLOT(i);
|
set_bit(slot, slot_device_system);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
|
||||||
|
set_bit(slot, slot_device_vga);
|
||||||
|
|
||||||
|
if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {
|
||||||
|
set_bit(slot, slot_device_qxl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dc->hotpluggable || pc->is_bridge) {
|
||||||
clear_bit(slot, slot_hotplug_enable);
|
clear_bit(slot, slot_hotplug_enable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append Device object for each slot which supports eject */
|
/* Append Device object for each slot */
|
||||||
for (i = 0; i < PCI_SLOT_MAX; i++) {
|
for (i = 0; i < PCI_SLOT_MAX; i++) {
|
||||||
bool can_eject = test_bit(i, slot_hotplug_enable);
|
bool can_eject = test_bit(i, slot_hotplug_enable);
|
||||||
|
bool present = test_bit(i, slot_device_present);
|
||||||
|
bool vga = test_bit(i, slot_device_vga);
|
||||||
|
bool qxl = test_bit(i, slot_device_qxl);
|
||||||
|
bool system = test_bit(i, slot_device_system);
|
||||||
if (can_eject) {
|
if (can_eject) {
|
||||||
void *pcihp = acpi_data_push(bus_table,
|
void *pcihp = acpi_data_push(bus_table,
|
||||||
ACPI_PCIHP_SIZEOF);
|
ACPI_PCIHP_SIZEOF);
|
||||||
memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
|
memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
|
||||||
patch_pcihp(i, pcihp);
|
patch_pcihp(i, pcihp);
|
||||||
bus_hotplug_support = true;
|
bus_hotplug_support = true;
|
||||||
|
} else if (qxl) {
|
||||||
|
void *pcihp = acpi_data_push(bus_table,
|
||||||
|
ACPI_PCIQXL_SIZEOF);
|
||||||
|
memcpy(pcihp, ACPI_PCIQXL_AML, ACPI_PCIQXL_SIZEOF);
|
||||||
|
patch_pciqxl(i, pcihp);
|
||||||
|
} else if (vga) {
|
||||||
|
void *pcihp = acpi_data_push(bus_table,
|
||||||
|
ACPI_PCIVGA_SIZEOF);
|
||||||
|
memcpy(pcihp, ACPI_PCIVGA_AML, ACPI_PCIVGA_SIZEOF);
|
||||||
|
patch_pcivga(i, pcihp);
|
||||||
|
} else if (system) {
|
||||||
|
/* Nothing to do: system devices are in DSDT. */
|
||||||
|
} else if (present) {
|
||||||
|
void *pcihp = acpi_data_push(bus_table,
|
||||||
|
ACPI_PCINOHP_SIZEOF);
|
||||||
|
memcpy(pcihp, ACPI_PCINOHP_AML, ACPI_PCINOHP_SIZEOF);
|
||||||
|
patch_pcinohp(i, pcihp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bsel) {
|
||||||
method = build_alloc_method("DVNT", 2);
|
method = build_alloc_method("DVNT", 2);
|
||||||
|
|
||||||
for (i = 0; i < PCI_SLOT_MAX; i++) {
|
for (i = 0; i < PCI_SLOT_MAX; i++) {
|
||||||
@@ -886,22 +980,17 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
|
|||||||
|
|
||||||
static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
|
static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
|
||||||
{
|
{
|
||||||
*ACPI_BUILD_PTR(start, size, acpi_pci32_start[0], uint32_t) =
|
ACPI_BUILD_SET_LE(start, size, acpi_pci32_start[0], 32, pci->w32.begin);
|
||||||
cpu_to_le32(pci->w32.begin);
|
|
||||||
|
|
||||||
*ACPI_BUILD_PTR(start, size, acpi_pci32_end[0], uint32_t) =
|
ACPI_BUILD_SET_LE(start, size, acpi_pci32_end[0], 32, pci->w32.end - 1);
|
||||||
cpu_to_le32(pci->w32.end - 1);
|
|
||||||
|
|
||||||
if (pci->w64.end || pci->w64.begin) {
|
if (pci->w64.end || pci->w64.begin) {
|
||||||
*ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 1;
|
ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 1);
|
||||||
*ACPI_BUILD_PTR(start, size, acpi_pci64_start[0], uint64_t) =
|
ACPI_BUILD_SET_LE(start, size, acpi_pci64_start[0], 64, pci->w64.begin);
|
||||||
cpu_to_le64(pci->w64.begin);
|
ACPI_BUILD_SET_LE(start, size, acpi_pci64_end[0], 64, pci->w64.end - 1);
|
||||||
*ACPI_BUILD_PTR(start, size, acpi_pci64_end[0], uint64_t) =
|
ACPI_BUILD_SET_LE(start, size, acpi_pci64_length[0], 64, pci->w64.end - pci->w64.begin);
|
||||||
cpu_to_le64(pci->w64.end - 1);
|
|
||||||
*ACPI_BUILD_PTR(start, size, acpi_pci64_length[0], uint64_t) =
|
|
||||||
cpu_to_le64(pci->w64.end - pci->w64.begin);
|
|
||||||
} else {
|
} else {
|
||||||
*ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 0;
|
ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -976,7 +1065,14 @@ build_ssdt(GArray *table_data, GArray *linker,
|
|||||||
|
|
||||||
{
|
{
|
||||||
AcpiBuildPciBusHotplugState hotplug_state;
|
AcpiBuildPciBusHotplugState hotplug_state;
|
||||||
PCIBus *bus = find_i440fx(); /* TODO: Q35 support */
|
Object *pci_host;
|
||||||
|
PCIBus *bus = NULL;
|
||||||
|
bool ambiguous;
|
||||||
|
|
||||||
|
pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
|
||||||
|
if (!ambiguous && pci_host) {
|
||||||
|
bus = PCI_HOST_BRIDGE(pci_host)->bus;
|
||||||
|
}
|
||||||
|
|
||||||
build_pci_bus_state_init(&hotplug_state, NULL);
|
build_pci_bus_state_init(&hotplug_state, NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ DefinitionBlock (
|
|||||||
Name(_HID, EisaId("PNP0A03"))
|
Name(_HID, EisaId("PNP0A03"))
|
||||||
Name(_ADR, 0x00)
|
Name(_ADR, 0x00)
|
||||||
Name(_UID, 1)
|
Name(_UID, 1)
|
||||||
|
//#define PX13 S0B_
|
||||||
|
// External(PX13, DeviceObj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,34 +89,6 @@ DefinitionBlock (
|
|||||||
#include "acpi-dsdt-hpet.dsl"
|
#include "acpi-dsdt-hpet.dsl"
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
|
||||||
* VGA
|
|
||||||
****************************************************************/
|
|
||||||
|
|
||||||
Scope(\_SB.PCI0) {
|
|
||||||
Device(VGA) {
|
|
||||||
Name(_ADR, 0x00020000)
|
|
||||||
OperationRegion(PCIC, PCI_Config, Zero, 0x4)
|
|
||||||
Field(PCIC, DWordAcc, NoLock, Preserve) {
|
|
||||||
VEND, 32
|
|
||||||
}
|
|
||||||
Method(_S1D, 0, NotSerialized) {
|
|
||||||
Return (0x00)
|
|
||||||
}
|
|
||||||
Method(_S2D, 0, NotSerialized) {
|
|
||||||
Return (0x00)
|
|
||||||
}
|
|
||||||
Method(_S3D, 0, NotSerialized) {
|
|
||||||
If (LEqual(VEND, 0x1001b36)) {
|
|
||||||
Return (0x03) // QXL
|
|
||||||
} Else {
|
|
||||||
Return (0x00)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
* PIIX4 PM
|
* PIIX4 PM
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
@@ -132,6 +106,9 @@ DefinitionBlock (
|
|||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
Scope(\_SB.PCI0) {
|
Scope(\_SB.PCI0) {
|
||||||
|
|
||||||
|
External(ISA, DeviceObj)
|
||||||
|
|
||||||
Device(ISA) {
|
Device(ISA) {
|
||||||
Name(_ADR, 0x00010000)
|
Name(_ADR, 0x00010000)
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x44,
|
0x44,
|
||||||
0x54,
|
0x54,
|
||||||
0x87,
|
0x85,
|
||||||
0x11,
|
0x11,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x1,
|
0x1,
|
||||||
0xb8,
|
0x8b,
|
||||||
0x42,
|
0x42,
|
||||||
0x58,
|
0x58,
|
||||||
0x50,
|
0x50,
|
||||||
@@ -146,7 +146,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x1,
|
0x1,
|
||||||
0x10,
|
0x10,
|
||||||
0x4e,
|
0x4e,
|
||||||
0x15,
|
0x18,
|
||||||
0x2e,
|
0x2e,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x53,
|
0x53,
|
||||||
@@ -163,9 +163,9 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x11,
|
0x11,
|
||||||
0x42,
|
0x42,
|
||||||
0x7,
|
|
||||||
0xa,
|
0xa,
|
||||||
0x6e,
|
0xa,
|
||||||
|
0x9e,
|
||||||
0x88,
|
0x88,
|
||||||
0xd,
|
0xd,
|
||||||
0x0,
|
0x0,
|
||||||
@@ -217,11 +217,59 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x0,
|
0x0,
|
||||||
0xd,
|
0xd,
|
||||||
0xff,
|
0xff,
|
||||||
|
0xad,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xa1,
|
||||||
|
0x88,
|
||||||
|
0xd,
|
||||||
|
0x0,
|
||||||
|
0x1,
|
||||||
|
0xc,
|
||||||
|
0x3,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xf,
|
||||||
|
0xae,
|
||||||
|
0xff,
|
||||||
|
0xae,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xf1,
|
||||||
|
0x0,
|
||||||
|
0x88,
|
||||||
|
0xd,
|
||||||
|
0x0,
|
||||||
|
0x1,
|
||||||
|
0xc,
|
||||||
|
0x3,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0x20,
|
||||||
|
0xaf,
|
||||||
|
0xdf,
|
||||||
|
0xaf,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xc0,
|
||||||
|
0x0,
|
||||||
|
0x88,
|
||||||
|
0xd,
|
||||||
|
0x0,
|
||||||
|
0x1,
|
||||||
|
0xc,
|
||||||
|
0x3,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xe4,
|
||||||
|
0xaf,
|
||||||
|
0xff,
|
||||||
0xff,
|
0xff,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x1c,
|
||||||
0xf3,
|
0x50,
|
||||||
0x87,
|
0x87,
|
||||||
0x17,
|
0x17,
|
||||||
0x0,
|
0x0,
|
||||||
@@ -347,7 +395,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x45,
|
0x45,
|
||||||
0x53,
|
0x53,
|
||||||
0xa,
|
0xa,
|
||||||
0x5c,
|
0x8c,
|
||||||
0x50,
|
0x50,
|
||||||
0x53,
|
0x53,
|
||||||
0x33,
|
0x33,
|
||||||
@@ -358,7 +406,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x45,
|
0x45,
|
||||||
0x53,
|
0x53,
|
||||||
0xa,
|
0xa,
|
||||||
0x60,
|
0x90,
|
||||||
0x50,
|
0x50,
|
||||||
0x45,
|
0x45,
|
||||||
0x33,
|
0x33,
|
||||||
@@ -369,7 +417,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x45,
|
0x45,
|
||||||
0x53,
|
0x53,
|
||||||
0xa,
|
0xa,
|
||||||
0x68,
|
0x98,
|
||||||
0x50,
|
0x50,
|
||||||
0x4c,
|
0x4c,
|
||||||
0x33,
|
0x33,
|
||||||
@@ -638,103 +686,6 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x79,
|
0x79,
|
||||||
0x0,
|
0x0,
|
||||||
0x10,
|
0x10,
|
||||||
0x40,
|
|
||||||
0x6,
|
|
||||||
0x2e,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x42,
|
|
||||||
0x5f,
|
|
||||||
0x50,
|
|
||||||
0x43,
|
|
||||||
0x49,
|
|
||||||
0x30,
|
|
||||||
0x5b,
|
|
||||||
0x82,
|
|
||||||
0x43,
|
|
||||||
0x5,
|
|
||||||
0x56,
|
|
||||||
0x47,
|
|
||||||
0x41,
|
|
||||||
0x5f,
|
|
||||||
0x8,
|
|
||||||
0x5f,
|
|
||||||
0x41,
|
|
||||||
0x44,
|
|
||||||
0x52,
|
|
||||||
0xc,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x2,
|
|
||||||
0x0,
|
|
||||||
0x5b,
|
|
||||||
0x80,
|
|
||||||
0x50,
|
|
||||||
0x43,
|
|
||||||
0x49,
|
|
||||||
0x43,
|
|
||||||
0x2,
|
|
||||||
0x0,
|
|
||||||
0xa,
|
|
||||||
0x4,
|
|
||||||
0x5b,
|
|
||||||
0x81,
|
|
||||||
0xb,
|
|
||||||
0x50,
|
|
||||||
0x43,
|
|
||||||
0x49,
|
|
||||||
0x43,
|
|
||||||
0x3,
|
|
||||||
0x56,
|
|
||||||
0x45,
|
|
||||||
0x4e,
|
|
||||||
0x44,
|
|
||||||
0x20,
|
|
||||||
0x14,
|
|
||||||
0x8,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x31,
|
|
||||||
0x44,
|
|
||||||
0x0,
|
|
||||||
0xa4,
|
|
||||||
0x0,
|
|
||||||
0x14,
|
|
||||||
0x8,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x32,
|
|
||||||
0x44,
|
|
||||||
0x0,
|
|
||||||
0xa4,
|
|
||||||
0x0,
|
|
||||||
0x14,
|
|
||||||
0x19,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x33,
|
|
||||||
0x44,
|
|
||||||
0x0,
|
|
||||||
0xa0,
|
|
||||||
0xe,
|
|
||||||
0x93,
|
|
||||||
0x56,
|
|
||||||
0x45,
|
|
||||||
0x4e,
|
|
||||||
0x44,
|
|
||||||
0xc,
|
|
||||||
0x36,
|
|
||||||
0x1b,
|
|
||||||
0x0,
|
|
||||||
0x1,
|
|
||||||
0xa4,
|
|
||||||
0xa,
|
|
||||||
0x3,
|
|
||||||
0xa1,
|
|
||||||
0x3,
|
|
||||||
0xa4,
|
|
||||||
0x0,
|
|
||||||
0x10,
|
|
||||||
0x25,
|
0x25,
|
||||||
0x2e,
|
0x2e,
|
||||||
0x5f,
|
0x5f,
|
||||||
@@ -860,7 +811,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x4e,
|
0x4e,
|
||||||
0x1,
|
0x1,
|
||||||
0x10,
|
0x10,
|
||||||
0x4b,
|
0x4a,
|
||||||
0x1e,
|
0x1e,
|
||||||
0x2f,
|
0x2f,
|
||||||
0x3,
|
0x3,
|
||||||
@@ -878,7 +829,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x5f,
|
0x5f,
|
||||||
0x5b,
|
0x5b,
|
||||||
0x82,
|
0x82,
|
||||||
0x2d,
|
0x2c,
|
||||||
0x53,
|
0x53,
|
||||||
0x4d,
|
0x4d,
|
||||||
0x43,
|
0x43,
|
||||||
@@ -898,9 +849,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x54,
|
0x54,
|
||||||
0x41,
|
0x41,
|
||||||
0xb,
|
0xa,
|
||||||
0x0,
|
0xf0,
|
||||||
0xff,
|
|
||||||
0x8,
|
0x8,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x43,
|
0x43,
|
||||||
@@ -4061,7 +4011,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x1,
|
0x1,
|
||||||
0x10,
|
0x10,
|
||||||
0x47,
|
0x47,
|
||||||
0xe,
|
0x11,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x53,
|
0x53,
|
||||||
0x42,
|
0x42,
|
||||||
@@ -4291,6 +4241,54 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x3,
|
0x3,
|
||||||
0x75,
|
0x75,
|
||||||
0x60,
|
0x60,
|
||||||
|
0x5b,
|
||||||
|
0x82,
|
||||||
|
0x2e,
|
||||||
|
0x50,
|
||||||
|
0x52,
|
||||||
|
0x45,
|
||||||
|
0x53,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x48,
|
||||||
|
0x49,
|
||||||
|
0x44,
|
||||||
|
0xd,
|
||||||
|
0x41,
|
||||||
|
0x43,
|
||||||
|
0x50,
|
||||||
|
0x49,
|
||||||
|
0x30,
|
||||||
|
0x30,
|
||||||
|
0x30,
|
||||||
|
0x34,
|
||||||
|
0x0,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x43,
|
||||||
|
0x52,
|
||||||
|
0x53,
|
||||||
|
0x11,
|
||||||
|
0xd,
|
||||||
|
0xa,
|
||||||
|
0xa,
|
||||||
|
0x47,
|
||||||
|
0x1,
|
||||||
|
0x0,
|
||||||
|
0xaf,
|
||||||
|
0x0,
|
||||||
|
0xaf,
|
||||||
|
0x0,
|
||||||
|
0x20,
|
||||||
|
0x79,
|
||||||
|
0x0,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x54,
|
||||||
|
0x41,
|
||||||
|
0xa,
|
||||||
|
0xb,
|
||||||
0x10,
|
0x10,
|
||||||
0x42,
|
0x42,
|
||||||
0xc,
|
0xc,
|
||||||
@@ -4488,5 +4486,5 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x0
|
0x0
|
||||||
};
|
};
|
||||||
static unsigned short piix_dsdt_applesmc_sta[] = {
|
static unsigned short piix_dsdt_applesmc_sta[] = {
|
||||||
0x384
|
0x353
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!kvm_enabled()) {
|
if (!kvm_enabled()) {
|
||||||
cpu_restore_state(env, env->mem_io_pc);
|
cpu_restore_state(cs, cs->mem_io_pc);
|
||||||
cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
|
cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
|
||||||
¤t_flags);
|
¤t_flags);
|
||||||
}
|
}
|
||||||
@@ -448,8 +448,8 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
|
|||||||
|
|
||||||
if (!kvm_enabled()) {
|
if (!kvm_enabled()) {
|
||||||
cs->current_tb = NULL;
|
cs->current_tb = NULL;
|
||||||
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
|
tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1);
|
||||||
cpu_resume_from_signal(env, NULL);
|
cpu_resume_from_signal(cs, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,10 +221,16 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
|||||||
} else {
|
} else {
|
||||||
for(i = 0; i < MAX_IDE_BUS; i++) {
|
for(i = 0; i < MAX_IDE_BUS; i++) {
|
||||||
ISADevice *dev;
|
ISADevice *dev;
|
||||||
|
char busname[] = "ide.0";
|
||||||
dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
|
dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
|
||||||
ide_irq[i],
|
ide_irq[i],
|
||||||
hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
|
hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
|
||||||
idebus[i] = qdev_get_child_bus(DEVICE(dev), "ide.0");
|
/*
|
||||||
|
* The ide bus name is ide.0 for the first bus and ide.1 for the
|
||||||
|
* second one.
|
||||||
|
*/
|
||||||
|
busname[4] = '0' + i;
|
||||||
|
idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,13 +266,15 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args)
|
|||||||
{
|
{
|
||||||
smbios_type1_defaults = false;
|
smbios_type1_defaults = false;
|
||||||
gigabyte_align = false;
|
gigabyte_align = false;
|
||||||
|
option_rom_has_mr = true;
|
||||||
|
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_compat_1_6(QEMUMachineInitArgs *args)
|
static void pc_compat_1_6(QEMUMachineInitArgs *args)
|
||||||
{
|
{
|
||||||
pc_compat_1_7(args);
|
pc_compat_1_7(args);
|
||||||
has_pci_info = false;
|
has_pci_info = false;
|
||||||
rom_file_in_ram = false;
|
rom_file_has_mr = false;
|
||||||
has_acpi_build = false;
|
has_acpi_build = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +300,7 @@ static void pc_compat_1_3(QEMUMachineInitArgs *args)
|
|||||||
static void pc_compat_1_2(QEMUMachineInitArgs *args)
|
static void pc_compat_1_2(QEMUMachineInitArgs *args)
|
||||||
{
|
{
|
||||||
pc_compat_1_3(args);
|
pc_compat_1_3(args);
|
||||||
disable_kvm_pv_eoi();
|
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_init_pci_1_7(QEMUMachineInitArgs *args)
|
static void pc_init_pci_1_7(QEMUMachineInitArgs *args)
|
||||||
@@ -338,7 +346,7 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
|
|||||||
has_pci_info = false;
|
has_pci_info = false;
|
||||||
has_acpi_build = false;
|
has_acpi_build = false;
|
||||||
smbios_type1_defaults = false;
|
smbios_type1_defaults = false;
|
||||||
disable_kvm_pv_eoi();
|
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||||
enable_compat_apic_id_mode();
|
enable_compat_apic_id_mode();
|
||||||
pc_init1(args, 1, 0);
|
pc_init1(args, 1, 0);
|
||||||
}
|
}
|
||||||
@@ -351,7 +359,7 @@ static void pc_init_isa(QEMUMachineInitArgs *args)
|
|||||||
if (!args->cpu_model) {
|
if (!args->cpu_model) {
|
||||||
args->cpu_model = "486";
|
args->cpu_model = "486";
|
||||||
}
|
}
|
||||||
disable_kvm_pv_eoi();
|
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||||
enable_compat_apic_id_mode();
|
enable_compat_apic_id_mode();
|
||||||
pc_init1(args, 0, 1);
|
pc_init1(args, 0, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,13 +244,15 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args)
|
|||||||
{
|
{
|
||||||
smbios_type1_defaults = false;
|
smbios_type1_defaults = false;
|
||||||
gigabyte_align = false;
|
gigabyte_align = false;
|
||||||
|
option_rom_has_mr = true;
|
||||||
|
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_compat_1_6(QEMUMachineInitArgs *args)
|
static void pc_compat_1_6(QEMUMachineInitArgs *args)
|
||||||
{
|
{
|
||||||
pc_compat_1_7(args);
|
pc_compat_1_7(args);
|
||||||
has_pci_info = false;
|
has_pci_info = false;
|
||||||
rom_file_in_ram = false;
|
rom_file_has_mr = false;
|
||||||
has_acpi_build = false;
|
has_acpi_build = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ DefinitionBlock (
|
|||||||
Name(_ADR, 0x00)
|
Name(_ADR, 0x00)
|
||||||
Name(_UID, 1)
|
Name(_UID, 1)
|
||||||
|
|
||||||
|
External(ISA, DeviceObj)
|
||||||
|
|
||||||
// _OSC: based on sample of ACPI3.0b spec
|
// _OSC: based on sample of ACPI3.0b spec
|
||||||
Name(SUPP, 0) // PCI _OSC Support Field value
|
Name(SUPP, 0) // PCI _OSC Support Field value
|
||||||
Name(CTRL, 0) // PCI _OSC Control Field value
|
Name(CTRL, 0) // PCI _OSC Control Field value
|
||||||
@@ -133,26 +135,6 @@ DefinitionBlock (
|
|||||||
#include "acpi-dsdt-hpet.dsl"
|
#include "acpi-dsdt-hpet.dsl"
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
|
||||||
* VGA
|
|
||||||
****************************************************************/
|
|
||||||
|
|
||||||
Scope(\_SB.PCI0) {
|
|
||||||
Device(VGA) {
|
|
||||||
Name(_ADR, 0x00010000)
|
|
||||||
Method(_S1D, 0, NotSerialized) {
|
|
||||||
Return (0x00)
|
|
||||||
}
|
|
||||||
Method(_S2D, 0, NotSerialized) {
|
|
||||||
Return (0x00)
|
|
||||||
}
|
|
||||||
Method(_S3D, 0, NotSerialized) {
|
|
||||||
Return (0x00)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
* LPC ISA bridge
|
* LPC ISA bridge
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
@@ -160,8 +142,7 @@ DefinitionBlock (
|
|||||||
Scope(\_SB.PCI0) {
|
Scope(\_SB.PCI0) {
|
||||||
/* PCI D31:f0 LPC ISA bridge */
|
/* PCI D31:f0 LPC ISA bridge */
|
||||||
Device(ISA) {
|
Device(ISA) {
|
||||||
/* PCI D31:f0 */
|
Name (_ADR, 0x001F0000) // _ADR: Address
|
||||||
Name(_ADR, 0x001f0000)
|
|
||||||
|
|
||||||
/* ICH9 PCI to ISA irq remapping */
|
/* ICH9 PCI to ISA irq remapping */
|
||||||
OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
|
OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x44,
|
0x44,
|
||||||
0x54,
|
0x54,
|
||||||
0xdf,
|
0xd7,
|
||||||
0x1c,
|
0x1c,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x1,
|
0x1,
|
||||||
0xff,
|
0x3e,
|
||||||
0x42,
|
0x42,
|
||||||
0x58,
|
0x58,
|
||||||
0x50,
|
0x50,
|
||||||
@@ -415,11 +415,11 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0xf7,
|
0xd7,
|
||||||
0xc,
|
0xc,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0xf8,
|
0xd8,
|
||||||
0xc,
|
0xc,
|
||||||
0x88,
|
0x88,
|
||||||
0xd,
|
0xd,
|
||||||
@@ -853,61 +853,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x79,
|
0x79,
|
||||||
0x0,
|
0x0,
|
||||||
0x10,
|
0x10,
|
||||||
0x36,
|
|
||||||
0x2e,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x42,
|
|
||||||
0x5f,
|
|
||||||
0x50,
|
|
||||||
0x43,
|
|
||||||
0x49,
|
|
||||||
0x30,
|
|
||||||
0x5b,
|
|
||||||
0x82,
|
|
||||||
0x2a,
|
|
||||||
0x56,
|
|
||||||
0x47,
|
|
||||||
0x41,
|
|
||||||
0x5f,
|
|
||||||
0x8,
|
|
||||||
0x5f,
|
|
||||||
0x41,
|
|
||||||
0x44,
|
|
||||||
0x52,
|
|
||||||
0xc,
|
|
||||||
0x0,
|
|
||||||
0x0,
|
|
||||||
0x1,
|
|
||||||
0x0,
|
|
||||||
0x14,
|
|
||||||
0x8,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x31,
|
|
||||||
0x44,
|
|
||||||
0x0,
|
|
||||||
0xa4,
|
|
||||||
0x0,
|
|
||||||
0x14,
|
|
||||||
0x8,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x32,
|
|
||||||
0x44,
|
|
||||||
0x0,
|
|
||||||
0xa4,
|
|
||||||
0x0,
|
|
||||||
0x14,
|
|
||||||
0x8,
|
|
||||||
0x5f,
|
|
||||||
0x53,
|
|
||||||
0x33,
|
|
||||||
0x44,
|
|
||||||
0x0,
|
|
||||||
0xa4,
|
|
||||||
0x0,
|
|
||||||
0x10,
|
|
||||||
0x4c,
|
0x4c,
|
||||||
0x7,
|
0x7,
|
||||||
0x2e,
|
0x2e,
|
||||||
@@ -1033,7 +978,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x4e,
|
0x4e,
|
||||||
0x1,
|
0x1,
|
||||||
0x10,
|
0x10,
|
||||||
0x4b,
|
0x4a,
|
||||||
0x1e,
|
0x1e,
|
||||||
0x2f,
|
0x2f,
|
||||||
0x3,
|
0x3,
|
||||||
@@ -1051,7 +996,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x5f,
|
0x5f,
|
||||||
0x5b,
|
0x5b,
|
||||||
0x82,
|
0x82,
|
||||||
0x2d,
|
0x2c,
|
||||||
0x53,
|
0x53,
|
||||||
0x4d,
|
0x4d,
|
||||||
0x43,
|
0x43,
|
||||||
@@ -1071,9 +1016,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x54,
|
0x54,
|
||||||
0x41,
|
0x41,
|
||||||
0xb,
|
0xa,
|
||||||
0x0,
|
0xf0,
|
||||||
0xff,
|
|
||||||
0x8,
|
0x8,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x43,
|
0x43,
|
||||||
@@ -7016,7 +6960,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x1,
|
0x1,
|
||||||
0x10,
|
0x10,
|
||||||
0x47,
|
0x47,
|
||||||
0xe,
|
0x11,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x53,
|
0x53,
|
||||||
0x42,
|
0x42,
|
||||||
@@ -7121,8 +7065,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x54,
|
0x54,
|
||||||
0x1,
|
0x1,
|
||||||
0xb,
|
0xb,
|
||||||
0x0,
|
0xd8,
|
||||||
0xaf,
|
0xc,
|
||||||
0xa,
|
0xa,
|
||||||
0x20,
|
0x20,
|
||||||
0x5b,
|
0x5b,
|
||||||
@@ -7246,6 +7190,54 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x3,
|
0x3,
|
||||||
0x75,
|
0x75,
|
||||||
0x60,
|
0x60,
|
||||||
|
0x5b,
|
||||||
|
0x82,
|
||||||
|
0x2e,
|
||||||
|
0x50,
|
||||||
|
0x52,
|
||||||
|
0x45,
|
||||||
|
0x53,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x48,
|
||||||
|
0x49,
|
||||||
|
0x44,
|
||||||
|
0xd,
|
||||||
|
0x41,
|
||||||
|
0x43,
|
||||||
|
0x50,
|
||||||
|
0x49,
|
||||||
|
0x30,
|
||||||
|
0x30,
|
||||||
|
0x30,
|
||||||
|
0x34,
|
||||||
|
0x0,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x43,
|
||||||
|
0x52,
|
||||||
|
0x53,
|
||||||
|
0x11,
|
||||||
|
0xd,
|
||||||
|
0xa,
|
||||||
|
0xa,
|
||||||
|
0x47,
|
||||||
|
0x1,
|
||||||
|
0xd8,
|
||||||
|
0xc,
|
||||||
|
0xd8,
|
||||||
|
0xc,
|
||||||
|
0x0,
|
||||||
|
0x20,
|
||||||
|
0x79,
|
||||||
|
0x0,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x54,
|
||||||
|
0x41,
|
||||||
|
0xa,
|
||||||
|
0xb,
|
||||||
0x10,
|
0x10,
|
||||||
0x4f,
|
0x4f,
|
||||||
0x8,
|
0x8,
|
||||||
@@ -7392,5 +7384,5 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x0
|
0x0
|
||||||
};
|
};
|
||||||
static unsigned short q35_dsdt_applesmc_sta[] = {
|
static unsigned short q35_dsdt_applesmc_sta[] = {
|
||||||
0x431
|
0x3fa
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,5 +46,55 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ACPI_EXTRACT_DEVICE_START ssdt_pcinohp_start
|
||||||
|
ACPI_EXTRACT_DEVICE_END ssdt_pcinohp_end
|
||||||
|
ACPI_EXTRACT_DEVICE_STRING ssdt_pcinohp_name
|
||||||
|
|
||||||
|
// Extract the offsets of the device name, address dword and the slot
|
||||||
|
// name byte - we fill them in for each device.
|
||||||
|
Device(SBB) {
|
||||||
|
ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcinohp_adr
|
||||||
|
Name(_ADR, 0xAA0000)
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPI_EXTRACT_DEVICE_START ssdt_pcivga_start
|
||||||
|
ACPI_EXTRACT_DEVICE_END ssdt_pcivga_end
|
||||||
|
ACPI_EXTRACT_DEVICE_STRING ssdt_pcivga_name
|
||||||
|
|
||||||
|
// Extract the offsets of the device name, address dword and the slot
|
||||||
|
// name byte - we fill them in for each device.
|
||||||
|
Device(SCC) {
|
||||||
|
ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcivga_adr
|
||||||
|
Name(_ADR, 0xAA0000)
|
||||||
|
Method(_S1D, 0, NotSerialized) {
|
||||||
|
Return (0x00)
|
||||||
|
}
|
||||||
|
Method(_S2D, 0, NotSerialized) {
|
||||||
|
Return (0x00)
|
||||||
|
}
|
||||||
|
Method(_S3D, 0, NotSerialized) {
|
||||||
|
Return (0x00)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPI_EXTRACT_DEVICE_START ssdt_pciqxl_start
|
||||||
|
ACPI_EXTRACT_DEVICE_END ssdt_pciqxl_end
|
||||||
|
ACPI_EXTRACT_DEVICE_STRING ssdt_pciqxl_name
|
||||||
|
|
||||||
|
// Extract the offsets of the device name, address dword and the slot
|
||||||
|
// name byte - we fill them in for each device.
|
||||||
|
Device(SDD) {
|
||||||
|
ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pciqxl_adr
|
||||||
|
Name(_ADR, 0xAA0000)
|
||||||
|
Method(_S1D, 0, NotSerialized) {
|
||||||
|
Return (0x00)
|
||||||
|
}
|
||||||
|
Method(_S2D, 0, NotSerialized) {
|
||||||
|
Return (0x00)
|
||||||
|
}
|
||||||
|
Method(_S3D, 0, NotSerialized) {
|
||||||
|
Return (0x03) // QXL
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,38 @@
|
|||||||
static unsigned char ssdt_pcihp_name[] = {
|
static unsigned char ssdt_pcihp_name[] = {
|
||||||
0x33
|
0x34
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcivga_end[] = {
|
||||||
|
0x99
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcivga_name[] = {
|
||||||
|
0x70
|
||||||
};
|
};
|
||||||
static unsigned char ssdt_pcihp_adr[] = {
|
static unsigned char ssdt_pcihp_adr[] = {
|
||||||
0x44
|
0x45
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcinohp_end[] = {
|
||||||
|
0x6d
|
||||||
};
|
};
|
||||||
static unsigned char ssdt_pcihp_end[] = {
|
static unsigned char ssdt_pcihp_end[] = {
|
||||||
0x5b
|
0x5c
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pciqxl_start[] = {
|
||||||
|
0x99
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcinohp_name[] = {
|
||||||
|
0x5f
|
||||||
};
|
};
|
||||||
static unsigned char ssdp_pcihp_aml[] = {
|
static unsigned char ssdp_pcihp_aml[] = {
|
||||||
0x53,
|
0x53,
|
||||||
0x53,
|
0x53,
|
||||||
0x44,
|
0x44,
|
||||||
0x54,
|
0x54,
|
||||||
0x5b,
|
0xc6,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x1,
|
0x1,
|
||||||
0xe8,
|
0x6b,
|
||||||
0x42,
|
0x42,
|
||||||
0x58,
|
0x58,
|
||||||
0x50,
|
0x50,
|
||||||
@@ -45,7 +60,8 @@ static unsigned char ssdp_pcihp_aml[] = {
|
|||||||
0x13,
|
0x13,
|
||||||
0x20,
|
0x20,
|
||||||
0x10,
|
0x10,
|
||||||
0x36,
|
0x41,
|
||||||
|
0xa,
|
||||||
0x5c,
|
0x5c,
|
||||||
0x2e,
|
0x2e,
|
||||||
0x5f,
|
0x5f,
|
||||||
@@ -98,11 +114,138 @@ static unsigned char ssdp_pcihp_aml[] = {
|
|||||||
0x5f,
|
0x5f,
|
||||||
0x53,
|
0x53,
|
||||||
0x55,
|
0x55,
|
||||||
0x4e
|
0x4e,
|
||||||
|
0x5b,
|
||||||
|
0x82,
|
||||||
|
0xf,
|
||||||
|
0x53,
|
||||||
|
0x42,
|
||||||
|
0x42,
|
||||||
|
0x5f,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x41,
|
||||||
|
0x44,
|
||||||
|
0x52,
|
||||||
|
0xc,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xaa,
|
||||||
|
0x0,
|
||||||
|
0x5b,
|
||||||
|
0x82,
|
||||||
|
0x2a,
|
||||||
|
0x53,
|
||||||
|
0x43,
|
||||||
|
0x43,
|
||||||
|
0x5f,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x41,
|
||||||
|
0x44,
|
||||||
|
0x52,
|
||||||
|
0xc,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xaa,
|
||||||
|
0x0,
|
||||||
|
0x14,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x31,
|
||||||
|
0x44,
|
||||||
|
0x0,
|
||||||
|
0xa4,
|
||||||
|
0x0,
|
||||||
|
0x14,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x32,
|
||||||
|
0x44,
|
||||||
|
0x0,
|
||||||
|
0xa4,
|
||||||
|
0x0,
|
||||||
|
0x14,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x33,
|
||||||
|
0x44,
|
||||||
|
0x0,
|
||||||
|
0xa4,
|
||||||
|
0x0,
|
||||||
|
0x5b,
|
||||||
|
0x82,
|
||||||
|
0x2b,
|
||||||
|
0x53,
|
||||||
|
0x44,
|
||||||
|
0x44,
|
||||||
|
0x5f,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x41,
|
||||||
|
0x44,
|
||||||
|
0x52,
|
||||||
|
0xc,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xaa,
|
||||||
|
0x0,
|
||||||
|
0x14,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x31,
|
||||||
|
0x44,
|
||||||
|
0x0,
|
||||||
|
0xa4,
|
||||||
|
0x0,
|
||||||
|
0x14,
|
||||||
|
0x8,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x32,
|
||||||
|
0x44,
|
||||||
|
0x0,
|
||||||
|
0xa4,
|
||||||
|
0x0,
|
||||||
|
0x14,
|
||||||
|
0x9,
|
||||||
|
0x5f,
|
||||||
|
0x53,
|
||||||
|
0x33,
|
||||||
|
0x44,
|
||||||
|
0x0,
|
||||||
|
0xa4,
|
||||||
|
0xa,
|
||||||
|
0x3
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pciqxl_adr[] = {
|
||||||
|
0xa6
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcinohp_adr[] = {
|
||||||
|
0x69
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcivga_adr[] = {
|
||||||
|
0x7a
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pciqxl_name[] = {
|
||||||
|
0x9c
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcivga_start[] = {
|
||||||
|
0x6d
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pciqxl_end[] = {
|
||||||
|
0xc6
|
||||||
};
|
};
|
||||||
static unsigned char ssdt_pcihp_start[] = {
|
static unsigned char ssdt_pcihp_start[] = {
|
||||||
0x30
|
0x31
|
||||||
};
|
};
|
||||||
static unsigned char ssdt_pcihp_id[] = {
|
static unsigned char ssdt_pcihp_id[] = {
|
||||||
0x3d
|
0x3e
|
||||||
|
};
|
||||||
|
static unsigned char ssdt_pcinohp_start[] = {
|
||||||
|
0x5c
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
|
#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
|
||||||
AHCI_RX_FIS_SZ)
|
AHCI_RX_FIS_SZ)
|
||||||
|
|
||||||
#define AHCI_IRQ_ON_SG (1 << 31)
|
#define AHCI_IRQ_ON_SG (1U << 31)
|
||||||
#define AHCI_CMD_ATAPI (1 << 5)
|
#define AHCI_CMD_ATAPI (1 << 5)
|
||||||
#define AHCI_CMD_WRITE (1 << 6)
|
#define AHCI_CMD_WRITE (1 << 6)
|
||||||
#define AHCI_CMD_PREFETCH (1 << 7)
|
#define AHCI_CMD_PREFETCH (1 << 7)
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
/* HOST_CTL bits */
|
/* HOST_CTL bits */
|
||||||
#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */
|
#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */
|
||||||
#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */
|
#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */
|
||||||
#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */
|
#define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */
|
||||||
|
|
||||||
/* HOST_CAP bits */
|
/* HOST_CAP bits */
|
||||||
#define HOST_CAP_SSC (1 << 14) /* Slumber capable */
|
#define HOST_CAP_SSC (1 << 14) /* Slumber capable */
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
#define HOST_CAP_CLO (1 << 24) /* Command List Override support */
|
#define HOST_CAP_CLO (1 << 24) /* Command List Override support */
|
||||||
#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */
|
#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */
|
||||||
#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */
|
#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */
|
||||||
#define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */
|
#define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */
|
||||||
|
|
||||||
/* registers for each SATA port */
|
/* registers for each SATA port */
|
||||||
#define PORT_LST_ADDR 0x00 /* command list DMA addr */
|
#define PORT_LST_ADDR 0x00 /* command list DMA addr */
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
#define PORT_RESERVED 0x3c /* reserved */
|
#define PORT_RESERVED 0x3c /* reserved */
|
||||||
|
|
||||||
/* PORT_IRQ_{STAT,MASK} bits */
|
/* PORT_IRQ_{STAT,MASK} bits */
|
||||||
#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */
|
#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */
|
||||||
#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
|
#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
|
||||||
#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */
|
#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */
|
||||||
#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
|
#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */
|
#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */
|
||||||
#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */
|
#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */
|
||||||
#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */
|
#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */
|
||||||
#define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */
|
#define PORT_IRQ_STAT_CPDS (1U << 31) /* Code Port Detect Status */
|
||||||
|
|
||||||
/* ap->flags bits */
|
/* ap->flags bits */
|
||||||
#define AHCI_FLAG_NO_NCQ (1 << 24)
|
#define AHCI_FLAG_NO_NCQ (1 << 24)
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ static void kbd_write_command(void *opaque, hwaddr addr,
|
|||||||
kbd_update_irq(s);
|
kbd_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case KBD_CCMD_READ_INPORT:
|
case KBD_CCMD_READ_INPORT:
|
||||||
kbd_queue(s, 0x00, 0);
|
kbd_queue(s, 0x80, 0);
|
||||||
break;
|
break;
|
||||||
case KBD_CCMD_READ_OUTPORT:
|
case KBD_CCMD_READ_OUTPORT:
|
||||||
kbd_queue(s, s->outport, 0);
|
kbd_queue(s, s->outport, 0);
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
|
|||||||
uint32_t *field, bool to_kernel);
|
uint32_t *field, bool to_kernel);
|
||||||
|
|
||||||
/* synthetic translate function used for clear/set registers to completely
|
/* synthetic translate function used for clear/set registers to completely
|
||||||
* clear a setting using a clear-register before setting the remaing bits
|
* clear a setting using a clear-register before setting the remaining bits
|
||||||
* using a set-register */
|
* using a set-register */
|
||||||
static void translate_clear(GICState *s, int irq, int cpu,
|
static void translate_clear(GICState *s, int irq, int cpu,
|
||||||
uint32_t *field, bool to_kernel)
|
uint32_t *field, bool to_kernel)
|
||||||
|
|||||||
@@ -93,9 +93,6 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
|
|||||||
uint32_t mask = 1 << vector;
|
uint32_t mask = 1 << vector;
|
||||||
uint64_t entry = s->ioredtbl[vector];
|
uint64_t entry = s->ioredtbl[vector];
|
||||||
|
|
||||||
if (entry & (1 << IOAPIC_LVT_POLARITY_SHIFT)) {
|
|
||||||
level = !level;
|
|
||||||
}
|
|
||||||
if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) ==
|
if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) ==
|
||||||
IOAPIC_TRIGGER_LEVEL) {
|
IOAPIC_TRIGGER_LEVEL) {
|
||||||
/* level triggered */
|
/* level triggered */
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
|
|||||||
|
|
||||||
encap.cap = KVM_CAP_IRQ_MPIC;
|
encap.cap = KVM_CAP_IRQ_MPIC;
|
||||||
encap.args[0] = opp->fd;
|
encap.args[0] = opp->fd;
|
||||||
encap.args[1] = cs->cpu_index;
|
encap.args[1] = kvm_arch_vcpu_id(cs);
|
||||||
|
|
||||||
return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
|
return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,17 @@
|
|||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
|
|
||||||
|
static int get_cpu_index_by_dt_id(int cpu_dt_id)
|
||||||
|
{
|
||||||
|
PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id);
|
||||||
|
|
||||||
|
if (cpu) {
|
||||||
|
return cpu->parent_obj.cpu_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
|
void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
@@ -659,7 +670,7 @@ static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||||
target_ulong opcode, target_ulong *args)
|
target_ulong opcode, target_ulong *args)
|
||||||
{
|
{
|
||||||
target_ulong server = args[0];
|
target_ulong server = get_cpu_index_by_dt_id(args[0]);
|
||||||
target_ulong mfrr = args[1];
|
target_ulong mfrr = args[1];
|
||||||
|
|
||||||
if (server >= spapr->icp->nr_servers) {
|
if (server >= spapr->icp->nr_servers) {
|
||||||
@@ -728,7 +739,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nr = rtas_ld(args, 0);
|
nr = rtas_ld(args, 0);
|
||||||
server = rtas_ld(args, 1);
|
server = get_cpu_index_by_dt_id(rtas_ld(args, 1));
|
||||||
priority = rtas_ld(args, 2);
|
priority = rtas_ld(args, 2);
|
||||||
|
|
||||||
if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
|
if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ static void icp_get_kvm_state(ICPState *ss)
|
|||||||
ret = kvm_vcpu_ioctl(ss->cs, KVM_GET_ONE_REG, ®);
|
ret = kvm_vcpu_ioctl(ss->cs, KVM_GET_ONE_REG, ®);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
error_report("Unable to retrieve KVM interrupt controller state"
|
error_report("Unable to retrieve KVM interrupt controller state"
|
||||||
" for CPU %d: %s", ss->cs->cpu_index, strerror(errno));
|
" for CPU %ld: %s", kvm_arch_vcpu_id(ss->cs), strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ static int icp_set_kvm_state(ICPState *ss, int version_id)
|
|||||||
ret = kvm_vcpu_ioctl(ss->cs, KVM_SET_ONE_REG, ®);
|
ret = kvm_vcpu_ioctl(ss->cs, KVM_SET_ONE_REG, ®);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
error_report("Unable to restore KVM interrupt controller state (0x%"
|
error_report("Unable to restore KVM interrupt controller state (0x%"
|
||||||
PRIx64 ") for CPU %d: %s", state, ss->cs->cpu_index,
|
PRIx64 ") for CPU %ld: %s", state, kvm_arch_vcpu_id(ss->cs),
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -269,7 +269,16 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
|
|||||||
|
|
||||||
static void ics_kvm_reset(DeviceState *dev)
|
static void ics_kvm_reset(DeviceState *dev)
|
||||||
{
|
{
|
||||||
ics_set_kvm_state(ICS(dev), 1);
|
ICSState *ics = ICS(dev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
|
||||||
|
for (i = 0; i < ics->nr_irqs; i++) {
|
||||||
|
ics->irqs[i].priority = 0xff;
|
||||||
|
ics->irqs[i].saved_priority = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
ics_set_kvm_state(ics, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ics_kvm_realize(DeviceState *dev, Error **errp)
|
static void ics_kvm_realize(DeviceState *dev, Error **errp)
|
||||||
@@ -325,15 +334,15 @@ static void xics_kvm_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
|
|||||||
struct kvm_enable_cap xics_enable_cap = {
|
struct kvm_enable_cap xics_enable_cap = {
|
||||||
.cap = KVM_CAP_IRQ_XICS,
|
.cap = KVM_CAP_IRQ_XICS,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.args = {icpkvm->kernel_xics_fd, cs->cpu_index, 0, 0},
|
.args = {icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs), 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
ss->cs = cs;
|
ss->cs = cs;
|
||||||
|
|
||||||
ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap);
|
ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("Unable to connect CPU%d to kernel XICS: %s",
|
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
||||||
cs->cpu_index, strerror(errno));
|
kvm_arch_vcpu_id(cs), strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
#include "hw/ssi.h"
|
#include "hw/ssi.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SSISlave ssidev;
|
SSISlave parent_obj;
|
||||||
|
|
||||||
qemu_irq interrupt;
|
qemu_irq interrupt;
|
||||||
uint8_t tb1, rb2, rb3;
|
uint8_t tb1, rb2, rb3;
|
||||||
int cycle;
|
int cycle;
|
||||||
@@ -22,6 +23,14 @@ typedef struct {
|
|||||||
int inputs, com;
|
int inputs, com;
|
||||||
} MAX111xState;
|
} MAX111xState;
|
||||||
|
|
||||||
|
#define TYPE_MAX_111X "max111x"
|
||||||
|
|
||||||
|
#define MAX_111X(obj) \
|
||||||
|
OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X)
|
||||||
|
|
||||||
|
#define TYPE_MAX_1110 "max1110"
|
||||||
|
#define TYPE_MAX_1111 "max1111"
|
||||||
|
|
||||||
/* Control-byte bitfields */
|
/* Control-byte bitfields */
|
||||||
#define CB_PD0 (1 << 0)
|
#define CB_PD0 (1 << 0)
|
||||||
#define CB_PD1 (1 << 1)
|
#define CB_PD1 (1 << 1)
|
||||||
@@ -92,7 +101,7 @@ static void max111x_write(MAX111xState *s, uint32_t value)
|
|||||||
|
|
||||||
static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
|
static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
|
||||||
{
|
{
|
||||||
MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev);
|
MAX111xState *s = MAX_111X(dev);
|
||||||
max111x_write(s, value);
|
max111x_write(s, value);
|
||||||
return max111x_read(s);
|
return max111x_read(s);
|
||||||
}
|
}
|
||||||
@@ -103,7 +112,7 @@ static const VMStateDescription vmstate_max111x = {
|
|||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
.minimum_version_id_old = 1,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_SSI_SLAVE(ssidev, MAX111xState),
|
VMSTATE_SSI_SLAVE(parent_obj, MAX111xState),
|
||||||
VMSTATE_UINT8(tb1, MAX111xState),
|
VMSTATE_UINT8(tb1, MAX111xState),
|
||||||
VMSTATE_UINT8(rb2, MAX111xState),
|
VMSTATE_UINT8(rb2, MAX111xState),
|
||||||
VMSTATE_UINT8(rb3, MAX111xState),
|
VMSTATE_UINT8(rb3, MAX111xState),
|
||||||
@@ -115,11 +124,12 @@ static const VMStateDescription vmstate_max111x = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int max111x_init(SSISlave *dev, int inputs)
|
static int max111x_init(SSISlave *d, int inputs)
|
||||||
{
|
{
|
||||||
MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev);
|
DeviceState *dev = DEVICE(d);
|
||||||
|
MAX111xState *s = MAX_111X(dev);
|
||||||
|
|
||||||
qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1);
|
qdev_init_gpio_out(dev, &s->interrupt, 1);
|
||||||
|
|
||||||
s->inputs = inputs;
|
s->inputs = inputs;
|
||||||
/* TODO: add a user interface for setting these */
|
/* TODO: add a user interface for setting these */
|
||||||
@@ -133,7 +143,7 @@ static int max111x_init(SSISlave *dev, int inputs)
|
|||||||
s->input[7] = 0x80;
|
s->input[7] = 0x80;
|
||||||
s->com = 0;
|
s->com = 0;
|
||||||
|
|
||||||
vmstate_register(&dev->qdev, -1, &vmstate_max111x, s);
|
vmstate_register(dev, -1, &vmstate_max111x, s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,23 +159,36 @@ static int max1111_init(SSISlave *dev)
|
|||||||
|
|
||||||
void max111x_set_input(DeviceState *dev, int line, uint8_t value)
|
void max111x_set_input(DeviceState *dev, int line, uint8_t value)
|
||||||
{
|
{
|
||||||
MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, SSI_SLAVE_FROM_QDEV(dev));
|
MAX111xState *s = MAX_111X(dev);
|
||||||
assert(line >= 0 && line < s->inputs);
|
assert(line >= 0 && line < s->inputs);
|
||||||
s->input[line] = value;
|
s->input[line] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void max111x_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||||
|
|
||||||
|
k->transfer = max111x_transfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo max111x_info = {
|
||||||
|
.name = TYPE_MAX_111X,
|
||||||
|
.parent = TYPE_SSI_SLAVE,
|
||||||
|
.instance_size = sizeof(MAX111xState),
|
||||||
|
.class_init = max111x_class_init,
|
||||||
|
.abstract = true,
|
||||||
|
};
|
||||||
|
|
||||||
static void max1110_class_init(ObjectClass *klass, void *data)
|
static void max1110_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||||
|
|
||||||
k->init = max1110_init;
|
k->init = max1110_init;
|
||||||
k->transfer = max111x_transfer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo max1110_info = {
|
static const TypeInfo max1110_info = {
|
||||||
.name = "max1110",
|
.name = TYPE_MAX_1110,
|
||||||
.parent = TYPE_SSI_SLAVE,
|
.parent = TYPE_MAX_111X,
|
||||||
.instance_size = sizeof(MAX111xState),
|
|
||||||
.class_init = max1110_class_init,
|
.class_init = max1110_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,18 +197,17 @@ static void max1111_class_init(ObjectClass *klass, void *data)
|
|||||||
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
|
||||||
|
|
||||||
k->init = max1111_init;
|
k->init = max1111_init;
|
||||||
k->transfer = max111x_transfer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo max1111_info = {
|
static const TypeInfo max1111_info = {
|
||||||
.name = "max1111",
|
.name = TYPE_MAX_1111,
|
||||||
.parent = TYPE_SSI_SLAVE,
|
.parent = TYPE_MAX_111X,
|
||||||
.instance_size = sizeof(MAX111xState),
|
|
||||||
.class_init = max1111_class_init,
|
.class_init = max1111_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void max111x_register_types(void)
|
static void max111x_register_types(void)
|
||||||
{
|
{
|
||||||
|
type_register_static(&max111x_info);
|
||||||
type_register_static(&max1110_info);
|
type_register_static(&max1110_info);
|
||||||
type_register_static(&max1111_info);
|
type_register_static(&max1111_info);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
|
|||||||
&entry, &kernel_low, &kernel_high, 1,
|
&entry, &kernel_low, &kernel_high, 1,
|
||||||
ELF_MACHINE, 0);
|
ELF_MACHINE, 0);
|
||||||
|
|
||||||
if (!kernel_size) {
|
if (kernel_size <= 0) {
|
||||||
fprintf(stderr, "qemu: could not load kernel '%s'\n",
|
fprintf(stderr, "qemu: could not load kernel '%s'\n",
|
||||||
loader_params->kernel_filename);
|
loader_params->kernel_filename);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@@ -32,3 +32,6 @@ obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
|
|||||||
|
|
||||||
obj-$(CONFIG_VIRTIO) += virtio-net.o
|
obj-$(CONFIG_VIRTIO) += virtio-net.o
|
||||||
obj-y += vhost_net.o
|
obj-y += vhost_net.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \
|
||||||
|
fsl_etsec/rings.o fsl_etsec/miim.o
|
||||||
|
|||||||
465
hw/net/fsl_etsec/etsec.c
Normal file
465
hw/net/fsl_etsec/etsec.c
Normal file
@@ -0,0 +1,465 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Freescale eTSEC Emulator
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011-2013 AdaCore
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "hw/sysbus.h"
|
||||||
|
#include "trace.h"
|
||||||
|
#include "hw/ptimer.h"
|
||||||
|
#include "etsec.h"
|
||||||
|
#include "registers.h"
|
||||||
|
|
||||||
|
/* #define HEX_DUMP */
|
||||||
|
/* #define DEBUG_REGISTER */
|
||||||
|
|
||||||
|
#ifdef DEBUG_REGISTER
|
||||||
|
static const int debug_etsec = 1;
|
||||||
|
#else
|
||||||
|
static const int debug_etsec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DPRINTF(fmt, ...) do { \
|
||||||
|
if (debug_etsec) { \
|
||||||
|
qemu_log(fmt , ## __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static uint64_t etsec_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = opaque;
|
||||||
|
uint32_t reg_index = addr / 4;
|
||||||
|
eTSEC_Register *reg = NULL;
|
||||||
|
uint32_t ret = 0x0;
|
||||||
|
|
||||||
|
assert(reg_index < ETSEC_REG_NUMBER);
|
||||||
|
|
||||||
|
reg = &etsec->regs[reg_index];
|
||||||
|
|
||||||
|
|
||||||
|
switch (reg->access) {
|
||||||
|
case ACC_WO:
|
||||||
|
ret = 0x00000000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACC_RW:
|
||||||
|
case ACC_W1C:
|
||||||
|
case ACC_RO:
|
||||||
|
default:
|
||||||
|
ret = reg->value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF("Read 0x%08x @ 0x" TARGET_FMT_plx
|
||||||
|
" : %s (%s)\n",
|
||||||
|
ret, addr, reg->name, reg->desc);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_tstat(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
/* Check THLTi flag in TSTAT */
|
||||||
|
if (value & (1 << (31 - i))) {
|
||||||
|
etsec_walk_tx_ring(etsec, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write 1 to clear */
|
||||||
|
reg->value &= ~value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_rstat(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
/* Check QHLTi flag in RSTAT */
|
||||||
|
if (value & (1 << (23 - i)) && !(reg->value & (1 << (23 - i)))) {
|
||||||
|
etsec_walk_rx_ring(etsec, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write 1 to clear */
|
||||||
|
reg->value &= ~value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_tbasex(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
reg->value = value & ~0x7;
|
||||||
|
|
||||||
|
/* Copy this value in the ring's TxBD pointer */
|
||||||
|
etsec->regs[TBPTR0 + (reg_index - TBASE0)].value = value & ~0x7;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_rbasex(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
reg->value = value & ~0x7;
|
||||||
|
|
||||||
|
/* Copy this value in the ring's RxBD pointer */
|
||||||
|
etsec->regs[RBPTR0 + (reg_index - RBASE0)].value = value & ~0x7;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_ievent(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
/* Write 1 to clear */
|
||||||
|
reg->value &= ~value;
|
||||||
|
|
||||||
|
if (!(reg->value & (IEVENT_TXF | IEVENT_TXF))) {
|
||||||
|
qemu_irq_lower(etsec->tx_irq);
|
||||||
|
}
|
||||||
|
if (!(reg->value & (IEVENT_RXF | IEVENT_RXF))) {
|
||||||
|
qemu_irq_lower(etsec->rx_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(reg->value & (IEVENT_MAG | IEVENT_GTSC | IEVENT_GRSC | IEVENT_TXC |
|
||||||
|
IEVENT_RXC | IEVENT_BABR | IEVENT_BABT | IEVENT_LC |
|
||||||
|
IEVENT_CRL | IEVENT_FGPI | IEVENT_FIR | IEVENT_FIQ |
|
||||||
|
IEVENT_DPE | IEVENT_PERR | IEVENT_EBERR | IEVENT_TXE |
|
||||||
|
IEVENT_XFUN | IEVENT_BSY | IEVENT_MSRO | IEVENT_MMRD |
|
||||||
|
IEVENT_MMRW))) {
|
||||||
|
qemu_irq_lower(etsec->err_irq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_dmactrl(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
reg->value = value;
|
||||||
|
|
||||||
|
if (value & DMACTRL_GRS) {
|
||||||
|
|
||||||
|
if (etsec->rx_buffer_len != 0) {
|
||||||
|
/* Graceful receive stop delayed until end of frame */
|
||||||
|
} else {
|
||||||
|
/* Graceful receive stop now */
|
||||||
|
etsec->regs[IEVENT].value |= IEVENT_GRSC;
|
||||||
|
if (etsec->regs[IMASK].value & IMASK_GRSCEN) {
|
||||||
|
qemu_irq_raise(etsec->err_irq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value & DMACTRL_GTS) {
|
||||||
|
|
||||||
|
if (etsec->tx_buffer_len != 0) {
|
||||||
|
/* Graceful transmit stop delayed until end of frame */
|
||||||
|
} else {
|
||||||
|
/* Graceful transmit stop now */
|
||||||
|
etsec->regs[IEVENT].value |= IEVENT_GTSC;
|
||||||
|
if (etsec->regs[IMASK].value & IMASK_GTSCEN) {
|
||||||
|
qemu_irq_raise(etsec->err_irq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(value & DMACTRL_WOP)) {
|
||||||
|
/* Start polling */
|
||||||
|
ptimer_stop(etsec->ptimer);
|
||||||
|
ptimer_set_count(etsec->ptimer, 1);
|
||||||
|
ptimer_run(etsec->ptimer, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void etsec_write(void *opaque,
|
||||||
|
hwaddr addr,
|
||||||
|
uint64_t value,
|
||||||
|
unsigned size)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = opaque;
|
||||||
|
uint32_t reg_index = addr / 4;
|
||||||
|
eTSEC_Register *reg = NULL;
|
||||||
|
uint32_t before = 0x0;
|
||||||
|
|
||||||
|
assert(reg_index < ETSEC_REG_NUMBER);
|
||||||
|
|
||||||
|
reg = &etsec->regs[reg_index];
|
||||||
|
before = reg->value;
|
||||||
|
|
||||||
|
switch (reg_index) {
|
||||||
|
case IEVENT:
|
||||||
|
write_ievent(etsec, reg, reg_index, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DMACTRL:
|
||||||
|
write_dmactrl(etsec, reg, reg_index, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSTAT:
|
||||||
|
write_tstat(etsec, reg, reg_index, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RSTAT:
|
||||||
|
write_rstat(etsec, reg, reg_index, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TBASE0 ... TBASE7:
|
||||||
|
write_tbasex(etsec, reg, reg_index, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RBASE0 ... RBASE7:
|
||||||
|
write_rbasex(etsec, reg, reg_index, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIIMCFG ... MIIMIND:
|
||||||
|
etsec_write_miim(etsec, reg, reg_index, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Default handling */
|
||||||
|
switch (reg->access) {
|
||||||
|
|
||||||
|
case ACC_RW:
|
||||||
|
case ACC_WO:
|
||||||
|
reg->value = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACC_W1C:
|
||||||
|
reg->value &= ~value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACC_RO:
|
||||||
|
default:
|
||||||
|
/* Read Only or Unknown register */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTF("Write 0x%08x @ 0x" TARGET_FMT_plx
|
||||||
|
" val:0x%08x->0x%08x : %s (%s)\n",
|
||||||
|
(unsigned int)value, addr, before, reg->value,
|
||||||
|
reg->name, reg->desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MemoryRegionOps etsec_ops = {
|
||||||
|
.read = etsec_read,
|
||||||
|
.write = etsec_write,
|
||||||
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
|
.impl = {
|
||||||
|
.min_access_size = 4,
|
||||||
|
.max_access_size = 4,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void etsec_timer_hit(void *opaque)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = opaque;
|
||||||
|
|
||||||
|
ptimer_stop(etsec->ptimer);
|
||||||
|
|
||||||
|
if (!(etsec->regs[DMACTRL].value & DMACTRL_WOP)) {
|
||||||
|
|
||||||
|
if (!(etsec->regs[DMACTRL].value & DMACTRL_GTS)) {
|
||||||
|
etsec_walk_tx_ring(etsec, 0);
|
||||||
|
}
|
||||||
|
ptimer_set_count(etsec->ptimer, 1);
|
||||||
|
ptimer_run(etsec->ptimer, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void etsec_reset(DeviceState *d)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = ETSEC_COMMON(d);
|
||||||
|
int i = 0;
|
||||||
|
int reg_index = 0;
|
||||||
|
|
||||||
|
/* Default value for all registers */
|
||||||
|
for (i = 0; i < ETSEC_REG_NUMBER; i++) {
|
||||||
|
etsec->regs[i].name = "Reserved";
|
||||||
|
etsec->regs[i].desc = "";
|
||||||
|
etsec->regs[i].access = ACC_UNKNOWN;
|
||||||
|
etsec->regs[i].value = 0x00000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set-up known registers */
|
||||||
|
for (i = 0; eTSEC_registers_def[i].name != NULL; i++) {
|
||||||
|
|
||||||
|
reg_index = eTSEC_registers_def[i].offset / 4;
|
||||||
|
|
||||||
|
etsec->regs[reg_index].name = eTSEC_registers_def[i].name;
|
||||||
|
etsec->regs[reg_index].desc = eTSEC_registers_def[i].desc;
|
||||||
|
etsec->regs[reg_index].access = eTSEC_registers_def[i].access;
|
||||||
|
etsec->regs[reg_index].value = eTSEC_registers_def[i].reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
etsec->tx_buffer = NULL;
|
||||||
|
etsec->tx_buffer_len = 0;
|
||||||
|
etsec->rx_buffer = NULL;
|
||||||
|
etsec->rx_buffer_len = 0;
|
||||||
|
|
||||||
|
etsec->phy_status =
|
||||||
|
MII_SR_EXTENDED_CAPS | MII_SR_LINK_STATUS | MII_SR_AUTONEG_CAPS |
|
||||||
|
MII_SR_AUTONEG_COMPLETE | MII_SR_PREAMBLE_SUPPRESS |
|
||||||
|
MII_SR_EXTENDED_STATUS | MII_SR_100T2_HD_CAPS | MII_SR_100T2_FD_CAPS |
|
||||||
|
MII_SR_10T_HD_CAPS | MII_SR_10T_FD_CAPS | MII_SR_100X_HD_CAPS |
|
||||||
|
MII_SR_100X_FD_CAPS | MII_SR_100T4_CAPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void etsec_cleanup(NetClientState *nc)
|
||||||
|
{
|
||||||
|
/* qemu_log("eTSEC cleanup\n"); */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int etsec_can_receive(NetClientState *nc)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
|
return etsec->rx_buffer_len == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t etsec_receive(NetClientState *nc,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
|
#if defined(HEX_DUMP)
|
||||||
|
fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
|
||||||
|
qemu_hexdump(buf, stderr, "", size);
|
||||||
|
#endif
|
||||||
|
etsec_rx_ring_write(etsec, buf, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void etsec_set_link_status(NetClientState *nc)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
|
etsec_miim_link_status(etsec, nc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NetClientInfo net_etsec_info = {
|
||||||
|
.type = NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
|
.size = sizeof(NICState),
|
||||||
|
.can_receive = etsec_can_receive,
|
||||||
|
.receive = etsec_receive,
|
||||||
|
.cleanup = etsec_cleanup,
|
||||||
|
.link_status_changed = etsec_set_link_status,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void etsec_realize(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = ETSEC_COMMON(dev);
|
||||||
|
|
||||||
|
etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf,
|
||||||
|
object_get_typename(OBJECT(dev)), dev->id, etsec);
|
||||||
|
qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a);
|
||||||
|
|
||||||
|
|
||||||
|
etsec->bh = qemu_bh_new(etsec_timer_hit, etsec);
|
||||||
|
etsec->ptimer = ptimer_init(etsec->bh);
|
||||||
|
ptimer_set_freq(etsec->ptimer, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void etsec_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
eTSEC *etsec = ETSEC_COMMON(obj);
|
||||||
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
|
|
||||||
|
memory_region_init_io(&etsec->io_area, OBJECT(etsec), &etsec_ops, etsec,
|
||||||
|
"eTSEC", 0x1000);
|
||||||
|
sysbus_init_mmio(sbd, &etsec->io_area);
|
||||||
|
|
||||||
|
sysbus_init_irq(sbd, &etsec->tx_irq);
|
||||||
|
sysbus_init_irq(sbd, &etsec->rx_irq);
|
||||||
|
sysbus_init_irq(sbd, &etsec->err_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Property etsec_properties[] = {
|
||||||
|
DEFINE_NIC_PROPERTIES(eTSEC, conf),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void etsec_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
dc->realize = etsec_realize;
|
||||||
|
dc->reset = etsec_reset;
|
||||||
|
dc->props = etsec_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TypeInfo etsec_info = {
|
||||||
|
.name = "eTSEC",
|
||||||
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
|
.instance_size = sizeof(eTSEC),
|
||||||
|
.class_init = etsec_class_init,
|
||||||
|
.instance_init = etsec_instance_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void etsec_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&etsec_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(etsec_register_types)
|
||||||
|
|
||||||
|
DeviceState *etsec_create(hwaddr base,
|
||||||
|
MemoryRegion * mr,
|
||||||
|
NICInfo * nd,
|
||||||
|
qemu_irq tx_irq,
|
||||||
|
qemu_irq rx_irq,
|
||||||
|
qemu_irq err_irq)
|
||||||
|
{
|
||||||
|
DeviceState *dev;
|
||||||
|
|
||||||
|
dev = qdev_create(NULL, "eTSEC");
|
||||||
|
qdev_set_nic_properties(dev, nd);
|
||||||
|
|
||||||
|
if (qdev_init(dev)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, tx_irq);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, rx_irq);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, err_irq);
|
||||||
|
|
||||||
|
memory_region_add_subregion(mr, base,
|
||||||
|
SYS_BUS_DEVICE(dev)->mmio[0].memory);
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
174
hw/net/fsl_etsec/etsec.h
Normal file
174
hw/net/fsl_etsec/etsec.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Freescale eTSEC Emulator
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011-2013 AdaCore
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef _ETSEC_H_
|
||||||
|
#define _ETSEC_H_
|
||||||
|
|
||||||
|
#include "hw/qdev.h"
|
||||||
|
#include "hw/sysbus.h"
|
||||||
|
#include "net/net.h"
|
||||||
|
#include "hw/ptimer.h"
|
||||||
|
|
||||||
|
/* Buffer Descriptors */
|
||||||
|
|
||||||
|
typedef struct eTSEC_rxtx_bd {
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t length;
|
||||||
|
uint32_t bufptr;
|
||||||
|
} eTSEC_rxtx_bd;
|
||||||
|
|
||||||
|
#define BD_WRAP (1 << 13)
|
||||||
|
#define BD_INTERRUPT (1 << 12)
|
||||||
|
#define BD_LAST (1 << 11)
|
||||||
|
|
||||||
|
#define BD_TX_READY (1 << 15)
|
||||||
|
#define BD_TX_PADCRC (1 << 14)
|
||||||
|
#define BD_TX_TC (1 << 10)
|
||||||
|
#define BD_TX_PREDEF (1 << 9)
|
||||||
|
#define BD_TX_HFELC (1 << 7)
|
||||||
|
#define BD_TX_CFRL (1 << 6)
|
||||||
|
#define BD_TX_RC_MASK 0xF
|
||||||
|
#define BD_TX_RC_OFFSET 0x2
|
||||||
|
#define BD_TX_TOEUN (1 << 1)
|
||||||
|
#define BD_TX_TR (1 << 0)
|
||||||
|
|
||||||
|
#define BD_RX_EMPTY (1 << 15)
|
||||||
|
#define BD_RX_RO1 (1 << 14)
|
||||||
|
#define BD_RX_FIRST (1 << 10)
|
||||||
|
#define BD_RX_MISS (1 << 8)
|
||||||
|
#define BD_RX_BROADCAST (1 << 7)
|
||||||
|
#define BD_RX_MULTICAST (1 << 6)
|
||||||
|
#define BD_RX_LG (1 << 5)
|
||||||
|
#define BD_RX_NO (1 << 4)
|
||||||
|
#define BD_RX_SH (1 << 3)
|
||||||
|
#define BD_RX_CR (1 << 2)
|
||||||
|
#define BD_RX_OV (1 << 1)
|
||||||
|
#define BD_RX_TR (1 << 0)
|
||||||
|
|
||||||
|
/* Tx FCB flags */
|
||||||
|
#define FCB_TX_VLN (1 << 7)
|
||||||
|
#define FCB_TX_IP (1 << 6)
|
||||||
|
#define FCB_TX_IP6 (1 << 5)
|
||||||
|
#define FCB_TX_TUP (1 << 4)
|
||||||
|
#define FCB_TX_UDP (1 << 3)
|
||||||
|
#define FCB_TX_CIP (1 << 2)
|
||||||
|
#define FCB_TX_CTU (1 << 1)
|
||||||
|
#define FCB_TX_NPH (1 << 0)
|
||||||
|
|
||||||
|
/* PHY Status Register */
|
||||||
|
#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
|
||||||
|
#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
|
||||||
|
#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
|
||||||
|
#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
|
||||||
|
#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
|
||||||
|
#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
|
||||||
|
#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
|
||||||
|
#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
|
||||||
|
#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
|
||||||
|
#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
|
||||||
|
#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
|
||||||
|
#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
|
||||||
|
#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
|
||||||
|
#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
|
||||||
|
#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
|
||||||
|
|
||||||
|
/* eTSEC */
|
||||||
|
|
||||||
|
/* Number of register in the device */
|
||||||
|
#define ETSEC_REG_NUMBER 1024
|
||||||
|
|
||||||
|
typedef struct eTSEC_Register {
|
||||||
|
const char *name;
|
||||||
|
const char *desc;
|
||||||
|
uint32_t access;
|
||||||
|
uint32_t value;
|
||||||
|
} eTSEC_Register;
|
||||||
|
|
||||||
|
typedef struct eTSEC {
|
||||||
|
SysBusDevice busdev;
|
||||||
|
|
||||||
|
MemoryRegion io_area;
|
||||||
|
|
||||||
|
eTSEC_Register regs[ETSEC_REG_NUMBER];
|
||||||
|
|
||||||
|
NICState *nic;
|
||||||
|
NICConf conf;
|
||||||
|
|
||||||
|
/* Tx */
|
||||||
|
|
||||||
|
uint8_t *tx_buffer;
|
||||||
|
uint32_t tx_buffer_len;
|
||||||
|
eTSEC_rxtx_bd first_bd;
|
||||||
|
|
||||||
|
/* Rx */
|
||||||
|
|
||||||
|
uint8_t *rx_buffer;
|
||||||
|
uint32_t rx_buffer_len;
|
||||||
|
uint32_t rx_remaining_data;
|
||||||
|
uint8_t rx_first_in_frame;
|
||||||
|
uint8_t rx_fcb_size;
|
||||||
|
eTSEC_rxtx_bd rx_first_bd;
|
||||||
|
uint8_t rx_fcb[10];
|
||||||
|
uint32_t rx_padding;
|
||||||
|
|
||||||
|
/* IRQs */
|
||||||
|
qemu_irq tx_irq;
|
||||||
|
qemu_irq rx_irq;
|
||||||
|
qemu_irq err_irq;
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t phy_status;
|
||||||
|
uint16_t phy_control;
|
||||||
|
|
||||||
|
/* Polling */
|
||||||
|
QEMUBH *bh;
|
||||||
|
struct ptimer_state *ptimer;
|
||||||
|
|
||||||
|
} eTSEC;
|
||||||
|
|
||||||
|
#define TYPE_ETSEC_COMMON "eTSEC"
|
||||||
|
#define ETSEC_COMMON(obj) \
|
||||||
|
OBJECT_CHECK(eTSEC, (obj), TYPE_ETSEC_COMMON)
|
||||||
|
|
||||||
|
#define eTSEC_TRANSMIT 1
|
||||||
|
#define eTSEC_RECEIVE 2
|
||||||
|
|
||||||
|
DeviceState *etsec_create(hwaddr base,
|
||||||
|
MemoryRegion *mr,
|
||||||
|
NICInfo *nd,
|
||||||
|
qemu_irq tx_irq,
|
||||||
|
qemu_irq rx_irq,
|
||||||
|
qemu_irq err_irq);
|
||||||
|
|
||||||
|
void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr);
|
||||||
|
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr);
|
||||||
|
void etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
void etsec_write_miim(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value);
|
||||||
|
|
||||||
|
void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc);
|
||||||
|
|
||||||
|
#endif /* ! _ETSEC_H_ */
|
||||||
146
hw/net/fsl_etsec/miim.c
Normal file
146
hw/net/fsl_etsec/miim.c
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Freescale eTSEC Emulator
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011-2013 AdaCore
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "etsec.h"
|
||||||
|
#include "registers.h"
|
||||||
|
|
||||||
|
/* #define DEBUG_MIIM */
|
||||||
|
|
||||||
|
#define MIIM_CONTROL 0
|
||||||
|
#define MIIM_STATUS 1
|
||||||
|
#define MIIM_PHY_ID_1 2
|
||||||
|
#define MIIM_PHY_ID_2 3
|
||||||
|
#define MIIM_T2_STATUS 10
|
||||||
|
#define MIIM_EXT_STATUS 15
|
||||||
|
|
||||||
|
static void miim_read_cycle(eTSEC *etsec)
|
||||||
|
{
|
||||||
|
uint8_t phy;
|
||||||
|
uint8_t addr;
|
||||||
|
uint16_t value;
|
||||||
|
|
||||||
|
phy = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
|
||||||
|
(void)phy; /* Unreferenced */
|
||||||
|
addr = etsec->regs[MIIMADD].value & 0x1F;
|
||||||
|
|
||||||
|
switch (addr) {
|
||||||
|
case MIIM_CONTROL:
|
||||||
|
value = etsec->phy_control;
|
||||||
|
break;
|
||||||
|
case MIIM_STATUS:
|
||||||
|
value = etsec->phy_status;
|
||||||
|
break;
|
||||||
|
case MIIM_T2_STATUS:
|
||||||
|
value = 0x1800; /* Local and remote receivers OK */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value = 0x0;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef DEBUG_MIIM
|
||||||
|
qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
etsec->regs[MIIMSTAT].value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void miim_write_cycle(eTSEC *etsec)
|
||||||
|
{
|
||||||
|
uint8_t phy;
|
||||||
|
uint8_t addr;
|
||||||
|
uint16_t value;
|
||||||
|
|
||||||
|
phy = (etsec->regs[MIIMADD].value >> 8) & 0x1F;
|
||||||
|
(void)phy; /* Unreferenced */
|
||||||
|
addr = etsec->regs[MIIMADD].value & 0x1F;
|
||||||
|
value = etsec->regs[MIIMCON].value & 0xffff;
|
||||||
|
|
||||||
|
#ifdef DEBUG_MIIM
|
||||||
|
qemu_log("%s phy:%d addr:0x%x value:0x%x\n", __func__, phy, addr, value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (addr) {
|
||||||
|
case MIIM_CONTROL:
|
||||||
|
etsec->phy_control = value & ~(0x8100);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void etsec_write_miim(eTSEC *etsec,
|
||||||
|
eTSEC_Register *reg,
|
||||||
|
uint32_t reg_index,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (reg_index) {
|
||||||
|
|
||||||
|
case MIIMCOM:
|
||||||
|
/* Read and scan cycle */
|
||||||
|
|
||||||
|
if ((!(reg->value & MIIMCOM_READ)) && (value & MIIMCOM_READ)) {
|
||||||
|
/* Read */
|
||||||
|
miim_read_cycle(etsec);
|
||||||
|
}
|
||||||
|
reg->value = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIIMCON:
|
||||||
|
reg->value = value & 0xffff;
|
||||||
|
miim_write_cycle(etsec);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Default handling */
|
||||||
|
switch (reg->access) {
|
||||||
|
|
||||||
|
case ACC_RW:
|
||||||
|
case ACC_WO:
|
||||||
|
reg->value = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACC_W1C:
|
||||||
|
reg->value &= ~value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACC_RO:
|
||||||
|
default:
|
||||||
|
/* Read Only or Unknown register */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void etsec_miim_link_status(eTSEC *etsec, NetClientState *nc)
|
||||||
|
{
|
||||||
|
/* Set link status */
|
||||||
|
if (nc->link_down) {
|
||||||
|
etsec->phy_status &= ~MII_SR_LINK_STATUS;
|
||||||
|
} else {
|
||||||
|
etsec->phy_status |= MII_SR_LINK_STATUS;
|
||||||
|
}
|
||||||
|
}
|
||||||
295
hw/net/fsl_etsec/registers.c
Normal file
295
hw/net/fsl_etsec/registers.c
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Freescale eTSEC Emulator
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011-2013 AdaCore
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "registers.h"
|
||||||
|
|
||||||
|
const eTSEC_Register_Definition eTSEC_registers_def[] = {
|
||||||
|
{0x000, "TSEC_ID", "Controller ID register", ACC_RO, 0x01240000},
|
||||||
|
{0x004, "TSEC_ID2", "Controller ID register 2", ACC_RO, 0x003000F0},
|
||||||
|
{0x010, "IEVENT", "Interrupt event register", ACC_W1C, 0x00000000},
|
||||||
|
{0x014, "IMASK", "Interrupt mask register", ACC_RW, 0x00000000},
|
||||||
|
{0x018, "EDIS", "Error disabled register", ACC_RW, 0x00000000},
|
||||||
|
{0x020, "ECNTRL", "Ethernet control register", ACC_RW, 0x00000040},
|
||||||
|
{0x028, "PTV", "Pause time value register", ACC_RW, 0x00000000},
|
||||||
|
{0x02C, "DMACTRL", "DMA control register", ACC_RW, 0x00000000},
|
||||||
|
{0x030, "TBIPA", "TBI PHY address register", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC FIFO Control and Status Registers */
|
||||||
|
|
||||||
|
{0x058, "FIFO_RX_ALARM", "FIFO receive alarm start threshold register", ACC_RW, 0x00000040},
|
||||||
|
{0x05C, "FIFO_RX_ALARM_SHUTOFF", "FIFO receive alarm shut-off threshold register", ACC_RW, 0x00000080},
|
||||||
|
{0x08C, "FIFO_TX_THR", "FIFO transmit threshold register", ACC_RW, 0x00000080},
|
||||||
|
{0x098, "FIFO_TX_STARVE", "FIFO transmit starve register", ACC_RW, 0x00000040},
|
||||||
|
{0x09C, "FIFO_TX_STARVE_SHUTOFF", "FIFO transmit starve shut-off register", ACC_RW, 0x00000080},
|
||||||
|
|
||||||
|
/* eTSEC Transmit Control and Status Registers */
|
||||||
|
|
||||||
|
{0x100, "TCTRL", "Transmit control register", ACC_RW, 0x00000000},
|
||||||
|
{0x104, "TSTAT", "Transmit status register", ACC_W1C, 0x00000000},
|
||||||
|
{0x108, "DFVLAN", "Default VLAN control word", ACC_RW, 0x81000000},
|
||||||
|
{0x110, "TXIC", "Transmit interrupt coalescing register", ACC_RW, 0x00000000},
|
||||||
|
{0x114, "TQUEUE", "Transmit queue control register", ACC_RW, 0x00008000},
|
||||||
|
{0x140, "TR03WT", "TxBD Rings 0-3 round-robin weightings", ACC_RW, 0x00000000},
|
||||||
|
{0x144, "TR47WT", "TxBD Rings 4-7 round-robin weightings", ACC_RW, 0x00000000},
|
||||||
|
{0x180, "TBDBPH", "Tx data buffer pointer high bits", ACC_RW, 0x00000000},
|
||||||
|
{0x184, "TBPTR0", "TxBD pointer for ring 0", ACC_RW, 0x00000000},
|
||||||
|
{0x18C, "TBPTR1", "TxBD pointer for ring 1", ACC_RW, 0x00000000},
|
||||||
|
{0x194, "TBPTR2", "TxBD pointer for ring 2", ACC_RW, 0x00000000},
|
||||||
|
{0x19C, "TBPTR3", "TxBD pointer for ring 3", ACC_RW, 0x00000000},
|
||||||
|
{0x1A4, "TBPTR4", "TxBD pointer for ring 4", ACC_RW, 0x00000000},
|
||||||
|
{0x1AC, "TBPTR5", "TxBD pointer for ring 5", ACC_RW, 0x00000000},
|
||||||
|
{0x1B4, "TBPTR6", "TxBD pointer for ring 6", ACC_RW, 0x00000000},
|
||||||
|
{0x1BC, "TBPTR7", "TxBD pointer for ring 7", ACC_RW, 0x00000000},
|
||||||
|
{0x200, "TBASEH", "TxBD base address high bits", ACC_RW, 0x00000000},
|
||||||
|
{0x204, "TBASE0", "TxBD base address of ring 0", ACC_RW, 0x00000000},
|
||||||
|
{0x20C, "TBASE1", "TxBD base address of ring 1", ACC_RW, 0x00000000},
|
||||||
|
{0x214, "TBASE2", "TxBD base address of ring 2", ACC_RW, 0x00000000},
|
||||||
|
{0x21C, "TBASE3", "TxBD base address of ring 3", ACC_RW, 0x00000000},
|
||||||
|
{0x224, "TBASE4", "TxBD base address of ring 4", ACC_RW, 0x00000000},
|
||||||
|
{0x22C, "TBASE5", "TxBD base address of ring 5", ACC_RW, 0x00000000},
|
||||||
|
{0x234, "TBASE6", "TxBD base address of ring 6", ACC_RW, 0x00000000},
|
||||||
|
{0x23C, "TBASE7", "TxBD base address of ring 7", ACC_RW, 0x00000000},
|
||||||
|
{0x280, "TMR_TXTS1_ID", "Tx time stamp identification tag (set 1)", ACC_RO, 0x00000000},
|
||||||
|
{0x284, "TMR_TXTS2_ID", "Tx time stamp identification tag (set 2)", ACC_RO, 0x00000000},
|
||||||
|
{0x2C0, "TMR_TXTS1_H", "Tx time stamp high (set 1)", ACC_RO, 0x00000000},
|
||||||
|
{0x2C4, "TMR_TXTS1_L", "Tx time stamp high (set 1)", ACC_RO, 0x00000000},
|
||||||
|
{0x2C8, "TMR_TXTS2_H", "Tx time stamp high (set 2)", ACC_RO, 0x00000000},
|
||||||
|
{0x2CC, "TMR_TXTS2_L", "Tx time stamp high (set 2)", ACC_RO, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC Receive Control and Status Registers */
|
||||||
|
|
||||||
|
{0x300, "RCTRL", "Receive control register", ACC_RW, 0x00000000},
|
||||||
|
{0x304, "RSTAT", "Receive status register", ACC_W1C, 0x00000000},
|
||||||
|
{0x310, "RXIC", "Receive interrupt coalescing register", ACC_RW, 0x00000000},
|
||||||
|
{0x314, "RQUEUE", "Receive queue control register.", ACC_RW, 0x00800080},
|
||||||
|
{0x330, "RBIFX", "Receive bit field extract control register", ACC_RW, 0x00000000},
|
||||||
|
{0x334, "RQFAR", "Receive queue filing table address register", ACC_RW, 0x00000000},
|
||||||
|
{0x338, "RQFCR", "Receive queue filing table control register", ACC_RW, 0x00000000},
|
||||||
|
{0x33C, "RQFPR", "Receive queue filing table property register", ACC_RW, 0x00000000},
|
||||||
|
{0x340, "MRBLR", "Maximum receive buffer length register", ACC_RW, 0x00000000},
|
||||||
|
{0x380, "RBDBPH", "Rx data buffer pointer high bits", ACC_RW, 0x00000000},
|
||||||
|
{0x384, "RBPTR0", "RxBD pointer for ring 0", ACC_RW, 0x00000000},
|
||||||
|
{0x38C, "RBPTR1", "RxBD pointer for ring 1", ACC_RW, 0x00000000},
|
||||||
|
{0x394, "RBPTR2", "RxBD pointer for ring 2", ACC_RW, 0x00000000},
|
||||||
|
{0x39C, "RBPTR3", "RxBD pointer for ring 3", ACC_RW, 0x00000000},
|
||||||
|
{0x3A4, "RBPTR4", "RxBD pointer for ring 4", ACC_RW, 0x00000000},
|
||||||
|
{0x3AC, "RBPTR5", "RxBD pointer for ring 5", ACC_RW, 0x00000000},
|
||||||
|
{0x3B4, "RBPTR6", "RxBD pointer for ring 6", ACC_RW, 0x00000000},
|
||||||
|
{0x3BC, "RBPTR7", "RxBD pointer for ring 7", ACC_RW, 0x00000000},
|
||||||
|
{0x400, "RBASEH", "RxBD base address high bits", ACC_RW, 0x00000000},
|
||||||
|
{0x404, "RBASE0", "RxBD base address of ring 0", ACC_RW, 0x00000000},
|
||||||
|
{0x40C, "RBASE1", "RxBD base address of ring 1", ACC_RW, 0x00000000},
|
||||||
|
{0x414, "RBASE2", "RxBD base address of ring 2", ACC_RW, 0x00000000},
|
||||||
|
{0x41C, "RBASE3", "RxBD base address of ring 3", ACC_RW, 0x00000000},
|
||||||
|
{0x424, "RBASE4", "RxBD base address of ring 4", ACC_RW, 0x00000000},
|
||||||
|
{0x42C, "RBASE5", "RxBD base address of ring 5", ACC_RW, 0x00000000},
|
||||||
|
{0x434, "RBASE6", "RxBD base address of ring 6", ACC_RW, 0x00000000},
|
||||||
|
{0x43C, "RBASE7", "RxBD base address of ring 7", ACC_RW, 0x00000000},
|
||||||
|
{0x4C0, "TMR_RXTS_H", "Rx timer time stamp register high", ACC_RW, 0x00000000},
|
||||||
|
{0x4C4, "TMR_RXTS_L", "Rx timer time stamp register low", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC MAC Registers */
|
||||||
|
|
||||||
|
{0x500, "MACCFG1", "MAC configuration register 1", ACC_RW, 0x00000000},
|
||||||
|
{0x504, "MACCFG2", "MAC configuration register 2", ACC_RW, 0x00007000},
|
||||||
|
{0x508, "IPGIFG", "Inter-packet/inter-frame gap register", ACC_RW, 0x40605060},
|
||||||
|
{0x50C, "HAFDUP", "Half-duplex control", ACC_RW, 0x00A1F037},
|
||||||
|
{0x510, "MAXFRM", "Maximum frame length", ACC_RW, 0x00000600},
|
||||||
|
{0x520, "MIIMCFG", "MII management configuration", ACC_RW, 0x00000007},
|
||||||
|
{0x524, "MIIMCOM", "MII management command", ACC_RW, 0x00000000},
|
||||||
|
{0x528, "MIIMADD", "MII management address", ACC_RW, 0x00000000},
|
||||||
|
{0x52C, "MIIMCON", "MII management control", ACC_WO, 0x00000000},
|
||||||
|
{0x530, "MIIMSTAT", "MII management status", ACC_RO, 0x00000000},
|
||||||
|
{0x534, "MIIMIND", "MII management indicator", ACC_RO, 0x00000000},
|
||||||
|
{0x53C, "IFSTAT", "Interface status", ACC_RO, 0x00000000},
|
||||||
|
{0x540, "MACSTNADDR1", "MAC station address register 1", ACC_RW, 0x00000000},
|
||||||
|
{0x544, "MACSTNADDR2", "MAC station address register 2", ACC_RW, 0x00000000},
|
||||||
|
{0x548, "MAC01ADDR1", "MAC exact match address 1, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x54C, "MAC01ADDR2", "MAC exact match address 1, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x550, "MAC02ADDR1", "MAC exact match address 2, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x554, "MAC02ADDR2", "MAC exact match address 2, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x558, "MAC03ADDR1", "MAC exact match address 3, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x55C, "MAC03ADDR2", "MAC exact match address 3, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x560, "MAC04ADDR1", "MAC exact match address 4, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x564, "MAC04ADDR2", "MAC exact match address 4, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x568, "MAC05ADDR1", "MAC exact match address 5, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x56C, "MAC05ADDR2", "MAC exact match address 5, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x570, "MAC06ADDR1", "MAC exact match address 6, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x574, "MAC06ADDR2", "MAC exact match address 6, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x578, "MAC07ADDR1", "MAC exact match address 7, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x57C, "MAC07ADDR2", "MAC exact match address 7, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x580, "MAC08ADDR1", "MAC exact match address 8, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x584, "MAC08ADDR2", "MAC exact match address 8, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x588, "MAC09ADDR1", "MAC exact match address 9, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x58C, "MAC09ADDR2", "MAC exact match address 9, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x590, "MAC10ADDR1", "MAC exact match address 10, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x594, "MAC10ADDR2", "MAC exact match address 10, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x598, "MAC11ADDR1", "MAC exact match address 11, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x59C, "MAC11ADDR2", "MAC exact match address 11, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x5A0, "MAC12ADDR1", "MAC exact match address 12, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x5A4, "MAC12ADDR2", "MAC exact match address 12, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x5A8, "MAC13ADDR1", "MAC exact match address 13, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x5AC, "MAC13ADDR2", "MAC exact match address 13, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x5B0, "MAC14ADDR1", "MAC exact match address 14, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x5B4, "MAC14ADDR2", "MAC exact match address 14, part 2", ACC_RW, 0x00000000},
|
||||||
|
{0x5B8, "MAC15ADDR1", "MAC exact match address 15, part 1", ACC_RW, 0x00000000},
|
||||||
|
{0x5BC, "MAC15ADDR2", "MAC exact match address 15, part 2", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC, "Transmit", "and", Receive, Counters */
|
||||||
|
|
||||||
|
{0x680, "TR64", "Transmit and receive 64-byte frame counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x684, "TR127", "Transmit and receive 65- to 127-byte frame counter", ACC_RW, 0x00000000},
|
||||||
|
{0x688, "TR255", "Transmit and receive 128- to 255-byte frame counter", ACC_RW, 0x00000000},
|
||||||
|
{0x68C, "TR511", "Transmit and receive 256- to 511-byte frame counter", ACC_RW, 0x00000000},
|
||||||
|
{0x690, "TR1K", "Transmit and receive 512- to 1023-byte frame counter", ACC_RW, 0x00000000},
|
||||||
|
{0x694, "TRMAX", "Transmit and receive 1024- to 1518-byte frame counter", ACC_RW, 0x00000000},
|
||||||
|
{0x698, "TRMGV", "Transmit and receive 1519- to 1522-byte good VLAN frame count", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC Receive Counters */
|
||||||
|
|
||||||
|
{0x69C, "RBYT", "Receive byte counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6A0, "RPKT", "Receive packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6A4, "RFCS", "Receive FCS error counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6A8, "RMCA", "Receive multicast packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6AC, "RBCA", "Receive broadcast packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6B0, "RXCF", "Receive control frame packet counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6B4, "RXPF", "Receive PAUSE frame packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6B8, "RXUO", "Receive unknown OP code counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6BC, "RALN", "Receive alignment error counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6C0, "RFLR", "Receive frame length error counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6C4, "RCDE", "Receive code error counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6C8, "RCSE", "Receive carrier sense error counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6CC, "RUND", "Receive undersize packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6D0, "ROVR", "Receive oversize packet counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6D4, "RFRG", "Receive fragments counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6D8, "RJBR", "Receive jabber counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6DC, "RDRP", "Receive drop counter", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC Transmit Counters */
|
||||||
|
|
||||||
|
{0x6E0, "TBYT", "Transmit byte counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6E4, "TPKT", "Transmit packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x6E8, "TMCA", "Transmit multicast packet counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6EC, "TBCA", "Transmit broadcast packet counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6F0, "TXPF", "Transmit PAUSE control frame counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6F4, "TDFR", "Transmit deferral packet counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6F8, "TEDF", "Transmit excessive deferral packet counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x6FC, "TSCL", "Transmit single collision packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x700, "TMCL", "Transmit multiple collision packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x704, "TLCL", "Transmit late collision packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x708, "TXCL", "Transmit excessive collision packet counter", ACC_RW, 0x00000000},
|
||||||
|
{0x70C, "TNCL", "Transmit total collision counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x714, "TDRP", "Transmit drop frame counter", ACC_RW, 0x00000000},
|
||||||
|
{0x718, "TJBR", "Transmit jabber frame counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x71C, "TFCS", "Transmit FCS error counter", ACC_RW, 0x00000000},
|
||||||
|
{0x720, "TXCF", "Transmit control frame counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x724, "TOVR", "Transmit oversize frame counter", ACC_RW, 0x00000000},
|
||||||
|
{0x728, "TUND", "Transmit undersize frame counter ", ACC_RW, 0x00000000},
|
||||||
|
{0x72C, "TFRG", "Transmit fragments frame counter ", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC Counter Control and TOE Statistics Registers */
|
||||||
|
|
||||||
|
{0x730, "CAR1", "Carry register one register", ACC_W1C, 0x00000000},
|
||||||
|
{0x734, "CAR2", "Carry register two register ", ACC_W1C, 0x00000000},
|
||||||
|
{0x738, "CAM1", "Carry register one mask register ", ACC_RW, 0xFE03FFFF},
|
||||||
|
{0x73C, "CAM2", "Carry register two mask register ", ACC_RW, 0x000FFFFD},
|
||||||
|
{0x740, "RREJ", "Receive filer rejected packet counter", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* Hash Function Registers */
|
||||||
|
|
||||||
|
{0x800, "IGADDR0", "Individual/group address register 0", ACC_RW, 0x00000000},
|
||||||
|
{0x804, "IGADDR1", "Individual/group address register 1", ACC_RW, 0x00000000},
|
||||||
|
{0x808, "IGADDR2", "Individual/group address register 2", ACC_RW, 0x00000000},
|
||||||
|
{0x80C, "IGADDR3", "Individual/group address register 3", ACC_RW, 0x00000000},
|
||||||
|
{0x810, "IGADDR4", "Individual/group address register 4", ACC_RW, 0x00000000},
|
||||||
|
{0x814, "IGADDR5", "Individual/group address register 5", ACC_RW, 0x00000000},
|
||||||
|
{0x818, "IGADDR6", "Individual/group address register 6", ACC_RW, 0x00000000},
|
||||||
|
{0x81C, "IGADDR7", "Individual/group address register 7", ACC_RW, 0x00000000},
|
||||||
|
{0x880, "GADDR0", "Group address register 0", ACC_RW, 0x00000000},
|
||||||
|
{0x884, "GADDR1", "Group address register 1", ACC_RW, 0x00000000},
|
||||||
|
{0x888, "GADDR2", "Group address register 2", ACC_RW, 0x00000000},
|
||||||
|
{0x88C, "GADDR3", "Group address register 3", ACC_RW, 0x00000000},
|
||||||
|
{0x890, "GADDR4", "Group address register 4", ACC_RW, 0x00000000},
|
||||||
|
{0x894, "GADDR5", "Group address register 5", ACC_RW, 0x00000000},
|
||||||
|
{0x898, "GADDR6", "Group address register 6", ACC_RW, 0x00000000},
|
||||||
|
{0x89C, "GADDR7", "Group address register 7", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC DMA Attribute Registers */
|
||||||
|
|
||||||
|
{0xBF8, "ATTR", "Attribute register", ACC_RW, 0x00000000},
|
||||||
|
{0xBFC, "ATTRELI", "Attribute extract length and extract index register", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
|
||||||
|
/* eTSEC Lossless Flow Control Registers */
|
||||||
|
|
||||||
|
{0xC00, "RQPRM0", "Receive Queue Parameters register 0 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC04, "RQPRM1", "Receive Queue Parameters register 1 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC08, "RQPRM2", "Receive Queue Parameters register 2 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC0C, "RQPRM3", "Receive Queue Parameters register 3 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC10, "RQPRM4", "Receive Queue Parameters register 4 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC14, "RQPRM5", "Receive Queue Parameters register 5 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC18, "RQPRM6", "Receive Queue Parameters register 6 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC1C, "RQPRM7", "Receive Queue Parameters register 7 ", ACC_RW, 0x00000000},
|
||||||
|
{0xC44, "RFBPTR0", "Last Free RxBD pointer for ring 0", ACC_RW, 0x00000000},
|
||||||
|
{0xC4C, "RFBPTR1", "Last Free RxBD pointer for ring 1", ACC_RW, 0x00000000},
|
||||||
|
{0xC54, "RFBPTR2", "Last Free RxBD pointer for ring 2", ACC_RW, 0x00000000},
|
||||||
|
{0xC5C, "RFBPTR3", "Last Free RxBD pointer for ring 3", ACC_RW, 0x00000000},
|
||||||
|
{0xC64, "RFBPTR4", "Last Free RxBD pointer for ring 4", ACC_RW, 0x00000000},
|
||||||
|
{0xC6C, "RFBPTR5", "Last Free RxBD pointer for ring 5", ACC_RW, 0x00000000},
|
||||||
|
{0xC74, "RFBPTR6", "Last Free RxBD pointer for ring 6", ACC_RW, 0x00000000},
|
||||||
|
{0xC7C, "RFBPTR7", "Last Free RxBD pointer for ring 7", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* eTSEC Future Expansion Space */
|
||||||
|
|
||||||
|
/* Reserved*/
|
||||||
|
|
||||||
|
/* eTSEC IEEE 1588 Registers */
|
||||||
|
|
||||||
|
{0xE00, "TMR_CTRL", "Timer control register", ACC_RW, 0x00010001},
|
||||||
|
{0xE04, "TMR_TEVENT", "time stamp event register", ACC_W1C, 0x00000000},
|
||||||
|
{0xE08, "TMR_TEMASK", "Timer event mask register", ACC_RW, 0x00000000},
|
||||||
|
{0xE0C, "TMR_PEVENT", "time stamp event register", ACC_RW, 0x00000000},
|
||||||
|
{0xE10, "TMR_PEMASK", "Timer event mask register", ACC_RW, 0x00000000},
|
||||||
|
{0xE14, "TMR_STAT", "time stamp status register", ACC_RW, 0x00000000},
|
||||||
|
{0xE18, "TMR_CNT_H", "timer counter high register", ACC_RW, 0x00000000},
|
||||||
|
{0xE1C, "TMR_CNT_L", "timer counter low register", ACC_RW, 0x00000000},
|
||||||
|
{0xE20, "TMR_ADD", "Timer drift compensation addend register", ACC_RW, 0x00000000},
|
||||||
|
{0xE24, "TMR_ACC", "Timer accumulator register", ACC_RW, 0x00000000},
|
||||||
|
{0xE28, "TMR_PRSC", "Timer prescale", ACC_RW, 0x00000002},
|
||||||
|
{0xE30, "TMROFF_H", "Timer offset high", ACC_RW, 0x00000000},
|
||||||
|
{0xE34, "TMROFF_L", "Timer offset low", ACC_RW, 0x00000000},
|
||||||
|
{0xE40, "TMR_ALARM1_H", "Timer alarm 1 high register", ACC_RW, 0xFFFFFFFF},
|
||||||
|
{0xE44, "TMR_ALARM1_L", "Timer alarm 1 high register", ACC_RW, 0xFFFFFFFF},
|
||||||
|
{0xE48, "TMR_ALARM2_H", "Timer alarm 2 high register", ACC_RW, 0xFFFFFFFF},
|
||||||
|
{0xE4C, "TMR_ALARM2_L", "Timer alarm 2 high register", ACC_RW, 0xFFFFFFFF},
|
||||||
|
{0xE80, "TMR_FIPER1", "Timer fixed period interval", ACC_RW, 0xFFFFFFFF},
|
||||||
|
{0xE84, "TMR_FIPER2", "Timer fixed period interval", ACC_RW, 0xFFFFFFFF},
|
||||||
|
{0xE88, "TMR_FIPER3", "Timer fixed period interval", ACC_RW, 0xFFFFFFFF},
|
||||||
|
{0xEA0, "TMR_ETTS1_H", "Time stamp of general purpose external trigger ", ACC_RW, 0x00000000},
|
||||||
|
{0xEA4, "TMR_ETTS1_L", "Time stamp of general purpose external trigger", ACC_RW, 0x00000000},
|
||||||
|
{0xEA8, "TMR_ETTS2_H", "Time stamp of general purpose external trigger ", ACC_RW, 0x00000000},
|
||||||
|
{0xEAC, "TMR_ETTS2_L", "Time stamp of general purpose external trigger", ACC_RW, 0x00000000},
|
||||||
|
|
||||||
|
/* End Of Table */
|
||||||
|
{0x0, 0x0, 0x0, 0x0, 0x0}
|
||||||
|
};
|
||||||
320
hw/net/fsl_etsec/registers.h
Normal file
320
hw/net/fsl_etsec/registers.h
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Freescale eTSEC Emulator
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011-2013 AdaCore
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef _ETSEC_REGISTERS_H_
|
||||||
|
#define _ETSEC_REGISTERS_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum eTSEC_Register_Access_Type {
|
||||||
|
ACC_RW = 1, /* Read/Write */
|
||||||
|
ACC_RO = 2, /* Read Only */
|
||||||
|
ACC_WO = 3, /* Write Only */
|
||||||
|
ACC_W1C = 4, /* Write 1 to clear */
|
||||||
|
ACC_UNKNOWN = 5 /* Unknown register*/
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct eTSEC_Register_Definition {
|
||||||
|
uint32_t offset;
|
||||||
|
const char *name;
|
||||||
|
const char *desc;
|
||||||
|
enum eTSEC_Register_Access_Type access;
|
||||||
|
uint32_t reset;
|
||||||
|
} eTSEC_Register_Definition;
|
||||||
|
|
||||||
|
extern const eTSEC_Register_Definition eTSEC_registers_def[];
|
||||||
|
|
||||||
|
#define DMACTRL_LE (1 << 15)
|
||||||
|
#define DMACTRL_GRS (1 << 4)
|
||||||
|
#define DMACTRL_GTS (1 << 3)
|
||||||
|
#define DMACTRL_WOP (1 << 0)
|
||||||
|
|
||||||
|
#define IEVENT_PERR (1 << 0)
|
||||||
|
#define IEVENT_DPE (1 << 1)
|
||||||
|
#define IEVENT_FIQ (1 << 2)
|
||||||
|
#define IEVENT_FIR (1 << 3)
|
||||||
|
#define IEVENT_FGPI (1 << 4)
|
||||||
|
#define IEVENT_RXF (1 << 7)
|
||||||
|
#define IEVENT_GRSC (1 << 8)
|
||||||
|
#define IEVENT_MMRW (1 << 9)
|
||||||
|
#define IEVENT_MMRD (1 << 10)
|
||||||
|
#define IEVENT_MAG (1 << 11)
|
||||||
|
#define IEVENT_RXB (1 << 15)
|
||||||
|
#define IEVENT_XFUN (1 << 16)
|
||||||
|
#define IEVENT_CRL (1 << 17)
|
||||||
|
#define IEVENT_LC (1 << 18)
|
||||||
|
#define IEVENT_TXF (1 << 20)
|
||||||
|
#define IEVENT_TXB (1 << 21)
|
||||||
|
#define IEVENT_TXE (1 << 22)
|
||||||
|
#define IEVENT_TXC (1 << 23)
|
||||||
|
#define IEVENT_BABT (1 << 24)
|
||||||
|
#define IEVENT_GTSC (1 << 25)
|
||||||
|
#define IEVENT_MSRO (1 << 26)
|
||||||
|
#define IEVENT_EBERR (1 << 28)
|
||||||
|
#define IEVENT_BSY (1 << 29)
|
||||||
|
#define IEVENT_RXC (1 << 30)
|
||||||
|
#define IEVENT_BABR (1 << 31)
|
||||||
|
|
||||||
|
#define IMASK_RXFEN (1 << 7)
|
||||||
|
#define IMASK_GRSCEN (1 << 8)
|
||||||
|
#define IMASK_RXBEN (1 << 15)
|
||||||
|
#define IMASK_TXFEN (1 << 20)
|
||||||
|
#define IMASK_TXBEN (1 << 21)
|
||||||
|
#define IMASK_GTSCEN (1 << 25)
|
||||||
|
|
||||||
|
#define MACCFG1_TX_EN (1 << 0)
|
||||||
|
#define MACCFG1_RX_EN (1 << 2)
|
||||||
|
|
||||||
|
#define MACCFG2_CRC_EN (1 << 1)
|
||||||
|
#define MACCFG2_PADCRC (1 << 2)
|
||||||
|
|
||||||
|
#define MIIMCOM_READ (1 << 0)
|
||||||
|
#define MIIMCOM_SCAN (1 << 1)
|
||||||
|
|
||||||
|
#define RCTRL_PRSDEP_MASK (0x3)
|
||||||
|
#define RCTRL_PRSDEP_OFFSET (6)
|
||||||
|
#define RCTRL_RSF (1 << 2)
|
||||||
|
|
||||||
|
/* Index of each register */
|
||||||
|
|
||||||
|
#define TSEC_ID (0x000 / 4)
|
||||||
|
#define TSEC_ID2 (0x004 / 4)
|
||||||
|
#define IEVENT (0x010 / 4)
|
||||||
|
#define IMASK (0x014 / 4)
|
||||||
|
#define EDIS (0x018 / 4)
|
||||||
|
#define ECNTRL (0x020 / 4)
|
||||||
|
#define PTV (0x028 / 4)
|
||||||
|
#define DMACTRL (0x02C / 4)
|
||||||
|
#define TBIPA (0x030 / 4)
|
||||||
|
#define TCTRL (0x100 / 4)
|
||||||
|
#define TSTAT (0x104 / 4)
|
||||||
|
#define DFVLAN (0x108 / 4)
|
||||||
|
#define TXIC (0x110 / 4)
|
||||||
|
#define TQUEUE (0x114 / 4)
|
||||||
|
#define TR03WT (0x140 / 4)
|
||||||
|
#define TR47WT (0x144 / 4)
|
||||||
|
#define TBDBPH (0x180 / 4)
|
||||||
|
#define TBPTR0 (0x184 / 4)
|
||||||
|
#define TBPTR1 (0x18C / 4)
|
||||||
|
#define TBPTR2 (0x194 / 4)
|
||||||
|
#define TBPTR3 (0x19C / 4)
|
||||||
|
#define TBPTR4 (0x1A4 / 4)
|
||||||
|
#define TBPTR5 (0x1AC / 4)
|
||||||
|
#define TBPTR6 (0x1B4 / 4)
|
||||||
|
#define TBPTR7 (0x1BC / 4)
|
||||||
|
#define TBASEH (0x200 / 4)
|
||||||
|
#define TBASE0 (0x204 / 4)
|
||||||
|
#define TBASE1 (0x20C / 4)
|
||||||
|
#define TBASE2 (0x214 / 4)
|
||||||
|
#define TBASE3 (0x21C / 4)
|
||||||
|
#define TBASE4 (0x224 / 4)
|
||||||
|
#define TBASE5 (0x22C / 4)
|
||||||
|
#define TBASE6 (0x234 / 4)
|
||||||
|
#define TBASE7 (0x23C / 4)
|
||||||
|
#define TMR_TXTS1_ID (0x280 / 4)
|
||||||
|
#define TMR_TXTS2_ID (0x284 / 4)
|
||||||
|
#define TMR_TXTS1_H (0x2C0 / 4)
|
||||||
|
#define TMR_TXTS1_L (0x2C4 / 4)
|
||||||
|
#define TMR_TXTS2_H (0x2C8 / 4)
|
||||||
|
#define TMR_TXTS2_L (0x2CC / 4)
|
||||||
|
#define RCTRL (0x300 / 4)
|
||||||
|
#define RSTAT (0x304 / 4)
|
||||||
|
#define RXIC (0x310 / 4)
|
||||||
|
#define RQUEUE (0x314 / 4)
|
||||||
|
#define RBIFX (0x330 / 4)
|
||||||
|
#define RQFAR (0x334 / 4)
|
||||||
|
#define RQFCR (0x338 / 4)
|
||||||
|
#define RQFPR (0x33C / 4)
|
||||||
|
#define MRBLR (0x340 / 4)
|
||||||
|
#define RBDBPH (0x380 / 4)
|
||||||
|
#define RBPTR0 (0x384 / 4)
|
||||||
|
#define RBPTR1 (0x38C / 4)
|
||||||
|
#define RBPTR2 (0x394 / 4)
|
||||||
|
#define RBPTR3 (0x39C / 4)
|
||||||
|
#define RBPTR4 (0x3A4 / 4)
|
||||||
|
#define RBPTR5 (0x3AC / 4)
|
||||||
|
#define RBPTR6 (0x3B4 / 4)
|
||||||
|
#define RBPTR7 (0x3BC / 4)
|
||||||
|
#define RBASEH (0x400 / 4)
|
||||||
|
#define RBASE0 (0x404 / 4)
|
||||||
|
#define RBASE1 (0x40C / 4)
|
||||||
|
#define RBASE2 (0x414 / 4)
|
||||||
|
#define RBASE3 (0x41C / 4)
|
||||||
|
#define RBASE4 (0x424 / 4)
|
||||||
|
#define RBASE5 (0x42C / 4)
|
||||||
|
#define RBASE6 (0x434 / 4)
|
||||||
|
#define RBASE7 (0x43C / 4)
|
||||||
|
#define TMR_RXTS_H (0x4C0 / 4)
|
||||||
|
#define TMR_RXTS_L (0x4C4 / 4)
|
||||||
|
#define MACCFG1 (0x500 / 4)
|
||||||
|
#define MACCFG2 (0x504 / 4)
|
||||||
|
#define IPGIFG (0x508 / 4)
|
||||||
|
#define HAFDUP (0x50C / 4)
|
||||||
|
#define MAXFRM (0x510 / 4)
|
||||||
|
#define MIIMCFG (0x520 / 4)
|
||||||
|
#define MIIMCOM (0x524 / 4)
|
||||||
|
#define MIIMADD (0x528 / 4)
|
||||||
|
#define MIIMCON (0x52C / 4)
|
||||||
|
#define MIIMSTAT (0x530 / 4)
|
||||||
|
#define MIIMIND (0x534 / 4)
|
||||||
|
#define IFSTAT (0x53C / 4)
|
||||||
|
#define MACSTNADDR1 (0x540 / 4)
|
||||||
|
#define MACSTNADDR2 (0x544 / 4)
|
||||||
|
#define MAC01ADDR1 (0x548 / 4)
|
||||||
|
#define MAC01ADDR2 (0x54C / 4)
|
||||||
|
#define MAC02ADDR1 (0x550 / 4)
|
||||||
|
#define MAC02ADDR2 (0x554 / 4)
|
||||||
|
#define MAC03ADDR1 (0x558 / 4)
|
||||||
|
#define MAC03ADDR2 (0x55C / 4)
|
||||||
|
#define MAC04ADDR1 (0x560 / 4)
|
||||||
|
#define MAC04ADDR2 (0x564 / 4)
|
||||||
|
#define MAC05ADDR1 (0x568 / 4)
|
||||||
|
#define MAC05ADDR2 (0x56C / 4)
|
||||||
|
#define MAC06ADDR1 (0x570 / 4)
|
||||||
|
#define MAC06ADDR2 (0x574 / 4)
|
||||||
|
#define MAC07ADDR1 (0x578 / 4)
|
||||||
|
#define MAC07ADDR2 (0x57C / 4)
|
||||||
|
#define MAC08ADDR1 (0x580 / 4)
|
||||||
|
#define MAC08ADDR2 (0x584 / 4)
|
||||||
|
#define MAC09ADDR1 (0x588 / 4)
|
||||||
|
#define MAC09ADDR2 (0x58C / 4)
|
||||||
|
#define MAC10ADDR1 (0x590 / 4)
|
||||||
|
#define MAC10ADDR2 (0x594 / 4)
|
||||||
|
#define MAC11ADDR1 (0x598 / 4)
|
||||||
|
#define MAC11ADDR2 (0x59C / 4)
|
||||||
|
#define MAC12ADDR1 (0x5A0 / 4)
|
||||||
|
#define MAC12ADDR2 (0x5A4 / 4)
|
||||||
|
#define MAC13ADDR1 (0x5A8 / 4)
|
||||||
|
#define MAC13ADDR2 (0x5AC / 4)
|
||||||
|
#define MAC14ADDR1 (0x5B0 / 4)
|
||||||
|
#define MAC14ADDR2 (0x5B4 / 4)
|
||||||
|
#define MAC15ADDR1 (0x5B8 / 4)
|
||||||
|
#define MAC15ADDR2 (0x5BC / 4)
|
||||||
|
#define TR64 (0x680 / 4)
|
||||||
|
#define TR127 (0x684 / 4)
|
||||||
|
#define TR255 (0x688 / 4)
|
||||||
|
#define TR511 (0x68C / 4)
|
||||||
|
#define TR1K (0x690 / 4)
|
||||||
|
#define TRMAX (0x694 / 4)
|
||||||
|
#define TRMGV (0x698 / 4)
|
||||||
|
#define RBYT (0x69C / 4)
|
||||||
|
#define RPKT (0x6A0 / 4)
|
||||||
|
#define RFCS (0x6A4 / 4)
|
||||||
|
#define RMCA (0x6A8 / 4)
|
||||||
|
#define RBCA (0x6AC / 4)
|
||||||
|
#define RXCF (0x6B0 / 4)
|
||||||
|
#define RXPF (0x6B4 / 4)
|
||||||
|
#define RXUO (0x6B8 / 4)
|
||||||
|
#define RALN (0x6BC / 4)
|
||||||
|
#define RFLR (0x6C0 / 4)
|
||||||
|
#define RCDE (0x6C4 / 4)
|
||||||
|
#define RCSE (0x6C8 / 4)
|
||||||
|
#define RUND (0x6CC / 4)
|
||||||
|
#define ROVR (0x6D0 / 4)
|
||||||
|
#define RFRG (0x6D4 / 4)
|
||||||
|
#define RJBR (0x6D8 / 4)
|
||||||
|
#define RDRP (0x6DC / 4)
|
||||||
|
#define TBYT (0x6E0 / 4)
|
||||||
|
#define TPKT (0x6E4 / 4)
|
||||||
|
#define TMCA (0x6E8 / 4)
|
||||||
|
#define TBCA (0x6EC / 4)
|
||||||
|
#define TXPF (0x6F0 / 4)
|
||||||
|
#define TDFR (0x6F4 / 4)
|
||||||
|
#define TEDF (0x6F8 / 4)
|
||||||
|
#define TSCL (0x6FC / 4)
|
||||||
|
#define TMCL (0x700 / 4)
|
||||||
|
#define TLCL (0x704 / 4)
|
||||||
|
#define TXCL (0x708 / 4)
|
||||||
|
#define TNCL (0x70C / 4)
|
||||||
|
#define TDRP (0x714 / 4)
|
||||||
|
#define TJBR (0x718 / 4)
|
||||||
|
#define TFCS (0x71C / 4)
|
||||||
|
#define TXCF (0x720 / 4)
|
||||||
|
#define TOVR (0x724 / 4)
|
||||||
|
#define TUND (0x728 / 4)
|
||||||
|
#define TFRG (0x72C / 4)
|
||||||
|
#define CAR1 (0x730 / 4)
|
||||||
|
#define CAR2 (0x734 / 4)
|
||||||
|
#define CAM1 (0x738 / 4)
|
||||||
|
#define CAM2 (0x73C / 4)
|
||||||
|
#define RREJ (0x740 / 4)
|
||||||
|
#define IGADDR0 (0x800 / 4)
|
||||||
|
#define IGADDR1 (0x804 / 4)
|
||||||
|
#define IGADDR2 (0x808 / 4)
|
||||||
|
#define IGADDR3 (0x80C / 4)
|
||||||
|
#define IGADDR4 (0x810 / 4)
|
||||||
|
#define IGADDR5 (0x814 / 4)
|
||||||
|
#define IGADDR6 (0x818 / 4)
|
||||||
|
#define IGADDR7 (0x81C / 4)
|
||||||
|
#define GADDR0 (0x880 / 4)
|
||||||
|
#define GADDR1 (0x884 / 4)
|
||||||
|
#define GADDR2 (0x888 / 4)
|
||||||
|
#define GADDR3 (0x88C / 4)
|
||||||
|
#define GADDR4 (0x890 / 4)
|
||||||
|
#define GADDR5 (0x894 / 4)
|
||||||
|
#define GADDR6 (0x898 / 4)
|
||||||
|
#define GADDR7 (0x89C / 4)
|
||||||
|
#define ATTR (0xBF8 / 4)
|
||||||
|
#define ATTRELI (0xBFC / 4)
|
||||||
|
#define RQPRM0 (0xC00 / 4)
|
||||||
|
#define RQPRM1 (0xC04 / 4)
|
||||||
|
#define RQPRM2 (0xC08 / 4)
|
||||||
|
#define RQPRM3 (0xC0C / 4)
|
||||||
|
#define RQPRM4 (0xC10 / 4)
|
||||||
|
#define RQPRM5 (0xC14 / 4)
|
||||||
|
#define RQPRM6 (0xC18 / 4)
|
||||||
|
#define RQPRM7 (0xC1C / 4)
|
||||||
|
#define RFBPTR0 (0xC44 / 4)
|
||||||
|
#define RFBPTR1 (0xC4C / 4)
|
||||||
|
#define RFBPTR2 (0xC54 / 4)
|
||||||
|
#define RFBPTR3 (0xC5C / 4)
|
||||||
|
#define RFBPTR4 (0xC64 / 4)
|
||||||
|
#define RFBPTR5 (0xC6C / 4)
|
||||||
|
#define RFBPTR6 (0xC74 / 4)
|
||||||
|
#define RFBPTR7 (0xC7C / 4)
|
||||||
|
#define TMR_CTRL (0xE00 / 4)
|
||||||
|
#define TMR_TEVENT (0xE04 / 4)
|
||||||
|
#define TMR_TEMASK (0xE08 / 4)
|
||||||
|
#define TMR_PEVENT (0xE0C / 4)
|
||||||
|
#define TMR_PEMASK (0xE10 / 4)
|
||||||
|
#define TMR_STAT (0xE14 / 4)
|
||||||
|
#define TMR_CNT_H (0xE18 / 4)
|
||||||
|
#define TMR_CNT_L (0xE1C / 4)
|
||||||
|
#define TMR_ADD (0xE20 / 4)
|
||||||
|
#define TMR_ACC (0xE24 / 4)
|
||||||
|
#define TMR_PRSC (0xE28 / 4)
|
||||||
|
#define TMROFF_H (0xE30 / 4)
|
||||||
|
#define TMROFF_L (0xE34 / 4)
|
||||||
|
#define TMR_ALARM1_H (0xE40 / 4)
|
||||||
|
#define TMR_ALARM1_L (0xE44 / 4)
|
||||||
|
#define TMR_ALARM2_H (0xE48 / 4)
|
||||||
|
#define TMR_ALARM2_L (0xE4C / 4)
|
||||||
|
#define TMR_FIPER1 (0xE80 / 4)
|
||||||
|
#define TMR_FIPER2 (0xE84 / 4)
|
||||||
|
#define TMR_FIPER3 (0xE88 / 4)
|
||||||
|
#define TMR_ETTS1_H (0xEA0 / 4)
|
||||||
|
#define TMR_ETTS1_L (0xEA4 / 4)
|
||||||
|
#define TMR_ETTS2_H (0xEA8 / 4)
|
||||||
|
#define TMR_ETTS2_L (0xEAC / 4)
|
||||||
|
|
||||||
|
#endif /* ! _ETSEC_REGISTERS_H_ */
|
||||||
650
hw/net/fsl_etsec/rings.c
Normal file
650
hw/net/fsl_etsec/rings.c
Normal file
@@ -0,0 +1,650 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Freescale eTSEC Emulator
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011-2013 AdaCore
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "net/checksum.h"
|
||||||
|
|
||||||
|
#include "etsec.h"
|
||||||
|
#include "registers.h"
|
||||||
|
|
||||||
|
/* #define ETSEC_RING_DEBUG */
|
||||||
|
/* #define HEX_DUMP */
|
||||||
|
/* #define DEBUG_BD */
|
||||||
|
|
||||||
|
#ifdef ETSEC_RING_DEBUG
|
||||||
|
static const int debug_etsec = 1;
|
||||||
|
#else
|
||||||
|
static const int debug_etsec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RING_DEBUG(fmt, ...) do { \
|
||||||
|
if (debug_etsec) { \
|
||||||
|
qemu_log(fmt , ## __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#ifdef DEBUG_BD
|
||||||
|
|
||||||
|
static void print_tx_bd_flags(uint16_t flags)
|
||||||
|
{
|
||||||
|
qemu_log(" Ready: %d\n", !!(flags & BD_TX_READY));
|
||||||
|
qemu_log(" PAD/CRC: %d\n", !!(flags & BD_TX_PADCRC));
|
||||||
|
qemu_log(" Wrap: %d\n", !!(flags & BD_WRAP));
|
||||||
|
qemu_log(" Interrupt: %d\n", !!(flags & BD_INTERRUPT));
|
||||||
|
qemu_log(" Last in frame: %d\n", !!(flags & BD_LAST));
|
||||||
|
qemu_log(" Tx CRC: %d\n", !!(flags & BD_TX_TC));
|
||||||
|
qemu_log(" User-defined preamble / defer: %d\n",
|
||||||
|
!!(flags & BD_TX_PREDEF));
|
||||||
|
qemu_log(" Huge frame enable / Late collision: %d\n",
|
||||||
|
!!(flags & BD_TX_HFELC));
|
||||||
|
qemu_log(" Control frame / Retransmission Limit: %d\n",
|
||||||
|
!!(flags & BD_TX_CFRL));
|
||||||
|
qemu_log(" Retry count: %d\n",
|
||||||
|
(flags >> BD_TX_RC_OFFSET) & BD_TX_RC_MASK);
|
||||||
|
qemu_log(" Underrun / TCP/IP off-load enable: %d\n",
|
||||||
|
!!(flags & BD_TX_TOEUN));
|
||||||
|
qemu_log(" Truncation: %d\n", !!(flags & BD_TX_TR));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_rx_bd_flags(uint16_t flags)
|
||||||
|
{
|
||||||
|
qemu_log(" Empty: %d\n", !!(flags & BD_RX_EMPTY));
|
||||||
|
qemu_log(" Receive software ownership: %d\n", !!(flags & BD_RX_RO1));
|
||||||
|
qemu_log(" Wrap: %d\n", !!(flags & BD_WRAP));
|
||||||
|
qemu_log(" Interrupt: %d\n", !!(flags & BD_INTERRUPT));
|
||||||
|
qemu_log(" Last in frame: %d\n", !!(flags & BD_LAST));
|
||||||
|
qemu_log(" First in frame: %d\n", !!(flags & BD_RX_FIRST));
|
||||||
|
qemu_log(" Miss: %d\n", !!(flags & BD_RX_MISS));
|
||||||
|
qemu_log(" Broadcast: %d\n", !!(flags & BD_RX_BROADCAST));
|
||||||
|
qemu_log(" Multicast: %d\n", !!(flags & BD_RX_MULTICAST));
|
||||||
|
qemu_log(" Rx frame length violation: %d\n", !!(flags & BD_RX_LG));
|
||||||
|
qemu_log(" Rx non-octet aligned frame: %d\n", !!(flags & BD_RX_NO));
|
||||||
|
qemu_log(" Short frame: %d\n", !!(flags & BD_RX_SH));
|
||||||
|
qemu_log(" Rx CRC Error: %d\n", !!(flags & BD_RX_CR));
|
||||||
|
qemu_log(" Overrun: %d\n", !!(flags & BD_RX_OV));
|
||||||
|
qemu_log(" Truncation: %d\n", !!(flags & BD_RX_TR));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_bd(eTSEC_rxtx_bd bd, int mode, uint32_t index)
|
||||||
|
{
|
||||||
|
qemu_log("eTSEC %s Data Buffer Descriptor (%u)\n",
|
||||||
|
mode == eTSEC_TRANSMIT ? "Transmit" : "Receive",
|
||||||
|
index);
|
||||||
|
qemu_log(" Flags : 0x%04x\n", bd.flags);
|
||||||
|
if (mode == eTSEC_TRANSMIT) {
|
||||||
|
print_tx_bd_flags(bd.flags);
|
||||||
|
} else {
|
||||||
|
print_rx_bd_flags(bd.flags);
|
||||||
|
}
|
||||||
|
qemu_log(" Length : 0x%04x\n", bd.length);
|
||||||
|
qemu_log(" Pointer : 0x%08x\n", bd.bufptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DEBUG_BD */
|
||||||
|
|
||||||
|
static void read_buffer_descriptor(eTSEC *etsec,
|
||||||
|
hwaddr addr,
|
||||||
|
eTSEC_rxtx_bd *bd)
|
||||||
|
{
|
||||||
|
assert(bd != NULL);
|
||||||
|
|
||||||
|
RING_DEBUG("READ Buffer Descriptor @ 0x" TARGET_FMT_plx"\n", addr);
|
||||||
|
cpu_physical_memory_read(addr,
|
||||||
|
bd,
|
||||||
|
sizeof(eTSEC_rxtx_bd));
|
||||||
|
|
||||||
|
if (etsec->regs[DMACTRL].value & DMACTRL_LE) {
|
||||||
|
bd->flags = lduw_le_p(&bd->flags);
|
||||||
|
bd->length = lduw_le_p(&bd->length);
|
||||||
|
bd->bufptr = ldl_le_p(&bd->bufptr);
|
||||||
|
} else {
|
||||||
|
bd->flags = lduw_be_p(&bd->flags);
|
||||||
|
bd->length = lduw_be_p(&bd->length);
|
||||||
|
bd->bufptr = ldl_be_p(&bd->bufptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_buffer_descriptor(eTSEC *etsec,
|
||||||
|
hwaddr addr,
|
||||||
|
eTSEC_rxtx_bd *bd)
|
||||||
|
{
|
||||||
|
assert(bd != NULL);
|
||||||
|
|
||||||
|
if (etsec->regs[DMACTRL].value & DMACTRL_LE) {
|
||||||
|
stw_le_p(&bd->flags, bd->flags);
|
||||||
|
stw_le_p(&bd->length, bd->length);
|
||||||
|
stl_le_p(&bd->bufptr, bd->bufptr);
|
||||||
|
} else {
|
||||||
|
stw_be_p(&bd->flags, bd->flags);
|
||||||
|
stw_be_p(&bd->length, bd->length);
|
||||||
|
stl_be_p(&bd->bufptr, bd->bufptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
RING_DEBUG("Write Buffer Descriptor @ 0x" TARGET_FMT_plx"\n", addr);
|
||||||
|
cpu_physical_memory_write(addr,
|
||||||
|
bd,
|
||||||
|
sizeof(eTSEC_rxtx_bd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ievent_set(eTSEC *etsec,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
etsec->regs[IEVENT].value |= flags;
|
||||||
|
|
||||||
|
if ((flags & IEVENT_TXB && etsec->regs[IMASK].value & IMASK_TXBEN)
|
||||||
|
|| (flags & IEVENT_TXF && etsec->regs[IMASK].value & IMASK_TXFEN)) {
|
||||||
|
qemu_irq_raise(etsec->tx_irq);
|
||||||
|
RING_DEBUG("%s Raise Tx IRQ\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & IEVENT_RXB && etsec->regs[IMASK].value & IMASK_RXBEN)
|
||||||
|
|| (flags & IEVENT_RXF && etsec->regs[IMASK].value & IMASK_RXFEN)) {
|
||||||
|
qemu_irq_pulse(etsec->rx_irq);
|
||||||
|
RING_DEBUG("%s Raise Rx IRQ\n", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tx_padding_and_crc(eTSEC *etsec, uint32_t min_frame_len)
|
||||||
|
{
|
||||||
|
int add = min_frame_len - etsec->tx_buffer_len;
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
if (add > 0) {
|
||||||
|
RING_DEBUG("pad:%u\n", add);
|
||||||
|
etsec->tx_buffer = g_realloc(etsec->tx_buffer,
|
||||||
|
etsec->tx_buffer_len + add);
|
||||||
|
|
||||||
|
memset(etsec->tx_buffer + etsec->tx_buffer_len, 0x0, add);
|
||||||
|
etsec->tx_buffer_len += add;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Never add CRC in QEMU */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_tx_fcb(eTSEC *etsec)
|
||||||
|
{
|
||||||
|
uint8_t flags = (uint8_t)(*etsec->tx_buffer);
|
||||||
|
/* L3 header offset from start of frame */
|
||||||
|
uint8_t l3_header_offset = (uint8_t)*(etsec->tx_buffer + 3);
|
||||||
|
/* L4 header offset from start of L3 header */
|
||||||
|
uint8_t l4_header_offset = (uint8_t)*(etsec->tx_buffer + 2);
|
||||||
|
/* L3 header */
|
||||||
|
uint8_t *l3_header = etsec->tx_buffer + 8 + l3_header_offset;
|
||||||
|
/* L4 header */
|
||||||
|
uint8_t *l4_header = l3_header + l4_header_offset;
|
||||||
|
|
||||||
|
/* if packet is IP4 and IP checksum is requested */
|
||||||
|
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
||||||
|
/* do IP4 checksum (TODO This function does TCP/UDP checksum
|
||||||
|
* but not sure if it also does IP4 checksum.) */
|
||||||
|
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||||
|
etsec->tx_buffer_len - 8);
|
||||||
|
}
|
||||||
|
/* TODO Check the correct usage of the PHCS field of the FCB in case the NPH
|
||||||
|
* flag is on */
|
||||||
|
|
||||||
|
/* if packet is IP4 and TCP or UDP */
|
||||||
|
if (flags & FCB_TX_IP && flags & FCB_TX_TUP) {
|
||||||
|
/* if UDP */
|
||||||
|
if (flags & FCB_TX_UDP) {
|
||||||
|
/* if checksum is requested */
|
||||||
|
if (flags & FCB_TX_CTU) {
|
||||||
|
/* do UDP checksum */
|
||||||
|
|
||||||
|
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||||
|
etsec->tx_buffer_len - 8);
|
||||||
|
} else {
|
||||||
|
/* set checksum field to 0 */
|
||||||
|
l4_header[6] = 0;
|
||||||
|
l4_header[7] = 0;
|
||||||
|
}
|
||||||
|
} else if (flags & FCB_TX_CTU) { /* if TCP and checksum is requested */
|
||||||
|
/* do TCP checksum */
|
||||||
|
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||||
|
etsec->tx_buffer_len - 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_tx_bd(eTSEC *etsec,
|
||||||
|
eTSEC_rxtx_bd *bd)
|
||||||
|
{
|
||||||
|
uint8_t *tmp_buff = NULL;
|
||||||
|
hwaddr tbdbth = (hwaddr)(etsec->regs[TBDBPH].value & 0xF) << 32;
|
||||||
|
|
||||||
|
if (bd->length == 0) {
|
||||||
|
/* ERROR */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (etsec->tx_buffer_len == 0) {
|
||||||
|
/* It's the first BD */
|
||||||
|
etsec->first_bd = *bd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: if TxBD[TOE/UN] skip the Tx Frame Control Block*/
|
||||||
|
|
||||||
|
/* Load this Data Buffer */
|
||||||
|
etsec->tx_buffer = g_realloc(etsec->tx_buffer,
|
||||||
|
etsec->tx_buffer_len + bd->length);
|
||||||
|
tmp_buff = etsec->tx_buffer + etsec->tx_buffer_len;
|
||||||
|
cpu_physical_memory_read(bd->bufptr + tbdbth, tmp_buff, bd->length);
|
||||||
|
|
||||||
|
/* Update buffer length */
|
||||||
|
etsec->tx_buffer_len += bd->length;
|
||||||
|
|
||||||
|
|
||||||
|
if (etsec->tx_buffer_len != 0 && (bd->flags & BD_LAST)) {
|
||||||
|
if (etsec->regs[MACCFG1].value & MACCFG1_TX_EN) {
|
||||||
|
/* MAC Transmit enabled */
|
||||||
|
|
||||||
|
/* Process offload Tx FCB */
|
||||||
|
if (etsec->first_bd.flags & BD_TX_TOEUN) {
|
||||||
|
process_tx_fcb(etsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (etsec->first_bd.flags & BD_TX_PADCRC
|
||||||
|
|| etsec->regs[MACCFG2].value & MACCFG2_PADCRC) {
|
||||||
|
|
||||||
|
/* Padding and CRC (Padding implies CRC) */
|
||||||
|
tx_padding_and_crc(etsec, 64);
|
||||||
|
|
||||||
|
} else if (etsec->first_bd.flags & BD_TX_TC
|
||||||
|
|| etsec->regs[MACCFG2].value & MACCFG2_CRC_EN) {
|
||||||
|
|
||||||
|
/* Only CRC */
|
||||||
|
/* Never add CRC in QEMU */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HEX_DUMP)
|
||||||
|
qemu_log("eTSEC Send packet size:%d\n", etsec->tx_buffer_len);
|
||||||
|
qemu_hexdump(etsec->tx_buffer, stderr, "", etsec->tx_buffer_len);
|
||||||
|
#endif /* ETSEC_RING_DEBUG */
|
||||||
|
|
||||||
|
if (etsec->first_bd.flags & BD_TX_TOEUN) {
|
||||||
|
qemu_send_packet(qemu_get_queue(etsec->nic),
|
||||||
|
etsec->tx_buffer + 8,
|
||||||
|
etsec->tx_buffer_len - 8);
|
||||||
|
} else {
|
||||||
|
qemu_send_packet(qemu_get_queue(etsec->nic),
|
||||||
|
etsec->tx_buffer,
|
||||||
|
etsec->tx_buffer_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
etsec->tx_buffer_len = 0;
|
||||||
|
|
||||||
|
if (bd->flags & BD_INTERRUPT) {
|
||||||
|
ievent_set(etsec, IEVENT_TXF);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bd->flags & BD_INTERRUPT) {
|
||||||
|
ievent_set(etsec, IEVENT_TXB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update DB flags */
|
||||||
|
|
||||||
|
/* Clear Ready */
|
||||||
|
bd->flags &= ~BD_TX_READY;
|
||||||
|
|
||||||
|
/* Clear Defer */
|
||||||
|
bd->flags &= ~BD_TX_PREDEF;
|
||||||
|
|
||||||
|
/* Clear Late Collision */
|
||||||
|
bd->flags &= ~BD_TX_HFELC;
|
||||||
|
|
||||||
|
/* Clear Retransmission Limit */
|
||||||
|
bd->flags &= ~BD_TX_CFRL;
|
||||||
|
|
||||||
|
/* Clear Retry Count */
|
||||||
|
bd->flags &= ~(BD_TX_RC_MASK << BD_TX_RC_OFFSET);
|
||||||
|
|
||||||
|
/* Clear Underrun */
|
||||||
|
bd->flags &= ~BD_TX_TOEUN;
|
||||||
|
|
||||||
|
/* Clear Truncation */
|
||||||
|
bd->flags &= ~BD_TX_TR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
|
||||||
|
{
|
||||||
|
hwaddr ring_base = 0;
|
||||||
|
hwaddr bd_addr = 0;
|
||||||
|
eTSEC_rxtx_bd bd;
|
||||||
|
uint16_t bd_flags;
|
||||||
|
|
||||||
|
if (!(etsec->regs[MACCFG1].value & MACCFG1_TX_EN)) {
|
||||||
|
RING_DEBUG("%s: MAC Transmit not enabled\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ring_base = (hwaddr)(etsec->regs[TBASEH].value & 0xF) << 32;
|
||||||
|
ring_base += etsec->regs[TBASE0 + ring_nbr].value & ~0x7;
|
||||||
|
bd_addr = etsec->regs[TBPTR0 + ring_nbr].value & ~0x7;
|
||||||
|
|
||||||
|
do {
|
||||||
|
read_buffer_descriptor(etsec, bd_addr, &bd);
|
||||||
|
|
||||||
|
#ifdef DEBUG_BD
|
||||||
|
print_bd(bd,
|
||||||
|
eTSEC_TRANSMIT,
|
||||||
|
(bd_addr - ring_base) / sizeof(eTSEC_rxtx_bd));
|
||||||
|
|
||||||
|
#endif /* DEBUG_BD */
|
||||||
|
|
||||||
|
/* Save flags before BD update */
|
||||||
|
bd_flags = bd.flags;
|
||||||
|
|
||||||
|
if (bd_flags & BD_TX_READY) {
|
||||||
|
process_tx_bd(etsec, &bd);
|
||||||
|
|
||||||
|
/* Write back BD after update */
|
||||||
|
write_buffer_descriptor(etsec, bd_addr, &bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrap or next BD */
|
||||||
|
if (bd_flags & BD_WRAP) {
|
||||||
|
bd_addr = ring_base;
|
||||||
|
} else {
|
||||||
|
bd_addr += sizeof(eTSEC_rxtx_bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (bd_addr != ring_base);
|
||||||
|
|
||||||
|
bd_addr = ring_base;
|
||||||
|
|
||||||
|
/* Save the Buffer Descriptor Pointers to current bd */
|
||||||
|
etsec->regs[TBPTR0 + ring_nbr].value = bd_addr;
|
||||||
|
|
||||||
|
/* Set transmit halt THLTx */
|
||||||
|
etsec->regs[TSTAT].value |= 1 << (31 - ring_nbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_rx_bd(eTSEC *etsec,
|
||||||
|
eTSEC_rxtx_bd *bd,
|
||||||
|
const uint8_t **buf,
|
||||||
|
size_t *size)
|
||||||
|
{
|
||||||
|
uint16_t to_write;
|
||||||
|
hwaddr bufptr = bd->bufptr +
|
||||||
|
((hwaddr)(etsec->regs[TBDBPH].value & 0xF) << 32);
|
||||||
|
uint8_t padd[etsec->rx_padding];
|
||||||
|
uint8_t rem;
|
||||||
|
|
||||||
|
RING_DEBUG("eTSEC fill Rx buffer @ 0x%016" HWADDR_PRIx
|
||||||
|
" size:%zu(padding + crc:%u) + fcb:%u\n",
|
||||||
|
bufptr, *size, etsec->rx_padding, etsec->rx_fcb_size);
|
||||||
|
|
||||||
|
bd->length = 0;
|
||||||
|
|
||||||
|
/* This operation will only write FCB */
|
||||||
|
if (etsec->rx_fcb_size != 0) {
|
||||||
|
|
||||||
|
cpu_physical_memory_write(bufptr, etsec->rx_fcb, etsec->rx_fcb_size);
|
||||||
|
|
||||||
|
bufptr += etsec->rx_fcb_size;
|
||||||
|
bd->length += etsec->rx_fcb_size;
|
||||||
|
etsec->rx_fcb_size = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We remove padding from the computation of to_write because it is not
|
||||||
|
* allocated in the buffer.
|
||||||
|
*/
|
||||||
|
to_write = MIN(*size - etsec->rx_padding,
|
||||||
|
etsec->regs[MRBLR].value - etsec->rx_fcb_size);
|
||||||
|
|
||||||
|
/* This operation can only write packet data and no padding */
|
||||||
|
if (to_write > 0) {
|
||||||
|
cpu_physical_memory_write(bufptr, *buf, to_write);
|
||||||
|
|
||||||
|
*buf += to_write;
|
||||||
|
bufptr += to_write;
|
||||||
|
*size -= to_write;
|
||||||
|
|
||||||
|
bd->flags &= ~BD_RX_EMPTY;
|
||||||
|
bd->length += to_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*size == etsec->rx_padding) {
|
||||||
|
/* The remaining bytes are only for padding which is not actually
|
||||||
|
* allocated in the data buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding);
|
||||||
|
|
||||||
|
if (rem > 0) {
|
||||||
|
memset(padd, 0x0, sizeof(padd));
|
||||||
|
etsec->rx_padding -= rem;
|
||||||
|
*size -= rem;
|
||||||
|
bd->length += rem;
|
||||||
|
cpu_physical_memory_write(bufptr, padd, rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
uint32_t fcb_size = 0;
|
||||||
|
uint8_t prsdep = (etsec->regs[RCTRL].value >> RCTRL_PRSDEP_OFFSET)
|
||||||
|
& RCTRL_PRSDEP_MASK;
|
||||||
|
|
||||||
|
if (prsdep != 0) {
|
||||||
|
/* Prepend FCB (FCB size + RCTRL[PAL]) */
|
||||||
|
fcb_size = 8 + ((etsec->regs[RCTRL].value >> 16) & 0x1F);
|
||||||
|
|
||||||
|
etsec->rx_fcb_size = fcb_size;
|
||||||
|
|
||||||
|
/* TODO: fill_FCB(etsec); */
|
||||||
|
memset(etsec->rx_fcb, 0x0, sizeof(etsec->rx_fcb));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
etsec->rx_fcb_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (etsec->rx_buffer != NULL) {
|
||||||
|
g_free(etsec->rx_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not copy the frame for now */
|
||||||
|
etsec->rx_buffer = (uint8_t *)buf;
|
||||||
|
etsec->rx_buffer_len = size;
|
||||||
|
|
||||||
|
/* CRC padding (We don't have to compute the CRC) */
|
||||||
|
etsec->rx_padding = 4;
|
||||||
|
|
||||||
|
etsec->rx_first_in_frame = 1;
|
||||||
|
etsec->rx_remaining_data = etsec->rx_buffer_len;
|
||||||
|
RING_DEBUG("%s: rx_buffer_len:%u rx_padding+crc:%u\n", __func__,
|
||||||
|
etsec->rx_buffer_len, etsec->rx_padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
void etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
int ring_nbr = 0; /* Always use ring0 (no filer) */
|
||||||
|
|
||||||
|
if (etsec->rx_buffer_len != 0) {
|
||||||
|
RING_DEBUG("%s: We can't receive now,"
|
||||||
|
" a buffer is already in the pipe\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (etsec->regs[RSTAT].value & 1 << (23 - ring_nbr)) {
|
||||||
|
RING_DEBUG("%s: The ring is halted\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (etsec->regs[DMACTRL].value & DMACTRL_GRS) {
|
||||||
|
RING_DEBUG("%s: Graceful receive stop\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(etsec->regs[MACCFG1].value & MACCFG1_RX_EN)) {
|
||||||
|
RING_DEBUG("%s: MAC Receive not enabled\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((etsec->regs[RCTRL].value & RCTRL_RSF) && (size < 60)) {
|
||||||
|
/* CRC is not in the packet yet, so short frame is below 60 bytes */
|
||||||
|
RING_DEBUG("%s: Drop short frame\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_init_frame(etsec, buf, size);
|
||||||
|
|
||||||
|
etsec_walk_rx_ring(etsec, ring_nbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
||||||
|
{
|
||||||
|
hwaddr ring_base = 0;
|
||||||
|
hwaddr bd_addr = 0;
|
||||||
|
hwaddr start_bd_addr = 0;
|
||||||
|
eTSEC_rxtx_bd bd;
|
||||||
|
uint16_t bd_flags;
|
||||||
|
size_t remaining_data;
|
||||||
|
const uint8_t *buf;
|
||||||
|
uint8_t *tmp_buf;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (etsec->rx_buffer_len == 0) {
|
||||||
|
/* No frame to send */
|
||||||
|
RING_DEBUG("No frame to send\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining_data = etsec->rx_remaining_data + etsec->rx_padding;
|
||||||
|
buf = etsec->rx_buffer
|
||||||
|
+ (etsec->rx_buffer_len - etsec->rx_remaining_data);
|
||||||
|
size = etsec->rx_buffer_len + etsec->rx_padding;
|
||||||
|
|
||||||
|
ring_base = (hwaddr)(etsec->regs[RBASEH].value & 0xF) << 32;
|
||||||
|
ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7;
|
||||||
|
start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7;
|
||||||
|
|
||||||
|
do {
|
||||||
|
read_buffer_descriptor(etsec, bd_addr, &bd);
|
||||||
|
|
||||||
|
#ifdef DEBUG_BD
|
||||||
|
print_bd(bd,
|
||||||
|
eTSEC_RECEIVE,
|
||||||
|
(bd_addr - ring_base) / sizeof(eTSEC_rxtx_bd));
|
||||||
|
|
||||||
|
#endif /* DEBUG_BD */
|
||||||
|
|
||||||
|
/* Save flags before BD update */
|
||||||
|
bd_flags = bd.flags;
|
||||||
|
|
||||||
|
if (bd_flags & BD_RX_EMPTY) {
|
||||||
|
fill_rx_bd(etsec, &bd, &buf, &remaining_data);
|
||||||
|
|
||||||
|
if (etsec->rx_first_in_frame) {
|
||||||
|
bd.flags |= BD_RX_FIRST;
|
||||||
|
etsec->rx_first_in_frame = 0;
|
||||||
|
etsec->rx_first_bd = bd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last in frame */
|
||||||
|
if (remaining_data == 0) {
|
||||||
|
|
||||||
|
/* Clear flags */
|
||||||
|
|
||||||
|
bd.flags &= ~0x7ff;
|
||||||
|
|
||||||
|
bd.flags |= BD_LAST;
|
||||||
|
|
||||||
|
/* NOTE: non-octet aligned frame is impossible in qemu */
|
||||||
|
|
||||||
|
if (size >= etsec->regs[MAXFRM].value) {
|
||||||
|
/* frame length violation */
|
||||||
|
qemu_log("%s frame length violation: size:%zu MAXFRM:%d\n",
|
||||||
|
__func__, size, etsec->regs[MAXFRM].value);
|
||||||
|
|
||||||
|
bd.flags |= BD_RX_LG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < 64) {
|
||||||
|
/* Short frame */
|
||||||
|
bd.flags |= BD_RX_SH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Broadcast and Multicast */
|
||||||
|
|
||||||
|
if (bd.flags & BD_INTERRUPT) {
|
||||||
|
/* Set RXFx */
|
||||||
|
etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
|
||||||
|
|
||||||
|
/* Set IEVENT */
|
||||||
|
ievent_set(etsec, IEVENT_RXF);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (bd.flags & BD_INTERRUPT) {
|
||||||
|
/* Set IEVENT */
|
||||||
|
ievent_set(etsec, IEVENT_RXB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write back BD after update */
|
||||||
|
write_buffer_descriptor(etsec, bd_addr, &bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrap or next BD */
|
||||||
|
if (bd_flags & BD_WRAP) {
|
||||||
|
bd_addr = ring_base;
|
||||||
|
} else {
|
||||||
|
bd_addr += sizeof(eTSEC_rxtx_bd);
|
||||||
|
}
|
||||||
|
} while (remaining_data != 0
|
||||||
|
&& (bd_flags & BD_RX_EMPTY)
|
||||||
|
&& bd_addr != start_bd_addr);
|
||||||
|
|
||||||
|
/* Reset ring ptr */
|
||||||
|
etsec->regs[RBPTR0 + ring_nbr].value = bd_addr;
|
||||||
|
|
||||||
|
/* The frame is too large to fit in the Rx ring */
|
||||||
|
if (remaining_data > 0) {
|
||||||
|
|
||||||
|
/* Set RSTAT[QHLTx] */
|
||||||
|
etsec->regs[RSTAT].value |= 1 << (23 - ring_nbr);
|
||||||
|
|
||||||
|
/* Save remaining data to send the end of the frame when the ring will
|
||||||
|
* be restarted
|
||||||
|
*/
|
||||||
|
etsec->rx_remaining_data = remaining_data;
|
||||||
|
|
||||||
|
/* Copy the frame */
|
||||||
|
tmp_buf = g_malloc(size);
|
||||||
|
memcpy(tmp_buf, etsec->rx_buffer, size);
|
||||||
|
etsec->rx_buffer = tmp_buf;
|
||||||
|
|
||||||
|
RING_DEBUG("no empty RxBD available any more\n");
|
||||||
|
} else {
|
||||||
|
etsec->rx_buffer_len = 0;
|
||||||
|
etsec->rx_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RING_DEBUG("eTSEC End of ring_write: remaining_data:%zu\n", remaining_data);
|
||||||
|
}
|
||||||
@@ -405,6 +405,8 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
|
|||||||
|
|
||||||
dev->rx_bufs++;
|
dev->rx_bufs++;
|
||||||
|
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(dev->nic));
|
||||||
|
|
||||||
DPRINTF("h_add_logical_lan_buffer(): Added buf ptr=%d rx_bufs=%d"
|
DPRINTF("h_add_logical_lan_buffer(): Added buf ptr=%d rx_bufs=%d"
|
||||||
" bd=0x%016llx\n", dev->add_buf_ptr, dev->rx_bufs,
|
" bd=0x%016llx\n", dev->add_buf_ptr, dev->rx_bufs,
|
||||||
(unsigned long long)buf);
|
(unsigned long long)buf);
|
||||||
|
|||||||
@@ -397,12 +397,15 @@ static int peer_detach(VirtIONet *n, int index)
|
|||||||
static void virtio_net_set_queues(VirtIONet *n)
|
static void virtio_net_set_queues(VirtIONet *n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int r;
|
||||||
|
|
||||||
for (i = 0; i < n->max_queues; i++) {
|
for (i = 0; i < n->max_queues; i++) {
|
||||||
if (i < n->curr_queues) {
|
if (i < n->curr_queues) {
|
||||||
assert(!peer_attach(n, i));
|
r = peer_attach(n, i);
|
||||||
|
assert(!r);
|
||||||
} else {
|
} else {
|
||||||
assert(!peer_detach(n, i));
|
r = peer_detach(n, i);
|
||||||
|
assert(!r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void init_pam(DeviceState *dev, MemoryRegion *ram_memory,
|
|||||||
/* XXX: should distinguish read/write cases */
|
/* XXX: should distinguish read/write cases */
|
||||||
memory_region_init_alias(&mem->alias[0], OBJECT(dev), "pam-pci", pci_address_space,
|
memory_region_init_alias(&mem->alias[0], OBJECT(dev), "pam-pci", pci_address_space,
|
||||||
start, size);
|
start, size);
|
||||||
memory_region_init_alias(&mem->alias[2], OBJECT(dev), "pam-pci", pci_address_space,
|
memory_region_init_alias(&mem->alias[2], OBJECT(dev), "pam-pci", ram_memory,
|
||||||
start, size);
|
start, size);
|
||||||
|
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
|
|||||||
@@ -28,7 +28,9 @@
|
|||||||
#include "hw/pci/pci_bus.h"
|
#include "hw/pci/pci_bus.h"
|
||||||
#include "hw/pci/pci_host.h"
|
#include "hw/pci/pci_host.h"
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
|
#include "hw/loader.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
|
#include "elf.h"
|
||||||
|
|
||||||
#define TYPE_RAVEN_PCI_DEVICE "raven"
|
#define TYPE_RAVEN_PCI_DEVICE "raven"
|
||||||
#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
|
#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
|
||||||
@@ -38,6 +40,10 @@
|
|||||||
|
|
||||||
typedef struct RavenPCIState {
|
typedef struct RavenPCIState {
|
||||||
PCIDevice dev;
|
PCIDevice dev;
|
||||||
|
|
||||||
|
uint32_t elf_machine;
|
||||||
|
char *bios_name;
|
||||||
|
MemoryRegion bios;
|
||||||
} RavenPCIState;
|
} RavenPCIState;
|
||||||
|
|
||||||
#define RAVEN_PCI_HOST_BRIDGE(obj) \
|
#define RAVEN_PCI_HOST_BRIDGE(obj) \
|
||||||
@@ -52,6 +58,8 @@ typedef struct PRePPCIState {
|
|||||||
RavenPCIState pci_dev;
|
RavenPCIState pci_dev;
|
||||||
} PREPPCIState;
|
} PREPPCIState;
|
||||||
|
|
||||||
|
#define BIOS_SIZE (1024 * 1024)
|
||||||
|
|
||||||
static inline uint32_t PPC_PCIIO_config(hwaddr addr)
|
static inline uint32_t PPC_PCIIO_config(hwaddr addr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -169,10 +177,45 @@ static void raven_pcihost_initfn(Object *obj)
|
|||||||
|
|
||||||
static int raven_init(PCIDevice *d)
|
static int raven_init(PCIDevice *d)
|
||||||
{
|
{
|
||||||
|
RavenPCIState *s = RAVEN_PCI_DEVICE(d);
|
||||||
|
char *filename;
|
||||||
|
int bios_size = -1;
|
||||||
|
|
||||||
d->config[0x0C] = 0x08; // cache_line_size
|
d->config[0x0C] = 0x08; // cache_line_size
|
||||||
d->config[0x0D] = 0x10; // latency_timer
|
d->config[0x0D] = 0x10; // latency_timer
|
||||||
d->config[0x34] = 0x00; // capabilities_pointer
|
d->config[0x34] = 0x00; // capabilities_pointer
|
||||||
|
|
||||||
|
memory_region_init_ram(&s->bios, OBJECT(s), "bios", BIOS_SIZE);
|
||||||
|
memory_region_set_readonly(&s->bios, true);
|
||||||
|
memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE),
|
||||||
|
&s->bios);
|
||||||
|
vmstate_register_ram_global(&s->bios);
|
||||||
|
if (s->bios_name) {
|
||||||
|
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name);
|
||||||
|
if (filename) {
|
||||||
|
if (s->elf_machine != EM_NONE) {
|
||||||
|
bios_size = load_elf(filename, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, 1, s->elf_machine, 0);
|
||||||
|
}
|
||||||
|
if (bios_size < 0) {
|
||||||
|
bios_size = get_image_size(filename);
|
||||||
|
if (bios_size > 0 && bios_size <= BIOS_SIZE) {
|
||||||
|
hwaddr bios_addr;
|
||||||
|
bios_size = (bios_size + 0xfff) & ~0xfff;
|
||||||
|
bios_addr = (uint32_t)(-BIOS_SIZE);
|
||||||
|
bios_size = load_image_targphys(filename, bios_addr,
|
||||||
|
bios_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bios_size < 0 || bios_size > BIOS_SIZE) {
|
||||||
|
hw_error("qemu: could not load bios image '%s'\n", s->bios_name);
|
||||||
|
}
|
||||||
|
if (filename) {
|
||||||
|
g_free(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,12 +255,20 @@ static const TypeInfo raven_info = {
|
|||||||
.class_init = raven_class_init,
|
.class_init = raven_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property raven_pcihost_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("elf-machine", PREPPCIState, pci_dev.elf_machine,
|
||||||
|
EM_NONE),
|
||||||
|
DEFINE_PROP_STRING("bios-name", PREPPCIState, pci_dev.bios_name),
|
||||||
|
DEFINE_PROP_END_OF_LIST()
|
||||||
|
};
|
||||||
|
|
||||||
static void raven_pcihost_class_init(ObjectClass *klass, void *data)
|
static void raven_pcihost_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||||
dc->realize = raven_pcihost_realizefn;
|
dc->realize = raven_pcihost_realizefn;
|
||||||
|
dc->props = raven_pcihost_properties;
|
||||||
dc->fw_name = "pci";
|
dc->fw_name = "pci";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ static void mch_update_smram(MCHPCIState *mch)
|
|||||||
PCIDevice *pd = PCI_DEVICE(mch);
|
PCIDevice *pd = PCI_DEVICE(mch);
|
||||||
|
|
||||||
memory_region_transaction_begin();
|
memory_region_transaction_begin();
|
||||||
smram_update(&mch->smram_region, pd->config[MCH_HOST_BRDIGE_SMRAM],
|
smram_update(&mch->smram_region, pd->config[MCH_HOST_BRIDGE_SMRAM],
|
||||||
mch->smm_enabled);
|
mch->smm_enabled);
|
||||||
memory_region_transaction_commit();
|
memory_region_transaction_commit();
|
||||||
}
|
}
|
||||||
@@ -283,7 +283,7 @@ static void mch_set_smm(int smm, void *arg)
|
|||||||
PCIDevice *pd = PCI_DEVICE(mch);
|
PCIDevice *pd = PCI_DEVICE(mch);
|
||||||
|
|
||||||
memory_region_transaction_begin();
|
memory_region_transaction_begin();
|
||||||
smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRDIGE_SMRAM],
|
smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRIDGE_SMRAM],
|
||||||
&mch->smram_region);
|
&mch->smram_region);
|
||||||
memory_region_transaction_commit();
|
memory_region_transaction_commit();
|
||||||
}
|
}
|
||||||
@@ -306,8 +306,8 @@ static void mch_write_config(PCIDevice *d,
|
|||||||
mch_update_pciexbar(mch);
|
mch_update_pciexbar(mch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM,
|
if (ranges_overlap(address, len, MCH_HOST_BRIDGE_SMRAM,
|
||||||
MCH_HOST_BRDIGE_SMRAM_SIZE)) {
|
MCH_HOST_BRIDGE_SMRAM_SIZE)) {
|
||||||
mch_update_smram(mch);
|
mch_update_smram(mch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,7 +347,7 @@ static void mch_reset(DeviceState *qdev)
|
|||||||
pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR,
|
pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR,
|
||||||
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
|
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
|
||||||
|
|
||||||
d->config[MCH_HOST_BRDIGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
|
d->config[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
|
||||||
|
|
||||||
mch_update(mch);
|
mch_update(mch);
|
||||||
}
|
}
|
||||||
|
|||||||
51
hw/pci/pci.c
51
hw/pci/pci.c
@@ -48,7 +48,6 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
|
|||||||
static char *pcibus_get_dev_path(DeviceState *dev);
|
static char *pcibus_get_dev_path(DeviceState *dev);
|
||||||
static char *pcibus_get_fw_dev_path(DeviceState *dev);
|
static char *pcibus_get_fw_dev_path(DeviceState *dev);
|
||||||
static void pcibus_reset(BusState *qbus);
|
static void pcibus_reset(BusState *qbus);
|
||||||
static void pci_bus_finalize(Object *obj);
|
|
||||||
|
|
||||||
static Property pci_props[] = {
|
static Property pci_props[] = {
|
||||||
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
|
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
|
||||||
@@ -61,6 +60,34 @@ static Property pci_props[] = {
|
|||||||
DEFINE_PROP_END_OF_LIST()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_pcibus = {
|
||||||
|
.name = "PCIBUS",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.minimum_version_id_old = 1,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_INT32_EQUAL(nirq, PCIBus),
|
||||||
|
VMSTATE_VARRAY_INT32(irq_count, PCIBus,
|
||||||
|
nirq, 0, vmstate_info_int32,
|
||||||
|
int32_t),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void pci_bus_realize(BusState *qbus, Error **errp)
|
||||||
|
{
|
||||||
|
PCIBus *bus = PCI_BUS(qbus);
|
||||||
|
|
||||||
|
vmstate_register(NULL, -1, &vmstate_pcibus, bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pci_bus_unrealize(BusState *qbus, Error **errp)
|
||||||
|
{
|
||||||
|
PCIBus *bus = PCI_BUS(qbus);
|
||||||
|
|
||||||
|
vmstate_unregister(NULL, &vmstate_pcibus, bus);
|
||||||
|
}
|
||||||
|
|
||||||
static void pci_bus_class_init(ObjectClass *klass, void *data)
|
static void pci_bus_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
BusClass *k = BUS_CLASS(klass);
|
BusClass *k = BUS_CLASS(klass);
|
||||||
@@ -68,6 +95,8 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
|
|||||||
k->print_dev = pcibus_dev_print;
|
k->print_dev = pcibus_dev_print;
|
||||||
k->get_dev_path = pcibus_get_dev_path;
|
k->get_dev_path = pcibus_get_dev_path;
|
||||||
k->get_fw_dev_path = pcibus_get_fw_dev_path;
|
k->get_fw_dev_path = pcibus_get_fw_dev_path;
|
||||||
|
k->realize = pci_bus_realize;
|
||||||
|
k->unrealize = pci_bus_unrealize;
|
||||||
k->reset = pcibus_reset;
|
k->reset = pcibus_reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +104,6 @@ static const TypeInfo pci_bus_info = {
|
|||||||
.name = TYPE_PCI_BUS,
|
.name = TYPE_PCI_BUS,
|
||||||
.parent = TYPE_BUS,
|
.parent = TYPE_BUS,
|
||||||
.instance_size = sizeof(PCIBus),
|
.instance_size = sizeof(PCIBus),
|
||||||
.instance_finalize = pci_bus_finalize,
|
|
||||||
.class_init = pci_bus_class_init,
|
.class_init = pci_bus_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,17 +123,6 @@ static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
|
|||||||
|
|
||||||
static QLIST_HEAD(, PCIHostState) pci_host_bridges;
|
static QLIST_HEAD(, PCIHostState) pci_host_bridges;
|
||||||
|
|
||||||
static const VMStateDescription vmstate_pcibus = {
|
|
||||||
.name = "PCIBUS",
|
|
||||||
.version_id = 1,
|
|
||||||
.minimum_version_id = 1,
|
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField []) {
|
|
||||||
VMSTATE_INT32_EQUAL(nirq, PCIBus),
|
|
||||||
VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, int32_t),
|
|
||||||
VMSTATE_END_OF_LIST()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static int pci_bar(PCIDevice *d, int reg)
|
static int pci_bar(PCIDevice *d, int reg)
|
||||||
{
|
{
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -299,8 +316,6 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
|
|||||||
QLIST_INIT(&bus->child);
|
QLIST_INIT(&bus->child);
|
||||||
|
|
||||||
pci_host_bus_register(bus, parent);
|
pci_host_bus_register(bus, parent);
|
||||||
|
|
||||||
vmstate_register(NULL, -1, &vmstate_pcibus, bus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pci_bus_is_express(PCIBus *bus)
|
bool pci_bus_is_express(PCIBus *bus)
|
||||||
@@ -369,12 +384,6 @@ int pci_bus_num(PCIBus *s)
|
|||||||
return s->parent_dev->config[PCI_SECONDARY_BUS];
|
return s->parent_dev->config[PCI_SECONDARY_BUS];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_bus_finalize(Object *obj)
|
|
||||||
{
|
|
||||||
PCIBus *bus = PCI_BUS(obj);
|
|
||||||
vmstate_unregister(NULL, &vmstate_pcibus, bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
|
static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
|
||||||
{
|
{
|
||||||
PCIDevice *s = container_of(pv, PCIDevice, config);
|
PCIDevice *s = container_of(pv, PCIDevice, config);
|
||||||
|
|||||||
@@ -221,29 +221,23 @@ static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev,
|
|||||||
DeviceState *dev,
|
DeviceState *dev,
|
||||||
uint8_t **exp_cap, Error **errp)
|
uint8_t **exp_cap, Error **errp)
|
||||||
{
|
{
|
||||||
PCIDevice *pci_dev = PCI_DEVICE(dev);
|
|
||||||
*exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
|
*exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
|
||||||
uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA);
|
uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA);
|
||||||
|
|
||||||
PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state);
|
PCIE_DEV_PRINTF(PCI_DEVICE(dev), "hotplug state: %d\n", state);
|
||||||
if (sltsta & PCI_EXP_SLTSTA_EIS) {
|
if (sltsta & PCI_EXP_SLTSTA_EIS) {
|
||||||
/* the slot is electromechanically locked.
|
/* the slot is electromechanically locked.
|
||||||
* This error is propagated up to qdev and then to HMP/QMP.
|
* This error is propagated up to qdev and then to HMP/QMP.
|
||||||
*/
|
*/
|
||||||
error_setg_errno(errp, -EBUSY, "slot is electromechanically locked");
|
error_setg_errno(errp, -EBUSY, "slot is electromechanically locked");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: multifunction hot-plug.
|
|
||||||
* Right now, only a device of function = 0 is allowed to be
|
|
||||||
* hot plugged/unplugged.
|
|
||||||
*/
|
|
||||||
assert(PCI_FUNC(pci_dev->devfn) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
uint8_t *exp_cap;
|
uint8_t *exp_cap;
|
||||||
|
PCIDevice *pci_dev = PCI_DEVICE(dev);
|
||||||
|
|
||||||
pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
|
pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
|
||||||
|
|
||||||
@@ -256,6 +250,12 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: multifunction hot-plug.
|
||||||
|
* Right now, only a device of function = 0 is allowed to be
|
||||||
|
* hot plugged/unplugged.
|
||||||
|
*/
|
||||||
|
assert(PCI_FUNC(pci_dev->devfn) == 0);
|
||||||
|
|
||||||
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
|
||||||
PCI_EXP_SLTSTA_PDS);
|
PCI_EXP_SLTSTA_PDS);
|
||||||
pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
|
pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
|
|||||||
the first node as boot node and be happy */
|
the first node as boot node and be happy */
|
||||||
for (i = smp_cpus - 1; i >= 0; i--) {
|
for (i = smp_cpus - 1; i >= 0; i--) {
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
|
PowerPCCPU *pcpu;
|
||||||
char cpu_name[128];
|
char cpu_name[128];
|
||||||
uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
|
uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
|
||||||
|
|
||||||
@@ -246,14 +247,16 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
env = cpu->env_ptr;
|
env = cpu->env_ptr;
|
||||||
|
pcpu = POWERPC_CPU(cpu);
|
||||||
|
|
||||||
snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
|
snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
|
||||||
cpu->cpu_index);
|
ppc_get_vcpu_dt_id(pcpu));
|
||||||
qemu_fdt_add_subnode(fdt, cpu_name);
|
qemu_fdt_add_subnode(fdt, cpu_name);
|
||||||
qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
|
qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
|
||||||
qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
|
qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
|
||||||
qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
|
qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
|
||||||
qemu_fdt_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
|
qemu_fdt_setprop_cell(fdt, cpu_name, "reg",
|
||||||
|
ppc_get_vcpu_dt_id(pcpu));
|
||||||
qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size",
|
qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size",
|
||||||
env->dcache_line_size);
|
env->dcache_line_size);
|
||||||
qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size",
|
qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size",
|
||||||
@@ -469,14 +472,13 @@ static void ppce500_cpu_reset_sec(void *opaque)
|
|||||||
{
|
{
|
||||||
PowerPCCPU *cpu = opaque;
|
PowerPCCPU *cpu = opaque;
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
CPUPPCState *env = &cpu->env;
|
|
||||||
|
|
||||||
cpu_reset(cs);
|
cpu_reset(cs);
|
||||||
|
|
||||||
/* Secondary CPU starts in halted state for now. Needs to change when
|
/* Secondary CPU starts in halted state for now. Needs to change when
|
||||||
implementing non-kernel boot. */
|
implementing non-kernel boot. */
|
||||||
cs->halted = 1;
|
cs->halted = 1;
|
||||||
env->exception_index = EXCP_HLT;
|
cs->exception_index = EXCP_HLT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ppce500_cpu_reset(void *opaque)
|
static void ppce500_cpu_reset(void *opaque)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user