Compare commits
407 Commits
prep-for-u
...
pull-input
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdcc3a28b7 | ||
|
|
0419f78fae | ||
|
|
e82597f6f8 | ||
|
|
63678e17cf | ||
|
|
58b590148c | ||
|
|
7d4d7975e5 | ||
|
|
0d6d1ab499 | ||
|
|
c8c14bcb72 | ||
|
|
8648fcd52a | ||
|
|
b3706faf0d | ||
|
|
3b6144bdbb | ||
|
|
b89834f4d7 | ||
|
|
1a8e80d7e8 | ||
|
|
9c5793c503 | ||
|
|
c6c09ba995 | ||
|
|
c36ad13fe9 | ||
|
|
5c31207941 | ||
|
|
6ff45f01c7 | ||
|
|
3768d505ad | ||
|
|
c9f2d70cc8 | ||
|
|
af23906d50 | ||
|
|
0bc60bd7b3 | ||
|
|
7d45e78401 | ||
|
|
a879125b47 | ||
|
|
a1f7f97b95 | ||
|
|
def6029882 | ||
|
|
00b0179347 | ||
|
|
f45cb2f43f | ||
|
|
d9631b90da | ||
|
|
ac43fa508c | ||
|
|
6d55574a65 | ||
|
|
2cd49cbfab | ||
|
|
e939c6ed61 | ||
|
|
340fb41b31 | ||
|
|
3363278808 | ||
|
|
b533f658a9 | ||
|
|
a443bc3496 | ||
|
|
08cf99629d | ||
|
|
06ab66cfab | ||
|
|
6df05bdd17 | ||
|
|
ecb4e01e34 | ||
|
|
76ac9940c3 | ||
|
|
5b2b7dc4e5 | ||
|
|
536492ebb3 | ||
|
|
d6fb330f70 | ||
|
|
6f1834a2ba | ||
|
|
9ad665df2a | ||
|
|
a7a5544a3a | ||
|
|
d4715c4183 | ||
|
|
bea4acda3b | ||
|
|
9013dca553 | ||
|
|
4297c8ee6f | ||
|
|
6a5b69a959 | ||
|
|
db237e33c0 | ||
|
|
61898bc020 | ||
|
|
0a87466ef3 | ||
|
|
0acf0a50c8 | ||
|
|
ec8929a555 | ||
|
|
b0f49d1387 | ||
|
|
ad1c7e0faa | ||
|
|
f7bc8ef809 | ||
|
|
0b1eaa8803 | ||
|
|
53a786acac | ||
|
|
b4f4d54812 | ||
|
|
bbbf9bfb9c | ||
|
|
7f6613cedc | ||
|
|
b9bf8a1abb | ||
|
|
4e505ddd9a | ||
|
|
169e4878ee | ||
|
|
d4cc1a213f | ||
|
|
db01eedb6d | ||
|
|
7b770c720b | ||
|
|
cc8c9d6c6f | ||
|
|
dc6fb73d21 | ||
|
|
4fd6a984b9 | ||
|
|
ae2990c259 | ||
|
|
131e744a15 | ||
|
|
839a554757 | ||
|
|
90c49ef165 | ||
|
|
e12b2a4fab | ||
|
|
e279e252ac | ||
|
|
da0af40dd7 | ||
|
|
d108609bf9 | ||
|
|
dac23a6c05 | ||
|
|
b2c494c3a4 | ||
|
|
3a87f8b685 | ||
|
|
71461b0fef | ||
|
|
29ee324740 | ||
|
|
5a06393f1d | ||
|
|
ad4f62d015 | ||
|
|
6b1566cbe3 | ||
|
|
30e32af746 | ||
|
|
a46622fd07 | ||
|
|
df99d30d4e | ||
|
|
5ec83c73e5 | ||
|
|
a80172a476 | ||
|
|
d197fdbc3b | ||
|
|
7aaf4957ef | ||
|
|
06c1bee85a | ||
|
|
f205da688b | ||
|
|
2403837e67 | ||
|
|
d16644ec4c | ||
|
|
1fe9e2626f | ||
|
|
1ae1dc5ba2 | ||
|
|
9a1839164c | ||
|
|
49a4e21251 | ||
|
|
d1a1451cd3 | ||
|
|
037b7addb7 | ||
|
|
abdffd1fb7 | ||
|
|
39f72ef94b | ||
|
|
7e4fb26d75 | ||
|
|
9561fda8d9 | ||
|
|
c6aed98334 | ||
|
|
f5ec6704c7 | ||
|
|
c8897e8eb9 | ||
|
|
f5946dbab3 | ||
|
|
f71e769d07 | ||
|
|
c01a71c1a5 | ||
|
|
ec864874bd | ||
|
|
cfd54a0409 | ||
|
|
4c8821d134 | ||
|
|
c1b94a0ed2 | ||
|
|
319c66d5ab | ||
|
|
af67ee9264 | ||
|
|
d2995916ea | ||
|
|
198fd05c35 | ||
|
|
20fccb187c | ||
|
|
b7d769c932 | ||
|
|
a134d90f50 | ||
|
|
8a15b813e6 | ||
|
|
d208cc353a | ||
|
|
6e6507c06b | ||
|
|
5a8a30db47 | ||
|
|
09e037354b | ||
|
|
0a79bc87c3 | ||
|
|
f72dbf3d26 | ||
|
|
ce8f0905a5 | ||
|
|
22709e90a2 | ||
|
|
bd16430777 | ||
|
|
059b3527f0 | ||
|
|
821e322786 | ||
|
|
c225aa3c6d | ||
|
|
2dda43bacc | ||
|
|
2fd71f1be2 | ||
|
|
d07e0e9cdd | ||
|
|
9bcc80cd71 | ||
|
|
f03bd716a2 | ||
|
|
798325ed38 | ||
|
|
39ee3af3a8 | ||
|
|
5ff020b7b0 | ||
|
|
1d14ac5af0 | ||
|
|
3dd46eb496 | ||
|
|
2f487a3d40 | ||
|
|
315b593441 | ||
|
|
cdf0592cb8 | ||
|
|
4f3ed190a6 | ||
|
|
b074e62205 | ||
|
|
7b53f2940e | ||
|
|
0a1bec8a4e | ||
|
|
cab0a7ea00 | ||
|
|
7ea5d7256d | ||
|
|
a8b12c108c | ||
|
|
eef0d9e740 | ||
|
|
a9c7d27bd1 | ||
|
|
1d0a60681a | ||
|
|
5f9eb02555 | ||
|
|
c8fc56cedd | ||
|
|
aad2f06a7f | ||
|
|
d801a8f2ce | ||
|
|
e7bc9004e7 | ||
|
|
1ed27a17cd | ||
|
|
c2fb418e35 | ||
|
|
5553955eb6 | ||
|
|
5201c13654 | ||
|
|
8b092ca9ef | ||
|
|
b6d4443a7b | ||
|
|
7baeabce1d | ||
|
|
2ed3ea110f | ||
|
|
a847f32c04 | ||
|
|
14dcdac82f | ||
|
|
03df01ed9a | ||
|
|
37a706adbf | ||
|
|
8f0c6758b0 | ||
|
|
a566da1b02 | ||
|
|
931c8cc270 | ||
|
|
261a5b4dd1 | ||
|
|
04c7c6c261 | ||
|
|
73a81d10fd | ||
|
|
6781fa119f | ||
|
|
c1b876b2e9 | ||
|
|
b05c306857 | ||
|
|
f612537e07 | ||
|
|
10113b6903 | ||
|
|
cf4ab1af29 | ||
|
|
a984e42c91 | ||
|
|
d6d60581f3 | ||
|
|
ba7500852d | ||
|
|
4719ab918a | ||
|
|
b5a3ca3e30 | ||
|
|
9948c38bd9 | ||
|
|
87f6396293 | ||
|
|
2bda66028b | ||
|
|
298526fe92 | ||
|
|
881249c792 | ||
|
|
e0eb210ec0 | ||
|
|
087edb503a | ||
|
|
025172d56e | ||
|
|
83d1c8ae88 | ||
|
|
0c544d73bb | ||
|
|
6295b98d7b | ||
|
|
f4b11eee2f | ||
|
|
a7ec0f98e3 | ||
|
|
1c275925bf | ||
|
|
6b1275ff15 | ||
| 8d5d30046b | |||
|
|
3b899ea7d4 | ||
|
|
7f72cd235f | ||
|
|
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 | ||
|
|
a822837d12 | ||
|
|
eee822e359 | ||
|
|
01ac27ce7f | ||
|
|
84f3fe1b07 | ||
|
|
d58b912271 | ||
|
|
7f5e07d9b3 | ||
|
|
dc9528fdf9 | ||
|
|
68e5ec6400 |
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]
|
||||||
|
|||||||
53
.travis.yml
53
.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"
|
||||||
@@ -14,23 +20,23 @@ env:
|
|||||||
- GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev"
|
- GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev"
|
||||||
- EXTRA_PKGS=""
|
- EXTRA_PKGS=""
|
||||||
matrix:
|
matrix:
|
||||||
- TARGETS=alpha-softmmu,alpha-linux-user
|
- TARGETS=alpha-softmmu,alpha-linux-user
|
||||||
- TARGETS=arm-softmmu,arm-linux-user
|
- TARGETS=arm-softmmu,arm-linux-user
|
||||||
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
- TARGETS=aarch64-softmmu,aarch64-linux-user
|
||||||
- TARGETS=cris-softmmu
|
- TARGETS=cris-softmmu
|
||||||
- TARGETS=i386-softmmu,x86_64-softmmu
|
- TARGETS=i386-softmmu,x86_64-softmmu
|
||||||
- TARGETS=lm32-softmmu
|
- TARGETS=lm32-softmmu
|
||||||
- TARGETS=m68k-softmmu
|
- TARGETS=m68k-softmmu
|
||||||
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
- TARGETS=microblaze-softmmu,microblazeel-softmmu
|
||||||
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
- TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu
|
||||||
- TARGETS=moxie-softmmu
|
- TARGETS=moxie-softmmu
|
||||||
- TARGETS=or32-softmmu,
|
- TARGETS=or32-softmmu,
|
||||||
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
- TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu
|
||||||
- TARGETS=s390x-softmmu
|
- TARGETS=s390x-softmmu
|
||||||
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
- TARGETS=sh4-softmmu,sh4eb-softmmu
|
||||||
- TARGETS=sparc-softmmu,sparc64-softmmu
|
- TARGETS=sparc-softmmu,sparc64-softmmu
|
||||||
- TARGETS=unicore32-softmmu
|
- TARGETS=unicore32-softmmu
|
||||||
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
- TARGETS=xtensa-softmmu,xtensaeb-softmmu
|
||||||
before_install:
|
before_install:
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
@@ -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"
|
|
||||||
|
|||||||
@@ -84,3 +84,10 @@ and clarity it comes on a line by itself:
|
|||||||
Rationale: a consistent (except for functions...) bracing style reduces
|
Rationale: a consistent (except for functions...) bracing style reduces
|
||||||
ambiguity and avoids needless churn when lines are added or removed.
|
ambiguity and avoids needless churn when lines are added or removed.
|
||||||
Furthermore, it is the QEMU coding style.
|
Furthermore, it is the QEMU coding style.
|
||||||
|
|
||||||
|
5. Declarations
|
||||||
|
|
||||||
|
Mixed declarations (interleaving statements and declarations within blocks)
|
||||||
|
are not allowed; declarations should be at the beginning of blocks. In other
|
||||||
|
words, the code should not generate warnings if using GCC's
|
||||||
|
-Wdeclaration-after-statement option.
|
||||||
|
|||||||
5
Makefile
5
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
|
||||||
|
|||||||
@@ -39,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
|
||||||
|
|||||||
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -566,8 +566,10 @@ CharDriverState *chr_baum_init(void)
|
|||||||
BaumDriverState *baum;
|
BaumDriverState *baum;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
brlapi_handle_t *handle;
|
brlapi_handle_t *handle;
|
||||||
#if defined(CONFIG_SDL) && SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
#if defined(CONFIG_SDL)
|
||||||
|
#if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
||||||
SDL_SysWMinfo info;
|
SDL_SysWMinfo info;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
int tty;
|
int tty;
|
||||||
|
|
||||||
@@ -595,12 +597,14 @@ CharDriverState *chr_baum_init(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_SDL) && SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
#if defined(CONFIG_SDL)
|
||||||
|
#if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
SDL_VERSION(&info.version);
|
SDL_VERSION(&info.version);
|
||||||
if (SDL_GetWMInfo(&info))
|
if (SDL_GetWMInfo(&info))
|
||||||
tty = info.info.x11.wmwindow;
|
tty = info.info.x11.wmwindow;
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
tty = BRLAPI_TTY_DEFAULT;
|
tty = BRLAPI_TTY_DEFAULT;
|
||||||
|
|
||||||
|
|||||||
102
block.c
102
block.c
@@ -1321,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 */
|
||||||
@@ -1388,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;
|
||||||
|
|
||||||
@@ -4055,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4774,19 +4781,43 @@ flush_parent:
|
|||||||
return bdrv_co_flush(bs->file);
|
return bdrv_co_flush(bs->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bdrv_invalidate_cache(BlockDriverState *bs)
|
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
if (bs->drv && bs->drv->bdrv_invalidate_cache) {
|
Error *local_err = NULL;
|
||||||
bs->drv->bdrv_invalidate_cache(bs);
|
int ret;
|
||||||
|
|
||||||
|
if (!bs->drv) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs->drv->bdrv_invalidate_cache) {
|
||||||
|
bs->drv->bdrv_invalidate_cache(bs, &local_err);
|
||||||
|
} else if (bs->file) {
|
||||||
|
bdrv_invalidate_cache(bs->file, &local_err);
|
||||||
|
}
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = refresh_total_sectors(bs, bs->total_sectors);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Could not refresh total sector count");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bdrv_invalidate_cache_all(void)
|
void bdrv_invalidate_cache_all(Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||||
bdrv_invalidate_cache(bs);
|
bdrv_invalidate_cache(bs, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5390,43 +5421,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
|
||||||
@@ -5441,6 +5466,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)
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ static int parse_volume_options(GlusterConf *gconf, char *path)
|
|||||||
* 'server' specifies the server where the volume file specification for
|
* 'server' specifies the server where the volume file specification for
|
||||||
* the given volume resides. This can be either hostname, ipv4 address
|
* the given volume resides. This can be either hostname, ipv4 address
|
||||||
* or ipv6 address. ipv6 address needs to be within square brackets [ ].
|
* or ipv6 address. ipv6 address needs to be within square brackets [ ].
|
||||||
* If transport type is 'unix', then 'server' field should not be specifed.
|
* If transport type is 'unix', then 'server' field should not be specified.
|
||||||
* The 'socket' field needs to be populated with the path to unix domain
|
* The 'socket' field needs to be populated with the path to unix domain
|
||||||
* socket.
|
* socket.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -98,7 +98,14 @@ static void mirror_iteration_done(MirrorOp *op, int ret)
|
|||||||
|
|
||||||
qemu_iovec_destroy(&op->qiov);
|
qemu_iovec_destroy(&op->qiov);
|
||||||
g_slice_free(MirrorOp, op);
|
g_slice_free(MirrorOp, op);
|
||||||
qemu_coroutine_enter(s->common.co, NULL);
|
|
||||||
|
/* Enter coroutine when it is not sleeping. The coroutine sleeps to
|
||||||
|
* rate-limit itself. The coroutine will eventually resume since there is
|
||||||
|
* a sleep timeout so don't wake it early.
|
||||||
|
*/
|
||||||
|
if (s->common.busy) {
|
||||||
|
qemu_coroutine_enter(s->common.co, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mirror_write_complete(void *opaque, int ret)
|
static void mirror_write_complete(void *opaque, int ret)
|
||||||
@@ -139,11 +146,12 @@ static void mirror_read_complete(void *opaque, int ret)
|
|||||||
mirror_write_complete, op);
|
mirror_write_complete, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||||
{
|
{
|
||||||
BlockDriverState *source = s->common.bs;
|
BlockDriverState *source = s->common.bs;
|
||||||
int nb_sectors, sectors_per_chunk, nb_chunks;
|
int nb_sectors, sectors_per_chunk, nb_chunks;
|
||||||
int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector;
|
int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector;
|
||||||
|
uint64_t delay_ns;
|
||||||
MirrorOp *op;
|
MirrorOp *op;
|
||||||
|
|
||||||
s->sector_num = hbitmap_iter_next(&s->hbi);
|
s->sector_num = hbitmap_iter_next(&s->hbi);
|
||||||
@@ -231,7 +239,12 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
|||||||
nb_chunks += added_chunks;
|
nb_chunks += added_chunks;
|
||||||
next_sector += added_sectors;
|
next_sector += added_sectors;
|
||||||
next_chunk += added_chunks;
|
next_chunk += added_chunks;
|
||||||
} while (next_sector < end);
|
if (!s->synced && s->common.speed) {
|
||||||
|
delay_ns = ratelimit_calculate_delay(&s->limit, added_sectors);
|
||||||
|
} else {
|
||||||
|
delay_ns = 0;
|
||||||
|
}
|
||||||
|
} while (delay_ns == 0 && next_sector < end);
|
||||||
|
|
||||||
/* Allocate a MirrorOp that is used as an AIO callback. */
|
/* Allocate a MirrorOp that is used as an AIO callback. */
|
||||||
op = g_slice_new(MirrorOp);
|
op = g_slice_new(MirrorOp);
|
||||||
@@ -268,6 +281,7 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
|||||||
trace_mirror_one_iteration(s, sector_num, nb_sectors);
|
trace_mirror_one_iteration(s, sector_num, nb_sectors);
|
||||||
bdrv_aio_readv(source, sector_num, &op->qiov, nb_sectors,
|
bdrv_aio_readv(source, sector_num, &op->qiov, nb_sectors,
|
||||||
mirror_read_complete, op);
|
mirror_read_complete, op);
|
||||||
|
return delay_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mirror_free_init(MirrorBlockJob *s)
|
static void mirror_free_init(MirrorBlockJob *s)
|
||||||
@@ -362,7 +376,7 @@ static void coroutine_fn mirror_run(void *opaque)
|
|||||||
bdrv_dirty_iter_init(bs, s->dirty_bitmap, &s->hbi);
|
bdrv_dirty_iter_init(bs, s->dirty_bitmap, &s->hbi);
|
||||||
last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint64_t delay_ns;
|
uint64_t delay_ns = 0;
|
||||||
int64_t cnt;
|
int64_t cnt;
|
||||||
bool should_complete;
|
bool should_complete;
|
||||||
|
|
||||||
@@ -386,8 +400,10 @@ static void coroutine_fn mirror_run(void *opaque)
|
|||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
continue;
|
continue;
|
||||||
} else if (cnt != 0) {
|
} else if (cnt != 0) {
|
||||||
mirror_iteration(s);
|
delay_ns = mirror_iteration(s);
|
||||||
continue;
|
if (delay_ns == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,17 +448,10 @@ static void coroutine_fn mirror_run(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
trace_mirror_before_sleep(s, cnt, s->synced);
|
trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
|
||||||
if (!s->synced) {
|
if (!s->synced) {
|
||||||
/* Publish progress */
|
/* Publish progress */
|
||||||
s->common.offset = (end - cnt) * BDRV_SECTOR_SIZE;
|
s->common.offset = (end - cnt) * BDRV_SECTOR_SIZE;
|
||||||
|
|
||||||
if (s->common.speed) {
|
|
||||||
delay_ns = ratelimit_calculate_delay(&s->limit, sectors_per_chunk);
|
|
||||||
} else {
|
|
||||||
delay_ns = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
|
block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
|
||||||
if (block_job_is_cancelled(&s->common)) {
|
if (block_job_is_cancelled(&s->common)) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -112,6 +112,9 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
|
|||||||
if (task->ret == 0 && task->st) {
|
if (task->ret == 0 && task->st) {
|
||||||
memcpy(task->st, data, sizeof(struct stat));
|
memcpy(task->st, data, sizeof(struct stat));
|
||||||
}
|
}
|
||||||
|
if (task->ret < 0) {
|
||||||
|
error_report("NFS Error: %s", nfs_get_error(nfs));
|
||||||
|
}
|
||||||
if (task->co) {
|
if (task->co) {
|
||||||
task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task);
|
task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task);
|
||||||
qemu_bh_schedule(task->bh);
|
qemu_bh_schedule(task->bh);
|
||||||
|
|||||||
@@ -723,7 +723,7 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
backing_file = NULL;
|
backing_file = NULL;
|
||||||
}
|
}
|
||||||
header.cluster_bits = 9; /* 512 byte cluster to avoid copying
|
header.cluster_bits = 9; /* 512 byte cluster to avoid copying
|
||||||
unmodifyed sectors */
|
unmodified sectors */
|
||||||
header.l2_bits = 12; /* 32 KB L2 tables */
|
header.l2_bits = 12; /* 32 KB L2 tables */
|
||||||
} else {
|
} else {
|
||||||
header.cluster_bits = 12; /* 4 KB clusters */
|
header.cluster_bits = 12; /* 4 KB clusters */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -1382,7 +1383,7 @@ static int write_reftable_entry(BlockDriverState *bs, int rt_index)
|
|||||||
* does _not_ decrement the reference count for the currently occupied cluster.
|
* does _not_ decrement the reference count for the currently occupied cluster.
|
||||||
*
|
*
|
||||||
* This function prints an informative message to stderr on error (and returns
|
* This function prints an informative message to stderr on error (and returns
|
||||||
* -errno); on success, 0 is returned.
|
* -errno); on success, the offset of the newly allocated cluster is returned.
|
||||||
*/
|
*/
|
||||||
static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
|
static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
|
||||||
uint64_t offset)
|
uint64_t offset)
|
||||||
@@ -1398,14 +1399,14 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
|
|||||||
fprintf(stderr, "Could not allocate new cluster: %s\n",
|
fprintf(stderr, "Could not allocate new cluster: %s\n",
|
||||||
strerror(-new_offset));
|
strerror(-new_offset));
|
||||||
ret = new_offset;
|
ret = new_offset;
|
||||||
goto fail;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fetch current refcount block content */
|
/* fetch current refcount block content */
|
||||||
ret = qcow2_cache_get(bs, s->refcount_block_cache, offset, &refcount_block);
|
ret = qcow2_cache_get(bs, s->refcount_block_cache, offset, &refcount_block);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Could not fetch refcount block: %s\n", strerror(-ret));
|
fprintf(stderr, "Could not fetch refcount block: %s\n", strerror(-ret));
|
||||||
goto fail;
|
goto fail_free_cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new block has not yet been entered into refcount table, therefore it is
|
/* new block has not yet been entered into refcount table, therefore it is
|
||||||
@@ -1416,8 +1417,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
|
|||||||
"check failed: %s\n", strerror(-ret));
|
"check failed: %s\n", strerror(-ret));
|
||||||
/* the image will be marked corrupt, so don't even attempt on freeing
|
/* the image will be marked corrupt, so don't even attempt on freeing
|
||||||
* the cluster */
|
* the cluster */
|
||||||
new_offset = 0;
|
goto done;
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write to new block */
|
/* write to new block */
|
||||||
@@ -1425,7 +1425,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
|
|||||||
s->cluster_sectors);
|
s->cluster_sectors);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Could not write refcount block: %s\n", strerror(-ret));
|
fprintf(stderr, "Could not write refcount block: %s\n", strerror(-ret));
|
||||||
goto fail;
|
goto fail_free_cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update refcount table */
|
/* update refcount table */
|
||||||
@@ -1435,24 +1435,27 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Could not update refcount table: %s\n",
|
fprintf(stderr, "Could not update refcount table: %s\n",
|
||||||
strerror(-ret));
|
strerror(-ret));
|
||||||
goto fail;
|
goto fail_free_cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
goto done;
|
||||||
if (new_offset && (ret < 0)) {
|
|
||||||
qcow2_free_clusters(bs, new_offset, s->cluster_size,
|
fail_free_cluster:
|
||||||
QCOW2_DISCARD_ALWAYS);
|
qcow2_free_clusters(bs, new_offset, s->cluster_size, QCOW2_DISCARD_OTHER);
|
||||||
}
|
|
||||||
|
done:
|
||||||
if (refcount_block) {
|
if (refcount_block) {
|
||||||
if (ret < 0) {
|
/* This should never fail, as it would only do so if the given refcount
|
||||||
qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
|
* block cannot be found in the cache. As this is impossible as long as
|
||||||
} else {
|
* there are no bugs, assert the success. */
|
||||||
ret = qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
|
int tmp = qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
|
||||||
}
|
assert(tmp == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_offset;
|
return new_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
qcow2_cache_flush(bs, s->l2_table_cache);
|
if (!(bs->open_flags & BDRV_O_INCOMING)) {
|
||||||
qcow2_cache_flush(bs, s->refcount_block_cache);
|
qcow2_cache_flush(bs, s->l2_table_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);
|
||||||
@@ -1154,7 +1156,7 @@ static void qcow2_close(BlockDriverState *bs)
|
|||||||
qcow2_free_snapshots(bs);
|
qcow2_free_snapshots(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qcow2_invalidate_cache(BlockDriverState *bs)
|
static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
int flags = s->flags;
|
int flags = s->flags;
|
||||||
@@ -1162,6 +1164,8 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
|
|||||||
AES_KEY aes_decrypt_key;
|
AES_KEY aes_decrypt_key;
|
||||||
uint32_t crypt_method = 0;
|
uint32_t crypt_method = 0;
|
||||||
QDict *options;
|
QDict *options;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Backing files are read-only which makes all of their metadata immutable,
|
* Backing files are read-only which makes all of their metadata immutable,
|
||||||
@@ -1176,12 +1180,25 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
|
|||||||
|
|
||||||
qcow2_close(bs);
|
qcow2_close(bs);
|
||||||
|
|
||||||
options = qdict_new();
|
bdrv_invalidate_cache(bs->file, &local_err);
|
||||||
qdict_put(options, QCOW2_OPT_LAZY_REFCOUNTS,
|
if (local_err) {
|
||||||
qbool_from_int(s->use_lazy_refcounts));
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memset(s, 0, sizeof(BDRVQcowState));
|
memset(s, 0, sizeof(BDRVQcowState));
|
||||||
qcow2_open(bs, options, flags, NULL);
|
options = qdict_clone_shallow(bs->options);
|
||||||
|
|
||||||
|
ret = qcow2_open(bs, options, flags, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_setg(errp, "Could not reopen qcow2 layer: %s",
|
||||||
|
error_get_pretty(local_err));
|
||||||
|
error_free(local_err);
|
||||||
|
return;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Could not reopen qcow2 layer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QDECREF(options);
|
QDECREF(options);
|
||||||
|
|
||||||
|
|||||||
22
block/qed.c
22
block/qed.c
@@ -1558,13 +1558,31 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bdrv_qed_invalidate_cache(BlockDriverState *bs)
|
static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
BDRVQEDState *s = bs->opaque;
|
BDRVQEDState *s = bs->opaque;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
bdrv_qed_close(bs);
|
bdrv_qed_close(bs);
|
||||||
|
|
||||||
|
bdrv_invalidate_cache(bs->file, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memset(s, 0, sizeof(BDRVQEDState));
|
memset(s, 0, sizeof(BDRVQEDState));
|
||||||
bdrv_qed_open(bs, NULL, bs->open_flags, NULL);
|
ret = bdrv_qed_open(bs, NULL, bs->open_flags, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_setg(errp, "Could not reopen qed layer: %s",
|
||||||
|
error_get_pretty(local_err));
|
||||||
|
error_free(local_err);
|
||||||
|
return;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Could not reopen qed layer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,
|
static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,
|
||||||
|
|||||||
@@ -625,13 +625,18 @@ static int64_t quorum_getlength(BlockDriverState *bs)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void quorum_invalidate_cache(BlockDriverState *bs)
|
static void quorum_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
BDRVQuorumState *s = bs->opaque;
|
BDRVQuorumState *s = bs->opaque;
|
||||||
|
Error *local_err = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < s->num_children; i++) {
|
for (i = 0; i < s->num_children; i++) {
|
||||||
bdrv_invalidate_cache(s->bs[i]);
|
bdrv_invalidate_cache(s->bs[i], &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,8 +857,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 +865,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1561,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)
|
||||||
{
|
{
|
||||||
@@ -1767,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) {
|
||||||
@@ -1805,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,
|
||||||
@@ -1834,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)
|
||||||
{
|
{
|
||||||
@@ -1939,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,
|
||||||
@@ -1963,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)
|
||||||
{
|
{
|
||||||
@@ -2050,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,
|
||||||
@@ -2180,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,
|
||||||
|
|||||||
@@ -593,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)
|
||||||
{
|
{
|
||||||
@@ -663,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,
|
||||||
|
|||||||
@@ -909,9 +909,9 @@ static void co_write_request(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a socket discriptor to read/write objects.
|
* Return a socket descriptor to read/write objects.
|
||||||
*
|
*
|
||||||
* We cannot use this discriptor for other operations because
|
* We cannot use this descriptor for other operations because
|
||||||
* the block driver may be on waiting response from the server.
|
* the block driver may be on waiting response from the server.
|
||||||
*/
|
*/
|
||||||
static int get_sheep_fd(BDRVSheepdogState *s)
|
static int get_sheep_fd(BDRVSheepdogState *s)
|
||||||
@@ -1896,7 +1896,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Even If deletion fails, we will just create extra snapshot based on
|
* Even If deletion fails, we will just create extra snapshot based on
|
||||||
* the workding VDI which was supposed to be deleted. So no need to
|
* the working VDI which was supposed to be deleted. So no need to
|
||||||
* false bail out.
|
* false bail out.
|
||||||
*/
|
*/
|
||||||
deleted = sd_delete(s);
|
deleted = sd_delete(s);
|
||||||
@@ -2194,7 +2194,7 @@ cleanup:
|
|||||||
* We implement rollback(loadvm) operation to the specified snapshot by
|
* We implement rollback(loadvm) operation to the specified snapshot by
|
||||||
* 1) switch to the snapshot
|
* 1) switch to the snapshot
|
||||||
* 2) rely on sd_create_branch to delete working VDI and
|
* 2) rely on sd_create_branch to delete working VDI and
|
||||||
* 3) create a new working VDI based on the speicified snapshot
|
* 3) create a new working VDI based on the specified snapshot
|
||||||
*/
|
*/
|
||||||
static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
* Allocation of blocks could be optimized (less writes to block map and
|
* Allocation of blocks could be optimized (less writes to block map and
|
||||||
* header).
|
* header).
|
||||||
*
|
*
|
||||||
* Read and write of adjacents blocks could be done in one operation
|
* Read and write of adjacent blocks could be done in one operation
|
||||||
* (current code uses one operation per block (1 MiB).
|
* (current code uses one operation per block (1 MiB).
|
||||||
*
|
*
|
||||||
* The code is not thread safe (missing locks for changes in header and
|
* The code is not thread safe (missing locks for changes in header and
|
||||||
|
|||||||
@@ -578,7 +578,7 @@ static int vhdx_validate_log_entry(BlockDriverState *bs, BDRVVHDXState *s,
|
|||||||
total_sectors = hdr.entry_length / VHDX_LOG_SECTOR_SIZE;
|
total_sectors = hdr.entry_length / VHDX_LOG_SECTOR_SIZE;
|
||||||
|
|
||||||
|
|
||||||
/* read_desc() will incrememnt the read idx */
|
/* read_desc() will increment the read idx */
|
||||||
ret = vhdx_log_read_desc(bs, s, log, &desc_buffer);
|
ret = vhdx_log_read_desc(bs, s, log, &desc_buffer);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
107
configure
vendored
107
configure
vendored
@@ -198,6 +198,7 @@ audio_win_int=""
|
|||||||
cc_i386=i386-pc-linux-gnu-gcc
|
cc_i386=i386-pc-linux-gnu-gcc
|
||||||
libs_qga=""
|
libs_qga=""
|
||||||
debug_info="yes"
|
debug_info="yes"
|
||||||
|
stack_protector=""
|
||||||
|
|
||||||
# Don't accept a target_list environment variable.
|
# Don't accept a target_list environment variable.
|
||||||
unset target_list
|
unset target_list
|
||||||
@@ -318,6 +319,7 @@ glusterfs_zerofill="no"
|
|||||||
virtio_blk_data_plane=""
|
virtio_blk_data_plane=""
|
||||||
gtk=""
|
gtk=""
|
||||||
gtkabi="2.0"
|
gtkabi="2.0"
|
||||||
|
vte=""
|
||||||
tpm="no"
|
tpm="no"
|
||||||
libssh2=""
|
libssh2=""
|
||||||
vhdx=""
|
vhdx=""
|
||||||
@@ -949,6 +951,10 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--disable-werror) werror="no"
|
--disable-werror) werror="no"
|
||||||
;;
|
;;
|
||||||
|
--enable-stack-protector) stack_protector="yes"
|
||||||
|
;;
|
||||||
|
--disable-stack-protector) stack_protector="no"
|
||||||
|
;;
|
||||||
--disable-curses) curses="no"
|
--disable-curses) curses="no"
|
||||||
;;
|
;;
|
||||||
--enable-curses) curses="yes"
|
--enable-curses) curses="yes"
|
||||||
@@ -1063,6 +1069,10 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--with-gtkabi=*) gtkabi="$optarg"
|
--with-gtkabi=*) gtkabi="$optarg"
|
||||||
;;
|
;;
|
||||||
|
--disable-vte) vte="no"
|
||||||
|
;;
|
||||||
|
--enable-vte) vte="yes"
|
||||||
|
;;
|
||||||
--enable-tpm) tpm="yes"
|
--enable-tpm) tpm="yes"
|
||||||
;;
|
;;
|
||||||
--disable-libssh2) libssh2="no"
|
--disable-libssh2) libssh2="no"
|
||||||
@@ -1214,6 +1224,7 @@ Advanced options (experts only):
|
|||||||
--disable-sparse disable sparse checker (default)
|
--disable-sparse disable sparse checker (default)
|
||||||
--disable-strip disable stripping binaries
|
--disable-strip disable stripping binaries
|
||||||
--disable-werror disable compilation abort on warning
|
--disable-werror disable compilation abort on warning
|
||||||
|
--disable-stack-protector disable compiler-provided stack protection
|
||||||
--disable-sdl disable SDL
|
--disable-sdl disable SDL
|
||||||
--enable-sdl enable SDL
|
--enable-sdl enable SDL
|
||||||
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
|
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
|
||||||
@@ -1434,9 +1445,15 @@ for flag in $gcc_flags; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if compile_prog "-Werror -fstack-protector-all" "" ; then
|
if test "$stack_protector" != "no" ; then
|
||||||
QEMU_CFLAGS="$QEMU_CFLAGS -fstack-protector-all"
|
gcc_flags="-fstack-protector-strong -fstack-protector-all"
|
||||||
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,-fstack-protector-all"
|
for flag in $gcc_flags; do
|
||||||
|
if compile_prog "-Werror $flag" "" ; then
|
||||||
|
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
|
||||||
|
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
|
# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
|
||||||
@@ -1946,30 +1963,41 @@ if test "$gtk" != "no"; then
|
|||||||
gtkpackage="gtk+-$gtkabi"
|
gtkpackage="gtk+-$gtkabi"
|
||||||
if test "$gtkabi" = "3.0" ; then
|
if test "$gtkabi" = "3.0" ; then
|
||||||
gtkversion="3.0.0"
|
gtkversion="3.0.0"
|
||||||
|
else
|
||||||
|
gtkversion="2.18.0"
|
||||||
|
fi
|
||||||
|
if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
|
||||||
|
gtk_cflags=`$pkg_config --cflags $gtkpackage`
|
||||||
|
gtk_libs=`$pkg_config --libs $gtkpackage`
|
||||||
|
libs_softmmu="$gtk_libs $libs_softmmu"
|
||||||
|
gtk="yes"
|
||||||
|
elif test "$gtk" = "yes"; then
|
||||||
|
feature_not_found "gtk" "Install gtk2 or gtk3 (requires --with-gtkabi=3.0 option to configure) devel"
|
||||||
|
else
|
||||||
|
gtk="no"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
# VTE probe
|
||||||
|
|
||||||
|
if test "$vte" != "no"; then
|
||||||
|
if test "$gtkabi" = "3.0"; then
|
||||||
vtepackage="vte-2.90"
|
vtepackage="vte-2.90"
|
||||||
vteversion="0.32.0"
|
vteversion="0.32.0"
|
||||||
else
|
else
|
||||||
gtkversion="2.18.0"
|
|
||||||
vtepackage="vte"
|
vtepackage="vte"
|
||||||
vteversion="0.24.0"
|
vteversion="0.24.0"
|
||||||
fi
|
fi
|
||||||
if ! $pkg_config --exists "$gtkpackage >= $gtkversion"; then
|
if $pkg_config --exists "$vtepackage >= $vteversion"; then
|
||||||
if test "$gtk" = "yes" ; then
|
vte_cflags=`$pkg_config --cflags $vtepackage`
|
||||||
feature_not_found "gtk" "Install gtk2 or gtk3 (requires --with-gtkabi=3.0 option to configure) devel"
|
vte_libs=`$pkg_config --libs $vtepackage`
|
||||||
fi
|
libs_softmmu="$vte_libs $libs_softmmu"
|
||||||
gtk="no"
|
vte="yes"
|
||||||
elif ! $pkg_config --exists "$vtepackage >= $vteversion"; then
|
elif test "$vte" = "yes"; then
|
||||||
if test "$gtk" = "yes" ; then
|
feature_not_found "vte" "Install libvte or libvte-2.90 (requires --with-gtkabi=3.0 option to configure) devel"
|
||||||
error_exit "libvte not found (required for gtk support)"
|
|
||||||
fi
|
|
||||||
gtk="no"
|
|
||||||
else
|
else
|
||||||
gtk_cflags=`$pkg_config --cflags $gtkpackage`
|
vte="no"
|
||||||
gtk_libs=`$pkg_config --libs $gtkpackage`
|
|
||||||
vte_cflags=`$pkg_config --cflags $vtepackage`
|
|
||||||
vte_libs=`$pkg_config --libs $vtepackage`
|
|
||||||
libs_softmmu="$gtk_libs $vte_libs $libs_softmmu"
|
|
||||||
gtk="yes"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -2696,6 +2724,24 @@ if test "$mingw32" != yes -a "$pthread" = no; then
|
|||||||
"Make sure to have the pthread libs and headers installed."
|
"Make sure to have the pthread libs and headers installed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# check for pthread_setname_np
|
||||||
|
pthread_setname_np=no
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
static void *f(void *p) { return NULL; }
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
pthread_t thread;
|
||||||
|
pthread_create(&thread, 0, f, 0);
|
||||||
|
pthread_setname_np(thread, "QEMU");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "" "$pthread_lib" ; then
|
||||||
|
pthread_setname_np=yes
|
||||||
|
fi
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# rbd probe
|
# rbd probe
|
||||||
if test "$rbd" != "no" ; then
|
if test "$rbd" != "no" ; then
|
||||||
@@ -3822,6 +3868,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) {
|
||||||
@@ -3863,7 +3914,7 @@ fi
|
|||||||
##########################################
|
##########################################
|
||||||
# Do we have libnfs
|
# Do we have libnfs
|
||||||
if test "$libnfs" != "no" ; then
|
if test "$libnfs" != "no" ; then
|
||||||
if $pkg_config --atleast-version=1.9.2 libnfs; then
|
if $pkg_config --atleast-version=1.9.3 libnfs; then
|
||||||
libnfs="yes"
|
libnfs="yes"
|
||||||
libnfs_libs=$($pkg_config --libs libnfs)
|
libnfs_libs=$($pkg_config --libs libnfs)
|
||||||
LIBS="$LIBS $libnfs_libs"
|
LIBS="$LIBS $libnfs_libs"
|
||||||
@@ -4048,6 +4099,7 @@ fi
|
|||||||
echo "pixman $pixman"
|
echo "pixman $pixman"
|
||||||
echo "SDL support $sdl"
|
echo "SDL support $sdl"
|
||||||
echo "GTK support $gtk"
|
echo "GTK support $gtk"
|
||||||
|
echo "VTE support $vte"
|
||||||
echo "curses support $curses"
|
echo "curses support $curses"
|
||||||
echo "curl support $curl"
|
echo "curl support $curl"
|
||||||
echo "mingw32 support $mingw32"
|
echo "mingw32 support $mingw32"
|
||||||
@@ -4376,6 +4428,9 @@ echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
|||||||
if test "$gtk" = "yes" ; then
|
if test "$gtk" = "yes" ; then
|
||||||
echo "CONFIG_GTK=y" >> $config_host_mak
|
echo "CONFIG_GTK=y" >> $config_host_mak
|
||||||
echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak
|
echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
if test "$vte" = "yes" ; then
|
||||||
|
echo "CONFIG_VTE=y" >> $config_host_mak
|
||||||
echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak
|
echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
if test "$xen" = "yes" ; then
|
if test "$xen" = "yes" ; then
|
||||||
@@ -4623,6 +4678,16 @@ if test "$rdma" = "yes" ; then
|
|||||||
echo "CONFIG_RDMA=y" >> $config_host_mak
|
echo "CONFIG_RDMA=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Hold two types of flag:
|
||||||
|
# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on
|
||||||
|
# a thread we have a handle to
|
||||||
|
# CONFIG_PTHREAD_SETNAME_NP - A way of doing it on a particular
|
||||||
|
# platform
|
||||||
|
if test "$pthread_setname_np" = "yes" ; then
|
||||||
|
echo "CONFIG_THREAD_SETNAME_BYTHREAD=y" >> $config_host_mak
|
||||||
|
echo "CONFIG_PTHREAD_SETNAME_NP=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$tcg_interpreter" = "yes"; then
|
if test "$tcg_interpreter" = "yes"; then
|
||||||
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
|
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
|
||||||
elif test "$ARCH" = "sparc64" ; then
|
elif test "$ARCH" = "sparc64" ; then
|
||||||
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
25
cpus.c
25
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);
|
||||||
}
|
}
|
||||||
@@ -1236,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;
|
||||||
@@ -1248,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
|
||||||
@@ -1266,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
|
||||||
@@ -1276,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"
|
|
||||||
|
|||||||
120
exec.c
120
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"
|
||||||
@@ -419,7 +420,7 @@ static int cpu_common_post_load(void *opaque, int version_id)
|
|||||||
/* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
|
/* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
|
||||||
version_id is increased. */
|
version_id is increased. */
|
||||||
cpu->interrupt_request &= ~0x01;
|
cpu->interrupt_request &= ~0x01;
|
||||||
tlb_flush(cpu->env_ptr, 1);
|
tlb_flush(cpu, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -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)) {
|
||||||
@@ -1553,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1572,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 {
|
||||||
@@ -1830,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ INLINE flag extractFloat32Sign( float32 a )
|
|||||||
| If `a' is denormal and we are in flush-to-zero mode then set the
|
| If `a' is denormal and we are in flush-to-zero mode then set the
|
||||||
| input-denormal exception and return zero. Otherwise just return the value.
|
| input-denormal exception and return zero. Otherwise just return the value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
|
float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
|
||||||
{
|
{
|
||||||
if (STATUS(flush_inputs_to_zero)) {
|
if (STATUS(flush_inputs_to_zero)) {
|
||||||
if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) {
|
if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) {
|
||||||
@@ -473,7 +473,7 @@ INLINE flag extractFloat64Sign( float64 a )
|
|||||||
| If `a' is denormal and we are in flush-to-zero mode then set the
|
| If `a' is denormal and we are in flush-to-zero mode then set the
|
||||||
| input-denormal exception and return zero. Otherwise just return the value.
|
| input-denormal exception and return zero. Otherwise just return the value.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
|
float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
|
||||||
{
|
{
|
||||||
if (STATUS(flush_inputs_to_zero)) {
|
if (STATUS(flush_inputs_to_zero)) {
|
||||||
if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) {
|
if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) {
|
||||||
|
|||||||
48
gdbstub.c
48
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,10 +645,10 @@ 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
|
||||||
@@ -657,8 +656,7 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
|
|||||||
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,10 +681,10 @@ 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
|
||||||
@@ -695,8 +692,7 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
|
|||||||
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)
|
|
||||||
return;
|
if (gdbserver_fd < 0 || s->fd < 0) {
|
||||||
|
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)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ void AcpiCpuHotplug_add(ACPIGPE *gpe, AcpiCpuHotplug *g, CPUState *cpu)
|
|||||||
|
|
||||||
*gpe->sts = *gpe->sts | ACPI_CPU_HOTPLUG_STATUS;
|
*gpe->sts = *gpe->sts | ACPI_CPU_HOTPLUG_STATUS;
|
||||||
cpu_id = k->get_arch_id(CPU(cpu));
|
cpu_id = k->get_arch_id(CPU(cpu));
|
||||||
|
g_assert((cpu_id / 8) < ACPI_GPE_PROC_LEN);
|
||||||
g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
|
g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -448,6 +448,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
|
|||||||
int initrd_size;
|
int initrd_size;
|
||||||
int is_linux = 0;
|
int is_linux = 0;
|
||||||
uint64_t elf_entry;
|
uint64_t elf_entry;
|
||||||
|
int elf_machine;
|
||||||
hwaddr entry, kernel_load_offset;
|
hwaddr entry, kernel_load_offset;
|
||||||
int big_endian;
|
int big_endian;
|
||||||
static const ARMInsnFixup *primary_loader;
|
static const ARMInsnFixup *primary_loader;
|
||||||
@@ -463,9 +464,11 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
|
|||||||
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
|
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
|
||||||
primary_loader = bootloader_aarch64;
|
primary_loader = bootloader_aarch64;
|
||||||
kernel_load_offset = KERNEL64_LOAD_ADDR;
|
kernel_load_offset = KERNEL64_LOAD_ADDR;
|
||||||
|
elf_machine = EM_AARCH64;
|
||||||
} else {
|
} else {
|
||||||
primary_loader = bootloader;
|
primary_loader = bootloader;
|
||||||
kernel_load_offset = KERNEL_LOAD_ADDR;
|
kernel_load_offset = KERNEL_LOAD_ADDR;
|
||||||
|
elf_machine = EM_ARM;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
||||||
@@ -501,7 +504,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
|
|||||||
|
|
||||||
/* Assume that raw images are linux kernels, and ELF images are not. */
|
/* Assume that raw images are linux kernels, and ELF images are not. */
|
||||||
kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
|
kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
|
||||||
NULL, NULL, big_endian, ELF_MACHINE, 1);
|
NULL, NULL, big_endian, elf_machine, 1);
|
||||||
entry = elf_entry;
|
entry = elf_entry;
|
||||||
if (kernel_size < 0) {
|
if (kernel_size < 0) {
|
||||||
kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
|
kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
|
||||||
|
|||||||
@@ -143,11 +143,21 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
|
|||||||
unsigned long mem_size;
|
unsigned long mem_size;
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
SysBusDevice *busdev;
|
SysBusDevice *busdev;
|
||||||
|
ObjectClass *cpu_oc;
|
||||||
|
|
||||||
|
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, "cortex-a9");
|
||||||
|
assert(cpu_oc);
|
||||||
|
|
||||||
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
|
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
|
||||||
s->cpu[n] = cpu_arm_init("cortex-a9");
|
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||||
if (!s->cpu[n]) {
|
Error *err = NULL;
|
||||||
fprintf(stderr, "Unable to find CPU %d definition\n", n);
|
|
||||||
|
s->cpu[n] = ARM_CPU(cpuobj);
|
||||||
|
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
|
||||||
|
"reset-cbar", &error_abort);
|
||||||
|
object_property_set_bool(cpuobj, true, "realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_report("%s", error_get_pretty(err));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -534,7 +534,6 @@ static QEMUMachine integratorcp_machine = {
|
|||||||
.name = "integratorcp",
|
.name = "integratorcp",
|
||||||
.desc = "ARM Integrator/CP (ARM926EJ-S)",
|
.desc = "ARM Integrator/CP (ARM926EJ-S)",
|
||||||
.init = integratorcp_init,
|
.init = integratorcp_init,
|
||||||
.is_default = 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void integratorcp_machine_init(void)
|
static void integratorcp_machine_init(void)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "hw/i2c/i2c.h"
|
#include "hw/i2c/i2c.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
#define SMP_BOOT_ADDR 0xe0000000
|
#define SMP_BOOT_ADDR 0xe0000000
|
||||||
#define SMP_BOOTREG_ADDR 0x10000030
|
#define SMP_BOOTREG_ADDR 0x10000030
|
||||||
@@ -49,6 +50,7 @@ static void realview_init(QEMUMachineInitArgs *args,
|
|||||||
{
|
{
|
||||||
ARMCPU *cpu = NULL;
|
ARMCPU *cpu = NULL;
|
||||||
CPUARMState *env;
|
CPUARMState *env;
|
||||||
|
ObjectClass *cpu_oc;
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
|
MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
|
||||||
MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
|
MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
|
||||||
@@ -70,12 +72,14 @@ static void realview_init(QEMUMachineInitArgs *args,
|
|||||||
uint32_t sys_id;
|
uint32_t sys_id;
|
||||||
ram_addr_t low_ram_size;
|
ram_addr_t low_ram_size;
|
||||||
ram_addr_t ram_size = args->ram_size;
|
ram_addr_t ram_size = args->ram_size;
|
||||||
|
hwaddr periphbase = 0;
|
||||||
|
|
||||||
switch (board_type) {
|
switch (board_type) {
|
||||||
case BOARD_EB:
|
case BOARD_EB:
|
||||||
break;
|
break;
|
||||||
case BOARD_EB_MPCORE:
|
case BOARD_EB_MPCORE:
|
||||||
is_mpcore = 1;
|
is_mpcore = 1;
|
||||||
|
periphbase = 0x10100000;
|
||||||
break;
|
break;
|
||||||
case BOARD_PB_A8:
|
case BOARD_PB_A8:
|
||||||
is_pb = 1;
|
is_pb = 1;
|
||||||
@@ -83,16 +87,37 @@ static void realview_init(QEMUMachineInitArgs *args,
|
|||||||
case BOARD_PBX_A9:
|
case BOARD_PBX_A9:
|
||||||
is_mpcore = 1;
|
is_mpcore = 1;
|
||||||
is_pb = 1;
|
is_pb = 1;
|
||||||
|
periphbase = 0x1f000000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, args->cpu_model);
|
||||||
|
if (!cpu_oc) {
|
||||||
|
fprintf(stderr, "Unable to find CPU definition\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
for (n = 0; n < smp_cpus; n++) {
|
||||||
cpu = cpu_arm_init(args->cpu_model);
|
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||||
if (!cpu) {
|
Error *err = NULL;
|
||||||
fprintf(stderr, "Unable to find CPU definition\n");
|
|
||||||
|
if (is_pb && is_mpcore) {
|
||||||
|
object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
|
||||||
|
if (err) {
|
||||||
|
error_report("%s", error_get_pretty(err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_property_set_bool(cpuobj, true, "realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_report("%s", error_get_pretty(err));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
|
|
||||||
|
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpuobj), ARM_CPU_IRQ);
|
||||||
}
|
}
|
||||||
|
cpu = ARM_CPU(first_cpu);
|
||||||
env = &cpu->env;
|
env = &cpu->env;
|
||||||
if (arm_feature(env, ARM_FEATURE_V7)) {
|
if (arm_feature(env, ARM_FEATURE_V7)) {
|
||||||
if (is_mpcore) {
|
if (is_mpcore) {
|
||||||
@@ -141,16 +166,10 @@ static void realview_init(QEMUMachineInitArgs *args,
|
|||||||
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
|
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
|
||||||
|
|
||||||
if (is_mpcore) {
|
if (is_mpcore) {
|
||||||
hwaddr periphbase;
|
|
||||||
dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
|
dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
|
||||||
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
|
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
|
||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
busdev = SYS_BUS_DEVICE(dev);
|
busdev = SYS_BUS_DEVICE(dev);
|
||||||
if (is_pb) {
|
|
||||||
periphbase = 0x1f000000;
|
|
||||||
} else {
|
|
||||||
periphbase = 0x10100000;
|
|
||||||
}
|
|
||||||
sysbus_mmio_map(busdev, 0, periphbase);
|
sysbus_mmio_map(busdev, 0, periphbase);
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
for (n = 0; n < smp_cpus; n++) {
|
||||||
sysbus_connect_irq(busdev, n, cpu_irq[n]);
|
sysbus_connect_irq(busdev, n, cpu_irq[n]);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "hw/block/flash.h"
|
#include "hw/block/flash.h"
|
||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
#define VEXPRESS_BOARD_ID 0x8e0
|
#define VEXPRESS_BOARD_ID 0x8e0
|
||||||
@@ -173,6 +174,64 @@ struct VEDBoardInfo {
|
|||||||
DBoardInitFn *init;
|
DBoardInitFn *init;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void init_cpus(const char *cpu_model, const char *privdev,
|
||||||
|
hwaddr periphbase, qemu_irq *pic)
|
||||||
|
{
|
||||||
|
ObjectClass *cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
|
||||||
|
DeviceState *dev;
|
||||||
|
SysBusDevice *busdev;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (!cpu_oc) {
|
||||||
|
fprintf(stderr, "Unable to find CPU definition\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the actual CPUs */
|
||||||
|
for (n = 0; n < smp_cpus; n++) {
|
||||||
|
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
|
||||||
|
if (err) {
|
||||||
|
error_report("%s", error_get_pretty(err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
object_property_set_bool(cpuobj, true, "realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_report("%s", error_get_pretty(err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the private peripheral devices (including the GIC);
|
||||||
|
* this must happen after the CPUs are created because a15mpcore_priv
|
||||||
|
* wires itself up to the CPU's generic_timer gpio out lines.
|
||||||
|
*/
|
||||||
|
dev = qdev_create(NULL, privdev);
|
||||||
|
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
|
||||||
|
qdev_init_nofail(dev);
|
||||||
|
busdev = SYS_BUS_DEVICE(dev);
|
||||||
|
sysbus_mmio_map(busdev, 0, periphbase);
|
||||||
|
|
||||||
|
/* Interrupts [42:0] are from the motherboard;
|
||||||
|
* [47:43] are reserved; [63:48] are daughterboard
|
||||||
|
* peripherals. Note that some documentation numbers
|
||||||
|
* external interrupts starting from 32 (because there
|
||||||
|
* are internal interrupts 0..31).
|
||||||
|
*/
|
||||||
|
for (n = 0; n < 64; n++) {
|
||||||
|
pic[n] = qdev_get_gpio_in(dev, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect the CPUs to the GIC */
|
||||||
|
for (n = 0; n < smp_cpus; n++) {
|
||||||
|
DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
|
||||||
|
|
||||||
|
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
|
static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
|
||||||
ram_addr_t ram_size,
|
ram_addr_t ram_size,
|
||||||
const char *cpu_model,
|
const char *cpu_model,
|
||||||
@@ -181,25 +240,12 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
|
|||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
MemoryRegion *lowram = g_new(MemoryRegion, 1);
|
MemoryRegion *lowram = g_new(MemoryRegion, 1);
|
||||||
DeviceState *dev;
|
|
||||||
SysBusDevice *busdev;
|
|
||||||
int n;
|
|
||||||
qemu_irq cpu_irq[4];
|
|
||||||
ram_addr_t low_ram_size;
|
ram_addr_t low_ram_size;
|
||||||
|
|
||||||
if (!cpu_model) {
|
if (!cpu_model) {
|
||||||
cpu_model = "cortex-a9";
|
cpu_model = "cortex-a9";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
|
||||||
ARMCPU *cpu = cpu_arm_init(cpu_model);
|
|
||||||
if (!cpu) {
|
|
||||||
fprintf(stderr, "Unable to find CPU definition\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ram_size > 0x40000000) {
|
if (ram_size > 0x40000000) {
|
||||||
/* 1GB is the maximum the address space permits */
|
/* 1GB is the maximum the address space permits */
|
||||||
fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
|
fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
|
||||||
@@ -221,23 +267,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
|
|||||||
memory_region_add_subregion(sysmem, 0x60000000, ram);
|
memory_region_add_subregion(sysmem, 0x60000000, ram);
|
||||||
|
|
||||||
/* 0x1e000000 A9MPCore (SCU) private memory region */
|
/* 0x1e000000 A9MPCore (SCU) private memory region */
|
||||||
dev = qdev_create(NULL, "a9mpcore_priv");
|
init_cpus(cpu_model, "a9mpcore_priv", 0x1e000000, pic);
|
||||||
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
|
|
||||||
qdev_init_nofail(dev);
|
|
||||||
busdev = SYS_BUS_DEVICE(dev);
|
|
||||||
sysbus_mmio_map(busdev, 0, 0x1e000000);
|
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
|
||||||
sysbus_connect_irq(busdev, n, cpu_irq[n]);
|
|
||||||
}
|
|
||||||
/* Interrupts [42:0] are from the motherboard;
|
|
||||||
* [47:43] are reserved; [63:48] are daughterboard
|
|
||||||
* peripherals. Note that some documentation numbers
|
|
||||||
* external interrupts starting from 32 (because the
|
|
||||||
* A9MP has internal interrupts 0..31).
|
|
||||||
*/
|
|
||||||
for (n = 0; n < 64; n++) {
|
|
||||||
pic[n] = qdev_get_gpio_in(dev, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
|
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
|
||||||
|
|
||||||
@@ -296,29 +326,14 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
|
|||||||
const char *cpu_model,
|
const char *cpu_model,
|
||||||
qemu_irq *pic)
|
qemu_irq *pic)
|
||||||
{
|
{
|
||||||
int n;
|
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
MemoryRegion *sram = g_new(MemoryRegion, 1);
|
MemoryRegion *sram = g_new(MemoryRegion, 1);
|
||||||
qemu_irq cpu_irq[4];
|
|
||||||
DeviceState *dev;
|
|
||||||
SysBusDevice *busdev;
|
|
||||||
|
|
||||||
if (!cpu_model) {
|
if (!cpu_model) {
|
||||||
cpu_model = "cortex-a15";
|
cpu_model = "cortex-a15";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
|
||||||
ARMCPU *cpu;
|
|
||||||
|
|
||||||
cpu = cpu_arm_init(cpu_model);
|
|
||||||
if (!cpu) {
|
|
||||||
fprintf(stderr, "Unable to find CPU definition\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
/* We have to use a separate 64 bit variable here to avoid the gcc
|
/* We have to use a separate 64 bit variable here to avoid the gcc
|
||||||
* "comparison is always false due to limited range of data type"
|
* "comparison is always false due to limited range of data type"
|
||||||
@@ -337,23 +352,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
|
|||||||
memory_region_add_subregion(sysmem, 0x80000000, ram);
|
memory_region_add_subregion(sysmem, 0x80000000, ram);
|
||||||
|
|
||||||
/* 0x2c000000 A15MPCore private memory region (GIC) */
|
/* 0x2c000000 A15MPCore private memory region (GIC) */
|
||||||
dev = qdev_create(NULL, "a15mpcore_priv");
|
init_cpus(cpu_model, "a15mpcore_priv", 0x2c000000, pic);
|
||||||
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
|
|
||||||
qdev_init_nofail(dev);
|
|
||||||
busdev = SYS_BUS_DEVICE(dev);
|
|
||||||
sysbus_mmio_map(busdev, 0, 0x2c000000);
|
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
|
||||||
sysbus_connect_irq(busdev, n, cpu_irq[n]);
|
|
||||||
}
|
|
||||||
/* Interrupts [42:0] are from the motherboard;
|
|
||||||
* [47:43] are reserved; [63:48] are daughterboard
|
|
||||||
* peripherals. Note that some documentation numbers
|
|
||||||
* external interrupts starting from 32 (because there
|
|
||||||
* are internal interrupts 0..31).
|
|
||||||
*/
|
|
||||||
for (n = 0; n < 64; n++) {
|
|
||||||
pic[n] = qdev_get_gpio_in(dev, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A15 daughterboard peripherals: */
|
/* A15 daughterboard peripherals: */
|
||||||
|
|
||||||
|
|||||||
@@ -390,6 +390,12 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
|||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
|
object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||||
|
object_property_set_int(cpuobj, vbi->memmap[VIRT_CPUPERIPHS].base,
|
||||||
|
"reset-cbar", &error_abort);
|
||||||
|
}
|
||||||
|
|
||||||
object_property_set_bool(cpuobj, true, "realized", NULL);
|
object_property_set_bool(cpuobj, true, "realized", NULL);
|
||||||
}
|
}
|
||||||
fdt_add_cpu_nodes(vbi);
|
fdt_add_cpu_nodes(vbi);
|
||||||
|
|||||||
@@ -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", 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;
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
object_ref(OBJECT(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;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ typedef struct PL011State {
|
|||||||
uint32_t readbuff;
|
uint32_t readbuff;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t lcr;
|
uint32_t lcr;
|
||||||
|
uint32_t rsr;
|
||||||
uint32_t cr;
|
uint32_t cr;
|
||||||
uint32_t dmacr;
|
uint32_t dmacr;
|
||||||
uint32_t int_enabled;
|
uint32_t int_enabled;
|
||||||
@@ -81,13 +82,14 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
|
|||||||
}
|
}
|
||||||
if (s->read_count == s->read_trigger - 1)
|
if (s->read_count == s->read_trigger - 1)
|
||||||
s->int_level &= ~ PL011_INT_RX;
|
s->int_level &= ~ PL011_INT_RX;
|
||||||
|
s->rsr = c >> 8;
|
||||||
pl011_update(s);
|
pl011_update(s);
|
||||||
if (s->chr) {
|
if (s->chr) {
|
||||||
qemu_chr_accept_input(s->chr);
|
qemu_chr_accept_input(s->chr);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
case 1: /* UARTCR */
|
case 1: /* UARTRSR */
|
||||||
return 0;
|
return s->rsr;
|
||||||
case 6: /* UARTFR */
|
case 6: /* UARTFR */
|
||||||
return s->flags;
|
return s->flags;
|
||||||
case 8: /* UARTILPR */
|
case 8: /* UARTILPR */
|
||||||
@@ -146,8 +148,8 @@ static void pl011_write(void *opaque, hwaddr offset,
|
|||||||
s->int_level |= PL011_INT_TX;
|
s->int_level |= PL011_INT_TX;
|
||||||
pl011_update(s);
|
pl011_update(s);
|
||||||
break;
|
break;
|
||||||
case 1: /* UARTCR */
|
case 1: /* UARTRSR/UARTECR */
|
||||||
s->cr = value;
|
s->rsr = 0;
|
||||||
break;
|
break;
|
||||||
case 6: /* UARTFR */
|
case 6: /* UARTFR */
|
||||||
/* Writes to Flag register are ignored. */
|
/* Writes to Flag register are ignored. */
|
||||||
@@ -162,6 +164,11 @@ static void pl011_write(void *opaque, hwaddr offset,
|
|||||||
s->fbrd = value;
|
s->fbrd = value;
|
||||||
break;
|
break;
|
||||||
case 11: /* UARTLCR_H */
|
case 11: /* UARTLCR_H */
|
||||||
|
/* Reset the FIFO state on FIFO enable or disable */
|
||||||
|
if ((s->lcr ^ value) & 0x10) {
|
||||||
|
s->read_count = 0;
|
||||||
|
s->read_pos = 0;
|
||||||
|
}
|
||||||
s->lcr = value;
|
s->lcr = value;
|
||||||
pl011_set_read_trigger(s);
|
pl011_set_read_trigger(s);
|
||||||
break;
|
break;
|
||||||
@@ -214,7 +221,7 @@ static void pl011_put_fifo(void *opaque, uint32_t value)
|
|||||||
s->read_fifo[slot] = value;
|
s->read_fifo[slot] = value;
|
||||||
s->read_count++;
|
s->read_count++;
|
||||||
s->flags &= ~PL011_FLAG_RXFE;
|
s->flags &= ~PL011_FLAG_RXFE;
|
||||||
if (s->cr & 0x10 || s->read_count == 16) {
|
if (!(s->lcr & 0x10) || s->read_count == 16) {
|
||||||
s->flags |= PL011_FLAG_RXFF;
|
s->flags |= PL011_FLAG_RXFF;
|
||||||
}
|
}
|
||||||
if (s->read_count == s->read_trigger) {
|
if (s->read_count == s->read_trigger) {
|
||||||
@@ -242,13 +249,14 @@ static const MemoryRegionOps pl011_ops = {
|
|||||||
|
|
||||||
static const VMStateDescription vmstate_pl011 = {
|
static const VMStateDescription vmstate_pl011 = {
|
||||||
.name = "pl011",
|
.name = "pl011",
|
||||||
.version_id = 1,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 2,
|
||||||
.minimum_version_id_old = 1,
|
.minimum_version_id_old = 2,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(readbuff, PL011State),
|
VMSTATE_UINT32(readbuff, PL011State),
|
||||||
VMSTATE_UINT32(flags, PL011State),
|
VMSTATE_UINT32(flags, PL011State),
|
||||||
VMSTATE_UINT32(lcr, PL011State),
|
VMSTATE_UINT32(lcr, PL011State),
|
||||||
|
VMSTATE_UINT32(rsr, PL011State),
|
||||||
VMSTATE_UINT32(cr, PL011State),
|
VMSTATE_UINT32(cr, PL011State),
|
||||||
VMSTATE_UINT32(dmacr, PL011State),
|
VMSTATE_UINT32(dmacr, PL011State),
|
||||||
VMSTATE_UINT32(int_enabled, PL011State),
|
VMSTATE_UINT32(int_enabled, PL011State),
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ typedef struct SCLPConsoleLM {
|
|||||||
uint32_t write_errors; /* errors writing to char layer */
|
uint32_t write_errors; /* errors writing to char layer */
|
||||||
uint32_t length; /* length of byte stream in buffer */
|
uint32_t length; /* length of byte stream in buffer */
|
||||||
uint8_t buf[SIZE_CONSOLE_BUFFER];
|
uint8_t buf[SIZE_CONSOLE_BUFFER];
|
||||||
qemu_irq irq_console_read;
|
|
||||||
} SCLPConsoleLM;
|
} SCLPConsoleLM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -68,13 +67,15 @@ static int chr_can_read(void *opaque)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void receive_from_chr_layer(SCLPConsoleLM *scon, const uint8_t *buf,
|
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||||
int size)
|
|
||||||
{
|
{
|
||||||
|
SCLPConsoleLM *scon = opaque;
|
||||||
|
|
||||||
assert(size == 1);
|
assert(size == 1);
|
||||||
|
|
||||||
if (*buf == '\r' || *buf == '\n') {
|
if (*buf == '\r' || *buf == '\n') {
|
||||||
scon->event.event_pending = true;
|
scon->event.event_pending = true;
|
||||||
|
sclp_service_interrupt(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scon->buf[scon->length] = *buf;
|
scon->buf[scon->length] = *buf;
|
||||||
@@ -84,20 +85,6 @@ static void receive_from_chr_layer(SCLPConsoleLM *scon, const uint8_t *buf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Send data from a char device over to the guest
|
|
||||||
*/
|
|
||||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
|
||||||
{
|
|
||||||
SCLPConsoleLM *scon = opaque;
|
|
||||||
|
|
||||||
receive_from_chr_layer(scon, buf, size);
|
|
||||||
if (scon->event.event_pending) {
|
|
||||||
/* trigger SCLP read operation */
|
|
||||||
qemu_irq_raise(scon->irq_console_read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* functions to be called by event facility */
|
/* functions to be called by event facility */
|
||||||
|
|
||||||
static bool can_handle_event(uint8_t type)
|
static bool can_handle_event(uint8_t type)
|
||||||
@@ -298,11 +285,6 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh)
|
|||||||
return SCLP_RC_NORMAL_COMPLETION;
|
return SCLP_RC_NORMAL_COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trigger_console_data(void *opaque, int n, int level)
|
|
||||||
{
|
|
||||||
sclp_service_interrupt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* functions for live migration */
|
/* functions for live migration */
|
||||||
|
|
||||||
static const VMStateDescription vmstate_sclplmconsole = {
|
static const VMStateDescription vmstate_sclplmconsole = {
|
||||||
@@ -338,7 +320,6 @@ static int console_init(SCLPEvent *event)
|
|||||||
if (scon->chr) {
|
if (scon->chr) {
|
||||||
qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
|
qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
|
||||||
}
|
}
|
||||||
scon->irq_console_read = *qemu_allocate_irqs(trigger_console_data, NULL, 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ typedef struct SCLPConsole {
|
|||||||
uint32_t iov_bs; /* offset in buf for char layer read operation */
|
uint32_t iov_bs; /* offset in buf for char layer read operation */
|
||||||
uint32_t iov_data_len; /* length of byte stream in buffer */
|
uint32_t iov_data_len; /* length of byte stream in buffer */
|
||||||
uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
|
uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
|
||||||
qemu_irq irq_read_vt220;
|
|
||||||
} SCLPConsole;
|
} SCLPConsole;
|
||||||
|
|
||||||
/* character layer call-back functions */
|
/* character layer call-back functions */
|
||||||
@@ -49,11 +48,12 @@ static int chr_can_read(void *opaque)
|
|||||||
return SIZE_BUFFER_VT220 - scon->iov_data_len;
|
return SIZE_BUFFER_VT220 - scon->iov_data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive n bytes from character layer, save in iov buffer,
|
/* Send data from a char device over to the guest */
|
||||||
* and set event pending */
|
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||||
static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
|
|
||||||
int size)
|
|
||||||
{
|
{
|
||||||
|
SCLPConsole *scon = opaque;
|
||||||
|
|
||||||
|
assert(scon);
|
||||||
/* read data must fit into current buffer */
|
/* read data must fit into current buffer */
|
||||||
assert(size <= SIZE_BUFFER_VT220 - scon->iov_data_len);
|
assert(size <= SIZE_BUFFER_VT220 - scon->iov_data_len);
|
||||||
|
|
||||||
@@ -63,18 +63,7 @@ static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
|
|||||||
scon->iov_sclp_rest += size;
|
scon->iov_sclp_rest += size;
|
||||||
scon->iov_bs += size;
|
scon->iov_bs += size;
|
||||||
scon->event.event_pending = true;
|
scon->event.event_pending = true;
|
||||||
}
|
sclp_service_interrupt(0);
|
||||||
|
|
||||||
/* Send data from a char device over to the guest */
|
|
||||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
|
||||||
{
|
|
||||||
SCLPConsole *scon = opaque;
|
|
||||||
|
|
||||||
assert(scon);
|
|
||||||
|
|
||||||
receive_from_chr_layer(scon, buf, size);
|
|
||||||
/* trigger SCLP read operation */
|
|
||||||
qemu_irq_raise(scon->irq_read_vt220);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* functions to be called by event facility */
|
/* functions to be called by event facility */
|
||||||
@@ -192,11 +181,6 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trigger_ascii_console_data(void *opaque, int n, int level)
|
|
||||||
{
|
|
||||||
sclp_service_interrupt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const VMStateDescription vmstate_sclpconsole = {
|
static const VMStateDescription vmstate_sclpconsole = {
|
||||||
.name = "sclpconsole",
|
.name = "sclpconsole",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
@@ -232,8 +216,6 @@ static int console_init(SCLPEvent *event)
|
|||||||
qemu_chr_add_handlers(scon->chr, chr_can_read,
|
qemu_chr_add_handlers(scon->chr, chr_can_read,
|
||||||
chr_read, NULL, scon);
|
chr_read, NULL, scon);
|
||||||
}
|
}
|
||||||
scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
|
|
||||||
NULL, 1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# core qdev-related obj files, also used by *-user:
|
# core qdev-related obj files, also used by *-user:
|
||||||
common-obj-y += qdev.o qdev-properties.o
|
common-obj-y += qdev.o qdev-properties.o
|
||||||
|
common-obj-y += fw-path-provider.o
|
||||||
# irq.o needed for qdev GPIO handling:
|
# irq.o needed for qdev GPIO handling:
|
||||||
common-obj-y += irq.o
|
common-obj-y += irq.o
|
||||||
common-obj-y += hotplug.o
|
common-obj-y += hotplug.o
|
||||||
@@ -8,7 +9,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
|
||||||
|
|
||||||
|
|||||||
51
hw/core/fw-path-provider.c
Normal file
51
hw/core/fw-path-provider.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Firmware patch provider class and helpers.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; under version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hw/fw-path-provider.h"
|
||||||
|
|
||||||
|
char *fw_path_provider_get_dev_path(FWPathProvider *p, BusState *bus,
|
||||||
|
DeviceState *dev)
|
||||||
|
{
|
||||||
|
FWPathProviderClass *k = FW_PATH_PROVIDER_GET_CLASS(p);
|
||||||
|
|
||||||
|
return k->get_dev_path(p, bus, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *fw_path_provider_try_get_dev_path(Object *o, BusState *bus,
|
||||||
|
DeviceState *dev)
|
||||||
|
{
|
||||||
|
FWPathProvider *p = (FWPathProvider *)
|
||||||
|
object_dynamic_cast(o, TYPE_FW_PATH_PROVIDER);
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
return fw_path_provider_get_dev_path(p, bus, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo fw_path_provider_info = {
|
||||||
|
.name = TYPE_FW_PATH_PROVIDER,
|
||||||
|
.parent = TYPE_INTERFACE,
|
||||||
|
.class_size = sizeof(FWPathProviderClass),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void fw_path_provider_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&fw_path_provider_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(fw_path_provider_register_types)
|
||||||
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;
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
|
||||||
|
Object *val, Error **errp)
|
||||||
|
{
|
||||||
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
|
||||||
|
if (dev->realized) {
|
||||||
|
error_setg(errp, "Attempt to set link property '%s' on device '%s' "
|
||||||
|
"(type '%s') after it was realized",
|
||||||
|
name, dev->id, object_get_typename(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
|
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
|
||||||
{
|
{
|
||||||
void *ptr = dev;
|
void *ptr = dev;
|
||||||
|
|||||||
115
hw/core/qdev.c
115
hw/core/qdev.c
@@ -26,6 +26,7 @@
|
|||||||
this API directly. */
|
this API directly. */
|
||||||
|
|
||||||
#include "hw/qdev.h"
|
#include "hw/qdev.h"
|
||||||
|
#include "hw/fw-path-provider.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
@@ -98,6 +99,8 @@ static void bus_add_child(BusState *bus, DeviceState *child)
|
|||||||
object_property_add_link(OBJECT(bus), name,
|
object_property_add_link(OBJECT(bus), name,
|
||||||
object_get_typename(OBJECT(child)),
|
object_get_typename(OBJECT(child)),
|
||||||
(Object **)&kid->child,
|
(Object **)&kid->child,
|
||||||
|
NULL, /* read-only property */
|
||||||
|
0, /* return ownership on prop deletion */
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,6 +504,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)
|
||||||
{
|
{
|
||||||
@@ -529,6 +571,18 @@ static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *qdev_get_fw_dev_path_from_handler(BusState *bus, DeviceState *dev)
|
||||||
|
{
|
||||||
|
Object *obj = OBJECT(dev);
|
||||||
|
char *d = NULL;
|
||||||
|
|
||||||
|
while (!d && obj->parent) {
|
||||||
|
obj = obj->parent;
|
||||||
|
d = fw_path_provider_try_get_dev_path(obj, bus, dev);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
|
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
|
||||||
{
|
{
|
||||||
int l = 0;
|
int l = 0;
|
||||||
@@ -536,7 +590,10 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
|
|||||||
if (dev && dev->parent_bus) {
|
if (dev && dev->parent_bus) {
|
||||||
char *d;
|
char *d;
|
||||||
l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
|
l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
|
||||||
d = bus_get_fw_dev_path(dev->parent_bus, dev);
|
d = qdev_get_fw_dev_path_from_handler(dev->parent_bus, dev);
|
||||||
|
if (!d) {
|
||||||
|
d = bus_get_fw_dev_path(dev->parent_bus, dev);
|
||||||
|
}
|
||||||
if (d) {
|
if (d) {
|
||||||
l += snprintf(p + l, size - l, "%s", d);
|
l += snprintf(p + l, size - l, "%s", d);
|
||||||
g_free(d);
|
g_free(d);
|
||||||
@@ -677,6 +734,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) {
|
||||||
@@ -710,14 +768,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -735,7 +809,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)
|
||||||
@@ -767,7 +842,8 @@ static void device_initfn(Object *obj)
|
|||||||
} while (class != object_class_by_name(TYPE_DEVICE));
|
} while (class != object_class_by_name(TYPE_DEVICE));
|
||||||
|
|
||||||
object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
|
object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
|
||||||
(Object **)&dev->parent_bus, &error_abort);
|
(Object **)&dev->parent_bus, NULL, 0,
|
||||||
|
&error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_post_init(Object *obj)
|
static void device_post_init(Object *obj)
|
||||||
@@ -792,14 +868,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)
|
||||||
@@ -809,13 +877,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));
|
||||||
@@ -845,6 +913,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)
|
||||||
@@ -887,7 +963,12 @@ static void qbus_initfn(Object *obj)
|
|||||||
QTAILQ_INIT(&bus->children);
|
QTAILQ_INIT(&bus->children);
|
||||||
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,
|
||||||
|
object_property_allow_set_link,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
|
#include "ui/vnc.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
|
|
||||||
#undef VERBOSE
|
#undef VERBOSE
|
||||||
@@ -218,7 +219,7 @@ enum {
|
|||||||
|
|
||||||
/* These values can probably be changed arbitrarily. */
|
/* These values can probably be changed arbitrarily. */
|
||||||
#define SVGA_SCRATCH_SIZE 0x8000
|
#define SVGA_SCRATCH_SIZE 0x8000
|
||||||
#define SVGA_MAX_WIDTH 2360
|
#define SVGA_MAX_WIDTH ROUND_UP(2360, VNC_DIRTY_PIXELS_PER_BIT)
|
||||||
#define SVGA_MAX_HEIGHT 1770
|
#define SVGA_MAX_HEIGHT 1770
|
||||||
|
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
|
|||||||
@@ -537,9 +537,15 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
|
|||||||
Error *local_errp = NULL;
|
Error *local_errp = NULL;
|
||||||
|
|
||||||
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
|
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
|
||||||
(Object **)&ds->dma, &local_errp);
|
(Object **)&ds->dma,
|
||||||
|
object_property_allow_set_link,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&local_errp);
|
||||||
object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
|
object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
|
||||||
(Object **)&cs->dma, &local_errp);
|
(Object **)&cs->dma,
|
||||||
|
object_property_allow_set_link,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&local_errp);
|
||||||
if (local_errp) {
|
if (local_errp) {
|
||||||
goto xilinx_axidma_realize_fail;
|
goto xilinx_axidma_realize_fail;
|
||||||
}
|
}
|
||||||
@@ -571,10 +577,16 @@ static void xilinx_axidma_init(Object *obj)
|
|||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
|
|
||||||
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
|
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
|
||||||
(Object **)&s->tx_data_dev, &error_abort);
|
(Object **)&s->tx_data_dev,
|
||||||
|
qdev_prop_allow_set_link_before_realize,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&error_abort);
|
||||||
object_property_add_link(obj, "axistream-control-connected",
|
object_property_add_link(obj, "axistream-control-connected",
|
||||||
TYPE_STREAM_SLAVE,
|
TYPE_STREAM_SLAVE,
|
||||||
(Object **)&s->tx_control_dev, &error_abort);
|
(Object **)&s->tx_control_dev,
|
||||||
|
qdev_prop_allow_set_link_before_realize,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
|
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
|
||||||
TYPE_XILINX_AXI_DMA_DATA_STREAM);
|
TYPE_XILINX_AXI_DMA_DATA_STREAM);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
#include "qom/qom-qobject.h"
|
#include "qom/qom-qobject.h"
|
||||||
|
|
||||||
typedef struct AcpiCpuInfo {
|
typedef struct AcpiCpuInfo {
|
||||||
DECLARE_BITMAP(found_cpus, MAX_CPUMASK_BITS + 1);
|
DECLARE_BITMAP(found_cpus, ACPI_CPU_HOTPLUG_ID_LIMIT);
|
||||||
} AcpiCpuInfo;
|
} AcpiCpuInfo;
|
||||||
|
|
||||||
typedef struct AcpiMcfgInfo {
|
typedef struct AcpiMcfgInfo {
|
||||||
@@ -117,7 +117,7 @@ int acpi_add_cpu_info(Object *o, void *opaque)
|
|||||||
|
|
||||||
if (object_dynamic_cast(o, TYPE_CPU)) {
|
if (object_dynamic_cast(o, TYPE_CPU)) {
|
||||||
apic_id = object_property_get_int(o, "apic-id", NULL);
|
apic_id = object_property_get_int(o, "apic-id", NULL);
|
||||||
assert(apic_id <= MAX_CPUMASK_BITS);
|
assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT);
|
||||||
|
|
||||||
set_bit(apic_id, cpu->found_cpus);
|
set_bit(apic_id, cpu->found_cpus);
|
||||||
}
|
}
|
||||||
@@ -226,14 +226,14 @@ static void acpi_get_pci_info(PcPciInfo *info)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
build_header(GArray *linker, GArray *table_data,
|
build_header(GArray *linker, GArray *table_data,
|
||||||
AcpiTableHeader *h, uint32_t sig, int len, uint8_t rev)
|
AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
|
||||||
{
|
{
|
||||||
h->signature = cpu_to_le32(sig);
|
memcpy(&h->signature, sig, 4);
|
||||||
h->length = cpu_to_le32(len);
|
h->length = cpu_to_le32(len);
|
||||||
h->revision = rev;
|
h->revision = rev;
|
||||||
memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
|
memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
|
||||||
memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
|
memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
|
||||||
memcpy(h->oem_table_id + 4, (void *)&sig, 4);
|
memcpy(h->oem_table_id + 4, sig, 4);
|
||||||
h->oem_revision = cpu_to_le32(1);
|
h->oem_revision = cpu_to_le32(1);
|
||||||
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
|
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
|
||||||
h->asl_compiler_revision = cpu_to_le32(1);
|
h->asl_compiler_revision = cpu_to_le32(1);
|
||||||
@@ -495,7 +495,7 @@ static void
|
|||||||
build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
|
build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
|
||||||
{
|
{
|
||||||
AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
|
AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
|
||||||
facs->signature = cpu_to_le32(ACPI_FACS_SIGNATURE);
|
memcpy(&facs->signature, "FACS", 4);
|
||||||
facs->length = cpu_to_le32(sizeof(*facs));
|
facs->length = cpu_to_le32(sizeof(*facs));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +552,7 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
|
|||||||
fadt_setup(fadt, pm);
|
fadt_setup(fadt, pm);
|
||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)fadt, ACPI_FACP_SIGNATURE, sizeof(*fadt), 1);
|
(void *)fadt, "FACP", sizeof(*fadt), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -621,7 +621,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
|
|||||||
local_nmi->lint = 1; /* ACPI_LINT1 */
|
local_nmi->lint = 1; /* ACPI_LINT1 */
|
||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)(table_data->data + madt_start), ACPI_APIC_SIGNATURE,
|
(void *)(table_data->data + madt_start), "APIC",
|
||||||
table_data->len - madt_start, 1);
|
table_data->len - madt_start, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,7 +841,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
|
|||||||
pc = PCI_DEVICE_GET_CLASS(pdev);
|
pc = PCI_DEVICE_GET_CLASS(pdev);
|
||||||
dc = DEVICE_GET_CLASS(pdev);
|
dc = DEVICE_GET_CLASS(pdev);
|
||||||
|
|
||||||
if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {
|
if (pc->class_id == PCI_CLASS_BRIDGE_ISA || pc->is_bridge) {
|
||||||
set_bit(slot, slot_device_system);
|
set_bit(slot, slot_device_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,7 +882,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
|
|||||||
memcpy(pcihp, ACPI_PCIVGA_AML, ACPI_PCIVGA_SIZEOF);
|
memcpy(pcihp, ACPI_PCIVGA_AML, ACPI_PCIVGA_SIZEOF);
|
||||||
patch_pcivga(i, pcihp);
|
patch_pcivga(i, pcihp);
|
||||||
} else if (system) {
|
} else if (system) {
|
||||||
/* Nothing to do: system devices are in DSDT. */
|
/* Nothing to do: system devices are in DSDT or in SSDT above. */
|
||||||
} else if (present) {
|
} else if (present) {
|
||||||
void *pcihp = acpi_data_push(bus_table,
|
void *pcihp = acpi_data_push(bus_table,
|
||||||
ACPI_PCINOHP_SIZEOF);
|
ACPI_PCINOHP_SIZEOF);
|
||||||
@@ -907,7 +907,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
|
|||||||
|
|
||||||
build_append_byte(notify, 0x7B); /* AndOp */
|
build_append_byte(notify, 0x7B); /* AndOp */
|
||||||
build_append_byte(notify, 0x68); /* Arg0Op */
|
build_append_byte(notify, 0x68); /* Arg0Op */
|
||||||
build_append_int(notify, 0x1 << i);
|
build_append_int(notify, 0x1U << i);
|
||||||
build_append_byte(notify, 0x00); /* NullName */
|
build_append_byte(notify, 0x00); /* NullName */
|
||||||
build_append_byte(notify, 0x86); /* NotifyOp */
|
build_append_byte(notify, 0x86); /* NotifyOp */
|
||||||
build_append_nameseg(notify, "S%.02X_", PCI_DEVFN(i, 0));
|
build_append_nameseg(notify, "S%.02X_", PCI_DEVFN(i, 0));
|
||||||
@@ -999,11 +999,16 @@ build_ssdt(GArray *table_data, GArray *linker,
|
|||||||
AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc,
|
AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc,
|
||||||
PcPciInfo *pci, PcGuestInfo *guest_info)
|
PcPciInfo *pci, PcGuestInfo *guest_info)
|
||||||
{
|
{
|
||||||
int acpi_cpus = MIN(0xff, guest_info->apic_id_limit);
|
unsigned acpi_cpus = guest_info->apic_id_limit;
|
||||||
int ssdt_start = table_data->len;
|
int ssdt_start = table_data->len;
|
||||||
uint8_t *ssdt_ptr;
|
uint8_t *ssdt_ptr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* The current AML generator can cover the APIC ID range [0..255],
|
||||||
|
* inclusive, for VCPU hotplug. */
|
||||||
|
QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
|
||||||
|
g_assert(acpi_cpus <= ACPI_CPU_HOTPLUG_ID_LIMIT);
|
||||||
|
|
||||||
/* Copy header and patch values in the S3_ / S4_ / S5_ packages */
|
/* Copy header and patch values in the S3_ / S4_ / S5_ packages */
|
||||||
ssdt_ptr = acpi_data_push(table_data, sizeof(ssdp_misc_aml));
|
ssdt_ptr = acpi_data_push(table_data, sizeof(ssdp_misc_aml));
|
||||||
memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
|
memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
|
||||||
@@ -1019,8 +1024,8 @@ build_ssdt(GArray *table_data, GArray *linker,
|
|||||||
|
|
||||||
patch_pci_windows(pci, ssdt_ptr, sizeof(ssdp_misc_aml));
|
patch_pci_windows(pci, ssdt_ptr, sizeof(ssdp_misc_aml));
|
||||||
|
|
||||||
*(uint16_t *)(ssdt_ptr + *ssdt_isa_pest) =
|
ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml),
|
||||||
cpu_to_le16(misc->pvpanic_port);
|
ssdt_isa_pest[0], 16, misc->pvpanic_port);
|
||||||
|
|
||||||
{
|
{
|
||||||
GArray *sb_scope = build_alloc_array();
|
GArray *sb_scope = build_alloc_array();
|
||||||
@@ -1050,9 +1055,21 @@ build_ssdt(GArray *table_data, GArray *linker,
|
|||||||
|
|
||||||
{
|
{
|
||||||
GArray *package = build_alloc_array();
|
GArray *package = build_alloc_array();
|
||||||
uint8_t op = 0x12; /* PackageOp */
|
uint8_t op;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: The ability to create variable-sized packages was first introduced in ACPI 2.0. ACPI 1.0 only
|
||||||
|
* allowed fixed-size packages with up to 255 elements.
|
||||||
|
* Windows guests up to win2k8 fail when VarPackageOp is used.
|
||||||
|
*/
|
||||||
|
if (acpi_cpus <= 255) {
|
||||||
|
op = 0x12; /* PackageOp */
|
||||||
|
build_append_byte(package, acpi_cpus); /* NumElements */
|
||||||
|
} else {
|
||||||
|
op = 0x13; /* VarPackageOp */
|
||||||
|
build_append_int(package, acpi_cpus); /* VarNumElements */
|
||||||
|
}
|
||||||
|
|
||||||
build_append_byte(package, acpi_cpus); /* NumElements */
|
|
||||||
for (i = 0; i < acpi_cpus; i++) {
|
for (i = 0; i < acpi_cpus; i++) {
|
||||||
uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00;
|
uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00;
|
||||||
build_append_byte(package, b);
|
build_append_byte(package, b);
|
||||||
@@ -1093,7 +1110,7 @@ build_ssdt(GArray *table_data, GArray *linker,
|
|||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)(table_data->data + ssdt_start),
|
(void *)(table_data->data + ssdt_start),
|
||||||
ACPI_SSDT_SIGNATURE, table_data->len - ssdt_start, 1);
|
"SSDT", table_data->len - ssdt_start, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1108,7 +1125,7 @@ build_hpet(GArray *table_data, GArray *linker)
|
|||||||
hpet->timer_block_id = cpu_to_le32(0x8086a201);
|
hpet->timer_block_id = cpu_to_le32(0x8086a201);
|
||||||
hpet->addr.address = cpu_to_le64(HPET_BASE);
|
hpet->addr.address = cpu_to_le64(HPET_BASE);
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)hpet, ACPI_HPET_SIGNATURE, sizeof(*hpet), 1);
|
(void *)hpet, "HPET", sizeof(*hpet), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1200,7 +1217,7 @@ build_srat(GArray *table_data, GArray *linker,
|
|||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)(table_data->data + srat_start),
|
(void *)(table_data->data + srat_start),
|
||||||
ACPI_SRAT_SIGNATURE,
|
"SRAT",
|
||||||
table_data->len - srat_start, 1);
|
table_data->len - srat_start, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1208,7 +1225,7 @@ static void
|
|||||||
build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
|
build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
|
||||||
{
|
{
|
||||||
AcpiTableMcfg *mcfg;
|
AcpiTableMcfg *mcfg;
|
||||||
uint32_t sig;
|
const char *sig;
|
||||||
int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
|
int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
|
||||||
|
|
||||||
mcfg = acpi_data_push(table_data, len);
|
mcfg = acpi_data_push(table_data, len);
|
||||||
@@ -1225,9 +1242,10 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
|
|||||||
* ACPI spec requires OSPMs to ignore such tables.
|
* ACPI spec requires OSPMs to ignore such tables.
|
||||||
*/
|
*/
|
||||||
if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
|
if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
|
||||||
sig = ACPI_RSRV_SIGNATURE;
|
/* Reserved signature: ignored by OSPM */
|
||||||
|
sig = "QEMU";
|
||||||
} else {
|
} else {
|
||||||
sig = ACPI_MCFG_SIGNATURE;
|
sig = "MCFG";
|
||||||
}
|
}
|
||||||
build_header(linker, table_data, (void *)mcfg, sig, len, 1);
|
build_header(linker, table_data, (void *)mcfg, sig, len, 1);
|
||||||
}
|
}
|
||||||
@@ -1243,7 +1261,7 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
|
|||||||
memcpy(dsdt, misc->dsdt_code, misc->dsdt_size);
|
memcpy(dsdt, misc->dsdt_code, misc->dsdt_size);
|
||||||
|
|
||||||
memset(dsdt, 0, sizeof *dsdt);
|
memset(dsdt, 0, sizeof *dsdt);
|
||||||
build_header(linker, table_data, dsdt, ACPI_DSDT_SIGNATURE,
|
build_header(linker, table_data, dsdt, "DSDT",
|
||||||
misc->dsdt_size, 1);
|
misc->dsdt_size, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1268,7 +1286,7 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
|
|||||||
sizeof(uint32_t));
|
sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)rsdt, ACPI_RSDT_SIGNATURE, rsdt_len, 1);
|
(void *)rsdt, "RSDT", rsdt_len, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GArray *
|
static GArray *
|
||||||
@@ -1279,7 +1297,7 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
|
|||||||
bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 1,
|
bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 1,
|
||||||
true /* fseg memory */);
|
true /* fseg memory */);
|
||||||
|
|
||||||
rsdp->signature = cpu_to_le64(ACPI_RSDP_SIGNATURE);
|
memcpy(&rsdp->signature, "RSD PTR ", 8);
|
||||||
memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
|
memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
|
||||||
rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
|
rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
|
||||||
/* Address to be filled by Guest linker */
|
/* Address to be filled by Guest linker */
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ struct Acpi20GenericAddress {
|
|||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
typedef struct Acpi20GenericAddress Acpi20GenericAddress;
|
typedef struct Acpi20GenericAddress Acpi20GenericAddress;
|
||||||
|
|
||||||
#define ACPI_RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
|
|
||||||
|
|
||||||
struct AcpiRsdpDescriptor { /* Root System Descriptor Pointer */
|
struct AcpiRsdpDescriptor { /* Root System Descriptor Pointer */
|
||||||
uint64_t signature; /* ACPI signature, contains "RSD PTR " */
|
uint64_t signature; /* ACPI signature, contains "RSD PTR " */
|
||||||
uint8_t checksum; /* To make sum of struct == 0 */
|
uint8_t checksum; /* To make sum of struct == 0 */
|
||||||
@@ -92,7 +90,6 @@ typedef struct AcpiTableHeader AcpiTableHeader;
|
|||||||
/*
|
/*
|
||||||
* ACPI 1.0 Fixed ACPI Description Table (FADT)
|
* ACPI 1.0 Fixed ACPI Description Table (FADT)
|
||||||
*/
|
*/
|
||||||
#define ACPI_FACP_SIGNATURE 0x50434146 // FACP
|
|
||||||
struct AcpiFadtDescriptorRev1
|
struct AcpiFadtDescriptorRev1
|
||||||
{
|
{
|
||||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||||
@@ -141,7 +138,6 @@ typedef struct AcpiFadtDescriptorRev1 AcpiFadtDescriptorRev1;
|
|||||||
/*
|
/*
|
||||||
* ACPI 1.0 Root System Description Table (RSDT)
|
* ACPI 1.0 Root System Description Table (RSDT)
|
||||||
*/
|
*/
|
||||||
#define ACPI_RSDT_SIGNATURE 0x54445352 // RSDT
|
|
||||||
struct AcpiRsdtDescriptorRev1
|
struct AcpiRsdtDescriptorRev1
|
||||||
{
|
{
|
||||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||||
@@ -153,7 +149,6 @@ typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1;
|
|||||||
/*
|
/*
|
||||||
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
|
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
|
||||||
*/
|
*/
|
||||||
#define ACPI_FACS_SIGNATURE 0x53434146 // FACS
|
|
||||||
struct AcpiFacsDescriptorRev1
|
struct AcpiFacsDescriptorRev1
|
||||||
{
|
{
|
||||||
uint32_t signature; /* ACPI Signature */
|
uint32_t signature; /* ACPI Signature */
|
||||||
@@ -169,7 +164,6 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
|
|||||||
/*
|
/*
|
||||||
* Differentiated System Description Table (DSDT)
|
* Differentiated System Description Table (DSDT)
|
||||||
*/
|
*/
|
||||||
#define ACPI_DSDT_SIGNATURE 0x54445344 // DSDT
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MADT values and structures
|
* MADT values and structures
|
||||||
@@ -182,7 +176,6 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
|
|||||||
|
|
||||||
/* Master MADT */
|
/* Master MADT */
|
||||||
|
|
||||||
#define ACPI_APIC_SIGNATURE 0x43495041 // APIC
|
|
||||||
struct AcpiMultipleApicTable
|
struct AcpiMultipleApicTable
|
||||||
{
|
{
|
||||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||||
@@ -253,7 +246,6 @@ typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
|
|||||||
/*
|
/*
|
||||||
* HPET Description Table
|
* HPET Description Table
|
||||||
*/
|
*/
|
||||||
#define ACPI_HPET_SIGNATURE 0x54455048 // HPET
|
|
||||||
struct Acpi20Hpet {
|
struct Acpi20Hpet {
|
||||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||||
uint32_t timer_block_id;
|
uint32_t timer_block_id;
|
||||||
@@ -268,7 +260,6 @@ typedef struct Acpi20Hpet Acpi20Hpet;
|
|||||||
* SRAT (NUMA topology description) table
|
* SRAT (NUMA topology description) table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ACPI_SRAT_SIGNATURE 0x54415253 // SRAT
|
|
||||||
struct AcpiSystemResourceAffinityTable
|
struct AcpiSystemResourceAffinityTable
|
||||||
{
|
{
|
||||||
ACPI_TABLE_HEADER_DEF
|
ACPI_TABLE_HEADER_DEF
|
||||||
@@ -316,11 +307,6 @@ struct AcpiMcfgAllocation {
|
|||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
typedef struct AcpiMcfgAllocation AcpiMcfgAllocation;
|
typedef struct AcpiMcfgAllocation AcpiMcfgAllocation;
|
||||||
|
|
||||||
#define ACPI_MCFG_SIGNATURE 0x4746434d // MCFG
|
|
||||||
|
|
||||||
/* Reserved signature: ignored by OSPM */
|
|
||||||
#define ACPI_RSRV_SIGNATURE 0x554d4551 // QEMU
|
|
||||||
|
|
||||||
struct AcpiTableMcfg {
|
struct AcpiTableMcfg {
|
||||||
ACPI_TABLE_HEADER_DEF;
|
ACPI_TABLE_HEADER_DEF;
|
||||||
uint8_t reserved[8];
|
uint8_t reserved[8];
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
hw/i386/pc.c
16
hw/i386/pc.c
@@ -53,6 +53,7 @@
|
|||||||
#include "qemu/bitmap.h"
|
#include "qemu/bitmap.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "hw/acpi/acpi.h"
|
#include "hw/acpi/acpi.h"
|
||||||
|
#include "hw/acpi/cpu_hotplug.h"
|
||||||
#include "hw/cpu/icc_bus.h"
|
#include "hw/cpu/icc_bus.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "hw/pci/pci_host.h"
|
#include "hw/pci/pci_host.h"
|
||||||
@@ -974,6 +975,13 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (apic_id >= ACPI_CPU_HOTPLUG_ID_LIMIT) {
|
||||||
|
error_setg(errp, "Unable to add CPU: %" PRIi64
|
||||||
|
", resulting APIC ID (%" PRIi64 ") is too large",
|
||||||
|
id, apic_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
icc_bridge = DEVICE(object_resolve_path_type("icc-bridge",
|
icc_bridge = DEVICE(object_resolve_path_type("icc-bridge",
|
||||||
TYPE_ICC_BRIDGE, NULL));
|
TYPE_ICC_BRIDGE, NULL));
|
||||||
pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
|
pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
|
||||||
@@ -984,6 +992,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
|
|||||||
int i;
|
int i;
|
||||||
X86CPU *cpu = NULL;
|
X86CPU *cpu = NULL;
|
||||||
Error *error = NULL;
|
Error *error = NULL;
|
||||||
|
unsigned long apic_id_limit;
|
||||||
|
|
||||||
/* init CPUs */
|
/* init CPUs */
|
||||||
if (cpu_model == NULL) {
|
if (cpu_model == NULL) {
|
||||||
@@ -995,6 +1004,13 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
|
|||||||
}
|
}
|
||||||
current_cpu_model = cpu_model;
|
current_cpu_model = cpu_model;
|
||||||
|
|
||||||
|
apic_id_limit = pc_apic_id_limit(max_cpus);
|
||||||
|
if (apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) {
|
||||||
|
error_report("max_cpus is too large. APIC ID of last CPU is %lu",
|
||||||
|
apic_id_limit - 1);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < smp_cpus; i++) {
|
for (i = 0; i < smp_cpus; i++) {
|
||||||
cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
|
cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
|
||||||
icc_bridge, &error);
|
icc_bridge, &error);
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ 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;
|
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)
|
||||||
@@ -299,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)
|
||||||
@@ -345,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);
|
||||||
}
|
}
|
||||||
@@ -358,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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ 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;
|
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)
|
||||||
|
|||||||
@@ -118,11 +118,12 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
|
|||||||
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
||||||
{
|
{
|
||||||
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
|
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
|
||||||
PCIDevice *pci_dev = PCI_DEVICE(d);
|
PCIDevice *pci_dev =
|
||||||
|
(PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
|
||||||
|
|
||||||
DPRINTF(0, "raise irq\n");
|
DPRINTF(0, "raise irq\n");
|
||||||
|
|
||||||
if (msi_enabled(pci_dev)) {
|
if (pci_dev && msi_enabled(pci_dev)) {
|
||||||
msi_notify(pci_dev, 0);
|
msi_notify(pci_dev, 0);
|
||||||
} else {
|
} else {
|
||||||
qemu_irq_raise(s->irq);
|
qemu_irq_raise(s->irq);
|
||||||
@@ -132,10 +133,12 @@ static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
|||||||
static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
|
static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
|
||||||
{
|
{
|
||||||
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
|
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
|
||||||
|
PCIDevice *pci_dev =
|
||||||
|
(PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
|
||||||
|
|
||||||
DPRINTF(0, "lower irq\n");
|
DPRINTF(0, "lower irq\n");
|
||||||
|
|
||||||
if (!msi_enabled(PCI_DEVICE(d))) {
|
if (!pci_dev || !msi_enabled(pci_dev)) {
|
||||||
qemu_irq_lower(s->irq);
|
qemu_irq_lower(s->irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1311,7 +1314,7 @@ static const VMStateDescription vmstate_sysbus_ahci = {
|
|||||||
.name = "sysbus-ahci",
|
.name = "sysbus-ahci",
|
||||||
.unmigratable = 1, /* Still buggy under I/O load */
|
.unmigratable = 1, /* Still buggy under I/O load */
|
||||||
.fields = (VMStateField []) {
|
.fields = (VMStateField []) {
|
||||||
VMSTATE_AHCI(ahci, AHCIPCIState),
|
VMSTATE_AHCI(ahci, SysbusAHCIState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1328,7 +1331,7 @@ static void sysbus_ahci_realize(DeviceState *dev, Error **errp)
|
|||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||||
SysbusAHCIState *s = SYSBUS_AHCI(dev);
|
SysbusAHCIState *s = SYSBUS_AHCI(dev);
|
||||||
|
|
||||||
ahci_init(&s->ahci, dev, NULL, s->num_ports);
|
ahci_init(&s->ahci, dev, &address_space_memory, s->num_ports);
|
||||||
|
|
||||||
sysbus_init_mmio(sbd, &s->ahci.mem);
|
sysbus_init_mmio(sbd, &s->ahci.mem);
|
||||||
sysbus_init_irq(sbd, &s->ahci.irq);
|
sysbus_init_irq(sbd, &s->ahci.irq);
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ static const VMStateDescription vmstate_bmdma_current = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const VMStateDescription vmstate_bmdma_status = {
|
static const VMStateDescription vmstate_bmdma_status = {
|
||||||
.name ="ide bmdma/status",
|
.name ="ide bmdma/status",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
|
|||||||
@@ -201,12 +201,12 @@ static void apic_external_nmi(APICCommonState *s)
|
|||||||
|
|
||||||
#define foreach_apic(apic, deliver_bitmask, code) \
|
#define foreach_apic(apic, deliver_bitmask, code) \
|
||||||
{\
|
{\
|
||||||
int __i, __j, __mask;\
|
int __i, __j;\
|
||||||
for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
|
for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
|
||||||
__mask = deliver_bitmask[__i];\
|
uint32_t __mask = deliver_bitmask[__i];\
|
||||||
if (__mask) {\
|
if (__mask) {\
|
||||||
for(__j = 0; __j < 32; __j++) {\
|
for(__j = 0; __j < 32; __j++) {\
|
||||||
if (__mask & (1 << __j)) {\
|
if (__mask & (1U << __j)) {\
|
||||||
apic = local_apics[__i * 32 + __j];\
|
apic = local_apics[__i * 32 + __j];\
|
||||||
if (apic) {\
|
if (apic) {\
|
||||||
code;\
|
code;\
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ static FslMpicInfo fsl_mpic_42 = {
|
|||||||
#define TCCR_TOG 0x80000000 /* toggles when decrement to zero */
|
#define TCCR_TOG 0x80000000 /* toggles when decrement to zero */
|
||||||
|
|
||||||
#define IDR_EP_SHIFT 31
|
#define IDR_EP_SHIFT 31
|
||||||
#define IDR_EP_MASK (1 << IDR_EP_SHIFT)
|
#define IDR_EP_MASK (1U << IDR_EP_SHIFT)
|
||||||
#define IDR_CI0_SHIFT 30
|
#define IDR_CI0_SHIFT 30
|
||||||
#define IDR_CI1_SHIFT 29
|
#define IDR_CI1_SHIFT 29
|
||||||
#define IDR_P1_SHIFT 1
|
#define IDR_P1_SHIFT 1
|
||||||
@@ -220,17 +220,17 @@ typedef struct IRQSource {
|
|||||||
} IRQSource;
|
} IRQSource;
|
||||||
|
|
||||||
#define IVPR_MASK_SHIFT 31
|
#define IVPR_MASK_SHIFT 31
|
||||||
#define IVPR_MASK_MASK (1 << IVPR_MASK_SHIFT)
|
#define IVPR_MASK_MASK (1U << IVPR_MASK_SHIFT)
|
||||||
#define IVPR_ACTIVITY_SHIFT 30
|
#define IVPR_ACTIVITY_SHIFT 30
|
||||||
#define IVPR_ACTIVITY_MASK (1 << IVPR_ACTIVITY_SHIFT)
|
#define IVPR_ACTIVITY_MASK (1U << IVPR_ACTIVITY_SHIFT)
|
||||||
#define IVPR_MODE_SHIFT 29
|
#define IVPR_MODE_SHIFT 29
|
||||||
#define IVPR_MODE_MASK (1 << IVPR_MODE_SHIFT)
|
#define IVPR_MODE_MASK (1U << IVPR_MODE_SHIFT)
|
||||||
#define IVPR_POLARITY_SHIFT 23
|
#define IVPR_POLARITY_SHIFT 23
|
||||||
#define IVPR_POLARITY_MASK (1 << IVPR_POLARITY_SHIFT)
|
#define IVPR_POLARITY_MASK (1U << IVPR_POLARITY_SHIFT)
|
||||||
#define IVPR_SENSE_SHIFT 22
|
#define IVPR_SENSE_SHIFT 22
|
||||||
#define IVPR_SENSE_MASK (1 << IVPR_SENSE_SHIFT)
|
#define IVPR_SENSE_MASK (1U << IVPR_SENSE_SHIFT)
|
||||||
|
|
||||||
#define IVPR_PRIORITY_MASK (0xF << 16)
|
#define IVPR_PRIORITY_MASK (0xFU << 16)
|
||||||
#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
|
#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
|
||||||
#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
|
#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
|
||||||
|
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ static void kvm_openpic_realize(DeviceState *dev, Error **errp)
|
|||||||
qdev_init_gpio_in(dev, kvm_openpic_set_irq, OPENPIC_MAX_IRQ);
|
qdev_init_gpio_in(dev, kvm_openpic_set_irq, OPENPIC_MAX_IRQ);
|
||||||
|
|
||||||
opp->mem_listener.region_add = kvm_openpic_region_add;
|
opp->mem_listener.region_add = kvm_openpic_region_add;
|
||||||
opp->mem_listener.region_add = kvm_openpic_region_del;
|
opp->mem_listener.region_del = kvm_openpic_region_del;
|
||||||
memory_listener_register(&opp->mem_listener, &address_space_memory);
|
memory_listener_register(&opp->mem_listener, &address_space_memory);
|
||||||
|
|
||||||
/* indicate pic capabilities */
|
/* indicate pic capabilities */
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
|
|||||||
CPU_IRQ_TIMER_IN;
|
CPU_IRQ_TIMER_IN;
|
||||||
if (i == s->target_cpu) {
|
if (i == s->target_cpu) {
|
||||||
for (j = 0; j < 32; j++) {
|
for (j = 0; j < 32; j++) {
|
||||||
if ((s->intregm_pending & (1 << j)) && intbit_to_level[j]) {
|
if ((s->intregm_pending & (1U << j)) && intbit_to_level[j]) {
|
||||||
s->slaves[i].intreg_pending |= 1 << intbit_to_level[j];
|
s->slaves[i].intreg_pending |= 1 << intbit_to_level[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -71,8 +71,9 @@ static void update_irq(struct xlx_pic *p)
|
|||||||
|
|
||||||
/* Update the vector register. */
|
/* Update the vector register. */
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
if (p->regs[R_IPR] & (1 << i))
|
if (p->regs[R_IPR] & (1U << i)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i == 32)
|
if (i == 32)
|
||||||
i = ~0;
|
i = ~0;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1043,7 +1043,7 @@ static void vfio_bar_write(void *opaque, hwaddr addr,
|
|||||||
buf.dword = cpu_to_le32(data);
|
buf.dword = cpu_to_le32(data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hw_error("vfio: unsupported write size, %d bytes\n", size);
|
hw_error("vfio: unsupported write size, %d bytes", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,7 +1103,7 @@ static uint64_t vfio_bar_read(void *opaque,
|
|||||||
data = le32_to_cpu(buf.dword);
|
data = le32_to_cpu(buf.dword);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hw_error("vfio: unsupported read size, %d bytes\n", size);
|
hw_error("vfio: unsupported read size, %d bytes", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1157,7 +1157,7 @@ static void vfio_pci_load_rom(VFIODevice *vdev)
|
|||||||
if (!vdev->rom_size) {
|
if (!vdev->rom_size) {
|
||||||
vdev->rom_read_failed = true;
|
vdev->rom_read_failed = true;
|
||||||
error_report("vfio-pci: Cannot read device rom at "
|
error_report("vfio-pci: Cannot read device rom at "
|
||||||
"%04x:%02x:%02x.%x\n",
|
"%04x:%02x:%02x.%x",
|
||||||
vdev->host.domain, vdev->host.bus, vdev->host.slot,
|
vdev->host.domain, vdev->host.bus, vdev->host.slot,
|
||||||
vdev->host.function);
|
vdev->host.function);
|
||||||
error_printf("Device option ROM contents are probably invalid "
|
error_printf("Device option ROM contents are probably invalid "
|
||||||
@@ -1192,11 +1192,8 @@ static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size)
|
|||||||
uint64_t val = ((uint64_t)1 << (size * 8)) - 1;
|
uint64_t val = ((uint64_t)1 << (size * 8)) - 1;
|
||||||
|
|
||||||
/* Load the ROM lazily when the guest tries to read it */
|
/* Load the ROM lazily when the guest tries to read it */
|
||||||
if (unlikely(!vdev->rom)) {
|
if (unlikely(!vdev->rom && !vdev->rom_read_failed)) {
|
||||||
vfio_pci_load_rom(vdev);
|
vfio_pci_load_rom(vdev);
|
||||||
if (unlikely(!vdev->rom && !vdev->rom_read_failed)) {
|
|
||||||
vfio_pci_load_rom(vdev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&val, vdev->rom + addr,
|
memcpy(&val, vdev->rom + addr,
|
||||||
@@ -1341,7 +1338,7 @@ static void vfio_vga_write(void *opaque, hwaddr addr,
|
|||||||
buf.dword = cpu_to_le32(data);
|
buf.dword = cpu_to_le32(data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hw_error("vfio: unsupported write size, %d bytes\n", size);
|
hw_error("vfio: unsupported write size, %d bytes", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1384,7 +1381,7 @@ static uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size)
|
|||||||
data = le32_to_cpu(buf.dword);
|
data = le32_to_cpu(buf.dword);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hw_error("vfio: unsupported read size, %d bytes\n", size);
|
hw_error("vfio: unsupported read size, %d bytes", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1429,7 +1426,7 @@ static uint64_t vfio_generic_window_quirk_read(void *opaque,
|
|||||||
|
|
||||||
if (!vfio_range_contained(addr, size, quirk->data.data_offset,
|
if (!vfio_range_contained(addr, size, quirk->data.data_offset,
|
||||||
quirk->data.data_size)) {
|
quirk->data.data_size)) {
|
||||||
hw_error("%s: window data read not fully contained: %s\n",
|
hw_error("%s: window data read not fully contained: %s",
|
||||||
__func__, memory_region_name(&quirk->mem));
|
__func__, memory_region_name(&quirk->mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1458,7 +1455,7 @@ static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr,
|
|||||||
quirk->data.address_offset, quirk->data.address_size)) {
|
quirk->data.address_offset, quirk->data.address_size)) {
|
||||||
|
|
||||||
if (addr != quirk->data.address_offset) {
|
if (addr != quirk->data.address_offset) {
|
||||||
hw_error("%s: offset write into address window: %s\n",
|
hw_error("%s: offset write into address window: %s",
|
||||||
__func__, memory_region_name(&quirk->mem));
|
__func__, memory_region_name(&quirk->mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1479,7 +1476,7 @@ static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr,
|
|||||||
|
|
||||||
if (!vfio_range_contained(addr, size, quirk->data.data_offset,
|
if (!vfio_range_contained(addr, size, quirk->data.data_offset,
|
||||||
quirk->data.data_size)) {
|
quirk->data.data_size)) {
|
||||||
hw_error("%s: window data write not fully contained: %s\n",
|
hw_error("%s: window data write not fully contained: %s",
|
||||||
__func__, memory_region_name(&quirk->mem));
|
__func__, memory_region_name(&quirk->mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1515,7 +1512,7 @@ static uint64_t vfio_generic_quirk_read(void *opaque,
|
|||||||
ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) {
|
ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) {
|
||||||
if (!vfio_range_contained(addr, size, offset,
|
if (!vfio_range_contained(addr, size, offset,
|
||||||
quirk->data.address_mask + 1)) {
|
quirk->data.address_mask + 1)) {
|
||||||
hw_error("%s: read not fully contained: %s\n",
|
hw_error("%s: read not fully contained: %s",
|
||||||
__func__, memory_region_name(&quirk->mem));
|
__func__, memory_region_name(&quirk->mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1544,7 +1541,7 @@ static void vfio_generic_quirk_write(void *opaque, hwaddr addr,
|
|||||||
ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) {
|
ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) {
|
||||||
if (!vfio_range_contained(addr, size, offset,
|
if (!vfio_range_contained(addr, size, offset,
|
||||||
quirk->data.address_mask + 1)) {
|
quirk->data.address_mask + 1)) {
|
||||||
hw_error("%s: write not fully contained: %s\n",
|
hw_error("%s: write not fully contained: %s",
|
||||||
__func__, memory_region_name(&quirk->mem));
|
__func__, memory_region_name(&quirk->mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2302,7 +2299,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
|||||||
container->iommu_data.type1.error = ret;
|
container->iommu_data.type1.error = ret;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hw_error("vfio: DMA mapping failed, unable to continue\n");
|
hw_error("vfio: DMA mapping failed, unable to continue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2972,7 +2969,7 @@ static void vfio_pci_pre_reset(VFIODevice *vdev)
|
|||||||
pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
|
pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
|
||||||
state = pmcsr & PCI_PM_CTRL_STATE_MASK;
|
state = pmcsr & PCI_PM_CTRL_STATE_MASK;
|
||||||
if (state) {
|
if (state) {
|
||||||
error_report("vfio: Unable to power on device, stuck in D%d\n",
|
error_report("vfio: Unable to power on device, stuck in D%d",
|
||||||
state);
|
state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3271,7 +3268,7 @@ static void vfio_kvm_device_del_group(VFIOGroup *group)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
|
if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
|
||||||
error_report("Failed to remove group %d to KVM VFIO device: %m",
|
error_report("Failed to remove group %d from KVM VFIO device: %m",
|
||||||
group->groupid);
|
group->groupid);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -3339,7 +3336,7 @@ static int vfio_connect_container(VFIOGroup *group)
|
|||||||
vfio_listener_release(container);
|
vfio_listener_release(container);
|
||||||
g_free(container);
|
g_free(container);
|
||||||
close(fd);
|
close(fd);
|
||||||
error_report("vfio: memory listener initialization failed for container\n");
|
error_report("vfio: memory listener initialization failed for container");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ static void process_tx_fcb(eTSEC *etsec)
|
|||||||
|
|
||||||
/* if packet is IP4 and IP checksum is requested */
|
/* if packet is IP4 and IP checksum is requested */
|
||||||
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
if (flags & FCB_TX_IP && flags & FCB_TX_CIP) {
|
||||||
/* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure
|
/* do IP4 checksum (TODO This function does TCP/UDP checksum
|
||||||
* if it also does IP4 checksum. */
|
* but not sure if it also does IP4 checksum.) */
|
||||||
net_checksum_calculate(etsec->tx_buffer + 8,
|
net_checksum_calculate(etsec->tx_buffer + 8,
|
||||||
etsec->tx_buffer_len - 8);
|
etsec->tx_buffer_len - 8);
|
||||||
}
|
}
|
||||||
@@ -592,7 +592,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
|||||||
|
|
||||||
/* TODO: Broadcast and Multicast */
|
/* TODO: Broadcast and Multicast */
|
||||||
|
|
||||||
if (bd.flags | BD_INTERRUPT) {
|
if (bd.flags & BD_INTERRUPT) {
|
||||||
/* Set RXFx */
|
/* Set RXFx */
|
||||||
etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
|
etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr);
|
||||||
|
|
||||||
@@ -601,7 +601,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (bd.flags | BD_INTERRUPT) {
|
if (bd.flags & BD_INTERRUPT) {
|
||||||
/* Set IEVENT */
|
/* Set IEVENT */
|
||||||
ievent_set(etsec, IEVENT_RXB);
|
ievent_set(etsec, IEVENT_RXB);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "hw/qdev.h"
|
#include "hw/qdev.h"
|
||||||
#include "hw/ppc/spapr.h"
|
#include "hw/ppc/spapr.h"
|
||||||
#include "hw/ppc/spapr_vio.h"
|
#include "hw/ppc/spapr_vio.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
@@ -213,6 +214,8 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev)
|
|||||||
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
|
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
|
||||||
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
||||||
|
|
||||||
|
add_boot_device_path(dev->nicconf.bootindex, DEVICE(dev), "");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -222,13 +222,33 @@ static char *mac_strdup_printf(const uint8_t *mac)
|
|||||||
mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static intList *get_vlan_table(VirtIONet *n)
|
||||||
|
{
|
||||||
|
intList *list, *entry;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
list = NULL;
|
||||||
|
for (i = 0; i < MAX_VLAN >> 5; i++) {
|
||||||
|
for (j = 0; n->vlans[i] && j <= 0x1f; j++) {
|
||||||
|
if (n->vlans[i] & (1U << j)) {
|
||||||
|
entry = g_malloc0(sizeof(*entry));
|
||||||
|
entry->value = (i << 5) + j;
|
||||||
|
entry->next = list;
|
||||||
|
list = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
|
static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
|
||||||
{
|
{
|
||||||
VirtIONet *n = qemu_get_nic_opaque(nc);
|
VirtIONet *n = qemu_get_nic_opaque(nc);
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||||
RxFilterInfo *info;
|
RxFilterInfo *info;
|
||||||
strList *str_list, *entry;
|
strList *str_list, *entry;
|
||||||
intList *int_list, *int_entry;
|
int i;
|
||||||
int i, j;
|
|
||||||
|
|
||||||
info = g_malloc0(sizeof(*info));
|
info = g_malloc0(sizeof(*info));
|
||||||
info->name = g_strdup(nc->name);
|
info->name = g_strdup(nc->name);
|
||||||
@@ -273,19 +293,15 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
|
|||||||
str_list = entry;
|
str_list = entry;
|
||||||
}
|
}
|
||||||
info->multicast_table = str_list;
|
info->multicast_table = str_list;
|
||||||
|
info->vlan_table = get_vlan_table(n);
|
||||||
|
|
||||||
int_list = NULL;
|
if (!((1 << VIRTIO_NET_F_CTRL_VLAN) & vdev->guest_features)) {
|
||||||
for (i = 0; i < MAX_VLAN >> 5; i++) {
|
info->vlan = RX_STATE_ALL;
|
||||||
for (j = 0; n->vlans[i] && j < 0x1f; j++) {
|
} else if (!info->vlan_table) {
|
||||||
if (n->vlans[i] & (1U << j)) {
|
info->vlan = RX_STATE_NONE;
|
||||||
int_entry = g_malloc0(sizeof(*int_entry));
|
} else {
|
||||||
int_entry->value = (i << 5) + j;
|
info->vlan = RX_STATE_NORMAL;
|
||||||
int_entry->next = int_list;
|
|
||||||
int_list = int_entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
info->vlan_table = int_list;
|
|
||||||
|
|
||||||
/* enable event notification after query */
|
/* enable event notification after query */
|
||||||
nc->rxfilter_notify_enabled = 1;
|
nc->rxfilter_notify_enabled = 1;
|
||||||
@@ -514,6 +530,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
|
|||||||
}
|
}
|
||||||
vhost_net_ack_features(tap_get_vhost_net(nc->peer), features);
|
vhost_net_ack_features(tap_get_vhost_net(nc->peer), features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((1 << VIRTIO_NET_F_CTRL_VLAN) & features) {
|
||||||
|
memset(n->vlans, 0, MAX_VLAN >> 3);
|
||||||
|
} else {
|
||||||
|
memset(n->vlans, 0xff, MAX_VLAN >> 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
|
static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
|
||||||
|
|||||||
@@ -945,9 +945,15 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
|
|||||||
Error *local_errp = NULL;
|
Error *local_errp = NULL;
|
||||||
|
|
||||||
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
|
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
|
||||||
(Object **) &ds->enet, &local_errp);
|
(Object **) &ds->enet,
|
||||||
|
object_property_allow_set_link,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&local_errp);
|
||||||
object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
|
object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
|
||||||
(Object **) &cs->enet, &local_errp);
|
(Object **) &cs->enet,
|
||||||
|
object_property_allow_set_link,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&local_errp);
|
||||||
if (local_errp) {
|
if (local_errp) {
|
||||||
goto xilinx_enet_realize_fail;
|
goto xilinx_enet_realize_fail;
|
||||||
}
|
}
|
||||||
@@ -982,10 +988,16 @@ static void xilinx_enet_init(Object *obj)
|
|||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
|
|
||||||
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
|
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
|
||||||
(Object **) &s->tx_data_dev, &error_abort);
|
(Object **) &s->tx_data_dev,
|
||||||
|
qdev_prop_allow_set_link_before_realize,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&error_abort);
|
||||||
object_property_add_link(obj, "axistream-control-connected",
|
object_property_add_link(obj, "axistream-control-connected",
|
||||||
TYPE_STREAM_SLAVE,
|
TYPE_STREAM_SLAVE,
|
||||||
(Object **) &s->tx_control_dev, &error_abort);
|
(Object **) &s->tx_control_dev,
|
||||||
|
qdev_prop_allow_set_link_before_realize,
|
||||||
|
OBJ_PROP_LINK_UNREF_ON_RELEASE,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
|
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
|
||||||
TYPE_XILINX_AXI_ENET_DATA_STREAM);
|
TYPE_XILINX_AXI_ENET_DATA_STREAM);
|
||||||
|
|||||||
@@ -504,7 +504,7 @@ static void fw_cfg_machine_ready(struct Notifier *n, void *data)
|
|||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
FWCfgState *s = container_of(n, FWCfgState, machine_ready);
|
FWCfgState *s = container_of(n, FWCfgState, machine_ready);
|
||||||
char *bootindex = get_boot_devices_list(&len);
|
char *bootindex = get_boot_devices_list(&len, false);
|
||||||
|
|
||||||
fw_cfg_add_file(s, "bootorder", (uint8_t*)bootindex, len);
|
fw_cfg_add_file(s, "bootorder", (uint8_t*)bootindex, len);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
|
|||||||
#define PBM_PCI_IMR_MASK 0x7fffffff
|
#define PBM_PCI_IMR_MASK 0x7fffffff
|
||||||
#define PBM_PCI_IMR_ENABLED 0x80000000
|
#define PBM_PCI_IMR_ENABLED 0x80000000
|
||||||
|
|
||||||
#define POR (1 << 31)
|
#define POR (1U << 31)
|
||||||
#define SOFT_POR (1 << 30)
|
#define SOFT_POR (1U << 30)
|
||||||
#define SOFT_XIR (1 << 29)
|
#define SOFT_XIR (1U << 29)
|
||||||
#define BTN_POR (1 << 28)
|
#define BTN_POR (1U << 28)
|
||||||
#define BTN_XIR (1 << 27)
|
#define BTN_XIR (1U << 27)
|
||||||
#define RESET_MASK 0xf8000000
|
#define RESET_MASK 0xf8000000
|
||||||
#define RESET_WCMASK 0x98000000
|
#define RESET_WCMASK 0x98000000
|
||||||
#define RESET_WMASK 0x60000000
|
#define RESET_WMASK 0x60000000
|
||||||
|
|||||||
@@ -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) \
|
||||||
@@ -46,13 +52,25 @@ typedef struct RavenPCIState {
|
|||||||
typedef struct PRePPCIState {
|
typedef struct PRePPCIState {
|
||||||
PCIHostState parent_obj;
|
PCIHostState parent_obj;
|
||||||
|
|
||||||
MemoryRegion intack;
|
|
||||||
qemu_irq irq[PCI_NUM_PINS];
|
qemu_irq irq[PCI_NUM_PINS];
|
||||||
PCIBus pci_bus;
|
PCIBus pci_bus;
|
||||||
|
AddressSpace pci_io_as;
|
||||||
|
MemoryRegion pci_io;
|
||||||
|
MemoryRegion pci_io_non_contiguous;
|
||||||
|
MemoryRegion pci_memory;
|
||||||
|
MemoryRegion pci_intack;
|
||||||
|
MemoryRegion bm;
|
||||||
|
MemoryRegion bm_ram_alias;
|
||||||
|
MemoryRegion bm_pci_memory_alias;
|
||||||
|
AddressSpace bm_as;
|
||||||
RavenPCIState pci_dev;
|
RavenPCIState pci_dev;
|
||||||
|
|
||||||
|
int contiguous_map;
|
||||||
} PREPPCIState;
|
} PREPPCIState;
|
||||||
|
|
||||||
static inline uint32_t PPC_PCIIO_config(hwaddr addr)
|
#define BIOS_SIZE (1024 * 1024)
|
||||||
|
|
||||||
|
static inline uint32_t raven_pci_io_config(hwaddr addr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -64,53 +82,133 @@ static inline uint32_t PPC_PCIIO_config(hwaddr addr)
|
|||||||
return (addr & 0x7ff) | (i << 11);
|
return (addr & 0x7ff) | (i << 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ppc_pci_io_write(void *opaque, hwaddr addr,
|
static void raven_pci_io_write(void *opaque, hwaddr addr,
|
||||||
uint64_t val, unsigned int size)
|
uint64_t val, unsigned int size)
|
||||||
{
|
{
|
||||||
PREPPCIState *s = opaque;
|
PREPPCIState *s = opaque;
|
||||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||||
pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size);
|
pci_data_write(phb->bus, raven_pci_io_config(addr), val, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t ppc_pci_io_read(void *opaque, hwaddr addr,
|
static uint64_t raven_pci_io_read(void *opaque, hwaddr addr,
|
||||||
unsigned int size)
|
unsigned int size)
|
||||||
{
|
{
|
||||||
PREPPCIState *s = opaque;
|
PREPPCIState *s = opaque;
|
||||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||||
return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size);
|
return pci_data_read(phb->bus, raven_pci_io_config(addr), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const MemoryRegionOps PPC_PCIIO_ops = {
|
static const MemoryRegionOps raven_pci_io_ops = {
|
||||||
.read = ppc_pci_io_read,
|
.read = raven_pci_io_read,
|
||||||
.write = ppc_pci_io_write,
|
.write = raven_pci_io_write,
|
||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint64_t ppc_intack_read(void *opaque, hwaddr addr,
|
static uint64_t raven_intack_read(void *opaque, hwaddr addr,
|
||||||
unsigned int size)
|
unsigned int size)
|
||||||
{
|
{
|
||||||
return pic_read_irq(isa_pic);
|
return pic_read_irq(isa_pic);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const MemoryRegionOps PPC_intack_ops = {
|
static const MemoryRegionOps raven_intack_ops = {
|
||||||
.read = ppc_intack_read,
|
.read = raven_intack_read,
|
||||||
.valid = {
|
.valid = {
|
||||||
.max_access_size = 1,
|
.max_access_size = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
|
static inline hwaddr raven_io_address(PREPPCIState *s,
|
||||||
|
hwaddr addr)
|
||||||
|
{
|
||||||
|
if (s->contiguous_map == 0) {
|
||||||
|
/* 64 KB contiguous space for IOs */
|
||||||
|
addr &= 0xFFFF;
|
||||||
|
} else {
|
||||||
|
/* 8 MB non-contiguous space for IOs */
|
||||||
|
addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: handle endianness switch */
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t raven_io_read(void *opaque, hwaddr addr,
|
||||||
|
unsigned int size)
|
||||||
|
{
|
||||||
|
PREPPCIState *s = opaque;
|
||||||
|
uint8_t buf[4];
|
||||||
|
|
||||||
|
addr = raven_io_address(s, addr);
|
||||||
|
address_space_read(&s->pci_io_as, addr + 0x80000000, buf, size);
|
||||||
|
|
||||||
|
if (size == 1) {
|
||||||
|
return buf[0];
|
||||||
|
} else if (size == 2) {
|
||||||
|
return lduw_p(buf);
|
||||||
|
} else if (size == 4) {
|
||||||
|
return ldl_p(buf);
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raven_io_write(void *opaque, hwaddr addr,
|
||||||
|
uint64_t val, unsigned int size)
|
||||||
|
{
|
||||||
|
PREPPCIState *s = opaque;
|
||||||
|
uint8_t buf[4];
|
||||||
|
|
||||||
|
addr = raven_io_address(s, addr);
|
||||||
|
|
||||||
|
if (size == 1) {
|
||||||
|
buf[0] = val;
|
||||||
|
} else if (size == 2) {
|
||||||
|
stw_p(buf, val);
|
||||||
|
} else if (size == 4) {
|
||||||
|
stl_p(buf, val);
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
address_space_write(&s->pci_io_as, addr + 0x80000000, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MemoryRegionOps raven_io_ops = {
|
||||||
|
.read = raven_io_read,
|
||||||
|
.write = raven_io_write,
|
||||||
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
|
.impl.max_access_size = 4,
|
||||||
|
.valid.unaligned = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int raven_map_irq(PCIDevice *pci_dev, int irq_num)
|
||||||
{
|
{
|
||||||
return (irq_num + (pci_dev->devfn >> 3)) & 1;
|
return (irq_num + (pci_dev->devfn >> 3)) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prep_set_irq(void *opaque, int irq_num, int level)
|
static void raven_set_irq(void *opaque, int irq_num, int level)
|
||||||
{
|
{
|
||||||
qemu_irq *pic = opaque;
|
qemu_irq *pic = opaque;
|
||||||
|
|
||||||
qemu_set_irq(pic[irq_num] , level);
|
qemu_set_irq(pic[irq_num] , level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AddressSpace *raven_pcihost_set_iommu(PCIBus *bus, void *opaque,
|
||||||
|
int devfn)
|
||||||
|
{
|
||||||
|
PREPPCIState *s = opaque;
|
||||||
|
|
||||||
|
return &s->bm_as;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raven_change_gpio(void *opaque, int n, int level)
|
||||||
|
{
|
||||||
|
PREPPCIState *s = opaque;
|
||||||
|
|
||||||
|
s->contiguous_map = level;
|
||||||
|
}
|
||||||
|
|
||||||
static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
|
static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
|
||||||
{
|
{
|
||||||
SysBusDevice *dev = SYS_BUS_DEVICE(d);
|
SysBusDevice *dev = SYS_BUS_DEVICE(d);
|
||||||
@@ -119,29 +217,30 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
|
|||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
isa_mem_base = 0xc0000000;
|
|
||||||
|
|
||||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
for (i = 0; i < PCI_NUM_PINS; i++) {
|
||||||
sysbus_init_irq(dev, &s->irq[i]);
|
sysbus_init_irq(dev, &s->irq[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, PCI_NUM_PINS);
|
qdev_init_gpio_in(d, raven_change_gpio, 1);
|
||||||
|
|
||||||
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, s,
|
pci_bus_irqs(&s->pci_bus, raven_set_irq, raven_map_irq, s->irq,
|
||||||
"pci-conf-idx", 1);
|
PCI_NUM_PINS);
|
||||||
sysbus_add_io(dev, 0xcf8, &h->conf_mem);
|
|
||||||
sysbus_init_ioports(&h->busdev, 0xcf8, 1);
|
|
||||||
|
|
||||||
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_be_ops, s,
|
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, s,
|
||||||
"pci-conf-data", 1);
|
"pci-conf-idx", 4);
|
||||||
sysbus_add_io(dev, 0xcfc, &h->data_mem);
|
memory_region_add_subregion(&s->pci_io, 0xcf8, &h->conf_mem);
|
||||||
sysbus_init_ioports(&h->busdev, 0xcfc, 1);
|
|
||||||
|
|
||||||
memory_region_init_io(&h->mmcfg, OBJECT(s), &PPC_PCIIO_ops, s, "pciio", 0x00400000);
|
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, s,
|
||||||
|
"pci-conf-data", 4);
|
||||||
|
memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem);
|
||||||
|
|
||||||
|
memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_pci_io_ops, s,
|
||||||
|
"pciio", 0x00400000);
|
||||||
memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
|
memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
|
||||||
|
|
||||||
memory_region_init_io(&s->intack, OBJECT(s), &PPC_intack_ops, s, "pci-intack", 1);
|
memory_region_init_io(&s->pci_intack, OBJECT(s), &raven_intack_ops, s,
|
||||||
memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack);
|
"pci-intack", 1);
|
||||||
|
memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack);
|
||||||
|
|
||||||
/* TODO Remove once realize propagates to child devices. */
|
/* TODO Remove once realize propagates to child devices. */
|
||||||
object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
|
object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
|
||||||
@@ -152,11 +251,36 @@ static void raven_pcihost_initfn(Object *obj)
|
|||||||
PCIHostState *h = PCI_HOST_BRIDGE(obj);
|
PCIHostState *h = PCI_HOST_BRIDGE(obj);
|
||||||
PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj);
|
PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj);
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
MemoryRegion *address_space_io = get_system_io();
|
|
||||||
DeviceState *pci_dev;
|
DeviceState *pci_dev;
|
||||||
|
|
||||||
|
memory_region_init(&s->pci_io, obj, "pci-io", 0x3f800000);
|
||||||
|
memory_region_init_io(&s->pci_io_non_contiguous, obj, &raven_io_ops, s,
|
||||||
|
"pci-io-non-contiguous", 0x00800000);
|
||||||
|
/* Open Hack'Ware hack: real size should be only 0x3f000000 bytes */
|
||||||
|
memory_region_init(&s->pci_memory, obj, "pci-memory",
|
||||||
|
0x3f000000 + 0xc0000000ULL);
|
||||||
|
address_space_init(&s->pci_io_as, &s->pci_io, "raven-io");
|
||||||
|
|
||||||
|
/* CPU address space */
|
||||||
|
memory_region_add_subregion(address_space_mem, 0x80000000, &s->pci_io);
|
||||||
|
memory_region_add_subregion_overlap(address_space_mem, 0x80000000,
|
||||||
|
&s->pci_io_non_contiguous, 1);
|
||||||
|
memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory);
|
||||||
pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL,
|
pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL,
|
||||||
address_space_mem, address_space_io, 0, TYPE_PCI_BUS);
|
&s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS);
|
||||||
|
|
||||||
|
/* Bus master address space */
|
||||||
|
memory_region_init(&s->bm, obj, "bm-raven", UINT32_MAX);
|
||||||
|
memory_region_init_alias(&s->bm_pci_memory_alias, obj, "bm-pci-memory",
|
||||||
|
&s->pci_memory, 0,
|
||||||
|
memory_region_size(&s->pci_memory));
|
||||||
|
memory_region_init_alias(&s->bm_ram_alias, obj, "bm-system",
|
||||||
|
get_system_memory(), 0, 0x80000000);
|
||||||
|
memory_region_add_subregion(&s->bm, 0 , &s->bm_pci_memory_alias);
|
||||||
|
memory_region_add_subregion(&s->bm, 0x80000000, &s->bm_ram_alias);
|
||||||
|
address_space_init(&s->bm_as, &s->bm, "raven-bm");
|
||||||
|
pci_setup_iommu(&s->pci_bus, raven_pcihost_set_iommu, s);
|
||||||
|
|
||||||
h->bus = &s->pci_bus;
|
h->bus = &s->pci_bus;
|
||||||
|
|
||||||
object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE);
|
object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE);
|
||||||
@@ -169,10 +293,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 +371,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";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
55
hw/pci/pci.c
55
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;
|
||||||
@@ -172,9 +189,9 @@ static void pci_do_device_reset(PCIDevice *dev)
|
|||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
dev->irq_state = 0;
|
|
||||||
pci_update_irq_status(dev);
|
|
||||||
pci_device_deassert_intx(dev);
|
pci_device_deassert_intx(dev);
|
||||||
|
assert(dev->irq_state == 0);
|
||||||
|
|
||||||
/* Clear all writable bits */
|
/* Clear all writable bits */
|
||||||
pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
|
pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
|
||||||
pci_get_word(dev->wmask + PCI_COMMAND) |
|
pci_get_word(dev->wmask + PCI_COMMAND) |
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -142,8 +142,9 @@ static uint64_t pci_host_data_read(void *opaque,
|
|||||||
{
|
{
|
||||||
PCIHostState *s = opaque;
|
PCIHostState *s = opaque;
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
if (!(s->config_reg & (1 << 31)))
|
if (!(s->config_reg & (1U << 31))) {
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
|
}
|
||||||
val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
|
val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
|
||||||
PCI_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
|
PCI_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
|
||||||
addr, len, val);
|
addr, len, val);
|
||||||
|
|||||||
@@ -198,7 +198,9 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
|
|||||||
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
|
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
|
||||||
|
|
||||||
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
|
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
|
||||||
(Object **)&s->card, NULL);
|
(Object **)&s->card,
|
||||||
|
NULL, /* read-only property */
|
||||||
|
0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert a new card into a slot */
|
/* Insert a new card into a slot */
|
||||||
|
|||||||
@@ -472,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)
|
||||||
|
|||||||
@@ -1002,7 +1002,7 @@ static void cpu_4xx_wdt_cb (void *opaque)
|
|||||||
case 0x1:
|
case 0x1:
|
||||||
timer_mod(ppc40x_timer->wdt_timer, next);
|
timer_mod(ppc40x_timer->wdt_timer, next);
|
||||||
ppc40x_timer->wdt_next = next;
|
ppc40x_timer->wdt_next = next;
|
||||||
env->spr[SPR_40x_TSR] |= 1 << 31;
|
env->spr[SPR_40x_TSR] |= 1U << 31;
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
timer_mod(ppc40x_timer->wdt_timer, next);
|
timer_mod(ppc40x_timer->wdt_timer, next);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
|
ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
|
||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
CPUState *cs = ENV_GET_CPU(env);
|
CPUState *cs = CPU(ppc_env_get_cpu(env));
|
||||||
ram_addr_t bdloc;
|
ram_addr_t bdloc;
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
|
|||||||
|
|
||||||
tlb->attr = 0;
|
tlb->attr = 0;
|
||||||
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
|
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
|
||||||
tlb->size = 1 << 31; /* up to 0x80000000 */
|
tlb->size = 1U << 31; /* up to 0x80000000 */
|
||||||
tlb->EPN = va & TARGET_PAGE_MASK;
|
tlb->EPN = va & TARGET_PAGE_MASK;
|
||||||
tlb->RPN = pa & TARGET_PAGE_MASK;
|
tlb->RPN = pa & TARGET_PAGE_MASK;
|
||||||
tlb->PID = 0;
|
tlb->PID = 0;
|
||||||
@@ -136,7 +136,7 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env,
|
|||||||
tlb = &env->tlb.tlbe[1];
|
tlb = &env->tlb.tlbe[1];
|
||||||
tlb->attr = 0;
|
tlb->attr = 0;
|
||||||
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
|
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
|
||||||
tlb->size = 1 << 31; /* up to 0xffffffff */
|
tlb->size = 1U << 31; /* up to 0xffffffff */
|
||||||
tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
|
tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
|
||||||
tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
|
tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
|
||||||
tlb->PID = 0;
|
tlb->PID = 0;
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ static void ppcuic_set_irq (void *opaque, int irq_num, int level)
|
|||||||
uint32_t mask, sr;
|
uint32_t mask, sr;
|
||||||
|
|
||||||
uic = opaque;
|
uic = opaque;
|
||||||
mask = 1 << (31-irq_num);
|
mask = 1U << (31-irq_num);
|
||||||
LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
|
LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
|
||||||
" mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
|
" mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
|
||||||
__func__, irq_num, level,
|
__func__, irq_num, level,
|
||||||
|
|||||||
@@ -34,15 +34,15 @@
|
|||||||
/* Timer Control Register */
|
/* Timer Control Register */
|
||||||
|
|
||||||
#define TCR_WP_SHIFT 30 /* Watchdog Timer Period */
|
#define TCR_WP_SHIFT 30 /* Watchdog Timer Period */
|
||||||
#define TCR_WP_MASK (0x3 << TCR_WP_SHIFT)
|
#define TCR_WP_MASK (0x3U << TCR_WP_SHIFT)
|
||||||
#define TCR_WRC_SHIFT 28 /* Watchdog Timer Reset Control */
|
#define TCR_WRC_SHIFT 28 /* Watchdog Timer Reset Control */
|
||||||
#define TCR_WRC_MASK (0x3 << TCR_WRC_SHIFT)
|
#define TCR_WRC_MASK (0x3U << TCR_WRC_SHIFT)
|
||||||
#define TCR_WIE (1 << 27) /* Watchdog Timer Interrupt Enable */
|
#define TCR_WIE (1U << 27) /* Watchdog Timer Interrupt Enable */
|
||||||
#define TCR_DIE (1 << 26) /* Decrementer Interrupt Enable */
|
#define TCR_DIE (1U << 26) /* Decrementer Interrupt Enable */
|
||||||
#define TCR_FP_SHIFT 24 /* Fixed-Interval Timer Period */
|
#define TCR_FP_SHIFT 24 /* Fixed-Interval Timer Period */
|
||||||
#define TCR_FP_MASK (0x3 << TCR_FP_SHIFT)
|
#define TCR_FP_MASK (0x3U << TCR_FP_SHIFT)
|
||||||
#define TCR_FIE (1 << 23) /* Fixed-Interval Timer Interrupt Enable */
|
#define TCR_FIE (1U << 23) /* Fixed-Interval Timer Interrupt Enable */
|
||||||
#define TCR_ARE (1 << 22) /* Auto-Reload Enable */
|
#define TCR_ARE (1U << 22) /* Auto-Reload Enable */
|
||||||
|
|
||||||
/* Timer Control Register (e500 specific fields) */
|
/* Timer Control Register (e500 specific fields) */
|
||||||
|
|
||||||
@@ -53,12 +53,12 @@
|
|||||||
|
|
||||||
/* Timer Status Register */
|
/* Timer Status Register */
|
||||||
|
|
||||||
#define TSR_FIS (1 << 26) /* Fixed-Interval Timer Interrupt Status */
|
#define TSR_FIS (1U << 26) /* Fixed-Interval Timer Interrupt Status */
|
||||||
#define TSR_DIS (1 << 27) /* Decrementer Interrupt Status */
|
#define TSR_DIS (1U << 27) /* Decrementer Interrupt Status */
|
||||||
#define TSR_WRS_SHIFT 28 /* Watchdog Timer Reset Status */
|
#define TSR_WRS_SHIFT 28 /* Watchdog Timer Reset Status */
|
||||||
#define TSR_WRS_MASK (0x3 << TSR_WRS_SHIFT)
|
#define TSR_WRS_MASK (0x3U << TSR_WRS_SHIFT)
|
||||||
#define TSR_WIS (1 << 30) /* Watchdog Timer Interrupt Status */
|
#define TSR_WIS (1U << 30) /* Watchdog Timer Interrupt Status */
|
||||||
#define TSR_ENW (1 << 31) /* Enable Next Watchdog Timer */
|
#define TSR_ENW (1U << 31) /* Enable Next Watchdog Timer */
|
||||||
|
|
||||||
typedef struct booke_timer_t booke_timer_t;
|
typedef struct booke_timer_t booke_timer_t;
|
||||||
struct booke_timer_t {
|
struct booke_timer_t {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ static void spin_kick(void *data)
|
|||||||
mmubooke_create_initial_mapping(env, 0, map_start, map_size);
|
mmubooke_create_initial_mapping(env, 0, map_start, map_size);
|
||||||
|
|
||||||
cpu->halted = 0;
|
cpu->halted = 0;
|
||||||
env->exception_index = -1;
|
cpu->exception_index = -1;
|
||||||
cpu->stopped = false;
|
cpu->stopped = false;
|
||||||
qemu_cpu_kick(cpu);
|
qemu_cpu_kick(cpu);
|
||||||
}
|
}
|
||||||
|
|||||||
149
hw/ppc/prep.c
149
hw/ppc/prep.c
@@ -185,6 +185,7 @@ typedef struct sysctrl_t {
|
|||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint8_t syscontrol;
|
uint8_t syscontrol;
|
||||||
int contiguous_map;
|
int contiguous_map;
|
||||||
|
qemu_irq contiguous_map_irq;
|
||||||
int endian;
|
int endian;
|
||||||
} sysctrl_t;
|
} sysctrl_t;
|
||||||
|
|
||||||
@@ -253,6 +254,7 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
|
|||||||
case 0x0850:
|
case 0x0850:
|
||||||
/* I/O map type register */
|
/* I/O map type register */
|
||||||
sysctrl->contiguous_map = val & 0x01;
|
sysctrl->contiguous_map = val & 0x01;
|
||||||
|
qemu_set_irq(sysctrl->contiguous_map_irq, sysctrl->contiguous_map);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("ERROR: unaffected IO port write: %04" PRIx32
|
printf("ERROR: unaffected IO port write: %04" PRIx32
|
||||||
@@ -327,91 +329,6 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline hwaddr prep_IO_address(sysctrl_t *sysctrl,
|
|
||||||
hwaddr addr)
|
|
||||||
{
|
|
||||||
if (sysctrl->contiguous_map == 0) {
|
|
||||||
/* 64 KB contiguous space for IOs */
|
|
||||||
addr &= 0xFFFF;
|
|
||||||
} else {
|
|
||||||
/* 8 MB non-contiguous space for IOs */
|
|
||||||
addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PPC_prep_io_writeb (void *opaque, hwaddr addr,
|
|
||||||
uint32_t value)
|
|
||||||
{
|
|
||||||
sysctrl_t *sysctrl = opaque;
|
|
||||||
|
|
||||||
addr = prep_IO_address(sysctrl, addr);
|
|
||||||
cpu_outb(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t PPC_prep_io_readb (void *opaque, hwaddr addr)
|
|
||||||
{
|
|
||||||
sysctrl_t *sysctrl = opaque;
|
|
||||||
uint32_t ret;
|
|
||||||
|
|
||||||
addr = prep_IO_address(sysctrl, addr);
|
|
||||||
ret = cpu_inb(addr);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PPC_prep_io_writew (void *opaque, hwaddr addr,
|
|
||||||
uint32_t value)
|
|
||||||
{
|
|
||||||
sysctrl_t *sysctrl = opaque;
|
|
||||||
|
|
||||||
addr = prep_IO_address(sysctrl, addr);
|
|
||||||
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
|
|
||||||
cpu_outw(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t PPC_prep_io_readw (void *opaque, hwaddr addr)
|
|
||||||
{
|
|
||||||
sysctrl_t *sysctrl = opaque;
|
|
||||||
uint32_t ret;
|
|
||||||
|
|
||||||
addr = prep_IO_address(sysctrl, addr);
|
|
||||||
ret = cpu_inw(addr);
|
|
||||||
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PPC_prep_io_writel (void *opaque, hwaddr addr,
|
|
||||||
uint32_t value)
|
|
||||||
{
|
|
||||||
sysctrl_t *sysctrl = opaque;
|
|
||||||
|
|
||||||
addr = prep_IO_address(sysctrl, addr);
|
|
||||||
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
|
|
||||||
cpu_outl(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t PPC_prep_io_readl (void *opaque, hwaddr addr)
|
|
||||||
{
|
|
||||||
sysctrl_t *sysctrl = opaque;
|
|
||||||
uint32_t ret;
|
|
||||||
|
|
||||||
addr = prep_IO_address(sysctrl, addr);
|
|
||||||
ret = cpu_inl(addr);
|
|
||||||
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const MemoryRegionOps PPC_prep_io_ops = {
|
|
||||||
.old_mmio = {
|
|
||||||
.read = { PPC_prep_io_readb, PPC_prep_io_readw, PPC_prep_io_readl },
|
|
||||||
.write = { PPC_prep_io_writeb, PPC_prep_io_writew, PPC_prep_io_writel },
|
|
||||||
},
|
|
||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NVRAM_SIZE 0x2000
|
#define NVRAM_SIZE 0x2000
|
||||||
|
|
||||||
@@ -456,17 +373,15 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
|
|||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
PowerPCCPU *cpu = NULL;
|
PowerPCCPU *cpu = NULL;
|
||||||
CPUPPCState *env = NULL;
|
CPUPPCState *env = NULL;
|
||||||
char *filename;
|
|
||||||
nvram_t nvram;
|
nvram_t nvram;
|
||||||
M48t59State *m48t59;
|
M48t59State *m48t59;
|
||||||
MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1);
|
|
||||||
PortioList *port_list = g_new(PortioList, 1);
|
PortioList *port_list = g_new(PortioList, 1);
|
||||||
#if 0
|
#if 0
|
||||||
MemoryRegion *xcsr = g_new(MemoryRegion, 1);
|
MemoryRegion *xcsr = g_new(MemoryRegion, 1);
|
||||||
#endif
|
#endif
|
||||||
int linux_boot, i, nb_nics1, bios_size;
|
int linux_boot, i, nb_nics1;
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
MemoryRegion *bios = g_new(MemoryRegion, 1);
|
MemoryRegion *vga = g_new(MemoryRegion, 1);
|
||||||
uint32_t kernel_base, initrd_base;
|
uint32_t kernel_base, initrd_base;
|
||||||
long kernel_size, initrd_size;
|
long kernel_size, initrd_size;
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
@@ -509,43 +424,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
|
|||||||
vmstate_register_ram_global(ram);
|
vmstate_register_ram_global(ram);
|
||||||
memory_region_add_subregion(sysmem, 0, ram);
|
memory_region_add_subregion(sysmem, 0, ram);
|
||||||
|
|
||||||
/* allocate and load BIOS */
|
|
||||||
memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE);
|
|
||||||
memory_region_set_readonly(bios, true);
|
|
||||||
memory_region_add_subregion(sysmem, (uint32_t)(-BIOS_SIZE), bios);
|
|
||||||
vmstate_register_ram_global(bios);
|
|
||||||
if (bios_name == NULL)
|
|
||||||
bios_name = BIOS_FILENAME;
|
|
||||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
|
||||||
if (filename) {
|
|
||||||
bios_size = load_elf(filename, NULL, NULL, NULL,
|
|
||||||
NULL, NULL, 1, 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 > BIOS_SIZE) {
|
|
||||||
fprintf(stderr, "qemu: PReP bios '%s' is too large (0x%x)\n",
|
|
||||||
bios_name, bios_size);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bios_size = -1;
|
|
||||||
}
|
|
||||||
if (bios_size < 0 && !qtest_enabled()) {
|
|
||||||
fprintf(stderr, "qemu: could not load PPC PReP bios '%s'\n",
|
|
||||||
bios_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (filename) {
|
|
||||||
g_free(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linux_boot) {
|
if (linux_boot) {
|
||||||
kernel_base = KERNEL_LOAD_ADDR;
|
kernel_base = KERNEL_LOAD_ADDR;
|
||||||
/* now we can load the kernel */
|
/* now we can load the kernel */
|
||||||
@@ -593,6 +471,11 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev = qdev_create(NULL, "raven-pcihost");
|
dev = qdev_create(NULL, "raven-pcihost");
|
||||||
|
if (bios_name == NULL) {
|
||||||
|
bios_name = BIOS_FILENAME;
|
||||||
|
}
|
||||||
|
qdev_prop_set_string(dev, "bios-name", bios_name);
|
||||||
|
qdev_prop_set_uint32(dev, "elf-machine", ELF_MACHINE);
|
||||||
pcihost = PCI_HOST_BRIDGE(dev);
|
pcihost = PCI_HOST_BRIDGE(dev);
|
||||||
object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
|
object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
|
||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
@@ -601,6 +484,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
|
|||||||
fprintf(stderr, "Couldn't create PCI host controller.\n");
|
fprintf(stderr, "Couldn't create PCI host controller.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
sysctrl->contiguous_map_irq = qdev_get_gpio_in(dev, 0);
|
||||||
|
|
||||||
/* PCI -> ISA bridge */
|
/* PCI -> ISA bridge */
|
||||||
pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378");
|
pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378");
|
||||||
@@ -621,13 +505,16 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
|
|||||||
qdev_prop_set_uint8(dev, "config", 13); /* fdc, ser0, ser1, par0 */
|
qdev_prop_set_uint8(dev, "config", 13); /* fdc, ser0, ser1, par0 */
|
||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
|
|
||||||
/* Register 8 MB of ISA IO space (needed for non-contiguous map) */
|
|
||||||
memory_region_init_io(PPC_io_memory, NULL, &PPC_prep_io_ops, sysctrl,
|
|
||||||
"ppc-io", 0x00800000);
|
|
||||||
memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory);
|
|
||||||
|
|
||||||
/* init basic PC hardware */
|
/* init basic PC hardware */
|
||||||
pci_vga_init(pci_bus);
|
pci_vga_init(pci_bus);
|
||||||
|
/* Open Hack'Ware hack: PCI BAR#0 is programmed to 0xf0000000.
|
||||||
|
* While bios will access framebuffer at 0xf0000000, real physical
|
||||||
|
* address is 0xf0000000 + 0xc0000000 (PCI memory base).
|
||||||
|
* Alias the wrong memory accesses to the right place.
|
||||||
|
*/
|
||||||
|
memory_region_init_alias(vga, NULL, "vga-alias", pci_address_space(pci),
|
||||||
|
0xf0000000, 0x1000000);
|
||||||
|
memory_region_add_subregion_overlap(sysmem, 0xf0000000, vga, 10);
|
||||||
|
|
||||||
nb_nics1 = nb_nics;
|
nb_nics1 = nb_nics;
|
||||||
if (nb_nics1 > NE2000_NB_MAX)
|
if (nb_nics1 > NE2000_NB_MAX)
|
||||||
|
|||||||
111
hw/ppc/spapr.c
111
hw/ppc/spapr.c
@@ -26,6 +26,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
|
#include "hw/fw-path-provider.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "net/net.h"
|
#include "net/net.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
@@ -45,6 +46,8 @@
|
|||||||
#include "hw/pci/msi.h"
|
#include "hw/pci/msi.h"
|
||||||
|
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
|
#include "hw/scsi/scsi.h"
|
||||||
|
#include "hw/virtio/virtio-scsi.h"
|
||||||
|
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "hw/usb.h"
|
#include "hw/usb.h"
|
||||||
@@ -81,6 +84,8 @@
|
|||||||
|
|
||||||
#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
|
#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
|
||||||
|
|
||||||
|
#define TYPE_SPAPR_MACHINE "spapr-machine"
|
||||||
|
|
||||||
sPAPREnvironment *spapr;
|
sPAPREnvironment *spapr;
|
||||||
|
|
||||||
int spapr_allocate_irq(int hint, bool lsi)
|
int spapr_allocate_irq(int hint, bool lsi)
|
||||||
@@ -598,7 +603,9 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
|
|||||||
hwaddr rtas_addr,
|
hwaddr rtas_addr,
|
||||||
hwaddr rtas_size)
|
hwaddr rtas_size)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret, i;
|
||||||
|
size_t cb = 0;
|
||||||
|
char *bootlist;
|
||||||
void *fdt;
|
void *fdt;
|
||||||
sPAPRPHBState *phb;
|
sPAPRPHBState *phb;
|
||||||
|
|
||||||
@@ -640,6 +647,21 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
|
|||||||
fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
|
fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bootlist = get_boot_devices_list(&cb, true);
|
||||||
|
if (cb && bootlist) {
|
||||||
|
int offset = fdt_path_offset(fdt, "/chosen");
|
||||||
|
if (offset < 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (i = 0; i < cb; i++) {
|
||||||
|
if (bootlist[i] == '\n') {
|
||||||
|
bootlist[i] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist);
|
||||||
|
}
|
||||||
|
|
||||||
if (!spapr->has_graphics) {
|
if (!spapr->has_graphics) {
|
||||||
spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
|
spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
|
||||||
}
|
}
|
||||||
@@ -781,13 +803,15 @@ static int spapr_vga_init(PCIBus *pci_bus)
|
|||||||
{
|
{
|
||||||
switch (vga_interface_type) {
|
switch (vga_interface_type) {
|
||||||
case VGA_NONE:
|
case VGA_NONE:
|
||||||
|
return false;
|
||||||
|
case VGA_DEVICE:
|
||||||
|
return true;
|
||||||
case VGA_STD:
|
case VGA_STD:
|
||||||
return pci_vga_init(pci_bus) != NULL;
|
return pci_vga_init(pci_bus) != NULL;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "This vga model is not supported,"
|
fprintf(stderr, "This vga model is not supported,"
|
||||||
"currently it only supports -vga std\n");
|
"currently it only supports -vga std\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1408,9 +1432,86 @@ static QEMUMachine spapr_machine = {
|
|||||||
.kvm_type = spapr_kvm_type,
|
.kvm_type = spapr_kvm_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void spapr_machine_init(void)
|
/*
|
||||||
|
* Implementation of an interface to adjust firmware patch
|
||||||
|
* for the bootindex property handling.
|
||||||
|
*/
|
||||||
|
static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
|
||||||
|
DeviceState *dev)
|
||||||
{
|
{
|
||||||
qemu_register_machine(&spapr_machine);
|
#define CAST(type, obj, name) \
|
||||||
|
((type *)object_dynamic_cast(OBJECT(obj), (name)))
|
||||||
|
SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE);
|
||||||
|
sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
|
||||||
|
|
||||||
|
if (d) {
|
||||||
|
void *spapr = CAST(void, bus->parent, "spapr-vscsi");
|
||||||
|
VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI);
|
||||||
|
USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE);
|
||||||
|
|
||||||
|
if (spapr) {
|
||||||
|
/*
|
||||||
|
* Replace "channel@0/disk@0,0" with "disk@8000000000000000":
|
||||||
|
* We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun
|
||||||
|
* in the top 16 bits of the 64-bit LUN
|
||||||
|
*/
|
||||||
|
unsigned id = 0x8000 | (d->id << 8) | d->lun;
|
||||||
|
return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
|
||||||
|
(uint64_t)id << 48);
|
||||||
|
} else if (virtio) {
|
||||||
|
/*
|
||||||
|
* We use SRP luns of the form 01000000 | (target << 8) | lun
|
||||||
|
* in the top 32 bits of the 64-bit LUN
|
||||||
|
* Note: the quote above is from SLOF and it is wrong,
|
||||||
|
* the actual binding is:
|
||||||
|
* swap 0100 or 10 << or 20 << ( target lun-id -- srplun )
|
||||||
|
*/
|
||||||
|
unsigned id = 0x1000000 | (d->id << 16) | d->lun;
|
||||||
|
return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
|
||||||
|
(uint64_t)id << 32);
|
||||||
|
} else if (usb) {
|
||||||
|
/*
|
||||||
|
* We use SRP luns of the form 01000000 | (usb-port << 16) | lun
|
||||||
|
* in the top 32 bits of the 64-bit LUN
|
||||||
|
*/
|
||||||
|
unsigned usb_port = atoi(usb->port->path);
|
||||||
|
unsigned id = 0x1000000 | (usb_port << 16) | d->lun;
|
||||||
|
return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
|
||||||
|
(uint64_t)id << 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phb) {
|
||||||
|
/* Replace "pci" with "pci@800000020000000" */
|
||||||
|
return g_strdup_printf("pci@%"PRIX64, phb->buid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_init(spapr_machine_init);
|
static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
|
||||||
|
|
||||||
|
mc->qemu_machine = data;
|
||||||
|
fwc->get_dev_path = spapr_get_fw_dev_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo spapr_machine_info = {
|
||||||
|
.name = TYPE_SPAPR_MACHINE,
|
||||||
|
.parent = TYPE_MACHINE,
|
||||||
|
.class_init = spapr_machine_class_init,
|
||||||
|
.class_data = &spapr_machine,
|
||||||
|
.interfaces = (InterfaceInfo[]) {
|
||||||
|
{ TYPE_FW_PATH_PROVIDER },
|
||||||
|
{ }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void spapr_machine_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&spapr_machine_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(spapr_machine_register_types)
|
||||||
|
|||||||
@@ -4,6 +4,36 @@
|
|||||||
#include "hw/ppc/spapr.h"
|
#include "hw/ppc/spapr.h"
|
||||||
#include "mmu-hash64.h"
|
#include "mmu-hash64.h"
|
||||||
|
|
||||||
|
struct SPRSyncState {
|
||||||
|
CPUState *cs;
|
||||||
|
int spr;
|
||||||
|
target_ulong value;
|
||||||
|
target_ulong mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void do_spr_sync(void *arg)
|
||||||
|
{
|
||||||
|
struct SPRSyncState *s = arg;
|
||||||
|
PowerPCCPU *cpu = POWERPC_CPU(s->cs);
|
||||||
|
CPUPPCState *env = &cpu->env;
|
||||||
|
|
||||||
|
cpu_synchronize_state(s->cs);
|
||||||
|
env->spr[s->spr] &= ~s->mask;
|
||||||
|
env->spr[s->spr] |= s->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_spr(CPUState *cs, int spr, target_ulong value,
|
||||||
|
target_ulong mask)
|
||||||
|
{
|
||||||
|
struct SPRSyncState s = {
|
||||||
|
.cs = cs,
|
||||||
|
.spr = spr,
|
||||||
|
.value = value,
|
||||||
|
.mask = mask
|
||||||
|
};
|
||||||
|
run_on_cpu(cs, do_spr_sync, &s);
|
||||||
|
}
|
||||||
|
|
||||||
static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
||||||
target_ulong pte_index)
|
target_ulong pte_index)
|
||||||
{
|
{
|
||||||
@@ -110,16 +140,15 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
if (likely((flags & H_EXACT) == 0)) {
|
if (likely((flags & H_EXACT) == 0)) {
|
||||||
pte_index &= ~7ULL;
|
pte_index &= ~7ULL;
|
||||||
token = ppc_hash64_start_access(cpu, pte_index);
|
token = ppc_hash64_start_access(cpu, pte_index);
|
||||||
do {
|
for (; index < 8; index++) {
|
||||||
if (index == 8) {
|
|
||||||
ppc_hash64_stop_access(token);
|
|
||||||
return H_PTEG_FULL;
|
|
||||||
}
|
|
||||||
if ((ppc_hash64_load_hpte0(env, token, index) & HPTE64_V_VALID) == 0) {
|
if ((ppc_hash64_load_hpte0(env, token, index) & HPTE64_V_VALID) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (index++);
|
}
|
||||||
ppc_hash64_stop_access(token);
|
ppc_hash64_stop_access(token);
|
||||||
|
if (index == 8) {
|
||||||
|
return H_PTEG_FULL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
token = ppc_hash64_start_access(cpu, pte_index);
|
token = ppc_hash64_start_access(cpu, pte_index);
|
||||||
if (ppc_hash64_load_hpte0(env, token, 0) & HPTE64_V_VALID) {
|
if (ppc_hash64_load_hpte0(env, token, 0) & HPTE64_V_VALID) {
|
||||||
@@ -356,7 +385,7 @@ static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
|
|
||||||
static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
|
static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
|
||||||
{
|
{
|
||||||
CPUState *cs = ENV_GET_CPU(env);
|
CPUState *cs = CPU(ppc_env_get_cpu(env));
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
|
|
||||||
@@ -406,7 +435,7 @@ static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
|
|||||||
|
|
||||||
static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
|
static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
|
||||||
{
|
{
|
||||||
CPUState *cs = ENV_GET_CPU(env);
|
CPUState *cs = CPU(ppc_env_get_cpu(env));
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
if (addr == 0) {
|
if (addr == 0) {
|
||||||
@@ -442,7 +471,7 @@ static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
|
|||||||
|
|
||||||
static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
|
static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
|
||||||
{
|
{
|
||||||
CPUState *cs = ENV_GET_CPU(env);
|
CPUState *cs = CPU(ppc_env_get_cpu(env));
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
if (addr == 0) {
|
if (addr == 0) {
|
||||||
@@ -529,7 +558,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
hreg_compute_hflags(env);
|
hreg_compute_hflags(env);
|
||||||
if (!cpu_has_work(cs)) {
|
if (!cpu_has_work(cs)) {
|
||||||
cs->halted = 1;
|
cs->halted = 1;
|
||||||
env->exception_index = EXCP_HLT;
|
cs->exception_index = EXCP_HLT;
|
||||||
cs->exit_request = 1;
|
cs->exit_request = 1;
|
||||||
}
|
}
|
||||||
return H_SUCCESS;
|
return H_SUCCESS;
|
||||||
@@ -690,7 +719,7 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
target_ulong value2 = args[3];
|
target_ulong value2 = args[3];
|
||||||
target_ulong ret = H_P2;
|
target_ulong ret = H_P2;
|
||||||
|
|
||||||
if (resource == H_SET_MODE_ENDIAN) {
|
if (resource == H_SET_MODE_RESOURCE_LE) {
|
||||||
if (value1) {
|
if (value1) {
|
||||||
ret = H_P3;
|
ret = H_P3;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -699,22 +728,17 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
ret = H_P4;
|
ret = H_P4;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mflags) {
|
switch (mflags) {
|
||||||
case H_SET_MODE_ENDIAN_BIG:
|
case H_SET_MODE_ENDIAN_BIG:
|
||||||
CPU_FOREACH(cs) {
|
CPU_FOREACH(cs) {
|
||||||
PowerPCCPU *cp = POWERPC_CPU(cs);
|
set_spr(cs, SPR_LPCR, 0, LPCR_ILE);
|
||||||
CPUPPCState *env = &cp->env;
|
|
||||||
env->spr[SPR_LPCR] &= ~LPCR_ILE;
|
|
||||||
}
|
}
|
||||||
ret = H_SUCCESS;
|
ret = H_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case H_SET_MODE_ENDIAN_LITTLE:
|
case H_SET_MODE_ENDIAN_LITTLE:
|
||||||
CPU_FOREACH(cs) {
|
CPU_FOREACH(cs) {
|
||||||
PowerPCCPU *cp = POWERPC_CPU(cs);
|
set_spr(cs, SPR_LPCR, LPCR_ILE, LPCR_ILE);
|
||||||
CPUPPCState *env = &cp->env;
|
|
||||||
env->spr[SPR_LPCR] |= LPCR_ILE;
|
|
||||||
}
|
}
|
||||||
ret = H_SUCCESS;
|
ret = H_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
|
||||||
#include "hw/pci/pci_bus.h"
|
#include "hw/pci/pci_bus.h"
|
||||||
|
|
||||||
@@ -292,7 +293,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
ret_intr_type = RTAS_TYPE_MSIX;
|
ret_intr_type = RTAS_TYPE_MSIX;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func);
|
error_report("rtas_ibm_change_msi(%u) is not implemented", func);
|
||||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -326,7 +327,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
/* Find a device number in the map to add or reuse the existing one */
|
/* Find a device number in the map to add or reuse the existing one */
|
||||||
ndev = spapr_msicfg_find(phb, config_addr, true);
|
ndev = spapr_msicfg_find(phb, config_addr, true);
|
||||||
if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) {
|
if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) {
|
||||||
fprintf(stderr, "No free entry for a new MSI device\n");
|
error_report("No free entry for a new MSI device");
|
||||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -335,7 +336,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
/* Check if there is an old config and MSI number has not changed */
|
/* Check if there is an old config and MSI number has not changed */
|
||||||
if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {
|
if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {
|
||||||
/* Unexpected behaviour */
|
/* Unexpected behaviour */
|
||||||
fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev);
|
error_report("Cannot reuse MSI config for device#%d", ndev);
|
||||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -345,7 +346,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||||||
irq = spapr_allocate_irq_block(req_num, false,
|
irq = spapr_allocate_irq_block(req_num, false,
|
||||||
ret_intr_type == RTAS_TYPE_MSI);
|
ret_intr_type == RTAS_TYPE_MSI);
|
||||||
if (irq < 0) {
|
if (irq < 0) {
|
||||||
fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);
|
error_report("Cannot allocate MSIs for device#%d", ndev);
|
||||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -505,12 +506,11 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
|
|||||||
return &phb->iommu_as;
|
return &phb->iommu_as;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spapr_phb_init(SysBusDevice *s)
|
static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
DeviceState *dev = DEVICE(s);
|
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
||||||
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
|
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
|
||||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||||
const char *busname;
|
|
||||||
char *namebuf;
|
char *namebuf;
|
||||||
int i;
|
int i;
|
||||||
PCIBus *bus;
|
PCIBus *bus;
|
||||||
@@ -521,9 +521,9 @@ static int spapr_phb_init(SysBusDevice *s)
|
|||||||
if ((sphb->buid != -1) || (sphb->dma_liobn != -1)
|
if ((sphb->buid != -1) || (sphb->dma_liobn != -1)
|
||||||
|| (sphb->mem_win_addr != -1)
|
|| (sphb->mem_win_addr != -1)
|
||||||
|| (sphb->io_win_addr != -1)) {
|
|| (sphb->io_win_addr != -1)) {
|
||||||
fprintf(stderr, "Either \"index\" or other parameters must"
|
error_setg(errp, "Either \"index\" or other parameters must"
|
||||||
" be specified for PAPR PHB, not both\n");
|
" be specified for PAPR PHB, not both");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
|
sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
|
||||||
@@ -536,28 +536,28 @@ static int spapr_phb_init(SysBusDevice *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sphb->buid == -1) {
|
if (sphb->buid == -1) {
|
||||||
fprintf(stderr, "BUID not specified for PHB\n");
|
error_setg(errp, "BUID not specified for PHB");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sphb->dma_liobn == -1) {
|
if (sphb->dma_liobn == -1) {
|
||||||
fprintf(stderr, "LIOBN not specified for PHB\n");
|
error_setg(errp, "LIOBN not specified for PHB");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sphb->mem_win_addr == -1) {
|
if (sphb->mem_win_addr == -1) {
|
||||||
fprintf(stderr, "Memory window address not specified for PHB\n");
|
error_setg(errp, "Memory window address not specified for PHB");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sphb->io_win_addr == -1) {
|
if (sphb->io_win_addr == -1) {
|
||||||
fprintf(stderr, "IO window address not specified for PHB\n");
|
error_setg(errp, "IO window address not specified for PHB");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (find_phb(spapr, sphb->buid)) {
|
if (find_phb(spapr, sphb->buid)) {
|
||||||
fprintf(stderr, "PCI host bridges must have unique BUIDs\n");
|
error_setg(errp, "PCI host bridges must have unique BUIDs");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
|
sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
|
||||||
@@ -594,26 +594,8 @@ static int spapr_phb_init(SysBusDevice *s)
|
|||||||
get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE);
|
get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE);
|
||||||
memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
|
memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
|
||||||
&sphb->iowindow);
|
&sphb->iowindow);
|
||||||
/*
|
|
||||||
* Selecting a busname is more complex than you'd think, due to
|
bus = pci_register_bus(dev, NULL,
|
||||||
* interacting constraints. If the user has specified an id
|
|
||||||
* explicitly for the phb , then we want to use the qdev default
|
|
||||||
* of naming the bus based on the bridge device (so the user can
|
|
||||||
* then assign devices to it in the way they expect). For the
|
|
||||||
* first / default PCI bus (index=0) we want to use just "pci"
|
|
||||||
* because libvirt expects there to be a bus called, simply,
|
|
||||||
* "pci". Otherwise, we use the same name as in the device tree,
|
|
||||||
* since it's unique by construction, and makes the guest visible
|
|
||||||
* BUID clear.
|
|
||||||
*/
|
|
||||||
if (dev->id) {
|
|
||||||
busname = NULL;
|
|
||||||
} else if (sphb->index == 0) {
|
|
||||||
busname = "pci";
|
|
||||||
} else {
|
|
||||||
busname = sphb->dtbusname;
|
|
||||||
}
|
|
||||||
bus = pci_register_bus(dev, busname,
|
|
||||||
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
|
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
|
||||||
&sphb->memspace, &sphb->iospace,
|
&sphb->memspace, &sphb->iospace,
|
||||||
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
|
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
|
||||||
@@ -624,8 +606,9 @@ static int spapr_phb_init(SysBusDevice *s)
|
|||||||
sphb->tcet = spapr_tce_new_table(dev, sphb->dma_liobn,
|
sphb->tcet = spapr_tce_new_table(dev, sphb->dma_liobn,
|
||||||
sphb->dma_window_size);
|
sphb->dma_window_size);
|
||||||
if (!sphb->tcet) {
|
if (!sphb->tcet) {
|
||||||
fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
|
error_setg(errp, "Unable to create TCE table for %s",
|
||||||
return -1;
|
sphb->dtbusname);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet),
|
address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet),
|
||||||
sphb->dtbusname);
|
sphb->dtbusname);
|
||||||
@@ -642,13 +625,12 @@ static int spapr_phb_init(SysBusDevice *s)
|
|||||||
|
|
||||||
irq = spapr_allocate_lsi(0);
|
irq = spapr_allocate_lsi(0);
|
||||||
if (!irq) {
|
if (!irq) {
|
||||||
return -1;
|
error_setg(errp, "spapr_allocate_lsi failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sphb->lsi_table[i].irq = irq;
|
sphb->lsi_table[i].irq = irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spapr_phb_reset(DeviceState *qdev)
|
static void spapr_phb_reset(DeviceState *qdev)
|
||||||
@@ -731,11 +713,10 @@ static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge,
|
|||||||
static void spapr_phb_class_init(ObjectClass *klass, void *data)
|
static void spapr_phb_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
|
PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
|
||||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
hc->root_bus_path = spapr_phb_root_bus_path;
|
hc->root_bus_path = spapr_phb_root_bus_path;
|
||||||
sdc->init = spapr_phb_init;
|
dc->realize = spapr_phb_realize;
|
||||||
dc->props = spapr_phb_properties;
|
dc->props = spapr_phb_properties;
|
||||||
dc->reset = spapr_phb_reset;
|
dc->reset = spapr_phb_reset;
|
||||||
dc->vmsd = &vmstate_spapr_pci;
|
dc->vmsd = &vmstate_spapr_pci;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user