Compare commits
254 Commits
pull-seabi
...
pull-ui-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e934644126 | ||
|
|
f27ff81070 | ||
|
|
97efe4f961 | ||
|
|
c952b71582 | ||
|
|
6250dff39a | ||
|
|
d825367172 | ||
|
|
f29b3431f6 | ||
|
|
b3cb21b9b5 | ||
|
|
a8ffb372a2 | ||
|
|
3d4da9d6f3 | ||
|
|
e92fbc753d | ||
|
|
9c904a7581 | ||
|
|
12597061b3 | ||
|
|
5e5db49953 | ||
|
|
82a4118694 | ||
|
|
a7c8215e3b | ||
|
|
684e508c23 | ||
|
|
aff8fd18f1 | ||
|
|
23425cc2b7 | ||
|
|
9ef9d40261 | ||
|
|
0d9d86fb4d | ||
|
|
ee68697551 | ||
|
|
0062ea0fd6 | ||
|
|
4a1cba3802 | ||
|
|
f6a51c84cd | ||
|
|
721671ade7 | ||
|
|
0891ee1112 | ||
|
|
a37c07022b | ||
|
|
ba0d10378c | ||
|
|
04b88c84a1 | ||
|
|
5c3df1f096 | ||
|
|
6cc9906b4c | ||
|
|
baecbde6d7 | ||
|
|
1211d81b17 | ||
|
|
d5ebc8272b | ||
|
|
f2b58c4375 | ||
|
|
88da0b0301 | ||
|
|
bcb8998fac | ||
|
|
ea83441cc4 | ||
|
|
583f21f8b9 | ||
|
|
204f01b309 | ||
|
|
33243031da | ||
|
|
b8e23926c5 | ||
|
|
dbe2b65566 | ||
|
|
2b5e217067 | ||
|
|
0194cf31cf | ||
|
|
367790cce8 | ||
|
|
72d2e4b6a4 | ||
|
|
7b542eb96d | ||
|
|
14f944063a | ||
|
|
fb5543d820 | ||
|
|
0ccb9c1d81 | ||
|
|
8be95defd6 | ||
|
|
817af1c72d | ||
|
|
f84aab269d | ||
|
|
8a1e52b69d | ||
|
|
0f72559fbc | ||
|
|
91db4642f8 | ||
|
|
9e41bade85 | ||
|
|
8e953a658f | ||
|
|
26d5df9578 | ||
|
|
0584d3c33f | ||
|
|
c491e1521f | ||
|
|
bd407a21a9 | ||
|
|
6efbac908f | ||
|
|
74af4eec29 | ||
|
|
ef17f83661 | ||
|
|
6a0e947b12 | ||
|
|
bd673bd8ab | ||
|
|
4c3386f421 | ||
|
|
2d105bd6b5 | ||
|
|
e03192fd62 | ||
|
|
e353aac51b | ||
|
|
0bfa02595a | ||
|
|
e971fa0422 | ||
|
|
c9b61d9aa1 | ||
|
|
92204403ef | ||
|
|
0a97c40f8e | ||
|
|
416d72b97b | ||
|
|
0f1944735b | ||
|
|
2494c9f640 | ||
|
|
450aaae863 | ||
|
|
e5fdf663cf | ||
|
|
e45d4ef6e3 | ||
|
|
65839b56b9 | ||
|
|
a470b33259 | ||
|
|
c76904ef2f | ||
|
|
6c7c3c21f9 | ||
|
|
c52ab08aee | ||
|
|
6053a86fe7 | ||
|
|
bc20403598 | ||
|
|
166dbda7e1 | ||
|
|
8929fc3a55 | ||
|
|
96a3d39277 | ||
|
|
e3592bc9d8 | ||
|
|
feddd2fd91 | ||
|
|
272f042877 | ||
|
|
be232eb076 | ||
|
|
638cbd452d | ||
|
|
722f8d9099 | ||
|
|
11717bc93a | ||
|
|
45241cf9d7 | ||
|
|
8caa05d889 | ||
|
|
e7a9f35321 | ||
|
|
c17a18ef30 | ||
|
|
a273f4cedf | ||
|
|
5ffb350541 | ||
|
|
eb7a20a361 | ||
|
|
1f4e496e1f | ||
|
|
715c31ec8e | ||
|
|
0ce265ffef | ||
|
|
2651efe7f5 | ||
|
|
225adf16d2 | ||
|
|
4fd460bf25 | ||
|
|
f4d7674722 | ||
|
|
e11680524a | ||
|
|
5ce9cfe737 | ||
|
|
12a4f2162a | ||
|
|
1f923c70bd | ||
|
|
d1e8e8ecc3 | ||
|
|
ffb7bf452a | ||
|
|
d4c64800bb | ||
|
|
9443598d7e | ||
|
|
893dcdbfa9 | ||
|
|
fcf5ef2ab5 | ||
|
|
82ecffa8c0 | ||
|
|
0737f32daf | ||
|
|
9b7621bca2 | ||
|
|
abd7f08b23 | ||
|
|
6a928d25b6 | ||
|
|
66d1c4c19f | ||
|
|
d70678a538 | ||
|
|
a08156321a | ||
|
|
3753c75db8 | ||
|
|
a92f7fe5a8 | ||
|
|
4230e5d128 | ||
|
|
a9353fe897 | ||
|
|
d750c3a966 | ||
|
|
b5b7b5deb4 | ||
|
|
68701de136 | ||
|
|
a3e1505dae | ||
|
|
ce1f3e88f8 | ||
|
|
8a04c80f9f | ||
|
|
5d3074f0db | ||
|
|
8a844b2603 | ||
|
|
e24f095e44 | ||
|
|
9f5832d34b | ||
|
|
76b5550f70 | ||
|
|
7103d9165b | ||
|
|
1a417e46ae | ||
|
|
5460da501a | ||
|
|
5072f7b38b | ||
|
|
9f2a70e465 | ||
|
|
4d5c8bc42f | ||
|
|
c5927e7abf | ||
|
|
49687ace02 | ||
|
|
95cd8fd909 | ||
|
|
29a6731afb | ||
|
|
1792d7d0a2 | ||
|
|
043b5a4951 | ||
|
|
bc66cedb41 | ||
|
|
4299b90e9b | ||
|
|
64f441d2e5 | ||
|
|
77d54985b8 | ||
|
|
2d1cd6c7a9 | ||
|
|
42a8dadc74 | ||
|
|
6c7565028c | ||
|
|
e6e2784cac | ||
|
|
b5a587b613 | ||
|
|
bb7cab5f34 | ||
|
|
9099a36b4b | ||
|
|
bd8ef5060d | ||
|
|
2cfe5d7bc2 | ||
|
|
5c0139a8c2 | ||
|
|
9730280d54 | ||
|
|
1b57bd4f2f | ||
|
|
aa6c6ae843 | ||
|
|
6cb99acc28 | ||
|
|
5449c230fa | ||
|
|
1cd56fd2e1 | ||
|
|
f05234df63 | ||
|
|
7ecf44a579 | ||
|
|
51cd8ef8ad | ||
|
|
38e532aa74 | ||
|
|
c5b95f6be7 | ||
|
|
6725f887ac | ||
|
|
c79ed23df5 | ||
|
|
5a55760226 | ||
|
|
517dcb8785 | ||
|
|
e514379de5 | ||
|
|
f37f29d314 | ||
|
|
ff3b8b8f86 | ||
|
|
406c97c41f | ||
|
|
c96f0ee6a6 | ||
|
|
f9f885b78a | ||
|
|
04e27c6bb0 | ||
|
|
64e184e260 | ||
|
|
9e55d58806 | ||
|
|
75f19f8c30 | ||
|
|
b77257d7ba | ||
|
|
6aa3a61657 | ||
|
|
685479bd5d | ||
|
|
8f57758311 | ||
|
|
a8b99dd516 | ||
|
|
91203f08f0 | ||
|
|
2f2c8d6b37 | ||
|
|
511008f5cc | ||
|
|
628d0a4bdf | ||
|
|
06c33754a1 | ||
|
|
4a18cd44f3 | ||
|
|
0fecd0292c | ||
|
|
801edfcbb5 | ||
|
|
5436c29d78 | ||
|
|
c090c97d92 | ||
|
|
7875efb9f6 | ||
|
|
898ae90a44 | ||
|
|
971f406b77 | ||
|
|
702dbcc274 | ||
|
|
4774718e5c | ||
|
|
659fc8d342 | ||
|
|
f0c10c392f | ||
|
|
5c4537bded | ||
|
|
5a78b821eb | ||
|
|
146c11f16f | ||
|
|
3fed86eefc | ||
|
|
16a2497bd4 | ||
|
|
39d97e14a1 | ||
|
|
a813fe7362 | ||
|
|
8a273cbe53 | ||
|
|
0d28aa197d | ||
|
|
62ef3760d4 | ||
|
|
171da9d5db | ||
|
|
00227fefd2 | ||
|
|
1d895feb3b | ||
|
|
169407e1f7 | ||
|
|
c2a8531690 | ||
|
|
01d7d15ce3 | ||
|
|
76989f4ffa | ||
|
|
5167dff8c7 | ||
|
|
f1784a222e | ||
|
|
3a6c9172ac | ||
|
|
ce49b734b4 | ||
|
|
873d57abba | ||
|
|
b85f9dfdb1 | ||
|
|
424ad8388f | ||
|
|
3482b9bc41 | ||
|
|
49228d1e95 | ||
|
|
b2f95feec5 | ||
|
|
ecdbead659 | ||
|
|
a7764f1548 | ||
|
|
06bf33cfe7 | ||
|
|
668c0e441d | ||
|
|
ab9125c021 | ||
|
|
804ba7c10b |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -82,10 +82,6 @@
|
|||||||
*.d
|
*.d
|
||||||
!/scripts/qemu-guest-agent/fsfreeze-hook.d
|
!/scripts/qemu-guest-agent/fsfreeze-hook.d
|
||||||
*.o
|
*.o
|
||||||
*.lo
|
|
||||||
*.la
|
|
||||||
*.pc
|
|
||||||
.libs
|
|
||||||
.sdk
|
.sdk
|
||||||
*.gcda
|
*.gcda
|
||||||
*.gcno
|
*.gcno
|
||||||
|
|||||||
18
HACKING
18
HACKING
@@ -1,10 +1,28 @@
|
|||||||
1. Preprocessor
|
1. Preprocessor
|
||||||
|
|
||||||
|
1.1. Variadic macros
|
||||||
|
|
||||||
For variadic macros, stick with this C99-like syntax:
|
For variadic macros, stick with this C99-like syntax:
|
||||||
|
|
||||||
#define DPRINTF(fmt, ...) \
|
#define DPRINTF(fmt, ...) \
|
||||||
do { printf("IRQ: " fmt, ## __VA_ARGS__); } while (0)
|
do { printf("IRQ: " fmt, ## __VA_ARGS__); } while (0)
|
||||||
|
|
||||||
|
1.2. Include directives
|
||||||
|
|
||||||
|
Order include directives as follows:
|
||||||
|
|
||||||
|
#include "qemu/osdep.h" /* Always first... */
|
||||||
|
#include <...> /* then system headers... */
|
||||||
|
#include "..." /* and finally QEMU headers. */
|
||||||
|
|
||||||
|
The "qemu/osdep.h" header contains preprocessor macros that affect the behavior
|
||||||
|
of core system headers like <stdint.h>. It must be the first include so that
|
||||||
|
core system headers included by external libraries get the preprocessor macros
|
||||||
|
that QEMU depends on.
|
||||||
|
|
||||||
|
Do not include "qemu/osdep.h" from header files since the .c file will have
|
||||||
|
already included it.
|
||||||
|
|
||||||
2. C types
|
2. C types
|
||||||
|
|
||||||
It should be common sense to use the right type, but we have collected
|
It should be common sense to use the right type, but we have collected
|
||||||
|
|||||||
48
MAINTAINERS
48
MAINTAINERS
@@ -106,7 +106,7 @@ F: include/fpu/
|
|||||||
Alpha
|
Alpha
|
||||||
M: Richard Henderson <rth@twiddle.net>
|
M: Richard Henderson <rth@twiddle.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-alpha/
|
F: target/alpha/
|
||||||
F: hw/alpha/
|
F: hw/alpha/
|
||||||
F: tests/tcg/alpha/
|
F: tests/tcg/alpha/
|
||||||
F: disas/alpha.c
|
F: disas/alpha.c
|
||||||
@@ -115,7 +115,7 @@ ARM
|
|||||||
M: Peter Maydell <peter.maydell@linaro.org>
|
M: Peter Maydell <peter.maydell@linaro.org>
|
||||||
L: qemu-arm@nongnu.org
|
L: qemu-arm@nongnu.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-arm/
|
F: target/arm/
|
||||||
F: hw/arm/
|
F: hw/arm/
|
||||||
F: hw/cpu/a*mpcore.c
|
F: hw/cpu/a*mpcore.c
|
||||||
F: include/hw/cpu/a*mpcore.h
|
F: include/hw/cpu/a*mpcore.h
|
||||||
@@ -126,7 +126,7 @@ F: disas/libvixl/
|
|||||||
CRIS
|
CRIS
|
||||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-cris/
|
F: target/cris/
|
||||||
F: hw/cris/
|
F: hw/cris/
|
||||||
F: include/hw/cris/
|
F: include/hw/cris/
|
||||||
F: tests/tcg/cris/
|
F: tests/tcg/cris/
|
||||||
@@ -135,7 +135,7 @@ F: disas/cris.c
|
|||||||
LM32
|
LM32
|
||||||
M: Michael Walle <michael@walle.cc>
|
M: Michael Walle <michael@walle.cc>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-lm32/
|
F: target/lm32/
|
||||||
F: disas/lm32.c
|
F: disas/lm32.c
|
||||||
F: hw/lm32/
|
F: hw/lm32/
|
||||||
F: hw/*/lm32_*
|
F: hw/*/lm32_*
|
||||||
@@ -147,13 +147,13 @@ F: tests/tcg/lm32/
|
|||||||
M68K
|
M68K
|
||||||
M: Laurent Vivier <laurent@vivier.eu>
|
M: Laurent Vivier <laurent@vivier.eu>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-m68k/
|
F: target/m68k/
|
||||||
F: disas/m68k.c
|
F: disas/m68k.c
|
||||||
|
|
||||||
MicroBlaze
|
MicroBlaze
|
||||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-microblaze/
|
F: target/microblaze/
|
||||||
F: hw/microblaze/
|
F: hw/microblaze/
|
||||||
F: disas/microblaze.c
|
F: disas/microblaze.c
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ MIPS
|
|||||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||||
M: Yongbok Kim <yongbok.kim@imgtec.com>
|
M: Yongbok Kim <yongbok.kim@imgtec.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-mips/
|
F: target/mips/
|
||||||
F: hw/mips/
|
F: hw/mips/
|
||||||
F: hw/misc/mips_*
|
F: hw/misc/mips_*
|
||||||
F: hw/intc/mips_gic.c
|
F: hw/intc/mips_gic.c
|
||||||
@@ -176,7 +176,7 @@ F: disas/mips.c
|
|||||||
Moxie
|
Moxie
|
||||||
M: Anthony Green <green@moxielogic.com>
|
M: Anthony Green <green@moxielogic.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-moxie/
|
F: target/moxie/
|
||||||
F: disas/moxie.c
|
F: disas/moxie.c
|
||||||
F: hw/moxie/
|
F: hw/moxie/
|
||||||
F: default-configs/moxie-softmmu.mak
|
F: default-configs/moxie-softmmu.mak
|
||||||
@@ -184,7 +184,7 @@ F: default-configs/moxie-softmmu.mak
|
|||||||
OpenRISC
|
OpenRISC
|
||||||
M: Jia Liu <proljc@gmail.com>
|
M: Jia Liu <proljc@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-openrisc/
|
F: target/openrisc/
|
||||||
F: hw/openrisc/
|
F: hw/openrisc/
|
||||||
F: tests/tcg/openrisc/
|
F: tests/tcg/openrisc/
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ M: David Gibson <david@gibson.dropbear.id.au>
|
|||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
L: qemu-ppc@nongnu.org
|
L: qemu-ppc@nongnu.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-ppc/
|
F: target/ppc/
|
||||||
F: hw/ppc/
|
F: hw/ppc/
|
||||||
F: include/hw/ppc/
|
F: include/hw/ppc/
|
||||||
F: disas/ppc.c
|
F: disas/ppc.c
|
||||||
@@ -202,14 +202,14 @@ S390
|
|||||||
M: Richard Henderson <rth@twiddle.net>
|
M: Richard Henderson <rth@twiddle.net>
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-s390x/
|
F: target/s390x/
|
||||||
F: hw/s390x/
|
F: hw/s390x/
|
||||||
F: disas/s390.c
|
F: disas/s390.c
|
||||||
|
|
||||||
SH4
|
SH4
|
||||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: target-sh4/
|
F: target/sh4/
|
||||||
F: hw/sh4/
|
F: hw/sh4/
|
||||||
F: disas/sh4.c
|
F: disas/sh4.c
|
||||||
F: include/hw/sh4/
|
F: include/hw/sh4/
|
||||||
@@ -218,7 +218,7 @@ SPARC
|
|||||||
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||||
M: Artyom Tarasenko <atar4qemu@gmail.com>
|
M: Artyom Tarasenko <atar4qemu@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-sparc/
|
F: target/sparc/
|
||||||
F: hw/sparc/
|
F: hw/sparc/
|
||||||
F: hw/sparc64/
|
F: hw/sparc64/
|
||||||
F: disas/sparc.c
|
F: disas/sparc.c
|
||||||
@@ -226,7 +226,7 @@ F: disas/sparc.c
|
|||||||
UniCore32
|
UniCore32
|
||||||
M: Guan Xuetao <gxt@mprc.pku.edu.cn>
|
M: Guan Xuetao <gxt@mprc.pku.edu.cn>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-unicore32/
|
F: target/unicore32/
|
||||||
F: hw/unicore32/
|
F: hw/unicore32/
|
||||||
F: include/hw/unicore32/
|
F: include/hw/unicore32/
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
|
|||||||
M: Richard Henderson <rth@twiddle.net>
|
M: Richard Henderson <rth@twiddle.net>
|
||||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-i386/
|
F: target/i386/
|
||||||
F: hw/i386/
|
F: hw/i386/
|
||||||
F: disas/i386.c
|
F: disas/i386.c
|
||||||
|
|
||||||
@@ -243,14 +243,14 @@ Xtensa
|
|||||||
M: Max Filippov <jcmvbkbc@gmail.com>
|
M: Max Filippov <jcmvbkbc@gmail.com>
|
||||||
W: http://wiki.osll.spb.ru/doku.php?id=etc:users:jcmvbkbc:qemu-target-xtensa
|
W: http://wiki.osll.spb.ru/doku.php?id=etc:users:jcmvbkbc:qemu-target-xtensa
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-xtensa/
|
F: target/xtensa/
|
||||||
F: hw/xtensa/
|
F: hw/xtensa/
|
||||||
F: tests/tcg/xtensa/
|
F: tests/tcg/xtensa/
|
||||||
|
|
||||||
TriCore
|
TriCore
|
||||||
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-tricore/
|
F: target/tricore/
|
||||||
F: hw/tricore/
|
F: hw/tricore/
|
||||||
F: include/hw/tricore/
|
F: include/hw/tricore/
|
||||||
|
|
||||||
@@ -269,26 +269,26 @@ ARM
|
|||||||
M: Peter Maydell <peter.maydell@linaro.org>
|
M: Peter Maydell <peter.maydell@linaro.org>
|
||||||
L: qemu-arm@nongnu.org
|
L: qemu-arm@nongnu.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-arm/kvm.c
|
F: target/arm/kvm.c
|
||||||
|
|
||||||
MIPS
|
MIPS
|
||||||
M: James Hogan <james.hogan@imgtec.com>
|
M: James Hogan <james.hogan@imgtec.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-mips/kvm.c
|
F: target/mips/kvm.c
|
||||||
|
|
||||||
PPC
|
PPC
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-ppc/kvm.c
|
F: target/ppc/kvm.c
|
||||||
|
|
||||||
S390
|
S390
|
||||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||||
M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
M: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-s390x/kvm.c
|
F: target/s390x/kvm.c
|
||||||
F: target-s390x/ioinst.[ch]
|
F: target/s390x/ioinst.[ch]
|
||||||
F: target-s390x/machine.c
|
F: target/s390x/machine.c
|
||||||
F: hw/intc/s390_flic.c
|
F: hw/intc/s390_flic.c
|
||||||
F: hw/intc/s390_flic_kvm.c
|
F: hw/intc/s390_flic_kvm.c
|
||||||
F: include/hw/s390x/s390_flic.h
|
F: include/hw/s390x/s390_flic.h
|
||||||
@@ -301,7 +301,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
|
|||||||
M: Marcelo Tosatti <mtosatti@redhat.com>
|
M: Marcelo Tosatti <mtosatti@redhat.com>
|
||||||
L: kvm@vger.kernel.org
|
L: kvm@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: target-i386/kvm.c
|
F: target/i386/kvm.c
|
||||||
|
|
||||||
Guest CPU Cores (Xen):
|
Guest CPU Cores (Xen):
|
||||||
----------------------
|
----------------------
|
||||||
|
|||||||
9
Makefile
9
Makefile
@@ -231,12 +231,10 @@ ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
|
|||||||
|
|
||||||
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
|
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
|
||||||
|
|
||||||
$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc config-host.h | $(BUILD_DIR)/version.lo
|
$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc config-host.h
|
||||||
$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"RC","version.o")
|
$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"RC","version.o")
|
||||||
$(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc config-host.h
|
|
||||||
$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"RC","version.lo")
|
|
||||||
|
|
||||||
Makefile: $(version-obj-y) $(version-lobj-y)
|
Makefile: $(version-obj-y)
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Build libraries
|
# Build libraries
|
||||||
@@ -358,10 +356,9 @@ clean:
|
|||||||
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
|
||||||
rm -f *.msi
|
rm -f *.msi
|
||||||
find . \( -name '*.l[oa]' -o -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
|
find . \( -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
|
||||||
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 -f qemu-img-cmds.h
|
rm -f qemu-img-cmds.h
|
||||||
rm -f ui/shader/*-vert.h ui/shader/*-frag.h
|
rm -f ui/shader/*-vert.h ui/shader/*-frag.h
|
||||||
@# May not be present in GENERATED_HEADERS
|
@# May not be present in GENERATED_HEADERS
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ common-obj-y += disas/
|
|||||||
######################################################################
|
######################################################################
|
||||||
# Resource file for Windows executables
|
# Resource file for Windows executables
|
||||||
version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o
|
version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o
|
||||||
version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# tracing
|
# tracing
|
||||||
@@ -155,11 +154,11 @@ trace-events-y += hw/alpha/trace-events
|
|||||||
trace-events-y += ui/trace-events
|
trace-events-y += ui/trace-events
|
||||||
trace-events-y += audio/trace-events
|
trace-events-y += audio/trace-events
|
||||||
trace-events-y += net/trace-events
|
trace-events-y += net/trace-events
|
||||||
trace-events-y += target-arm/trace-events
|
trace-events-y += target/arm/trace-events
|
||||||
trace-events-y += target-i386/trace-events
|
trace-events-y += target/i386/trace-events
|
||||||
trace-events-y += target-sparc/trace-events
|
trace-events-y += target/sparc/trace-events
|
||||||
trace-events-y += target-s390x/trace-events
|
trace-events-y += target/s390x/trace-events
|
||||||
trace-events-y += target-ppc/trace-events
|
trace-events-y += target/ppc/trace-events
|
||||||
trace-events-y += qom/trace-events
|
trace-events-y += qom/trace-events
|
||||||
trace-events-y += linux-user/trace-events
|
trace-events-y += linux-user/trace-events
|
||||||
trace-events-y += qapi/trace-events
|
trace-events-y += qapi/trace-events
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ $(call set-vpath, $(SRC_PATH):$(BUILD_DIR))
|
|||||||
ifdef CONFIG_LINUX
|
ifdef CONFIG_LINUX
|
||||||
QEMU_CFLAGS += -I../linux-headers
|
QEMU_CFLAGS += -I../linux-headers
|
||||||
endif
|
endif
|
||||||
QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H
|
QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target/$(TARGET_BASE_ARCH) -DNEED_CPU_H
|
||||||
|
|
||||||
QEMU_CFLAGS+=-I$(SRC_PATH)/include
|
QEMU_CFLAGS+=-I$(SRC_PATH)/include
|
||||||
|
|
||||||
@@ -76,6 +76,7 @@ $(QEMU_PROG)-simpletrace.stp: $(BUILD_DIR)/trace-events-all
|
|||||||
else
|
else
|
||||||
stap:
|
stap:
|
||||||
endif
|
endif
|
||||||
|
.PHONY: stap
|
||||||
|
|
||||||
all: $(PROGS) stap
|
all: $(PROGS) stap
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ obj-$(CONFIG_TCG_INTERPRETER) += tci.o
|
|||||||
obj-y += tcg/tcg-common.o
|
obj-y += tcg/tcg-common.o
|
||||||
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
|
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
|
||||||
obj-y += fpu/softfloat.o
|
obj-y += fpu/softfloat.o
|
||||||
obj-y += target-$(TARGET_BASE_ARCH)/
|
obj-y += target/$(TARGET_BASE_ARCH)/
|
||||||
obj-y += disas.o
|
obj-y += disas.o
|
||||||
obj-y += tcg-runtime.o
|
obj-y += tcg-runtime.o
|
||||||
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
|
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
|
||||||
|
|||||||
312
aio-posix.c
312
aio-posix.c
@@ -18,6 +18,8 @@
|
|||||||
#include "block/block.h"
|
#include "block/block.h"
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
|
#include "trace.h"
|
||||||
#ifdef CONFIG_EPOLL_CREATE1
|
#ifdef CONFIG_EPOLL_CREATE1
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -27,6 +29,9 @@ struct AioHandler
|
|||||||
GPollFD pfd;
|
GPollFD pfd;
|
||||||
IOHandler *io_read;
|
IOHandler *io_read;
|
||||||
IOHandler *io_write;
|
IOHandler *io_write;
|
||||||
|
AioPollFn *io_poll;
|
||||||
|
IOHandler *io_poll_begin;
|
||||||
|
IOHandler *io_poll_end;
|
||||||
int deleted;
|
int deleted;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
bool is_external;
|
bool is_external;
|
||||||
@@ -200,6 +205,7 @@ void aio_set_fd_handler(AioContext *ctx,
|
|||||||
bool is_external,
|
bool is_external,
|
||||||
IOHandler *io_read,
|
IOHandler *io_read,
|
||||||
IOHandler *io_write,
|
IOHandler *io_write,
|
||||||
|
AioPollFn *io_poll,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
AioHandler *node;
|
AioHandler *node;
|
||||||
@@ -209,7 +215,7 @@ void aio_set_fd_handler(AioContext *ctx,
|
|||||||
node = find_aio_handler(ctx, fd);
|
node = find_aio_handler(ctx, fd);
|
||||||
|
|
||||||
/* Are we deleting the fd handler? */
|
/* Are we deleting the fd handler? */
|
||||||
if (!io_read && !io_write) {
|
if (!io_read && !io_write && !io_poll) {
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -228,6 +234,10 @@ void aio_set_fd_handler(AioContext *ctx,
|
|||||||
QLIST_REMOVE(node, node);
|
QLIST_REMOVE(node, node);
|
||||||
deleted = true;
|
deleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!node->io_poll) {
|
||||||
|
ctx->poll_disable_cnt--;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
/* Alloc and insert if it's not already there */
|
/* Alloc and insert if it's not already there */
|
||||||
@@ -237,10 +247,16 @@ void aio_set_fd_handler(AioContext *ctx,
|
|||||||
|
|
||||||
g_source_add_poll(&ctx->source, &node->pfd);
|
g_source_add_poll(&ctx->source, &node->pfd);
|
||||||
is_new = true;
|
is_new = true;
|
||||||
|
|
||||||
|
ctx->poll_disable_cnt += !io_poll;
|
||||||
|
} else {
|
||||||
|
ctx->poll_disable_cnt += !io_poll - !node->io_poll;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update handler with latest information */
|
/* Update handler with latest information */
|
||||||
node->io_read = io_read;
|
node->io_read = io_read;
|
||||||
node->io_write = io_write;
|
node->io_write = io_write;
|
||||||
|
node->io_poll = io_poll;
|
||||||
node->opaque = opaque;
|
node->opaque = opaque;
|
||||||
node->is_external = is_external;
|
node->is_external = is_external;
|
||||||
|
|
||||||
@@ -250,22 +266,83 @@ void aio_set_fd_handler(AioContext *ctx,
|
|||||||
|
|
||||||
aio_epoll_update(ctx, node, is_new);
|
aio_epoll_update(ctx, node, is_new);
|
||||||
aio_notify(ctx);
|
aio_notify(ctx);
|
||||||
|
|
||||||
if (deleted) {
|
if (deleted) {
|
||||||
g_free(node);
|
g_free(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_set_fd_poll(AioContext *ctx, int fd,
|
||||||
|
IOHandler *io_poll_begin,
|
||||||
|
IOHandler *io_poll_end)
|
||||||
|
{
|
||||||
|
AioHandler *node = find_aio_handler(ctx, fd);
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->io_poll_begin = io_poll_begin;
|
||||||
|
node->io_poll_end = io_poll_end;
|
||||||
|
}
|
||||||
|
|
||||||
void aio_set_event_notifier(AioContext *ctx,
|
void aio_set_event_notifier(AioContext *ctx,
|
||||||
EventNotifier *notifier,
|
EventNotifier *notifier,
|
||||||
bool is_external,
|
bool is_external,
|
||||||
EventNotifierHandler *io_read)
|
EventNotifierHandler *io_read,
|
||||||
|
AioPollFn *io_poll)
|
||||||
{
|
{
|
||||||
aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
|
aio_set_fd_handler(ctx, event_notifier_get_fd(notifier), is_external,
|
||||||
is_external, (IOHandler *)io_read, NULL, notifier);
|
(IOHandler *)io_read, NULL, io_poll, notifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_set_event_notifier_poll(AioContext *ctx,
|
||||||
|
EventNotifier *notifier,
|
||||||
|
EventNotifierHandler *io_poll_begin,
|
||||||
|
EventNotifierHandler *io_poll_end)
|
||||||
|
{
|
||||||
|
aio_set_fd_poll(ctx, event_notifier_get_fd(notifier),
|
||||||
|
(IOHandler *)io_poll_begin,
|
||||||
|
(IOHandler *)io_poll_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void poll_set_started(AioContext *ctx, bool started)
|
||||||
|
{
|
||||||
|
AioHandler *node;
|
||||||
|
|
||||||
|
if (started == ctx->poll_started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->poll_started = started;
|
||||||
|
|
||||||
|
ctx->walking_handlers++;
|
||||||
|
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
|
||||||
|
IOHandler *fn;
|
||||||
|
|
||||||
|
if (node->deleted) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (started) {
|
||||||
|
fn = node->io_poll_begin;
|
||||||
|
} else {
|
||||||
|
fn = node->io_poll_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn) {
|
||||||
|
fn(node->opaque);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx->walking_handlers--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool aio_prepare(AioContext *ctx)
|
bool aio_prepare(AioContext *ctx)
|
||||||
{
|
{
|
||||||
|
/* Poll mode cannot be used with glib's event loop, disable it. */
|
||||||
|
poll_set_started(ctx, false);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,9 +367,13 @@ bool aio_pending(AioContext *ctx)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aio_dispatch(AioContext *ctx)
|
/*
|
||||||
|
* Note that dispatch_fds == false has the side-effect of post-poning the
|
||||||
|
* freeing of deleted handlers.
|
||||||
|
*/
|
||||||
|
bool aio_dispatch(AioContext *ctx, bool dispatch_fds)
|
||||||
{
|
{
|
||||||
AioHandler *node;
|
AioHandler *node = NULL;
|
||||||
bool progress = false;
|
bool progress = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -308,7 +389,9 @@ bool aio_dispatch(AioContext *ctx)
|
|||||||
* We have to walk very carefully in case aio_set_fd_handler is
|
* We have to walk very carefully in case aio_set_fd_handler is
|
||||||
* called while we're walking.
|
* called while we're walking.
|
||||||
*/
|
*/
|
||||||
node = QLIST_FIRST(&ctx->aio_handlers);
|
if (dispatch_fds) {
|
||||||
|
node = QLIST_FIRST(&ctx->aio_handlers);
|
||||||
|
}
|
||||||
while (node) {
|
while (node) {
|
||||||
AioHandler *tmp;
|
AioHandler *tmp;
|
||||||
int revents;
|
int revents;
|
||||||
@@ -400,12 +483,100 @@ static void add_pollfd(AioHandler *node)
|
|||||||
npfd++;
|
npfd++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool run_poll_handlers_once(AioContext *ctx)
|
||||||
|
{
|
||||||
|
bool progress = false;
|
||||||
|
AioHandler *node;
|
||||||
|
|
||||||
|
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
|
||||||
|
if (!node->deleted && node->io_poll &&
|
||||||
|
node->io_poll(node->opaque)) {
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Caller handles freeing deleted nodes. Don't do it here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* run_poll_handlers:
|
||||||
|
* @ctx: the AioContext
|
||||||
|
* @max_ns: maximum time to poll for, in nanoseconds
|
||||||
|
*
|
||||||
|
* Polls for a given time.
|
||||||
|
*
|
||||||
|
* Note that ctx->notify_me must be non-zero so this function can detect
|
||||||
|
* aio_notify().
|
||||||
|
*
|
||||||
|
* Note that the caller must have incremented ctx->walking_handlers.
|
||||||
|
*
|
||||||
|
* Returns: true if progress was made, false otherwise
|
||||||
|
*/
|
||||||
|
static bool run_poll_handlers(AioContext *ctx, int64_t max_ns)
|
||||||
|
{
|
||||||
|
bool progress;
|
||||||
|
int64_t end_time;
|
||||||
|
|
||||||
|
assert(ctx->notify_me);
|
||||||
|
assert(ctx->walking_handlers > 0);
|
||||||
|
assert(ctx->poll_disable_cnt == 0);
|
||||||
|
|
||||||
|
trace_run_poll_handlers_begin(ctx, max_ns);
|
||||||
|
|
||||||
|
end_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + max_ns;
|
||||||
|
|
||||||
|
do {
|
||||||
|
progress = run_poll_handlers_once(ctx);
|
||||||
|
} while (!progress && qemu_clock_get_ns(QEMU_CLOCK_REALTIME) < end_time);
|
||||||
|
|
||||||
|
trace_run_poll_handlers_end(ctx, progress);
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try_poll_mode:
|
||||||
|
* @ctx: the AioContext
|
||||||
|
* @blocking: busy polling is only attempted when blocking is true
|
||||||
|
*
|
||||||
|
* ctx->notify_me must be non-zero so this function can detect aio_notify().
|
||||||
|
*
|
||||||
|
* Note that the caller must have incremented ctx->walking_handlers.
|
||||||
|
*
|
||||||
|
* Returns: true if progress was made, false otherwise
|
||||||
|
*/
|
||||||
|
static bool try_poll_mode(AioContext *ctx, bool blocking)
|
||||||
|
{
|
||||||
|
if (blocking && ctx->poll_max_ns && ctx->poll_disable_cnt == 0) {
|
||||||
|
/* See qemu_soonest_timeout() uint64_t hack */
|
||||||
|
int64_t max_ns = MIN((uint64_t)aio_compute_timeout(ctx),
|
||||||
|
(uint64_t)ctx->poll_ns);
|
||||||
|
|
||||||
|
if (max_ns) {
|
||||||
|
poll_set_started(ctx, true);
|
||||||
|
|
||||||
|
if (run_poll_handlers(ctx, max_ns)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
poll_set_started(ctx, false);
|
||||||
|
|
||||||
|
/* Even if we don't run busy polling, try polling once in case it can make
|
||||||
|
* progress and the caller will be able to avoid ppoll(2)/epoll_wait(2).
|
||||||
|
*/
|
||||||
|
return run_poll_handlers_once(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
bool aio_poll(AioContext *ctx, bool blocking)
|
bool aio_poll(AioContext *ctx, bool blocking)
|
||||||
{
|
{
|
||||||
AioHandler *node;
|
AioHandler *node;
|
||||||
int i, ret;
|
int i;
|
||||||
|
int ret = 0;
|
||||||
bool progress;
|
bool progress;
|
||||||
int64_t timeout;
|
int64_t timeout;
|
||||||
|
int64_t start = 0;
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
aio_context_acquire(ctx);
|
||||||
progress = false;
|
progress = false;
|
||||||
@@ -423,41 +594,91 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|||||||
|
|
||||||
ctx->walking_handlers++;
|
ctx->walking_handlers++;
|
||||||
|
|
||||||
assert(npfd == 0);
|
if (ctx->poll_max_ns) {
|
||||||
|
start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||||
|
}
|
||||||
|
|
||||||
/* fill pollfds */
|
if (try_poll_mode(ctx, blocking)) {
|
||||||
|
progress = true;
|
||||||
|
} else {
|
||||||
|
assert(npfd == 0);
|
||||||
|
|
||||||
if (!aio_epoll_enabled(ctx)) {
|
/* fill pollfds */
|
||||||
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
|
|
||||||
if (!node->deleted && node->pfd.events
|
if (!aio_epoll_enabled(ctx)) {
|
||||||
&& aio_node_check(ctx, node->is_external)) {
|
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
|
||||||
add_pollfd(node);
|
if (!node->deleted && node->pfd.events
|
||||||
|
&& aio_node_check(ctx, node->is_external)) {
|
||||||
|
add_pollfd(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timeout = blocking ? aio_compute_timeout(ctx) : 0;
|
||||||
|
|
||||||
|
/* wait until next event */
|
||||||
|
if (timeout) {
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
|
||||||
|
AioHandler epoll_handler;
|
||||||
|
|
||||||
|
epoll_handler.pfd.fd = ctx->epollfd;
|
||||||
|
epoll_handler.pfd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
|
||||||
|
npfd = 0;
|
||||||
|
add_pollfd(&epoll_handler);
|
||||||
|
ret = aio_epoll(ctx, pollfds, npfd, timeout);
|
||||||
|
} else {
|
||||||
|
ret = qemu_poll_ns(pollfds, npfd, timeout);
|
||||||
|
}
|
||||||
|
if (timeout) {
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = blocking ? aio_compute_timeout(ctx) : 0;
|
|
||||||
|
|
||||||
/* wait until next event */
|
|
||||||
if (timeout) {
|
|
||||||
aio_context_release(ctx);
|
|
||||||
}
|
|
||||||
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
|
|
||||||
AioHandler epoll_handler;
|
|
||||||
|
|
||||||
epoll_handler.pfd.fd = ctx->epollfd;
|
|
||||||
epoll_handler.pfd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
|
|
||||||
npfd = 0;
|
|
||||||
add_pollfd(&epoll_handler);
|
|
||||||
ret = aio_epoll(ctx, pollfds, npfd, timeout);
|
|
||||||
} else {
|
|
||||||
ret = qemu_poll_ns(pollfds, npfd, timeout);
|
|
||||||
}
|
|
||||||
if (blocking) {
|
if (blocking) {
|
||||||
atomic_sub(&ctx->notify_me, 2);
|
atomic_sub(&ctx->notify_me, 2);
|
||||||
}
|
}
|
||||||
if (timeout) {
|
|
||||||
aio_context_acquire(ctx);
|
/* Adjust polling time */
|
||||||
|
if (ctx->poll_max_ns) {
|
||||||
|
int64_t block_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start;
|
||||||
|
|
||||||
|
if (block_ns <= ctx->poll_ns) {
|
||||||
|
/* This is the sweet spot, no adjustment needed */
|
||||||
|
} else if (block_ns > ctx->poll_max_ns) {
|
||||||
|
/* We'd have to poll for too long, poll less */
|
||||||
|
int64_t old = ctx->poll_ns;
|
||||||
|
|
||||||
|
if (ctx->poll_shrink) {
|
||||||
|
ctx->poll_ns /= ctx->poll_shrink;
|
||||||
|
} else {
|
||||||
|
ctx->poll_ns = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_poll_shrink(ctx, old, ctx->poll_ns);
|
||||||
|
} else if (ctx->poll_ns < ctx->poll_max_ns &&
|
||||||
|
block_ns < ctx->poll_max_ns) {
|
||||||
|
/* There is room to grow, poll longer */
|
||||||
|
int64_t old = ctx->poll_ns;
|
||||||
|
int64_t grow = ctx->poll_grow;
|
||||||
|
|
||||||
|
if (grow == 0) {
|
||||||
|
grow = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->poll_ns) {
|
||||||
|
ctx->poll_ns *= grow;
|
||||||
|
} else {
|
||||||
|
ctx->poll_ns = 4000; /* start polling at 4 microseconds */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->poll_ns > ctx->poll_max_ns) {
|
||||||
|
ctx->poll_ns = ctx->poll_max_ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_poll_grow(ctx, old, ctx->poll_ns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_notify_accept(ctx);
|
aio_notify_accept(ctx);
|
||||||
@@ -473,7 +694,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|||||||
ctx->walking_handlers--;
|
ctx->walking_handlers--;
|
||||||
|
|
||||||
/* Run dispatch even if there were no readable fds to run timers */
|
/* Run dispatch even if there were no readable fds to run timers */
|
||||||
if (aio_dispatch(ctx)) {
|
if (aio_dispatch(ctx, ret > 0)) {
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,6 +705,13 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|||||||
|
|
||||||
void aio_context_setup(AioContext *ctx)
|
void aio_context_setup(AioContext *ctx)
|
||||||
{
|
{
|
||||||
|
/* TODO remove this in final patch submission */
|
||||||
|
if (getenv("QEMU_AIO_POLL_MAX_NS")) {
|
||||||
|
fprintf(stderr, "The QEMU_AIO_POLL_MAX_NS environment variable has "
|
||||||
|
"been replaced with -object iothread,poll-max-ns=NUM\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EPOLL_CREATE1
|
#ifdef CONFIG_EPOLL_CREATE1
|
||||||
assert(!ctx->epollfd);
|
assert(!ctx->epollfd);
|
||||||
ctx->epollfd = epoll_create1(EPOLL_CLOEXEC);
|
ctx->epollfd = epoll_create1(EPOLL_CLOEXEC);
|
||||||
@@ -495,3 +723,17 @@ void aio_context_setup(AioContext *ctx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
|
||||||
|
int64_t grow, int64_t shrink, Error **errp)
|
||||||
|
{
|
||||||
|
/* No thread synchronization here, it doesn't matter if an incorrect value
|
||||||
|
* is used once.
|
||||||
|
*/
|
||||||
|
ctx->poll_max_ns = max_ns;
|
||||||
|
ctx->poll_ns = 0;
|
||||||
|
ctx->poll_grow = grow;
|
||||||
|
ctx->poll_shrink = shrink;
|
||||||
|
|
||||||
|
aio_notify(ctx);
|
||||||
|
}
|
||||||
|
|||||||
32
aio-win32.c
32
aio-win32.c
@@ -20,6 +20,7 @@
|
|||||||
#include "block/block.h"
|
#include "block/block.h"
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
struct AioHandler {
|
struct AioHandler {
|
||||||
EventNotifier *e;
|
EventNotifier *e;
|
||||||
@@ -38,6 +39,7 @@ void aio_set_fd_handler(AioContext *ctx,
|
|||||||
bool is_external,
|
bool is_external,
|
||||||
IOHandler *io_read,
|
IOHandler *io_read,
|
||||||
IOHandler *io_write,
|
IOHandler *io_write,
|
||||||
|
AioPollFn *io_poll,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
/* fd is a SOCKET in our case */
|
/* fd is a SOCKET in our case */
|
||||||
@@ -100,10 +102,18 @@ void aio_set_fd_handler(AioContext *ctx,
|
|||||||
aio_notify(ctx);
|
aio_notify(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_set_fd_poll(AioContext *ctx, int fd,
|
||||||
|
IOHandler *io_poll_begin,
|
||||||
|
IOHandler *io_poll_end)
|
||||||
|
{
|
||||||
|
/* Not implemented */
|
||||||
|
}
|
||||||
|
|
||||||
void aio_set_event_notifier(AioContext *ctx,
|
void aio_set_event_notifier(AioContext *ctx,
|
||||||
EventNotifier *e,
|
EventNotifier *e,
|
||||||
bool is_external,
|
bool is_external,
|
||||||
EventNotifierHandler *io_notify)
|
EventNotifierHandler *io_notify,
|
||||||
|
AioPollFn *io_poll)
|
||||||
{
|
{
|
||||||
AioHandler *node;
|
AioHandler *node;
|
||||||
|
|
||||||
@@ -150,6 +160,14 @@ void aio_set_event_notifier(AioContext *ctx,
|
|||||||
aio_notify(ctx);
|
aio_notify(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_set_event_notifier_poll(AioContext *ctx,
|
||||||
|
EventNotifier *notifier,
|
||||||
|
EventNotifierHandler *io_poll_begin,
|
||||||
|
EventNotifierHandler *io_poll_end)
|
||||||
|
{
|
||||||
|
/* Not implemented */
|
||||||
|
}
|
||||||
|
|
||||||
bool aio_prepare(AioContext *ctx)
|
bool aio_prepare(AioContext *ctx)
|
||||||
{
|
{
|
||||||
static struct timeval tv0;
|
static struct timeval tv0;
|
||||||
@@ -271,12 +289,14 @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
|
|||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aio_dispatch(AioContext *ctx)
|
bool aio_dispatch(AioContext *ctx, bool dispatch_fds)
|
||||||
{
|
{
|
||||||
bool progress;
|
bool progress;
|
||||||
|
|
||||||
progress = aio_bh_poll(ctx);
|
progress = aio_bh_poll(ctx);
|
||||||
progress |= aio_dispatch_handlers(ctx, INVALID_HANDLE_VALUE);
|
if (dispatch_fds) {
|
||||||
|
progress |= aio_dispatch_handlers(ctx, INVALID_HANDLE_VALUE);
|
||||||
|
}
|
||||||
progress |= timerlistgroup_run_timers(&ctx->tlg);
|
progress |= timerlistgroup_run_timers(&ctx->tlg);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
@@ -374,3 +394,9 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|||||||
void aio_context_setup(AioContext *ctx)
|
void aio_context_setup(AioContext *ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
|
||||||
|
int64_t grow, int64_t shrink, Error **errp)
|
||||||
|
{
|
||||||
|
error_setg(errp, "AioContext polling is not implemented on Windows");
|
||||||
|
}
|
||||||
|
|||||||
21
async.c
21
async.c
@@ -251,7 +251,7 @@ aio_ctx_dispatch(GSource *source,
|
|||||||
AioContext *ctx = (AioContext *) source;
|
AioContext *ctx = (AioContext *) source;
|
||||||
|
|
||||||
assert(callback == NULL);
|
assert(callback == NULL);
|
||||||
aio_dispatch(ctx);
|
aio_dispatch(ctx, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ aio_ctx_finalize(GSource *source)
|
|||||||
}
|
}
|
||||||
qemu_mutex_unlock(&ctx->bh_lock);
|
qemu_mutex_unlock(&ctx->bh_lock);
|
||||||
|
|
||||||
aio_set_event_notifier(ctx, &ctx->notifier, false, NULL);
|
aio_set_event_notifier(ctx, &ctx->notifier, false, NULL, NULL);
|
||||||
event_notifier_cleanup(&ctx->notifier);
|
event_notifier_cleanup(&ctx->notifier);
|
||||||
qemu_rec_mutex_destroy(&ctx->lock);
|
qemu_rec_mutex_destroy(&ctx->lock);
|
||||||
qemu_mutex_destroy(&ctx->bh_lock);
|
qemu_mutex_destroy(&ctx->bh_lock);
|
||||||
@@ -349,6 +349,15 @@ static void event_notifier_dummy_cb(EventNotifier *e)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns true if aio_notify() was called (e.g. a BH was scheduled) */
|
||||||
|
static bool event_notifier_poll(void *opaque)
|
||||||
|
{
|
||||||
|
EventNotifier *e = opaque;
|
||||||
|
AioContext *ctx = container_of(e, AioContext, notifier);
|
||||||
|
|
||||||
|
return atomic_read(&ctx->notified);
|
||||||
|
}
|
||||||
|
|
||||||
AioContext *aio_context_new(Error **errp)
|
AioContext *aio_context_new(Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -366,7 +375,8 @@ AioContext *aio_context_new(Error **errp)
|
|||||||
aio_set_event_notifier(ctx, &ctx->notifier,
|
aio_set_event_notifier(ctx, &ctx->notifier,
|
||||||
false,
|
false,
|
||||||
(EventNotifierHandler *)
|
(EventNotifierHandler *)
|
||||||
event_notifier_dummy_cb);
|
event_notifier_dummy_cb,
|
||||||
|
event_notifier_poll);
|
||||||
#ifdef CONFIG_LINUX_AIO
|
#ifdef CONFIG_LINUX_AIO
|
||||||
ctx->linux_aio = NULL;
|
ctx->linux_aio = NULL;
|
||||||
#endif
|
#endif
|
||||||
@@ -375,6 +385,11 @@ AioContext *aio_context_new(Error **errp)
|
|||||||
qemu_rec_mutex_init(&ctx->lock);
|
qemu_rec_mutex_init(&ctx->lock);
|
||||||
timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
|
timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
|
||||||
|
|
||||||
|
ctx->poll_ns = 0;
|
||||||
|
ctx->poll_max_ns = 0;
|
||||||
|
ctx->poll_grow = 0;
|
||||||
|
ctx->poll_shrink = 0;
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
fail:
|
fail:
|
||||||
g_source_destroy(&ctx->source);
|
g_source_destroy(&ctx->source);
|
||||||
|
|||||||
@@ -27,12 +27,10 @@
|
|||||||
#include "sysemu/char.h"
|
#include "sysemu/char.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "hw/usb.h"
|
#include "hw/usb.h"
|
||||||
|
#include "ui/console.h"
|
||||||
#include <brlapi.h>
|
#include <brlapi.h>
|
||||||
#include <brlapi_constants.h>
|
#include <brlapi_constants.h>
|
||||||
#include <brlapi_keycodes.h>
|
#include <brlapi_keycodes.h>
|
||||||
#ifdef CONFIG_SDL
|
|
||||||
#include <SDL_syswm.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define DPRINTF(fmt, ...) \
|
#define DPRINTF(fmt, ...) \
|
||||||
@@ -227,12 +225,8 @@ static const uint8_t nabcc_translation[2][256] = {
|
|||||||
/* The guest OS has started discussing with us, finish initializing BrlAPI */
|
/* The guest OS has started discussing with us, finish initializing BrlAPI */
|
||||||
static int baum_deferred_init(BaumDriverState *baum)
|
static int baum_deferred_init(BaumDriverState *baum)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_SDL)
|
int tty = BRLAPI_TTY_DEFAULT;
|
||||||
#if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
QemuConsole *con;
|
||||||
SDL_SysWMinfo info;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
int tty;
|
|
||||||
|
|
||||||
if (baum->deferred_init) {
|
if (baum->deferred_init) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -243,21 +237,12 @@ static int baum_deferred_init(BaumDriverState *baum)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_SDL)
|
con = qemu_console_lookup_by_index(0);
|
||||||
#if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
if (con && qemu_console_is_graphic(con)) {
|
||||||
memset(&info, 0, sizeof(info));
|
tty = qemu_console_get_window_id(con);
|
||||||
SDL_VERSION(&info.version);
|
if (tty == -1)
|
||||||
if (SDL_GetWMInfo(&info)) {
|
tty = BRLAPI_TTY_DEFAULT;
|
||||||
tty = info.info.x11.wmwindow;
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
tty = BRLAPI_TTY_DEFAULT;
|
|
||||||
#if defined(CONFIG_SDL)
|
|
||||||
#if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (brlapi__enterTtyMode(baum->brlapi, tty, NULL) == -1) {
|
if (brlapi__enterTtyMode(baum->brlapi, tty, NULL) == -1) {
|
||||||
brlapi_perror("baum: brlapi__enterTtyMode");
|
brlapi_perror("baum: brlapi__enterTtyMode");
|
||||||
|
|||||||
@@ -192,19 +192,19 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case CURL_POLL_IN:
|
case CURL_POLL_IN:
|
||||||
aio_set_fd_handler(s->aio_context, fd, false,
|
aio_set_fd_handler(s->aio_context, fd, false,
|
||||||
curl_multi_read, NULL, state);
|
curl_multi_read, NULL, NULL, state);
|
||||||
break;
|
break;
|
||||||
case CURL_POLL_OUT:
|
case CURL_POLL_OUT:
|
||||||
aio_set_fd_handler(s->aio_context, fd, false,
|
aio_set_fd_handler(s->aio_context, fd, false,
|
||||||
NULL, curl_multi_do, state);
|
NULL, curl_multi_do, NULL, state);
|
||||||
break;
|
break;
|
||||||
case CURL_POLL_INOUT:
|
case CURL_POLL_INOUT:
|
||||||
aio_set_fd_handler(s->aio_context, fd, false,
|
aio_set_fd_handler(s->aio_context, fd, false,
|
||||||
curl_multi_read, curl_multi_do, state);
|
curl_multi_read, curl_multi_do, NULL, state);
|
||||||
break;
|
break;
|
||||||
case CURL_POLL_REMOVE:
|
case CURL_POLL_REMOVE:
|
||||||
aio_set_fd_handler(s->aio_context, fd, false,
|
aio_set_fd_handler(s->aio_context, fd, false,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ typedef struct BDRVGlusterState {
|
|||||||
struct glfs_fd *fd;
|
struct glfs_fd *fd;
|
||||||
char *logfile;
|
char *logfile;
|
||||||
bool supports_seek_data;
|
bool supports_seek_data;
|
||||||
int debug_level;
|
int debug;
|
||||||
} BDRVGlusterState;
|
} BDRVGlusterState;
|
||||||
|
|
||||||
typedef struct BDRVGlusterReopenState {
|
typedef struct BDRVGlusterReopenState {
|
||||||
@@ -239,12 +239,13 @@ static glfs_t *glfs_find_preopened(const char *volume)
|
|||||||
static void glfs_clear_preopened(glfs_t *fs)
|
static void glfs_clear_preopened(glfs_t *fs)
|
||||||
{
|
{
|
||||||
ListElement *entry = NULL;
|
ListElement *entry = NULL;
|
||||||
|
ListElement *next;
|
||||||
|
|
||||||
if (fs == NULL) {
|
if (fs == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QLIST_FOREACH(entry, &glfs_list, list) {
|
QLIST_FOREACH_SAFE(entry, &glfs_list, list, next) {
|
||||||
if (entry->saved.fs == fs) {
|
if (entry->saved.fs == fs) {
|
||||||
if (--entry->saved.ref) {
|
if (--entry->saved.ref) {
|
||||||
return;
|
return;
|
||||||
@@ -433,7 +434,7 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = glfs_set_logging(glfs, gconf->logfile, gconf->debug_level);
|
ret = glfs_set_logging(glfs, gconf->logfile, gconf->debug);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -787,17 +788,17 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
|
|||||||
|
|
||||||
filename = qemu_opt_get(opts, GLUSTER_OPT_FILENAME);
|
filename = qemu_opt_get(opts, GLUSTER_OPT_FILENAME);
|
||||||
|
|
||||||
s->debug_level = qemu_opt_get_number(opts, GLUSTER_OPT_DEBUG,
|
s->debug = qemu_opt_get_number(opts, GLUSTER_OPT_DEBUG,
|
||||||
GLUSTER_DEBUG_DEFAULT);
|
GLUSTER_DEBUG_DEFAULT);
|
||||||
if (s->debug_level < 0) {
|
if (s->debug < 0) {
|
||||||
s->debug_level = 0;
|
s->debug = 0;
|
||||||
} else if (s->debug_level > GLUSTER_DEBUG_MAX) {
|
} else if (s->debug > GLUSTER_DEBUG_MAX) {
|
||||||
s->debug_level = GLUSTER_DEBUG_MAX;
|
s->debug = GLUSTER_DEBUG_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
gconf = g_new0(BlockdevOptionsGluster, 1);
|
gconf = g_new0(BlockdevOptionsGluster, 1);
|
||||||
gconf->debug_level = s->debug_level;
|
gconf->debug = s->debug;
|
||||||
gconf->has_debug_level = true;
|
gconf->has_debug = true;
|
||||||
|
|
||||||
logfile = qemu_opt_get(opts, GLUSTER_OPT_LOGFILE);
|
logfile = qemu_opt_get(opts, GLUSTER_OPT_LOGFILE);
|
||||||
s->logfile = g_strdup(logfile ? logfile : GLUSTER_LOGFILE_DEFAULT);
|
s->logfile = g_strdup(logfile ? logfile : GLUSTER_LOGFILE_DEFAULT);
|
||||||
@@ -873,8 +874,8 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
|
|||||||
qemu_gluster_parse_flags(state->flags, &open_flags);
|
qemu_gluster_parse_flags(state->flags, &open_flags);
|
||||||
|
|
||||||
gconf = g_new0(BlockdevOptionsGluster, 1);
|
gconf = g_new0(BlockdevOptionsGluster, 1);
|
||||||
gconf->debug_level = s->debug_level;
|
gconf->debug = s->debug;
|
||||||
gconf->has_debug_level = true;
|
gconf->has_debug = true;
|
||||||
gconf->logfile = g_strdup(s->logfile);
|
gconf->logfile = g_strdup(s->logfile);
|
||||||
gconf->has_logfile = true;
|
gconf->has_logfile = true;
|
||||||
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, NULL, errp);
|
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, NULL, errp);
|
||||||
@@ -1010,14 +1011,14 @@ static int qemu_gluster_create(const char *filename,
|
|||||||
char *tmp = NULL;
|
char *tmp = NULL;
|
||||||
|
|
||||||
gconf = g_new0(BlockdevOptionsGluster, 1);
|
gconf = g_new0(BlockdevOptionsGluster, 1);
|
||||||
gconf->debug_level = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
|
gconf->debug = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
|
||||||
GLUSTER_DEBUG_DEFAULT);
|
GLUSTER_DEBUG_DEFAULT);
|
||||||
if (gconf->debug_level < 0) {
|
if (gconf->debug < 0) {
|
||||||
gconf->debug_level = 0;
|
gconf->debug = 0;
|
||||||
} else if (gconf->debug_level > GLUSTER_DEBUG_MAX) {
|
} else if (gconf->debug > GLUSTER_DEBUG_MAX) {
|
||||||
gconf->debug_level = GLUSTER_DEBUG_MAX;
|
gconf->debug = GLUSTER_DEBUG_MAX;
|
||||||
}
|
}
|
||||||
gconf->has_debug_level = true;
|
gconf->has_debug = true;
|
||||||
|
|
||||||
gconf->logfile = qemu_opt_get_del(opts, GLUSTER_OPT_LOGFILE);
|
gconf->logfile = qemu_opt_get_del(opts, GLUSTER_OPT_LOGFILE);
|
||||||
if (!gconf->logfile) {
|
if (!gconf->logfile) {
|
||||||
|
|||||||
58
block/io.c
58
block/io.c
@@ -1214,6 +1214,8 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
|||||||
int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT_MAX);
|
int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT_MAX);
|
||||||
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
|
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
|
||||||
bs->bl.request_alignment);
|
bs->bl.request_alignment);
|
||||||
|
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
|
||||||
|
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
|
||||||
|
|
||||||
assert(alignment % bs->bl.request_alignment == 0);
|
assert(alignment % bs->bl.request_alignment == 0);
|
||||||
head = offset % alignment;
|
head = offset % alignment;
|
||||||
@@ -1229,9 +1231,12 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
|||||||
* boundaries.
|
* boundaries.
|
||||||
*/
|
*/
|
||||||
if (head) {
|
if (head) {
|
||||||
/* Make a small request up to the first aligned sector. */
|
/* Make a small request up to the first aligned sector. For
|
||||||
num = MIN(count, alignment - head);
|
* convenience, limit this request to max_transfer even if
|
||||||
head = 0;
|
* we don't need to fall back to writes. */
|
||||||
|
num = MIN(MIN(count, max_transfer), alignment - head);
|
||||||
|
head = (head + num) % alignment;
|
||||||
|
assert(num < max_write_zeroes);
|
||||||
} else if (tail && num > alignment) {
|
} else if (tail && num > alignment) {
|
||||||
/* Shorten the request to the last aligned sector. */
|
/* Shorten the request to the last aligned sector. */
|
||||||
num -= tail;
|
num -= tail;
|
||||||
@@ -1257,8 +1262,6 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
|||||||
|
|
||||||
if (ret == -ENOTSUP) {
|
if (ret == -ENOTSUP) {
|
||||||
/* Fall back to bounce buffer if write zeroes is unsupported */
|
/* Fall back to bounce buffer if write zeroes is unsupported */
|
||||||
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
|
|
||||||
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
|
|
||||||
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
|
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
|
||||||
|
|
||||||
if ((flags & BDRV_REQ_FUA) &&
|
if ((flags & BDRV_REQ_FUA) &&
|
||||||
@@ -2421,7 +2424,7 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||||||
{
|
{
|
||||||
BdrvTrackedRequest req;
|
BdrvTrackedRequest req;
|
||||||
int max_pdiscard, ret;
|
int max_pdiscard, ret;
|
||||||
int head, align;
|
int head, tail, align;
|
||||||
|
|
||||||
if (!bs->drv) {
|
if (!bs->drv) {
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
@@ -2444,19 +2447,15 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard is advisory, so ignore any unaligned head or tail */
|
/* Discard is advisory, but some devices track and coalesce
|
||||||
|
* unaligned requests, so we must pass everything down rather than
|
||||||
|
* round here. Still, most devices will just silently ignore
|
||||||
|
* unaligned requests (by returning -ENOTSUP), so we must fragment
|
||||||
|
* the request accordingly. */
|
||||||
align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment);
|
align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment);
|
||||||
assert(align % bs->bl.request_alignment == 0);
|
assert(align % bs->bl.request_alignment == 0);
|
||||||
head = offset % align;
|
head = offset % align;
|
||||||
if (head) {
|
tail = (offset + count) % align;
|
||||||
head = MIN(count, align - head);
|
|
||||||
count -= head;
|
|
||||||
offset += head;
|
|
||||||
}
|
|
||||||
count = QEMU_ALIGN_DOWN(count, align);
|
|
||||||
if (!count) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bdrv_inc_in_flight(bs);
|
bdrv_inc_in_flight(bs);
|
||||||
tracked_request_begin(&req, bs, offset, count, BDRV_TRACKED_DISCARD);
|
tracked_request_begin(&req, bs, offset, count, BDRV_TRACKED_DISCARD);
|
||||||
@@ -2468,11 +2467,34 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||||||
|
|
||||||
max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT_MAX),
|
max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT_MAX),
|
||||||
align);
|
align);
|
||||||
assert(max_pdiscard);
|
assert(max_pdiscard >= bs->bl.request_alignment);
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
int ret;
|
int ret;
|
||||||
int num = MIN(count, max_pdiscard);
|
int num = count;
|
||||||
|
|
||||||
|
if (head) {
|
||||||
|
/* Make small requests to get to alignment boundaries. */
|
||||||
|
num = MIN(count, align - head);
|
||||||
|
if (!QEMU_IS_ALIGNED(num, bs->bl.request_alignment)) {
|
||||||
|
num %= bs->bl.request_alignment;
|
||||||
|
}
|
||||||
|
head = (head + num) % align;
|
||||||
|
assert(num < max_pdiscard);
|
||||||
|
} else if (tail) {
|
||||||
|
if (num > align) {
|
||||||
|
/* Shorten the request to the last aligned cluster. */
|
||||||
|
num -= tail;
|
||||||
|
} else if (!QEMU_IS_ALIGNED(tail, bs->bl.request_alignment) &&
|
||||||
|
tail > bs->bl.request_alignment) {
|
||||||
|
tail %= bs->bl.request_alignment;
|
||||||
|
num -= tail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* limit request size */
|
||||||
|
if (num > max_pdiscard) {
|
||||||
|
num = max_pdiscard;
|
||||||
|
}
|
||||||
|
|
||||||
if (bs->drv->bdrv_co_pdiscard) {
|
if (bs->drv->bdrv_co_pdiscard) {
|
||||||
ret = bs->drv->bdrv_co_pdiscard(bs, offset, num);
|
ret = bs->drv->bdrv_co_pdiscard(bs, offset, num);
|
||||||
|
|||||||
@@ -362,6 +362,7 @@ iscsi_set_events(IscsiLun *iscsilun)
|
|||||||
false,
|
false,
|
||||||
(ev & POLLIN) ? iscsi_process_read : NULL,
|
(ev & POLLIN) ? iscsi_process_read : NULL,
|
||||||
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
||||||
|
NULL,
|
||||||
iscsilun);
|
iscsilun);
|
||||||
iscsilun->events = ev;
|
iscsilun->events = ev;
|
||||||
}
|
}
|
||||||
@@ -1083,7 +1084,9 @@ coroutine_fn iscsi_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
|
|||||||
struct IscsiTask iTask;
|
struct IscsiTask iTask;
|
||||||
struct unmap_list list;
|
struct unmap_list list;
|
||||||
|
|
||||||
assert(is_byte_request_lun_aligned(offset, count, iscsilun));
|
if (!is_byte_request_lun_aligned(offset, count, iscsilun)) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
if (!iscsilun->lbp.lbpu) {
|
if (!iscsilun->lbp.lbpu) {
|
||||||
/* UNMAP is not supported by the target */
|
/* UNMAP is not supported by the target */
|
||||||
@@ -1524,7 +1527,7 @@ static void iscsi_detach_aio_context(BlockDriverState *bs)
|
|||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
|
|
||||||
aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsilun->iscsi),
|
aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsilun->iscsi),
|
||||||
false, NULL, NULL, NULL);
|
false, NULL, NULL, NULL, NULL);
|
||||||
iscsilun->events = 0;
|
iscsilun->events = 0;
|
||||||
|
|
||||||
if (iscsilun->nop_timer) {
|
if (iscsilun->nop_timer) {
|
||||||
|
|||||||
@@ -255,6 +255,20 @@ static void qemu_laio_completion_cb(EventNotifier *e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool qemu_laio_poll_cb(void *opaque)
|
||||||
|
{
|
||||||
|
EventNotifier *e = opaque;
|
||||||
|
LinuxAioState *s = container_of(e, LinuxAioState, e);
|
||||||
|
struct io_event *events;
|
||||||
|
|
||||||
|
if (!io_getevents_peek(s->ctx, &events)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_laio_process_completions_and_submit(s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void laio_cancel(BlockAIOCB *blockacb)
|
static void laio_cancel(BlockAIOCB *blockacb)
|
||||||
{
|
{
|
||||||
struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
|
struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
|
||||||
@@ -439,7 +453,7 @@ BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
|
|||||||
|
|
||||||
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
|
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
|
||||||
{
|
{
|
||||||
aio_set_event_notifier(old_context, &s->e, false, NULL);
|
aio_set_event_notifier(old_context, &s->e, false, NULL, NULL);
|
||||||
qemu_bh_delete(s->completion_bh);
|
qemu_bh_delete(s->completion_bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,7 +462,8 @@ void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context)
|
|||||||
s->aio_context = new_context;
|
s->aio_context = new_context;
|
||||||
s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
|
s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
|
||||||
aio_set_event_notifier(new_context, &s->e, false,
|
aio_set_event_notifier(new_context, &s->e, false,
|
||||||
qemu_laio_completion_cb);
|
qemu_laio_completion_cb,
|
||||||
|
qemu_laio_poll_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinuxAioState *laio_init(void)
|
LinuxAioState *laio_init(void)
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ static int nbd_co_send_request(BlockDriverState *bs,
|
|||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
aio_set_fd_handler(aio_context, s->sioc->fd, false,
|
aio_set_fd_handler(aio_context, s->sioc->fd, false,
|
||||||
nbd_reply_ready, nbd_restart_write, bs);
|
nbd_reply_ready, nbd_restart_write, NULL, bs);
|
||||||
if (qiov) {
|
if (qiov) {
|
||||||
qio_channel_set_cork(s->ioc, true);
|
qio_channel_set_cork(s->ioc, true);
|
||||||
rc = nbd_send_request(s->ioc, request);
|
rc = nbd_send_request(s->ioc, request);
|
||||||
@@ -161,7 +161,7 @@ static int nbd_co_send_request(BlockDriverState *bs,
|
|||||||
rc = nbd_send_request(s->ioc, request);
|
rc = nbd_send_request(s->ioc, request);
|
||||||
}
|
}
|
||||||
aio_set_fd_handler(aio_context, s->sioc->fd, false,
|
aio_set_fd_handler(aio_context, s->sioc->fd, false,
|
||||||
nbd_reply_ready, NULL, bs);
|
nbd_reply_ready, NULL, NULL, bs);
|
||||||
s->send_coroutine = NULL;
|
s->send_coroutine = NULL;
|
||||||
qemu_co_mutex_unlock(&s->send_mutex);
|
qemu_co_mutex_unlock(&s->send_mutex);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -366,14 +366,14 @@ void nbd_client_detach_aio_context(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
aio_set_fd_handler(bdrv_get_aio_context(bs),
|
aio_set_fd_handler(bdrv_get_aio_context(bs),
|
||||||
nbd_get_client_session(bs)->sioc->fd,
|
nbd_get_client_session(bs)->sioc->fd,
|
||||||
false, NULL, NULL, NULL);
|
false, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nbd_client_attach_aio_context(BlockDriverState *bs,
|
void nbd_client_attach_aio_context(BlockDriverState *bs,
|
||||||
AioContext *new_context)
|
AioContext *new_context)
|
||||||
{
|
{
|
||||||
aio_set_fd_handler(new_context, nbd_get_client_session(bs)->sioc->fd,
|
aio_set_fd_handler(new_context, nbd_get_client_session(bs)->sioc->fd,
|
||||||
false, nbd_reply_ready, NULL, bs);
|
false, nbd_reply_ready, NULL, NULL, bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nbd_client_close(BlockDriverState *bs)
|
void nbd_client_close(BlockDriverState *bs)
|
||||||
@@ -415,6 +415,10 @@ int nbd_client_init(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
if (client->nbdflags & NBD_FLAG_SEND_FUA) {
|
if (client->nbdflags & NBD_FLAG_SEND_FUA) {
|
||||||
bs->supported_write_flags = BDRV_REQ_FUA;
|
bs->supported_write_flags = BDRV_REQ_FUA;
|
||||||
|
bs->supported_zero_flags |= BDRV_REQ_FUA;
|
||||||
|
}
|
||||||
|
if (client->nbdflags & NBD_FLAG_SEND_WRITE_ZEROES) {
|
||||||
|
bs->supported_zero_flags |= BDRV_REQ_MAY_UNMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_co_mutex_init(&client->send_mutex);
|
qemu_co_mutex_init(&client->send_mutex);
|
||||||
|
|||||||
11
block/nfs.c
11
block/nfs.c
@@ -134,7 +134,7 @@ static int nfs_parse_uri(const char *filename, QDict *options, Error **errp)
|
|||||||
qdict_put(options, "page-cache-size",
|
qdict_put(options, "page-cache-size",
|
||||||
qstring_from_str(qp->p[i].value));
|
qstring_from_str(qp->p[i].value));
|
||||||
} else if (!strcmp(qp->p[i].name, "debug")) {
|
} else if (!strcmp(qp->p[i].name, "debug")) {
|
||||||
qdict_put(options, "debug-level",
|
qdict_put(options, "debug",
|
||||||
qstring_from_str(qp->p[i].value));
|
qstring_from_str(qp->p[i].value));
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Unknown NFS parameter name: %s",
|
error_setg(errp, "Unknown NFS parameter name: %s",
|
||||||
@@ -165,7 +165,7 @@ static bool nfs_has_filename_options_conflict(QDict *options, Error **errp)
|
|||||||
!strcmp(qe->key, "tcp-syn-count") ||
|
!strcmp(qe->key, "tcp-syn-count") ||
|
||||||
!strcmp(qe->key, "readahead-size") ||
|
!strcmp(qe->key, "readahead-size") ||
|
||||||
!strcmp(qe->key, "page-cache-size") ||
|
!strcmp(qe->key, "page-cache-size") ||
|
||||||
!strcmp(qe->key, "debug-level") ||
|
!strcmp(qe->key, "debug") ||
|
||||||
strstart(qe->key, "server.", NULL))
|
strstart(qe->key, "server.", NULL))
|
||||||
{
|
{
|
||||||
error_setg(errp, "Option %s cannot be used with a filename",
|
error_setg(errp, "Option %s cannot be used with a filename",
|
||||||
@@ -197,7 +197,8 @@ static void nfs_set_events(NFSClient *client)
|
|||||||
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
||||||
false,
|
false,
|
||||||
(ev & POLLIN) ? nfs_process_read : NULL,
|
(ev & POLLIN) ? nfs_process_read : NULL,
|
||||||
(ev & POLLOUT) ? nfs_process_write : NULL, client);
|
(ev & POLLOUT) ? nfs_process_write : NULL,
|
||||||
|
NULL, client);
|
||||||
|
|
||||||
}
|
}
|
||||||
client->events = ev;
|
client->events = ev;
|
||||||
@@ -395,7 +396,7 @@ static void nfs_detach_aio_context(BlockDriverState *bs)
|
|||||||
NFSClient *client = bs->opaque;
|
NFSClient *client = bs->opaque;
|
||||||
|
|
||||||
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
||||||
false, NULL, NULL, NULL);
|
false, NULL, NULL, NULL, NULL);
|
||||||
client->events = 0;
|
client->events = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +416,7 @@ static void nfs_client_close(NFSClient *client)
|
|||||||
nfs_close(client->context, client->fh);
|
nfs_close(client->context, client->fh);
|
||||||
}
|
}
|
||||||
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
||||||
false, NULL, NULL, NULL);
|
false, NULL, NULL, NULL, NULL);
|
||||||
nfs_destroy_context(client->context);
|
nfs_destroy_context(client->context);
|
||||||
}
|
}
|
||||||
memset(client, 0, sizeof(NFSClient));
|
memset(client, 0, sizeof(NFSClient));
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Needed for CONFIG_MADVISE */
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
@@ -66,7 +65,8 @@ static inline int qcow2_cache_get_table_idx(BlockDriverState *bs,
|
|||||||
static void qcow2_cache_table_release(BlockDriverState *bs, Qcow2Cache *c,
|
static void qcow2_cache_table_release(BlockDriverState *bs, Qcow2Cache *c,
|
||||||
int i, int num_tables)
|
int i, int num_tables)
|
||||||
{
|
{
|
||||||
#if QEMU_MADV_DONTNEED != QEMU_MADV_INVALID
|
/* Using MADV_DONTNEED to discard memory is a Linux-specific feature */
|
||||||
|
#ifdef CONFIG_LINUX
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
void *t = qcow2_cache_get_table_addr(bs, c, i);
|
void *t = qcow2_cache_get_table_addr(bs, c, i);
|
||||||
int align = getpagesize();
|
int align = getpagesize();
|
||||||
@@ -74,7 +74,7 @@ static void qcow2_cache_table_release(BlockDriverState *bs, Qcow2Cache *c,
|
|||||||
size_t offset = QEMU_ALIGN_UP((uintptr_t) t, align) - (uintptr_t) t;
|
size_t offset = QEMU_ALIGN_UP((uintptr_t) t, align) - (uintptr_t) t;
|
||||||
size_t length = QEMU_ALIGN_DOWN(mem_size - offset, align);
|
size_t length = QEMU_ALIGN_DOWN(mem_size - offset, align);
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
qemu_madvise((uint8_t *) t + offset, length, QEMU_MADV_DONTNEED);
|
madvise((uint8_t *) t + offset, length, MADV_DONTNEED);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -668,6 +668,14 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
|
|||||||
r->cache_clean_interval =
|
r->cache_clean_interval =
|
||||||
qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL,
|
qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL,
|
||||||
s->cache_clean_interval);
|
s->cache_clean_interval);
|
||||||
|
#ifndef CONFIG_LINUX
|
||||||
|
if (r->cache_clean_interval != 0) {
|
||||||
|
error_setg(errp, QCOW2_OPT_CACHE_CLEAN_INTERVAL
|
||||||
|
" not supported on this host");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (r->cache_clean_interval > UINT_MAX) {
|
if (r->cache_clean_interval > UINT_MAX) {
|
||||||
error_setg(errp, "Cache clean interval too big");
|
error_setg(errp, "Cache clean interval too big");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@@ -1206,6 +1214,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
|||||||
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
|
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
|
||||||
}
|
}
|
||||||
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
|
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
|
||||||
|
bs->bl.pdiscard_alignment = s->cluster_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcow2_set_key(BlockDriverState *bs, const char *key)
|
static int qcow2_set_key(BlockDriverState *bs, const char *key)
|
||||||
@@ -2490,6 +2499,11 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
|
|||||||
int ret;
|
int ret;
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
|
||||||
|
if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
|
||||||
|
assert(count < s->cluster_size);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
ret = qcow2_discard_clusters(bs, offset, count >> BDRV_SECTOR_BITS,
|
ret = qcow2_discard_clusters(bs, offset, count >> BDRV_SECTOR_BITS,
|
||||||
QCOW2_DISCARD_REQUEST, false);
|
QCOW2_DISCARD_REQUEST, false);
|
||||||
@@ -2794,7 +2808,8 @@ static int qcow2_make_empty(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
uint64_t start_sector;
|
uint64_t start_sector;
|
||||||
int sector_step = INT_MAX / BDRV_SECTOR_SIZE;
|
int sector_step = (QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size) /
|
||||||
|
BDRV_SECTOR_SIZE);
|
||||||
int l1_clusters, ret = 0;
|
int l1_clusters, ret = 0;
|
||||||
|
|
||||||
l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t));
|
l1_clusters = DIV_ROUND_UP(s->l1_size, s->cluster_size / sizeof(uint64_t));
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ static coroutine_fn void do_co_req(void *opaque)
|
|||||||
|
|
||||||
co = qemu_coroutine_self();
|
co = qemu_coroutine_self();
|
||||||
aio_set_fd_handler(srco->aio_context, sockfd, false,
|
aio_set_fd_handler(srco->aio_context, sockfd, false,
|
||||||
NULL, restart_co_req, co);
|
NULL, restart_co_req, NULL, co);
|
||||||
|
|
||||||
ret = send_co_req(sockfd, hdr, data, wlen);
|
ret = send_co_req(sockfd, hdr, data, wlen);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -672,7 +672,7 @@ static coroutine_fn void do_co_req(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
aio_set_fd_handler(srco->aio_context, sockfd, false,
|
aio_set_fd_handler(srco->aio_context, sockfd, false,
|
||||||
restart_co_req, NULL, co);
|
restart_co_req, NULL, NULL, co);
|
||||||
|
|
||||||
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
|
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
|
||||||
if (ret != sizeof(*hdr)) {
|
if (ret != sizeof(*hdr)) {
|
||||||
@@ -698,7 +698,7 @@ out:
|
|||||||
/* there is at most one request for this sockfd, so it is safe to
|
/* there is at most one request for this sockfd, so it is safe to
|
||||||
* set each handler to NULL. */
|
* set each handler to NULL. */
|
||||||
aio_set_fd_handler(srco->aio_context, sockfd, false,
|
aio_set_fd_handler(srco->aio_context, sockfd, false,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
srco->ret = ret;
|
srco->ret = ret;
|
||||||
srco->finished = true;
|
srco->finished = true;
|
||||||
@@ -760,7 +760,7 @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
|
|||||||
AIOReq *aio_req, *next;
|
AIOReq *aio_req, *next;
|
||||||
|
|
||||||
aio_set_fd_handler(s->aio_context, s->fd, false, NULL,
|
aio_set_fd_handler(s->aio_context, s->fd, false, NULL,
|
||||||
NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
close(s->fd);
|
close(s->fd);
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
|
|
||||||
@@ -964,7 +964,7 @@ static int get_sheep_fd(BDRVSheepdogState *s, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
aio_set_fd_handler(s->aio_context, fd, false,
|
aio_set_fd_handler(s->aio_context, fd, false,
|
||||||
co_read_response, NULL, s);
|
co_read_response, NULL, NULL, s);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1226,7 +1226,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
|||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
s->co_send = qemu_coroutine_self();
|
s->co_send = qemu_coroutine_self();
|
||||||
aio_set_fd_handler(s->aio_context, s->fd, false,
|
aio_set_fd_handler(s->aio_context, s->fd, false,
|
||||||
co_read_response, co_write_request, s);
|
co_read_response, co_write_request, NULL, s);
|
||||||
socket_set_cork(s->fd, 1);
|
socket_set_cork(s->fd, 1);
|
||||||
|
|
||||||
/* send a header */
|
/* send a header */
|
||||||
@@ -1245,7 +1245,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
|||||||
out:
|
out:
|
||||||
socket_set_cork(s->fd, 0);
|
socket_set_cork(s->fd, 0);
|
||||||
aio_set_fd_handler(s->aio_context, s->fd, false,
|
aio_set_fd_handler(s->aio_context, s->fd, false,
|
||||||
co_read_response, NULL, s);
|
co_read_response, NULL, NULL, s);
|
||||||
s->co_send = NULL;
|
s->co_send = NULL;
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
}
|
}
|
||||||
@@ -1396,7 +1396,7 @@ static void sd_detach_aio_context(BlockDriverState *bs)
|
|||||||
BDRVSheepdogState *s = bs->opaque;
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
|
|
||||||
aio_set_fd_handler(s->aio_context, s->fd, false, NULL,
|
aio_set_fd_handler(s->aio_context, s->fd, false, NULL,
|
||||||
NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sd_attach_aio_context(BlockDriverState *bs,
|
static void sd_attach_aio_context(BlockDriverState *bs,
|
||||||
@@ -1406,7 +1406,7 @@ static void sd_attach_aio_context(BlockDriverState *bs,
|
|||||||
|
|
||||||
s->aio_context = new_context;
|
s->aio_context = new_context;
|
||||||
aio_set_fd_handler(new_context, s->fd, false,
|
aio_set_fd_handler(new_context, s->fd, false,
|
||||||
co_read_response, NULL, s);
|
co_read_response, NULL, NULL, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Convert to fine grained options */
|
/* TODO Convert to fine grained options */
|
||||||
@@ -1520,7 +1520,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd,
|
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd,
|
||||||
false, NULL, NULL, NULL);
|
false, NULL, NULL, NULL, NULL);
|
||||||
if (s->fd >= 0) {
|
if (s->fd >= 0) {
|
||||||
closesocket(s->fd);
|
closesocket(s->fd);
|
||||||
}
|
}
|
||||||
@@ -1559,7 +1559,7 @@ static void sd_reopen_commit(BDRVReopenState *state)
|
|||||||
|
|
||||||
if (s->fd) {
|
if (s->fd) {
|
||||||
aio_set_fd_handler(s->aio_context, s->fd, false,
|
aio_set_fd_handler(s->aio_context, s->fd, false,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
closesocket(s->fd);
|
closesocket(s->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1583,7 +1583,7 @@ static void sd_reopen_abort(BDRVReopenState *state)
|
|||||||
|
|
||||||
if (re_s->fd) {
|
if (re_s->fd) {
|
||||||
aio_set_fd_handler(s->aio_context, re_s->fd, false,
|
aio_set_fd_handler(s->aio_context, re_s->fd, false,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
closesocket(re_s->fd);
|
closesocket(re_s->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1972,7 +1972,7 @@ static void sd_close(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd,
|
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd,
|
||||||
false, NULL, NULL, NULL);
|
false, NULL, NULL, NULL, NULL);
|
||||||
closesocket(s->fd);
|
closesocket(s->fd);
|
||||||
g_free(s->host_spec);
|
g_free(s->host_spec);
|
||||||
}
|
}
|
||||||
@@ -2829,8 +2829,9 @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
|
|||||||
iov.iov_len = sizeof(zero);
|
iov.iov_len = sizeof(zero);
|
||||||
discard_iov.iov = &iov;
|
discard_iov.iov = &iov;
|
||||||
discard_iov.niov = 1;
|
discard_iov.niov = 1;
|
||||||
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
if (!QEMU_IS_ALIGNED(offset | count, BDRV_SECTOR_SIZE)) {
|
||||||
assert((count & (BDRV_SECTOR_SIZE - 1)) == 0);
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
|
acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
|
||||||
count >> BDRV_SECTOR_BITS);
|
count >> BDRV_SECTOR_BITS);
|
||||||
acb->aiocb_type = AIOCB_DISCARD_OBJ;
|
acb->aiocb_type = AIOCB_DISCARD_OBJ;
|
||||||
|
|||||||
@@ -911,7 +911,7 @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
|
|||||||
rd_handler, wr_handler);
|
rd_handler, wr_handler);
|
||||||
|
|
||||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
|
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
|
||||||
false, rd_handler, wr_handler, co);
|
false, rd_handler, wr_handler, NULL, co);
|
||||||
}
|
}
|
||||||
|
|
||||||
static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
|
static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
|
||||||
@@ -919,7 +919,7 @@ static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
|
|||||||
{
|
{
|
||||||
DPRINTF("s->sock=%d", s->sock);
|
DPRINTF("s->sock=%d", s->sock);
|
||||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
|
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
|
||||||
false, NULL, NULL, NULL);
|
false, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A non-blocking call returned EAGAIN, so yield, ensuring the
|
/* A non-blocking call returned EAGAIN, so yield, ensuring the
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
|
|||||||
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
|
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
|
||||||
AioContext *old_context)
|
AioContext *old_context)
|
||||||
{
|
{
|
||||||
aio_set_event_notifier(old_context, &aio->e, false, NULL);
|
aio_set_event_notifier(old_context, &aio->e, false, NULL, NULL);
|
||||||
aio->is_aio_context_attached = false;
|
aio->is_aio_context_attached = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
|
|||||||
{
|
{
|
||||||
aio->is_aio_context_attached = true;
|
aio->is_aio_context_attached = true;
|
||||||
aio_set_event_notifier(new_context, &aio->e, false,
|
aio_set_event_notifier(new_context, &aio->e, false,
|
||||||
win32_aio_completion_cb);
|
win32_aio_completion_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
QEMUWin32AIOState *win32_aio_init(void)
|
QEMUWin32AIOState *win32_aio_init(void)
|
||||||
|
|||||||
35
configure
vendored
35
configure
vendored
@@ -28,8 +28,6 @@ TMPB="qemu-conf"
|
|||||||
TMPC="${TMPDIR1}/${TMPB}.c"
|
TMPC="${TMPDIR1}/${TMPB}.c"
|
||||||
TMPO="${TMPDIR1}/${TMPB}.o"
|
TMPO="${TMPDIR1}/${TMPB}.o"
|
||||||
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
|
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
|
||||||
TMPL="${TMPDIR1}/${TMPB}.lo"
|
|
||||||
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
|
||||||
TMPE="${TMPDIR1}/${TMPB}.exe"
|
TMPE="${TMPDIR1}/${TMPB}.exe"
|
||||||
TMPMO="${TMPDIR1}/${TMPB}.mo"
|
TMPMO="${TMPDIR1}/${TMPB}.mo"
|
||||||
|
|
||||||
@@ -313,6 +311,7 @@ gnutls_rnd=""
|
|||||||
nettle=""
|
nettle=""
|
||||||
nettle_kdf="no"
|
nettle_kdf="no"
|
||||||
gcrypt=""
|
gcrypt=""
|
||||||
|
gcrypt_hmac="no"
|
||||||
gcrypt_kdf="no"
|
gcrypt_kdf="no"
|
||||||
vte=""
|
vte=""
|
||||||
virglrenderer=""
|
virglrenderer=""
|
||||||
@@ -582,6 +581,8 @@ FreeBSD)
|
|||||||
audio_possible_drivers="oss sdl pa"
|
audio_possible_drivers="oss sdl pa"
|
||||||
# needed for kinfo_getvmmap(3) in libutil.h
|
# needed for kinfo_getvmmap(3) in libutil.h
|
||||||
LIBS="-lutil $LIBS"
|
LIBS="-lutil $LIBS"
|
||||||
|
# needed for kinfo_getproc
|
||||||
|
libs_qga="-lutil $libs_qga"
|
||||||
netmap="" # enable netmap autodetect
|
netmap="" # enable netmap autodetect
|
||||||
HOST_VARIANT_DIR="freebsd"
|
HOST_VARIANT_DIR="freebsd"
|
||||||
;;
|
;;
|
||||||
@@ -2415,6 +2416,19 @@ EOF
|
|||||||
if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
|
if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
|
||||||
gcrypt_kdf=yes
|
gcrypt_kdf=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <gcrypt.h>
|
||||||
|
int main(void) {
|
||||||
|
gcry_mac_hd_t handle;
|
||||||
|
gcry_mac_open(&handle, GCRY_MAC_HMAC_MD5,
|
||||||
|
GCRY_MAC_FLAG_SECURE, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
|
||||||
|
gcrypt_hmac=yes
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
if test "$gcrypt" = "yes"; then
|
if test "$gcrypt" = "yes"; then
|
||||||
feature_not_found "gcrypt" "Install gcrypt devel"
|
feature_not_found "gcrypt" "Install gcrypt devel"
|
||||||
@@ -4303,11 +4317,11 @@ if have_backend "ust"; then
|
|||||||
#include <lttng/tracepoint.h>
|
#include <lttng/tracepoint.h>
|
||||||
int main(void) { return 0; }
|
int main(void) { return 0; }
|
||||||
EOF
|
EOF
|
||||||
if compile_prog "" "" ; then
|
if compile_prog "" "-Wl,--no-as-needed -ldl" ; then
|
||||||
if $pkg_config lttng-ust --exists; then
|
if $pkg_config lttng-ust --exists; then
|
||||||
lttng_ust_libs=$($pkg_config --libs lttng-ust)
|
lttng_ust_libs=$($pkg_config --libs lttng-ust)
|
||||||
else
|
else
|
||||||
lttng_ust_libs="-llttng-ust"
|
lttng_ust_libs="-llttng-ust -ldl"
|
||||||
fi
|
fi
|
||||||
if $pkg_config liburcu-bp --exists; then
|
if $pkg_config liburcu-bp --exists; then
|
||||||
urcu_bp_libs=$($pkg_config --libs liburcu-bp)
|
urcu_bp_libs=$($pkg_config --libs liburcu-bp)
|
||||||
@@ -4721,8 +4735,14 @@ EOF
|
|||||||
if ! compile_object ""; then
|
if ! compile_object ""; then
|
||||||
error_exit "Failed to compile object file for LD_REL_FLAGS test"
|
error_exit "Failed to compile object file for LD_REL_FLAGS test"
|
||||||
fi
|
fi
|
||||||
if do_cc -nostdlib -Wl,-r -Wl,--no-relax -o $TMPMO $TMPO; then
|
for i in '-Wl,-r -Wl,--no-relax' -Wl,-r -r; do
|
||||||
LD_REL_FLAGS="-Wl,--no-relax"
|
if do_cc -nostdlib $i -o $TMPMO $TMPO; then
|
||||||
|
LD_REL_FLAGS=$i
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test "$modules" = "yes" && test "$LD_REL_FLAGS" = ""; then
|
||||||
|
feature_not_found "modules" "Cannot find how to build relocatable objects"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
@@ -5379,6 +5399,9 @@ if test "$gnutls_rnd" = "yes" ; then
|
|||||||
fi
|
fi
|
||||||
if test "$gcrypt" = "yes" ; then
|
if test "$gcrypt" = "yes" ; then
|
||||||
echo "CONFIG_GCRYPT=y" >> $config_host_mak
|
echo "CONFIG_GCRYPT=y" >> $config_host_mak
|
||||||
|
if test "$gcrypt_hmac" = "yes" ; then
|
||||||
|
echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
if test "$gcrypt_kdf" = "yes" ; then
|
if test "$gcrypt_kdf" = "yes" ; then
|
||||||
echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak
|
echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ crypto-obj-y += hash.o
|
|||||||
crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o
|
crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o
|
||||||
crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o
|
crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o
|
||||||
crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o
|
crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o
|
||||||
|
crypto-obj-y += hmac.o
|
||||||
|
crypto-obj-$(CONFIG_NETTLE) += hmac-nettle.o
|
||||||
|
crypto-obj-$(CONFIG_GCRYPT_HMAC) += hmac-gcrypt.o
|
||||||
|
crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT_HMAC),n,y)) += hmac-glib.o
|
||||||
crypto-obj-y += aes.o
|
crypto-obj-y += aes.o
|
||||||
crypto-obj-y += desrfb.o
|
crypto-obj-y += desrfb.o
|
||||||
crypto-obj-y += cipher.o
|
crypto-obj-y += cipher.o
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
|||||||
{
|
{
|
||||||
switch (alg) {
|
switch (alg) {
|
||||||
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
||||||
|
case QCRYPTO_CIPHER_ALG_3DES:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_128:
|
case QCRYPTO_CIPHER_ALG_AES_128:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_192:
|
case QCRYPTO_CIPHER_ALG_AES_192:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_256:
|
case QCRYPTO_CIPHER_ALG_AES_256:
|
||||||
@@ -99,6 +100,10 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
gcryalg = GCRY_CIPHER_DES;
|
gcryalg = GCRY_CIPHER_DES;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QCRYPTO_CIPHER_ALG_3DES:
|
||||||
|
gcryalg = GCRY_CIPHER_3DES;
|
||||||
|
break;
|
||||||
|
|
||||||
case QCRYPTO_CIPHER_ALG_AES_128:
|
case QCRYPTO_CIPHER_ALG_AES_128:
|
||||||
gcryalg = GCRY_CIPHER_AES128;
|
gcryalg = GCRY_CIPHER_AES128;
|
||||||
break;
|
break;
|
||||||
@@ -200,6 +205,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
||||||
ctx->blocksize = 16;
|
ctx->blocksize = 16;
|
||||||
break;
|
break;
|
||||||
|
case QCRYPTO_CIPHER_ALG_3DES:
|
||||||
case QCRYPTO_CIPHER_ALG_CAST5_128:
|
case QCRYPTO_CIPHER_ALG_CAST5_128:
|
||||||
ctx->blocksize = 8;
|
ctx->blocksize = 8;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -78,6 +78,18 @@ static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
|
|||||||
des_decrypt(ctx, length, dst, src);
|
des_decrypt(ctx, length, dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
|
||||||
|
uint8_t *dst, const uint8_t *src)
|
||||||
|
{
|
||||||
|
des3_encrypt(ctx, length, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
|
||||||
|
uint8_t *dst, const uint8_t *src)
|
||||||
|
{
|
||||||
|
des3_decrypt(ctx, length, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
|
static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
|
||||||
uint8_t *dst, const uint8_t *src)
|
uint8_t *dst, const uint8_t *src)
|
||||||
{
|
{
|
||||||
@@ -140,6 +152,18 @@ static void des_decrypt_wrapper(const void *ctx, size_t length,
|
|||||||
des_decrypt(ctx, length, dst, src);
|
des_decrypt(ctx, length, dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void des3_encrypt_wrapper(const void *ctx, size_t length,
|
||||||
|
uint8_t *dst, const uint8_t *src)
|
||||||
|
{
|
||||||
|
des3_encrypt(ctx, length, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void des3_decrypt_wrapper(const void *ctx, size_t length,
|
||||||
|
uint8_t *dst, const uint8_t *src)
|
||||||
|
{
|
||||||
|
des3_decrypt(ctx, length, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
static void cast128_encrypt_wrapper(const void *ctx, size_t length,
|
static void cast128_encrypt_wrapper(const void *ctx, size_t length,
|
||||||
uint8_t *dst, const uint8_t *src)
|
uint8_t *dst, const uint8_t *src)
|
||||||
{
|
{
|
||||||
@@ -197,6 +221,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
|||||||
{
|
{
|
||||||
switch (alg) {
|
switch (alg) {
|
||||||
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
||||||
|
case QCRYPTO_CIPHER_ALG_3DES:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_128:
|
case QCRYPTO_CIPHER_ALG_AES_128:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_192:
|
case QCRYPTO_CIPHER_ALG_AES_192:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_256:
|
case QCRYPTO_CIPHER_ALG_AES_256:
|
||||||
@@ -254,6 +279,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
cipher->mode = mode;
|
cipher->mode = mode;
|
||||||
|
|
||||||
ctx = g_new0(QCryptoCipherNettle, 1);
|
ctx = g_new0(QCryptoCipherNettle, 1);
|
||||||
|
cipher->opaque = ctx;
|
||||||
|
|
||||||
switch (alg) {
|
switch (alg) {
|
||||||
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
||||||
@@ -270,6 +296,18 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
ctx->blocksize = DES_BLOCK_SIZE;
|
ctx->blocksize = DES_BLOCK_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QCRYPTO_CIPHER_ALG_3DES:
|
||||||
|
ctx->ctx = g_new0(struct des3_ctx, 1);
|
||||||
|
des3_set_key(ctx->ctx, key);
|
||||||
|
|
||||||
|
ctx->alg_encrypt_native = des3_encrypt_native;
|
||||||
|
ctx->alg_decrypt_native = des3_decrypt_native;
|
||||||
|
ctx->alg_encrypt_wrapper = des3_encrypt_wrapper;
|
||||||
|
ctx->alg_decrypt_wrapper = des3_decrypt_wrapper;
|
||||||
|
|
||||||
|
ctx->blocksize = DES3_BLOCK_SIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
case QCRYPTO_CIPHER_ALG_AES_128:
|
case QCRYPTO_CIPHER_ALG_AES_128:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_192:
|
case QCRYPTO_CIPHER_ALG_AES_192:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_256:
|
case QCRYPTO_CIPHER_ALG_AES_256:
|
||||||
@@ -384,13 +422,11 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->iv = g_new0(uint8_t, ctx->blocksize);
|
ctx->iv = g_new0(uint8_t, ctx->blocksize);
|
||||||
cipher->opaque = ctx;
|
|
||||||
|
|
||||||
return cipher;
|
return cipher;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
g_free(cipher);
|
qcrypto_cipher_free(cipher);
|
||||||
g_free(ctx);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
|||||||
[QCRYPTO_CIPHER_ALG_AES_192] = 24,
|
[QCRYPTO_CIPHER_ALG_AES_192] = 24,
|
||||||
[QCRYPTO_CIPHER_ALG_AES_256] = 32,
|
[QCRYPTO_CIPHER_ALG_AES_256] = 32,
|
||||||
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
||||||
|
[QCRYPTO_CIPHER_ALG_3DES] = 24,
|
||||||
[QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
|
[QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
|
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_SERPENT_192] = 24,
|
[QCRYPTO_CIPHER_ALG_SERPENT_192] = 24,
|
||||||
@@ -42,6 +43,7 @@ static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
|||||||
[QCRYPTO_CIPHER_ALG_AES_192] = 16,
|
[QCRYPTO_CIPHER_ALG_AES_192] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_AES_256] = 16,
|
[QCRYPTO_CIPHER_ALG_AES_256] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
||||||
|
[QCRYPTO_CIPHER_ALG_3DES] = 8,
|
||||||
[QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
|
[QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
|
||||||
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
|
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
|
||||||
[QCRYPTO_CIPHER_ALG_SERPENT_192] = 16,
|
[QCRYPTO_CIPHER_ALG_SERPENT_192] = 16,
|
||||||
@@ -107,8 +109,9 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
|
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
|
||||||
if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
|
if (alg == QCRYPTO_CIPHER_ALG_DES_RFB
|
||||||
error_setg(errp, "XTS mode not compatible with DES-RFB");
|
|| alg == QCRYPTO_CIPHER_ALG_3DES) {
|
||||||
|
error_setg(errp, "XTS mode not compatible with DES-RFB/3DES");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nkey % 2) {
|
if (nkey % 2) {
|
||||||
|
|||||||
152
crypto/hmac-gcrypt.c
Normal file
152
crypto/hmac-gcrypt.c
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Crypto hmac algorithms (based on libgcrypt)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Longpeng(Mike) <longpeng2@huawei.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* (at your option) any later version. See the COPYING file in the
|
||||||
|
* top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "crypto/hmac.h"
|
||||||
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||||
|
[QCRYPTO_HASH_ALG_MD5] = GCRY_MAC_HMAC_MD5,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA1] = GCRY_MAC_HMAC_SHA1,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA224] = GCRY_MAC_HMAC_SHA224,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA256] = GCRY_MAC_HMAC_SHA256,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA384] = GCRY_MAC_HMAC_SHA384,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA512] = GCRY_MAC_HMAC_SHA512,
|
||||||
|
[QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MAC_HMAC_RMD160,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt;
|
||||||
|
struct QCryptoHmacGcrypt {
|
||||||
|
gcry_mac_hd_t handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
|
{
|
||||||
|
if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
|
||||||
|
qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoHmac *hmac;
|
||||||
|
QCryptoHmacGcrypt *ctx;
|
||||||
|
gcry_error_t err;
|
||||||
|
|
||||||
|
if (!qcrypto_hmac_supports(alg)) {
|
||||||
|
error_setg(errp, "Unsupported hmac algorithm %s",
|
||||||
|
QCryptoHashAlgorithm_lookup[alg]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmac = g_new0(QCryptoHmac, 1);
|
||||||
|
hmac->alg = alg;
|
||||||
|
|
||||||
|
ctx = g_new0(QCryptoHmacGcrypt, 1);
|
||||||
|
|
||||||
|
err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg],
|
||||||
|
GCRY_MAC_FLAG_SECURE, NULL);
|
||||||
|
if (err != 0) {
|
||||||
|
error_setg(errp, "Cannot initialize hmac: %s",
|
||||||
|
gcry_strerror(err));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_mac_setkey(ctx->handle, (const void *)key, nkey);
|
||||||
|
if (err != 0) {
|
||||||
|
error_setg(errp, "Cannot set key: %s",
|
||||||
|
gcry_strerror(err));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmac->opaque = ctx;
|
||||||
|
return hmac;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_free(ctx);
|
||||||
|
g_free(hmac);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
||||||
|
{
|
||||||
|
QCryptoHmacGcrypt *ctx;
|
||||||
|
|
||||||
|
if (!hmac) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = hmac->opaque;
|
||||||
|
gcry_mac_close(ctx->handle);
|
||||||
|
|
||||||
|
g_free(ctx);
|
||||||
|
g_free(hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
uint8_t **result,
|
||||||
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoHmacGcrypt *ctx;
|
||||||
|
gcry_error_t err;
|
||||||
|
uint32_t ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ctx = hmac->opaque;
|
||||||
|
|
||||||
|
for (i = 0; i < niov; i++) {
|
||||||
|
gcry_mac_write(ctx->handle, iov[i].iov_base, iov[i].iov_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gcry_mac_get_algo_maclen(qcrypto_hmac_alg_map[hmac->alg]);
|
||||||
|
if (ret <= 0) {
|
||||||
|
error_setg(errp, "Unable to get hmac length: %s",
|
||||||
|
gcry_strerror(ret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*resultlen == 0) {
|
||||||
|
*resultlen = ret;
|
||||||
|
*result = g_new0(uint8_t, *resultlen);
|
||||||
|
} else if (*resultlen != ret) {
|
||||||
|
error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
|
||||||
|
*resultlen, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_mac_read(ctx->handle, *result, resultlen);
|
||||||
|
if (err != 0) {
|
||||||
|
error_setg(errp, "Cannot get result: %s",
|
||||||
|
gcry_strerror(err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_mac_reset(ctx->handle);
|
||||||
|
if (err != 0) {
|
||||||
|
error_setg(errp, "Cannot reset hmac context: %s",
|
||||||
|
gcry_strerror(err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
166
crypto/hmac-glib.c
Normal file
166
crypto/hmac-glib.c
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Crypto hmac algorithms (based on glib)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Longpeng(Mike) <longpeng2@huawei.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* (at your option) any later version. See the COPYING file in the
|
||||||
|
* top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "crypto/hmac.h"
|
||||||
|
|
||||||
|
/* Support for HMAC Algos has been added in GLib 2.30 */
|
||||||
|
#if GLIB_CHECK_VERSION(2, 30, 0)
|
||||||
|
|
||||||
|
static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||||
|
[QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256,
|
||||||
|
/* Support for HMAC SHA-512 in GLib 2.42 */
|
||||||
|
#if GLIB_CHECK_VERSION(2, 42, 0)
|
||||||
|
[QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512,
|
||||||
|
#else
|
||||||
|
[QCRYPTO_HASH_ALG_SHA512] = -1,
|
||||||
|
#endif
|
||||||
|
[QCRYPTO_HASH_ALG_SHA224] = -1,
|
||||||
|
[QCRYPTO_HASH_ALG_SHA384] = -1,
|
||||||
|
[QCRYPTO_HASH_ALG_RIPEMD160] = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct QCryptoHmacGlib QCryptoHmacGlib;
|
||||||
|
struct QCryptoHmacGlib {
|
||||||
|
GHmac *ghmac;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
|
{
|
||||||
|
if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
|
||||||
|
qcrypto_hmac_alg_map[alg] != -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoHmac *hmac;
|
||||||
|
QCryptoHmacGlib *ctx;
|
||||||
|
|
||||||
|
if (!qcrypto_hmac_supports(alg)) {
|
||||||
|
error_setg(errp, "Unsupported hmac algorithm %s",
|
||||||
|
QCryptoHashAlgorithm_lookup[alg]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmac = g_new0(QCryptoHmac, 1);
|
||||||
|
hmac->alg = alg;
|
||||||
|
|
||||||
|
ctx = g_new0(QCryptoHmacGlib, 1);
|
||||||
|
|
||||||
|
ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg],
|
||||||
|
(const uint8_t *)key, nkey);
|
||||||
|
if (!ctx->ghmac) {
|
||||||
|
error_setg(errp, "Cannot initialize hmac and set key");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmac->opaque = ctx;
|
||||||
|
return hmac;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_free(ctx);
|
||||||
|
g_free(hmac);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
||||||
|
{
|
||||||
|
QCryptoHmacGlib *ctx;
|
||||||
|
|
||||||
|
if (!hmac) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = hmac->opaque;
|
||||||
|
g_hmac_unref(ctx->ghmac);
|
||||||
|
|
||||||
|
g_free(ctx);
|
||||||
|
g_free(hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
uint8_t **result,
|
||||||
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoHmacGlib *ctx;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
ctx = hmac->opaque;
|
||||||
|
|
||||||
|
for (i = 0; i < niov; i++) {
|
||||||
|
g_hmac_update(ctx->ghmac, iov[i].iov_base, iov[i].iov_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = g_checksum_type_get_length(qcrypto_hmac_alg_map[hmac->alg]);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "Unable to get hmac length");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*resultlen == 0) {
|
||||||
|
*resultlen = ret;
|
||||||
|
*result = g_new0(uint8_t, *resultlen);
|
||||||
|
} else if (*resultlen != ret) {
|
||||||
|
error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
|
||||||
|
*resultlen, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hmac_get_digest(ctx->ghmac, *result, resultlen);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
uint8_t **result,
|
||||||
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
175
crypto/hmac-nettle.c
Normal file
175
crypto/hmac-nettle.c
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Crypto hmac algorithms (based on nettle)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Longpeng(Mike) <longpeng2@huawei.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* (at your option) any later version. See the COPYING file in the
|
||||||
|
* top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "crypto/hmac.h"
|
||||||
|
#include <nettle/hmac.h>
|
||||||
|
|
||||||
|
typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
|
||||||
|
size_t key_length, const uint8_t *key);
|
||||||
|
|
||||||
|
typedef void (*qcrypto_nettle_hmac_update)(void *ctx,
|
||||||
|
size_t length, const uint8_t *data);
|
||||||
|
|
||||||
|
typedef void (*qcrypto_nettle_hmac_digest)(void *ctx,
|
||||||
|
size_t length, uint8_t *digest);
|
||||||
|
|
||||||
|
typedef struct QCryptoHmacNettle QCryptoHmacNettle;
|
||||||
|
struct QCryptoHmacNettle {
|
||||||
|
union qcrypto_nettle_hmac_ctx {
|
||||||
|
struct hmac_md5_ctx md5_ctx;
|
||||||
|
struct hmac_sha1_ctx sha1_ctx;
|
||||||
|
struct hmac_sha256_ctx sha256_ctx; /* equals hmac_sha224_ctx */
|
||||||
|
struct hmac_sha512_ctx sha512_ctx; /* equals hmac_sha384_ctx */
|
||||||
|
struct hmac_ripemd160_ctx ripemd160_ctx;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qcrypto_nettle_hmac_alg {
|
||||||
|
qcrypto_nettle_hmac_setkey setkey;
|
||||||
|
qcrypto_nettle_hmac_update update;
|
||||||
|
qcrypto_nettle_hmac_digest digest;
|
||||||
|
size_t len;
|
||||||
|
} qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||||
|
[QCRYPTO_HASH_ALG_MD5] = {
|
||||||
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_md5_set_key,
|
||||||
|
.update = (qcrypto_nettle_hmac_update)hmac_md5_update,
|
||||||
|
.digest = (qcrypto_nettle_hmac_digest)hmac_md5_digest,
|
||||||
|
.len = MD5_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
[QCRYPTO_HASH_ALG_SHA1] = {
|
||||||
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha1_set_key,
|
||||||
|
.update = (qcrypto_nettle_hmac_update)hmac_sha1_update,
|
||||||
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha1_digest,
|
||||||
|
.len = SHA1_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
[QCRYPTO_HASH_ALG_SHA224] = {
|
||||||
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha224_set_key,
|
||||||
|
.update = (qcrypto_nettle_hmac_update)hmac_sha224_update,
|
||||||
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha224_digest,
|
||||||
|
.len = SHA224_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
[QCRYPTO_HASH_ALG_SHA256] = {
|
||||||
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha256_set_key,
|
||||||
|
.update = (qcrypto_nettle_hmac_update)hmac_sha256_update,
|
||||||
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha256_digest,
|
||||||
|
.len = SHA256_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
[QCRYPTO_HASH_ALG_SHA384] = {
|
||||||
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha384_set_key,
|
||||||
|
.update = (qcrypto_nettle_hmac_update)hmac_sha384_update,
|
||||||
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha384_digest,
|
||||||
|
.len = SHA384_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
[QCRYPTO_HASH_ALG_SHA512] = {
|
||||||
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha512_set_key,
|
||||||
|
.update = (qcrypto_nettle_hmac_update)hmac_sha512_update,
|
||||||
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha512_digest,
|
||||||
|
.len = SHA512_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
[QCRYPTO_HASH_ALG_RIPEMD160] = {
|
||||||
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_ripemd160_set_key,
|
||||||
|
.update = (qcrypto_nettle_hmac_update)hmac_ripemd160_update,
|
||||||
|
.digest = (qcrypto_nettle_hmac_digest)hmac_ripemd160_digest,
|
||||||
|
.len = RIPEMD160_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
|
{
|
||||||
|
if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
|
||||||
|
qcrypto_hmac_alg_map[alg].setkey != NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoHmac *hmac;
|
||||||
|
QCryptoHmacNettle *ctx;
|
||||||
|
|
||||||
|
if (!qcrypto_hmac_supports(alg)) {
|
||||||
|
error_setg(errp, "Unsupported hmac algorithm %s",
|
||||||
|
QCryptoHashAlgorithm_lookup[alg]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmac = g_new0(QCryptoHmac, 1);
|
||||||
|
hmac->alg = alg;
|
||||||
|
|
||||||
|
ctx = g_new0(QCryptoHmacNettle, 1);
|
||||||
|
|
||||||
|
qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key);
|
||||||
|
|
||||||
|
hmac->opaque = ctx;
|
||||||
|
|
||||||
|
return hmac;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
||||||
|
{
|
||||||
|
QCryptoHmacNettle *ctx;
|
||||||
|
|
||||||
|
if (!hmac) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = hmac->opaque;
|
||||||
|
|
||||||
|
g_free(ctx);
|
||||||
|
g_free(hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
uint8_t **result,
|
||||||
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoHmacNettle *ctx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ctx = (QCryptoHmacNettle *)hmac->opaque;
|
||||||
|
|
||||||
|
for (i = 0; i < niov; ++i) {
|
||||||
|
size_t len = iov[i].iov_len;
|
||||||
|
uint8_t *base = iov[i].iov_base;
|
||||||
|
while (len) {
|
||||||
|
size_t shortlen = MIN(len, UINT_MAX);
|
||||||
|
qcrypto_hmac_alg_map[hmac->alg].update(&ctx->u, len, base);
|
||||||
|
len -= shortlen;
|
||||||
|
base += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*resultlen == 0) {
|
||||||
|
*resultlen = qcrypto_hmac_alg_map[hmac->alg].len;
|
||||||
|
*result = g_new0(uint8_t, *resultlen);
|
||||||
|
} else if (*resultlen != qcrypto_hmac_alg_map[hmac->alg].len) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Result buffer size %zu is smaller than hash %zu",
|
||||||
|
*resultlen, qcrypto_hmac_alg_map[hmac->alg].len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qcrypto_hmac_alg_map[hmac->alg].digest(&ctx->u, *resultlen, *result);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
72
crypto/hmac.c
Normal file
72
crypto/hmac.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Crypto hmac algorithms
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* (at your option) any later version. See the COPYING file in the
|
||||||
|
* top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "crypto/hmac.h"
|
||||||
|
|
||||||
|
static const char hex[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
int qcrypto_hmac_bytes(QCryptoHmac *hmac,
|
||||||
|
const char *buf,
|
||||||
|
size_t len,
|
||||||
|
uint8_t **result,
|
||||||
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = (char *)buf,
|
||||||
|
.iov_len = len
|
||||||
|
};
|
||||||
|
|
||||||
|
return qcrypto_hmac_bytesv(hmac, &iov, 1, result, resultlen, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qcrypto_hmac_digestv(QCryptoHmac *hmac,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
char **digest,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
uint8_t *result = NULL;
|
||||||
|
size_t resultlen = 0;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (qcrypto_hmac_bytesv(hmac, iov, niov, &result, &resultlen, errp) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*digest = g_new0(char, (resultlen * 2) + 1);
|
||||||
|
|
||||||
|
for (i = 0 ; i < resultlen ; i++) {
|
||||||
|
(*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf];
|
||||||
|
(*digest)[(i * 2) + 1] = hex[result[i] & 0xf];
|
||||||
|
}
|
||||||
|
|
||||||
|
(*digest)[resultlen * 2] = '\0';
|
||||||
|
|
||||||
|
g_free(result);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qcrypto_hmac_digest(QCryptoHmac *hmac,
|
||||||
|
const char *buf,
|
||||||
|
size_t len,
|
||||||
|
char **digest,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = (char *)buf,
|
||||||
|
.iov_len = len
|
||||||
|
};
|
||||||
|
|
||||||
|
return qcrypto_hmac_digestv(hmac, &iov, 1, digest, errp);
|
||||||
|
}
|
||||||
166
crypto/hmac.h
Normal file
166
crypto/hmac.h
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* QEMU Crypto hmac algorithms
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
|
* (at your option) any later version. See the COPYING file in the
|
||||||
|
* top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QCRYPTO_HMAC_H
|
||||||
|
#define QCRYPTO_HMAC_H
|
||||||
|
|
||||||
|
#include "qapi-types.h"
|
||||||
|
|
||||||
|
typedef struct QCryptoHmac QCryptoHmac;
|
||||||
|
struct QCryptoHmac {
|
||||||
|
QCryptoHashAlgorithm alg;
|
||||||
|
void *opaque;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_hmac_supports:
|
||||||
|
* @alg: the hmac algorithm
|
||||||
|
*
|
||||||
|
* Determine if @alg hmac algorithm is supported by
|
||||||
|
* the current configured build
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* true if the algorithm is supported, false otherwise
|
||||||
|
*/
|
||||||
|
bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_hmac_new:
|
||||||
|
* @alg: the hmac algorithm
|
||||||
|
* @key: the key bytes
|
||||||
|
* @nkey: the length of @key
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Creates a new hmac object with the algorithm @alg
|
||||||
|
*
|
||||||
|
* The @key parameter provides the bytes representing
|
||||||
|
* the secret key to use. The @nkey parameter specifies
|
||||||
|
* the length of @key in bytes
|
||||||
|
*
|
||||||
|
* Note: must use qcrypto_hmac_free() to release the
|
||||||
|
* returned hmac object when no longer required
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* a new hmac object, or NULL on error
|
||||||
|
*/
|
||||||
|
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_hmac_free:
|
||||||
|
* @hmac: the hmac object
|
||||||
|
*
|
||||||
|
* Release the memory associated with @hmac that was
|
||||||
|
* previously allocated by qcrypto_hmac_new()
|
||||||
|
*/
|
||||||
|
void qcrypto_hmac_free(QCryptoHmac *hmac);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_hmac_bytesv:
|
||||||
|
* @hmac: the hmac object
|
||||||
|
* @iov: the array of memory regions to hmac
|
||||||
|
* @niov: the length of @iov
|
||||||
|
* @result: pointer to hold output hmac
|
||||||
|
* @resultlen: pointer to hold length of @result
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Computes the hmac across all the memory regions
|
||||||
|
* present in @iov. The @result pointer will be
|
||||||
|
* filled with raw bytes representing the computed
|
||||||
|
* hmac, which will have length @resultlen. The
|
||||||
|
* memory pointer in @result must be released
|
||||||
|
* with a call to g_free() when no longer required.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
uint8_t **result,
|
||||||
|
size_t *resultlen,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_hmac_bytes:
|
||||||
|
* @hmac: the hmac object
|
||||||
|
* @buf: the memory region to hmac
|
||||||
|
* @len: the length of @buf
|
||||||
|
* @result: pointer to hold output hmac
|
||||||
|
* @resultlen: pointer to hold length of @result
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Computes the hmac across all the memory region
|
||||||
|
* @buf of length @len. The @result pointer will be
|
||||||
|
* filled with raw bytes representing the computed
|
||||||
|
* hmac, which will have length @resultlen. The
|
||||||
|
* memory pointer in @result must be released
|
||||||
|
* with a call to g_free() when no longer required.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int qcrypto_hmac_bytes(QCryptoHmac *hmac,
|
||||||
|
const char *buf,
|
||||||
|
size_t len,
|
||||||
|
uint8_t **result,
|
||||||
|
size_t *resultlen,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_hmac_digestv:
|
||||||
|
* @hmac: the hmac object
|
||||||
|
* @iov: the array of memory regions to hmac
|
||||||
|
* @niov: the length of @iov
|
||||||
|
* @digest: pointer to hold output hmac
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Computes the hmac across all the memory regions
|
||||||
|
* present in @iov. The @digest pointer will be
|
||||||
|
* filled with the printable hex digest of the computed
|
||||||
|
* hmac, which will be terminated by '\0'. The
|
||||||
|
* memory pointer in @digest must be released
|
||||||
|
* with a call to g_free() when no longer required.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int qcrypto_hmac_digestv(QCryptoHmac *hmac,
|
||||||
|
const struct iovec *iov,
|
||||||
|
size_t niov,
|
||||||
|
char **digest,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_hmac_digest:
|
||||||
|
* @hmac: the hmac object
|
||||||
|
* @buf: the memory region to hmac
|
||||||
|
* @len: the length of @buf
|
||||||
|
* @digest: pointer to hold output hmac
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Computes the hmac across all the memory region
|
||||||
|
* @buf of length @len. The @digest pointer will be
|
||||||
|
* filled with the printable hex digest of the computed
|
||||||
|
* hmac, which will be terminated by '\0'. The
|
||||||
|
* memory pointer in @digest must be released
|
||||||
|
* with a call to g_free() when no longer required.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int qcrypto_hmac_digest(QCryptoHmac *hmac,
|
||||||
|
const char *buf,
|
||||||
|
size_t len,
|
||||||
|
char **digest,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -21,9 +21,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "disas/bfd.h"
|
#include "disas/bfd.h"
|
||||||
//#include "sysdep.h"
|
#include "target/cris/opcode-cris.h"
|
||||||
#include "target-cris/opcode-cris.h"
|
|
||||||
//#include "libiberty.h"
|
|
||||||
|
|
||||||
#define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0)
|
#define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0)
|
||||||
|
|
||||||
|
|||||||
@@ -4698,10 +4698,6 @@ get_field (const unsigned char *data, enum floatformat_byteorders order,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef min
|
|
||||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Convert from FMT to a double.
|
/* Convert from FMT to a double.
|
||||||
FROM is the address of the extended float.
|
FROM is the address of the extended float.
|
||||||
Store the double in *TO. */
|
Store the double in *TO. */
|
||||||
@@ -4733,7 +4729,7 @@ floatformat_to_double (const struct floatformat *fmt,
|
|||||||
nan = 0;
|
nan = 0;
|
||||||
while (mant_bits_left > 0)
|
while (mant_bits_left > 0)
|
||||||
{
|
{
|
||||||
mant_bits = min (mant_bits_left, 32);
|
mant_bits = MIN(mant_bits_left, 32);
|
||||||
|
|
||||||
if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
|
if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
|
||||||
mant_off, mant_bits) != 0)
|
mant_off, mant_bits) != 0)
|
||||||
@@ -4793,7 +4789,7 @@ floatformat_to_double (const struct floatformat *fmt,
|
|||||||
|
|
||||||
while (mant_bits_left > 0)
|
while (mant_bits_left > 0)
|
||||||
{
|
{
|
||||||
mant_bits = min (mant_bits_left, 32);
|
mant_bits = MIN(mant_bits_left, 32);
|
||||||
|
|
||||||
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
|
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
|
||||||
mant_off, mant_bits);
|
mant_off, mant_bits);
|
||||||
|
|||||||
@@ -160,5 +160,6 @@ If unset, the default value for this parameter is 0 and it disables
|
|||||||
this feature.
|
this feature.
|
||||||
|
|
||||||
Note that this functionality currently relies on the MADV_DONTNEED
|
Note that this functionality currently relies on the MADV_DONTNEED
|
||||||
argument for madvise() to actually free the memory, so it is not
|
argument for madvise() to actually free the memory. This is a
|
||||||
useful in systems that don't follow that behavior.
|
Linux-specific feature, so cache-clean-interval is not supported in
|
||||||
|
other systems.
|
||||||
|
|||||||
@@ -123,22 +123,22 @@ The communication consists of master sending message requests and slave sending
|
|||||||
message replies. Most of the requests don't require replies. Here is a list of
|
message replies. Most of the requests don't require replies. Here is a list of
|
||||||
the ones that do:
|
the ones that do:
|
||||||
|
|
||||||
* VHOST_GET_FEATURES
|
* VHOST_USER_GET_FEATURES
|
||||||
* VHOST_GET_PROTOCOL_FEATURES
|
* VHOST_USER_GET_PROTOCOL_FEATURES
|
||||||
* VHOST_GET_VRING_BASE
|
* VHOST_USER_GET_VRING_BASE
|
||||||
* VHOST_SET_LOG_BASE (if VHOST_USER_PROTOCOL_F_LOG_SHMFD)
|
* VHOST_USER_SET_LOG_BASE (if VHOST_USER_PROTOCOL_F_LOG_SHMFD)
|
||||||
|
|
||||||
[ Also see the section on REPLY_ACK protocol extension. ]
|
[ Also see the section on REPLY_ACK protocol extension. ]
|
||||||
|
|
||||||
There are several messages that the master sends with file descriptors passed
|
There are several messages that the master sends with file descriptors passed
|
||||||
in the ancillary data:
|
in the ancillary data:
|
||||||
|
|
||||||
* VHOST_SET_MEM_TABLE
|
* VHOST_USER_SET_MEM_TABLE
|
||||||
* VHOST_SET_LOG_BASE (if VHOST_USER_PROTOCOL_F_LOG_SHMFD)
|
* VHOST_USER_SET_LOG_BASE (if VHOST_USER_PROTOCOL_F_LOG_SHMFD)
|
||||||
* VHOST_SET_LOG_FD
|
* VHOST_USER_SET_LOG_FD
|
||||||
* VHOST_SET_VRING_KICK
|
* VHOST_USER_SET_VRING_KICK
|
||||||
* VHOST_SET_VRING_CALL
|
* VHOST_USER_SET_VRING_CALL
|
||||||
* VHOST_SET_VRING_ERR
|
* VHOST_USER_SET_VRING_ERR
|
||||||
|
|
||||||
If Master is unable to send the full message or receives a wrong reply it will
|
If Master is unable to send the full message or receives a wrong reply it will
|
||||||
close the connection. An optional reconnection mechanism can be implemented.
|
close the connection. An optional reconnection mechanism can be implemented.
|
||||||
|
|||||||
728
exec.c
728
exec.c
@@ -684,28 +684,15 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
||||||
{
|
{
|
||||||
mmap_lock();
|
/* Flush the whole TB as this will not have race conditions
|
||||||
tb_lock();
|
* even if we don't have proper locking yet.
|
||||||
tb_invalidate_phys_page_range(pc, pc + 1, 0);
|
* Ideally we would just invalidate the TBs for the
|
||||||
tb_unlock();
|
* specified PC.
|
||||||
mmap_unlock();
|
*/
|
||||||
|
tb_flush(cpu);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
|
||||||
{
|
|
||||||
MemTxAttrs attrs;
|
|
||||||
hwaddr phys = cpu_get_phys_page_attrs_debug(cpu, pc, &attrs);
|
|
||||||
int asidx = cpu_asidx_from_attrs(cpu, attrs);
|
|
||||||
if (phys != -1) {
|
|
||||||
/* Locks grabbed by tb_invalidate_phys_addr */
|
|
||||||
tb_invalidate_phys_addr(cpu->cpu_ases[asidx].as,
|
|
||||||
phys | (pc & ~TARGET_PAGE_MASK));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
|
void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
|
||||||
@@ -2951,6 +2938,31 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hwaddr
|
||||||
|
address_space_extend_translation(AddressSpace *as, hwaddr addr, hwaddr target_len,
|
||||||
|
MemoryRegion *mr, hwaddr base, hwaddr len,
|
||||||
|
bool is_write)
|
||||||
|
{
|
||||||
|
hwaddr done = 0;
|
||||||
|
hwaddr xlat;
|
||||||
|
MemoryRegion *this_mr;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
target_len -= len;
|
||||||
|
addr += len;
|
||||||
|
done += len;
|
||||||
|
if (target_len == 0) {
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = target_len;
|
||||||
|
this_mr = address_space_translate(as, addr, &xlat, &len, is_write);
|
||||||
|
if (this_mr != mr || xlat != base + done) {
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Map a physical memory region into a host virtual address.
|
/* Map a physical memory region into a host virtual address.
|
||||||
* May map a subset of the requested range, given by and returned in *plen.
|
* May map a subset of the requested range, given by and returned in *plen.
|
||||||
* May return NULL if resources needed to perform the mapping are exhausted.
|
* May return NULL if resources needed to perform the mapping are exhausted.
|
||||||
@@ -2964,9 +2976,8 @@ void *address_space_map(AddressSpace *as,
|
|||||||
bool is_write)
|
bool is_write)
|
||||||
{
|
{
|
||||||
hwaddr len = *plen;
|
hwaddr len = *plen;
|
||||||
hwaddr done = 0;
|
hwaddr l, xlat;
|
||||||
hwaddr l, xlat, base;
|
MemoryRegion *mr;
|
||||||
MemoryRegion *mr, *this_mr;
|
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
@@ -3000,26 +3011,10 @@ void *address_space_map(AddressSpace *as,
|
|||||||
return bounce.buffer;
|
return bounce.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
base = xlat;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
len -= l;
|
|
||||||
addr += l;
|
|
||||||
done += l;
|
|
||||||
if (len == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
l = len;
|
|
||||||
this_mr = address_space_translate(as, addr, &xlat, &l, is_write);
|
|
||||||
if (this_mr != mr || xlat != base + done) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memory_region_ref(mr);
|
memory_region_ref(mr);
|
||||||
*plen = done;
|
*plen = address_space_extend_translation(as, addr, len, mr, xlat, l, is_write);
|
||||||
ptr = qemu_ram_ptr_length(mr->ram_block, base, plen);
|
ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
@@ -3071,597 +3066,92 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len,
|
|||||||
return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len);
|
return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* warning: addr must be aligned */
|
#define ARG1_DECL AddressSpace *as
|
||||||
static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
|
#define ARG1 as
|
||||||
MemTxAttrs attrs,
|
#define SUFFIX
|
||||||
MemTxResult *result,
|
#define TRANSLATE(...) address_space_translate(as, __VA_ARGS__)
|
||||||
enum device_endian endian)
|
#define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write)
|
||||||
|
#define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs)
|
||||||
|
#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len)
|
||||||
|
#define RCU_READ_LOCK(...) rcu_read_lock()
|
||||||
|
#define RCU_READ_UNLOCK(...) rcu_read_unlock()
|
||||||
|
#include "memory_ldst.inc.c"
|
||||||
|
|
||||||
|
int64_t address_space_cache_init(MemoryRegionCache *cache,
|
||||||
|
AddressSpace *as,
|
||||||
|
hwaddr addr,
|
||||||
|
hwaddr len,
|
||||||
|
bool is_write)
|
||||||
{
|
{
|
||||||
uint8_t *ptr;
|
hwaddr l, xlat;
|
||||||
uint64_t val;
|
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
hwaddr l = 4;
|
void *ptr;
|
||||||
hwaddr addr1;
|
|
||||||
MemTxResult r;
|
|
||||||
bool release_lock = false;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
assert(len > 0);
|
||||||
mr = address_space_translate(as, addr, &addr1, &l, false);
|
|
||||||
if (l < 4 || !memory_access_is_direct(mr, false)) {
|
|
||||||
release_lock |= prepare_mmio_access(mr);
|
|
||||||
|
|
||||||
/* I/O case */
|
l = len;
|
||||||
r = memory_region_dispatch_read(mr, addr1, &val, 4, attrs);
|
mr = address_space_translate(as, addr, &xlat, &l, is_write);
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
if (!memory_access_is_direct(mr, is_write)) {
|
||||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
return -EINVAL;
|
||||||
val = bswap32(val);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (endian == DEVICE_BIG_ENDIAN) {
|
|
||||||
val = bswap32(val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/* RAM case */
|
|
||||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
||||||
switch (endian) {
|
|
||||||
case DEVICE_LITTLE_ENDIAN:
|
|
||||||
val = ldl_le_p(ptr);
|
|
||||||
break;
|
|
||||||
case DEVICE_BIG_ENDIAN:
|
|
||||||
val = ldl_be_p(ptr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
val = ldl_p(ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r = MEMTX_OK;
|
|
||||||
}
|
}
|
||||||
if (result) {
|
|
||||||
*result = r;
|
l = address_space_extend_translation(as, addr, len, mr, xlat, l, is_write);
|
||||||
|
ptr = qemu_ram_ptr_length(mr->ram_block, xlat, &l);
|
||||||
|
|
||||||
|
cache->xlat = xlat;
|
||||||
|
cache->is_write = is_write;
|
||||||
|
cache->mr = mr;
|
||||||
|
cache->ptr = ptr;
|
||||||
|
cache->len = l;
|
||||||
|
memory_region_ref(cache->mr);
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void address_space_cache_invalidate(MemoryRegionCache *cache,
|
||||||
|
hwaddr addr,
|
||||||
|
hwaddr access_len)
|
||||||
|
{
|
||||||
|
assert(cache->is_write);
|
||||||
|
invalidate_and_set_dirty(cache->mr, addr + cache->xlat, access_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void address_space_cache_destroy(MemoryRegionCache *cache)
|
||||||
|
{
|
||||||
|
if (!cache->mr) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (release_lock) {
|
|
||||||
qemu_mutex_unlock_iothread();
|
if (xen_enabled()) {
|
||||||
|
xen_invalidate_map_cache_entry(cache->ptr);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
memory_region_unref(cache->mr);
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
|
/* Called from RCU critical section. This function has the same
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
* semantics as address_space_translate, but it only works on a
|
||||||
|
* predefined range of a MemoryRegion that was mapped with
|
||||||
|
* address_space_cache_init.
|
||||||
|
*/
|
||||||
|
static inline MemoryRegion *address_space_translate_cached(
|
||||||
|
MemoryRegionCache *cache, hwaddr addr, hwaddr *xlat,
|
||||||
|
hwaddr *plen, bool is_write)
|
||||||
{
|
{
|
||||||
return address_space_ldl_internal(as, addr, attrs, result,
|
assert(addr < cache->len && *plen <= cache->len - addr);
|
||||||
DEVICE_NATIVE_ENDIAN);
|
*xlat = addr + cache->xlat;
|
||||||
|
return cache->mr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
|
#define ARG1_DECL MemoryRegionCache *cache
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
#define ARG1 cache
|
||||||
{
|
#define SUFFIX _cached
|
||||||
return address_space_ldl_internal(as, addr, attrs, result,
|
#define TRANSLATE(...) address_space_translate_cached(cache, __VA_ARGS__)
|
||||||
DEVICE_LITTLE_ENDIAN);
|
#define IS_DIRECT(mr, is_write) true
|
||||||
}
|
#define MAP_RAM(mr, ofs) (cache->ptr + (ofs - cache->xlat))
|
||||||
|
#define INVALIDATE(mr, ofs, len) ((void)0)
|
||||||
uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
|
#define RCU_READ_LOCK() ((void)0)
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
#define RCU_READ_UNLOCK() ((void)0)
|
||||||
{
|
#include "memory_ldst.inc.c"
|
||||||
return address_space_ldl_internal(as, addr, attrs, result,
|
|
||||||
DEVICE_BIG_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ldl_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_ldl(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_ldl_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ldl_be_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_ldl_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* warning: addr must be aligned */
|
|
||||||
static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs,
|
|
||||||
MemTxResult *result,
|
|
||||||
enum device_endian endian)
|
|
||||||
{
|
|
||||||
uint8_t *ptr;
|
|
||||||
uint64_t val;
|
|
||||||
MemoryRegion *mr;
|
|
||||||
hwaddr l = 8;
|
|
||||||
hwaddr addr1;
|
|
||||||
MemTxResult r;
|
|
||||||
bool release_lock = false;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
|
||||||
false);
|
|
||||||
if (l < 8 || !memory_access_is_direct(mr, false)) {
|
|
||||||
release_lock |= prepare_mmio_access(mr);
|
|
||||||
|
|
||||||
/* I/O case */
|
|
||||||
r = memory_region_dispatch_read(mr, addr1, &val, 8, attrs);
|
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
||||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
|
||||||
val = bswap64(val);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (endian == DEVICE_BIG_ENDIAN) {
|
|
||||||
val = bswap64(val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/* RAM case */
|
|
||||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
||||||
switch (endian) {
|
|
||||||
case DEVICE_LITTLE_ENDIAN:
|
|
||||||
val = ldq_le_p(ptr);
|
|
||||||
break;
|
|
||||||
case DEVICE_BIG_ENDIAN:
|
|
||||||
val = ldq_be_p(ptr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
val = ldq_p(ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r = MEMTX_OK;
|
|
||||||
}
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
if (release_lock) {
|
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
return address_space_ldq_internal(as, addr, attrs, result,
|
|
||||||
DEVICE_NATIVE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
return address_space_ldq_internal(as, addr, attrs, result,
|
|
||||||
DEVICE_LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
return address_space_ldq_internal(as, addr, attrs, result,
|
|
||||||
DEVICE_BIG_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t ldq_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_ldq(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t ldq_le_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_ldq_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_ldq_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: optimize */
|
|
||||||
uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
uint8_t val;
|
|
||||||
MemTxResult r;
|
|
||||||
|
|
||||||
r = address_space_rw(as, addr, attrs, &val, 1, 0);
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_ldub(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* warning: addr must be aligned */
|
|
||||||
static inline uint32_t address_space_lduw_internal(AddressSpace *as,
|
|
||||||
hwaddr addr,
|
|
||||||
MemTxAttrs attrs,
|
|
||||||
MemTxResult *result,
|
|
||||||
enum device_endian endian)
|
|
||||||
{
|
|
||||||
uint8_t *ptr;
|
|
||||||
uint64_t val;
|
|
||||||
MemoryRegion *mr;
|
|
||||||
hwaddr l = 2;
|
|
||||||
hwaddr addr1;
|
|
||||||
MemTxResult r;
|
|
||||||
bool release_lock = false;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
|
||||||
false);
|
|
||||||
if (l < 2 || !memory_access_is_direct(mr, false)) {
|
|
||||||
release_lock |= prepare_mmio_access(mr);
|
|
||||||
|
|
||||||
/* I/O case */
|
|
||||||
r = memory_region_dispatch_read(mr, addr1, &val, 2, attrs);
|
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
||||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
|
||||||
val = bswap16(val);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (endian == DEVICE_BIG_ENDIAN) {
|
|
||||||
val = bswap16(val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/* RAM case */
|
|
||||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
||||||
switch (endian) {
|
|
||||||
case DEVICE_LITTLE_ENDIAN:
|
|
||||||
val = lduw_le_p(ptr);
|
|
||||||
break;
|
|
||||||
case DEVICE_BIG_ENDIAN:
|
|
||||||
val = lduw_be_p(ptr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
val = lduw_p(ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r = MEMTX_OK;
|
|
||||||
}
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
if (release_lock) {
|
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
return address_space_lduw_internal(as, addr, attrs, result,
|
|
||||||
DEVICE_NATIVE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
return address_space_lduw_internal(as, addr, attrs, result,
|
|
||||||
DEVICE_LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
return address_space_lduw_internal(as, addr, attrs, result,
|
|
||||||
DEVICE_BIG_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lduw_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_lduw(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lduw_le_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_lduw_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lduw_be_phys(AddressSpace *as, hwaddr addr)
|
|
||||||
{
|
|
||||||
return address_space_lduw_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* warning: addr must be aligned. The ram page is not masked as dirty
|
|
||||||
and the code inside is not invalidated. It is useful if the dirty
|
|
||||||
bits are used to track modified PTEs */
|
|
||||||
void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
uint8_t *ptr;
|
|
||||||
MemoryRegion *mr;
|
|
||||||
hwaddr l = 4;
|
|
||||||
hwaddr addr1;
|
|
||||||
MemTxResult r;
|
|
||||||
uint8_t dirty_log_mask;
|
|
||||||
bool release_lock = false;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
|
||||||
true);
|
|
||||||
if (l < 4 || !memory_access_is_direct(mr, true)) {
|
|
||||||
release_lock |= prepare_mmio_access(mr);
|
|
||||||
|
|
||||||
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
|
|
||||||
} else {
|
|
||||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
||||||
stl_p(ptr, val);
|
|
||||||
|
|
||||||
dirty_log_mask = memory_region_get_dirty_log_mask(mr);
|
|
||||||
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
|
|
||||||
cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr,
|
|
||||||
4, dirty_log_mask);
|
|
||||||
r = MEMTX_OK;
|
|
||||||
}
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
if (release_lock) {
|
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stl_notdirty(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* warning: addr must be aligned */
|
|
||||||
static inline void address_space_stl_internal(AddressSpace *as,
|
|
||||||
hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs,
|
|
||||||
MemTxResult *result,
|
|
||||||
enum device_endian endian)
|
|
||||||
{
|
|
||||||
uint8_t *ptr;
|
|
||||||
MemoryRegion *mr;
|
|
||||||
hwaddr l = 4;
|
|
||||||
hwaddr addr1;
|
|
||||||
MemTxResult r;
|
|
||||||
bool release_lock = false;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
mr = address_space_translate(as, addr, &addr1, &l,
|
|
||||||
true);
|
|
||||||
if (l < 4 || !memory_access_is_direct(mr, true)) {
|
|
||||||
release_lock |= prepare_mmio_access(mr);
|
|
||||||
|
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
||||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
|
||||||
val = bswap32(val);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (endian == DEVICE_BIG_ENDIAN) {
|
|
||||||
val = bswap32(val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
|
|
||||||
} else {
|
|
||||||
/* RAM case */
|
|
||||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
||||||
switch (endian) {
|
|
||||||
case DEVICE_LITTLE_ENDIAN:
|
|
||||||
stl_le_p(ptr, val);
|
|
||||||
break;
|
|
||||||
case DEVICE_BIG_ENDIAN:
|
|
||||||
stl_be_p(ptr, val);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stl_p(ptr, val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
invalidate_and_set_dirty(mr, addr1, 4);
|
|
||||||
r = MEMTX_OK;
|
|
||||||
}
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
if (release_lock) {
|
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
address_space_stl_internal(as, addr, val, attrs, result,
|
|
||||||
DEVICE_NATIVE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
address_space_stl_internal(as, addr, val, attrs, result,
|
|
||||||
DEVICE_LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
address_space_stl_internal(as, addr, val, attrs, result,
|
|
||||||
DEVICE_BIG_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stl_phys(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stl(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stl_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stl_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stl_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: optimize */
|
|
||||||
void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
uint8_t v = val;
|
|
||||||
MemTxResult r;
|
|
||||||
|
|
||||||
r = address_space_rw(as, addr, attrs, &v, 1, 1);
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* warning: addr must be aligned */
|
|
||||||
static inline void address_space_stw_internal(AddressSpace *as,
|
|
||||||
hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs,
|
|
||||||
MemTxResult *result,
|
|
||||||
enum device_endian endian)
|
|
||||||
{
|
|
||||||
uint8_t *ptr;
|
|
||||||
MemoryRegion *mr;
|
|
||||||
hwaddr l = 2;
|
|
||||||
hwaddr addr1;
|
|
||||||
MemTxResult r;
|
|
||||||
bool release_lock = false;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
mr = address_space_translate(as, addr, &addr1, &l, true);
|
|
||||||
if (l < 2 || !memory_access_is_direct(mr, true)) {
|
|
||||||
release_lock |= prepare_mmio_access(mr);
|
|
||||||
|
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
||||||
if (endian == DEVICE_LITTLE_ENDIAN) {
|
|
||||||
val = bswap16(val);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (endian == DEVICE_BIG_ENDIAN) {
|
|
||||||
val = bswap16(val);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
r = memory_region_dispatch_write(mr, addr1, val, 2, attrs);
|
|
||||||
} else {
|
|
||||||
/* RAM case */
|
|
||||||
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
|
|
||||||
switch (endian) {
|
|
||||||
case DEVICE_LITTLE_ENDIAN:
|
|
||||||
stw_le_p(ptr, val);
|
|
||||||
break;
|
|
||||||
case DEVICE_BIG_ENDIAN:
|
|
||||||
stw_be_p(ptr, val);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stw_p(ptr, val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
invalidate_and_set_dirty(mr, addr1, 2);
|
|
||||||
r = MEMTX_OK;
|
|
||||||
}
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
if (release_lock) {
|
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
address_space_stw_internal(as, addr, val, attrs, result,
|
|
||||||
DEVICE_NATIVE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
address_space_stw_internal(as, addr, val, attrs, result,
|
|
||||||
DEVICE_LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
address_space_stw_internal(as, addr, val, attrs, result,
|
|
||||||
DEVICE_BIG_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stw_phys(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stw(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stw_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stw_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
|
|
||||||
{
|
|
||||||
address_space_stw_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: optimize */
|
|
||||||
void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
MemTxResult r;
|
|
||||||
val = tswap64(val);
|
|
||||||
r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
MemTxResult r;
|
|
||||||
val = cpu_to_le64(val);
|
|
||||||
r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
|
|
||||||
MemTxAttrs attrs, MemTxResult *result)
|
|
||||||
{
|
|
||||||
MemTxResult r;
|
|
||||||
val = cpu_to_be64(val);
|
|
||||||
r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
|
|
||||||
if (result) {
|
|
||||||
*result = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
|
|
||||||
{
|
|
||||||
address_space_stq(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
|
|
||||||
{
|
|
||||||
address_space_stq_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
|
|
||||||
{
|
|
||||||
address_space_stq_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual memory access for debug (includes writing to ROM) */
|
/* virtual memory access for debug (includes writing to ROM) */
|
||||||
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ struct FileOperations
|
|||||||
{
|
{
|
||||||
int (*parse_opts)(QemuOpts *, struct FsDriverEntry *);
|
int (*parse_opts)(QemuOpts *, struct FsDriverEntry *);
|
||||||
int (*init)(struct FsContext *);
|
int (*init)(struct FsContext *);
|
||||||
|
void (*cleanup)(struct FsContext *);
|
||||||
int (*lstat)(FsContext *, V9fsPath *, struct stat *);
|
int (*lstat)(FsContext *, V9fsPath *, struct stat *);
|
||||||
ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
|
ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
|
||||||
int (*chmod)(FsContext *, V9fsPath *, FsCred *);
|
int (*chmod)(FsContext *, V9fsPath *, FsCred *);
|
||||||
|
|||||||
@@ -649,6 +649,14 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_cleanup(FsContext *ctx)
|
||||||
|
{
|
||||||
|
struct handle_data *data = ctx->private;
|
||||||
|
|
||||||
|
close(data->mountfd);
|
||||||
|
g_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
|
static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
|
||||||
{
|
{
|
||||||
const char *sec_model = qemu_opt_get(opts, "security_model");
|
const char *sec_model = qemu_opt_get(opts, "security_model");
|
||||||
@@ -671,6 +679,7 @@ static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
|
|||||||
FileOperations handle_ops = {
|
FileOperations handle_ops = {
|
||||||
.parse_opts = handle_parse_opts,
|
.parse_opts = handle_parse_opts,
|
||||||
.init = handle_init,
|
.init = handle_init,
|
||||||
|
.cleanup = handle_cleanup,
|
||||||
.lstat = handle_lstat,
|
.lstat = handle_lstat,
|
||||||
.readlink = handle_readlink,
|
.readlink = handle_readlink,
|
||||||
.close = handle_close,
|
.close = handle_close,
|
||||||
|
|||||||
@@ -1168,9 +1168,22 @@ static int proxy_init(FsContext *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void proxy_cleanup(FsContext *ctx)
|
||||||
|
{
|
||||||
|
V9fsProxy *proxy = ctx->private;
|
||||||
|
|
||||||
|
g_free(proxy->out_iovec.iov_base);
|
||||||
|
g_free(proxy->in_iovec.iov_base);
|
||||||
|
if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
|
||||||
|
close(proxy->sockfd);
|
||||||
|
}
|
||||||
|
g_free(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
FileOperations proxy_ops = {
|
FileOperations proxy_ops = {
|
||||||
.parse_opts = proxy_parse_opts,
|
.parse_opts = proxy_parse_opts,
|
||||||
.init = proxy_init,
|
.init = proxy_init,
|
||||||
|
.cleanup = proxy_cleanup,
|
||||||
.lstat = proxy_lstat,
|
.lstat = proxy_lstat,
|
||||||
.readlink = proxy_readlink,
|
.readlink = proxy_readlink,
|
||||||
.close = proxy_close,
|
.close = proxy_close,
|
||||||
|
|||||||
86
hw/9pfs/9p.c
86
hw/9pfs/9p.c
@@ -47,7 +47,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = virtio_pdu_vmarshal(pdu, offset, fmt, ap);
|
ret = pdu->s->transport->pdu_vmarshal(pdu, offset, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -59,7 +59,7 @@ ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = virtio_pdu_vunmarshal(pdu, offset, fmt, ap);
|
ret = pdu->s->transport->pdu_vunmarshal(pdu, offset, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -67,7 +67,7 @@ ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
|
|||||||
|
|
||||||
static void pdu_push_and_notify(V9fsPDU *pdu)
|
static void pdu_push_and_notify(V9fsPDU *pdu)
|
||||||
{
|
{
|
||||||
virtio_9p_push_and_notify(pdu);
|
pdu->s->transport->push_and_notify(pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omode_to_uflags(int8_t mode)
|
static int omode_to_uflags(int8_t mode)
|
||||||
@@ -1633,14 +1633,43 @@ out_nofid:
|
|||||||
pdu_complete(pdu, err);
|
pdu_complete(pdu, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a QEMUIOVector for a sub-region of PDU iovecs
|
||||||
|
*
|
||||||
|
* @qiov: uninitialized QEMUIOVector
|
||||||
|
* @skip: number of bytes to skip from beginning of PDU
|
||||||
|
* @size: number of bytes to include
|
||||||
|
* @is_write: true - write, false - read
|
||||||
|
*
|
||||||
|
* The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
|
||||||
|
* with qemu_iovec_destroy().
|
||||||
|
*/
|
||||||
|
static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
|
||||||
|
size_t skip, size_t size,
|
||||||
|
bool is_write)
|
||||||
|
{
|
||||||
|
QEMUIOVector elem;
|
||||||
|
struct iovec *iov;
|
||||||
|
unsigned int niov;
|
||||||
|
|
||||||
|
if (is_write) {
|
||||||
|
pdu->s->transport->init_out_iov_from_pdu(pdu, &iov, &niov);
|
||||||
|
} else {
|
||||||
|
pdu->s->transport->init_in_iov_from_pdu(pdu, &iov, &niov, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_iovec_init_external(&elem, iov, niov);
|
||||||
|
qemu_iovec_init(qiov, niov);
|
||||||
|
qemu_iovec_concat(qiov, &elem, skip, size);
|
||||||
|
}
|
||||||
|
|
||||||
static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
|
static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
|
||||||
uint64_t off, uint32_t max_count)
|
uint64_t off, uint32_t max_count)
|
||||||
{
|
{
|
||||||
ssize_t err;
|
ssize_t err;
|
||||||
size_t offset = 7;
|
size_t offset = 7;
|
||||||
uint64_t read_count;
|
uint64_t read_count;
|
||||||
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
QEMUIOVector qiov_full;
|
||||||
VirtQueueElement *elem = v->elems[pdu->idx];
|
|
||||||
|
|
||||||
if (fidp->fs.xattr.len < off) {
|
if (fidp->fs.xattr.len < off) {
|
||||||
read_count = 0;
|
read_count = 0;
|
||||||
@@ -1656,9 +1685,11 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
|
|||||||
}
|
}
|
||||||
offset += err;
|
offset += err;
|
||||||
|
|
||||||
err = v9fs_pack(elem->in_sg, elem->in_num, offset,
|
v9fs_init_qiov_from_pdu(&qiov_full, pdu, 0, read_count, false);
|
||||||
|
err = v9fs_pack(qiov_full.iov, qiov_full.niov, offset,
|
||||||
((char *)fidp->fs.xattr.value) + off,
|
((char *)fidp->fs.xattr.value) + off,
|
||||||
read_count);
|
read_count);
|
||||||
|
qemu_iovec_destroy(&qiov_full);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1732,32 +1763,6 @@ static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu,
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a QEMUIOVector for a sub-region of PDU iovecs
|
|
||||||
*
|
|
||||||
* @qiov: uninitialized QEMUIOVector
|
|
||||||
* @skip: number of bytes to skip from beginning of PDU
|
|
||||||
* @size: number of bytes to include
|
|
||||||
* @is_write: true - write, false - read
|
|
||||||
*
|
|
||||||
* The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
|
|
||||||
* with qemu_iovec_destroy().
|
|
||||||
*/
|
|
||||||
static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
|
|
||||||
size_t skip, size_t size,
|
|
||||||
bool is_write)
|
|
||||||
{
|
|
||||||
QEMUIOVector elem;
|
|
||||||
struct iovec *iov;
|
|
||||||
unsigned int niov;
|
|
||||||
|
|
||||||
virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write);
|
|
||||||
|
|
||||||
qemu_iovec_init_external(&elem, iov, niov);
|
|
||||||
qemu_iovec_init(qiov, niov);
|
|
||||||
qemu_iovec_concat(qiov, &elem, skip, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void coroutine_fn v9fs_read(void *opaque)
|
static void coroutine_fn v9fs_read(void *opaque)
|
||||||
{
|
{
|
||||||
int32_t fid;
|
int32_t fid;
|
||||||
@@ -3440,7 +3445,6 @@ void pdu_submit(V9fsPDU *pdu)
|
|||||||
/* Returns 0 on success, 1 on failure. */
|
/* Returns 0 on success, 1 on failure. */
|
||||||
int v9fs_device_realize_common(V9fsState *s, Error **errp)
|
int v9fs_device_realize_common(V9fsState *s, Error **errp)
|
||||||
{
|
{
|
||||||
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
|
||||||
int i, len;
|
int i, len;
|
||||||
struct stat stat;
|
struct stat stat;
|
||||||
FsDriverEntry *fse;
|
FsDriverEntry *fse;
|
||||||
@@ -3451,9 +3455,9 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
|
|||||||
QLIST_INIT(&s->free_list);
|
QLIST_INIT(&s->free_list);
|
||||||
QLIST_INIT(&s->active_list);
|
QLIST_INIT(&s->active_list);
|
||||||
for (i = 0; i < (MAX_REQ - 1); i++) {
|
for (i = 0; i < (MAX_REQ - 1); i++) {
|
||||||
QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next);
|
QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
|
||||||
v->pdus[i].s = s;
|
s->pdus[i].s = s;
|
||||||
v->pdus[i].idx = i;
|
s->pdus[i].idx = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
v9fs_path_init(&path);
|
v9fs_path_init(&path);
|
||||||
@@ -3521,8 +3525,11 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
if (rc) {
|
if (rc) {
|
||||||
g_free(s->ctx.fs_root);
|
if (s->ops && s->ops->cleanup && s->ctx.private) {
|
||||||
|
s->ops->cleanup(&s->ctx);
|
||||||
|
}
|
||||||
g_free(s->tag);
|
g_free(s->tag);
|
||||||
|
g_free(s->ctx.fs_root);
|
||||||
v9fs_path_free(&path);
|
v9fs_path_free(&path);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3530,8 +3537,11 @@ out:
|
|||||||
|
|
||||||
void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
|
void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
|
||||||
{
|
{
|
||||||
g_free(s->ctx.fs_root);
|
if (s->ops->cleanup) {
|
||||||
|
s->ops->cleanup(&s->ctx);
|
||||||
|
}
|
||||||
g_free(s->tag);
|
g_free(s->tag);
|
||||||
|
g_free(s->ctx.fs_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct VirtfsCoResetData {
|
typedef struct VirtfsCoResetData {
|
||||||
|
|||||||
26
hw/9pfs/9p.h
26
hw/9pfs/9p.h
@@ -99,8 +99,8 @@ enum p9_proto_version {
|
|||||||
V9FS_PROTO_2000L = 0x02,
|
V9FS_PROTO_2000L = 0x02,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define P9_NOTAG (u16)(~0)
|
#define P9_NOTAG UINT16_MAX
|
||||||
#define P9_NOFID (u32)(~0)
|
#define P9_NOFID UINT32_MAX
|
||||||
#define P9_MAXWELEM 16
|
#define P9_MAXWELEM 16
|
||||||
|
|
||||||
#define FID_REFERENCED 0x1
|
#define FID_REFERENCED 0x1
|
||||||
@@ -229,6 +229,8 @@ typedef struct V9fsState
|
|||||||
char *tag;
|
char *tag;
|
||||||
enum p9_proto_version proto_version;
|
enum p9_proto_version proto_version;
|
||||||
int32_t msize;
|
int32_t msize;
|
||||||
|
V9fsPDU pdus[MAX_REQ];
|
||||||
|
const struct V9fsTransport *transport;
|
||||||
/*
|
/*
|
||||||
* lock ensuring atomic path update
|
* lock ensuring atomic path update
|
||||||
* on rename.
|
* on rename.
|
||||||
@@ -342,4 +344,24 @@ void pdu_free(V9fsPDU *pdu);
|
|||||||
void pdu_submit(V9fsPDU *pdu);
|
void pdu_submit(V9fsPDU *pdu);
|
||||||
void v9fs_reset(V9fsState *s);
|
void v9fs_reset(V9fsState *s);
|
||||||
|
|
||||||
|
struct V9fsTransport {
|
||||||
|
ssize_t (*pdu_vmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
|
||||||
|
va_list ap);
|
||||||
|
ssize_t (*pdu_vunmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
|
||||||
|
va_list ap);
|
||||||
|
void (*init_in_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
|
||||||
|
unsigned int *pniov, size_t size);
|
||||||
|
void (*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
|
||||||
|
unsigned int *pniov);
|
||||||
|
void (*push_and_notify)(V9fsPDU *pdu);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int v9fs_register_transport(V9fsState *s,
|
||||||
|
const struct V9fsTransport *t)
|
||||||
|
{
|
||||||
|
assert(!s->transport);
|
||||||
|
s->transport = t;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,7 +20,9 @@
|
|||||||
#include "hw/virtio/virtio-access.h"
|
#include "hw/virtio/virtio-access.h"
|
||||||
#include "qemu/iov.h"
|
#include "qemu/iov.h"
|
||||||
|
|
||||||
void virtio_9p_push_and_notify(V9fsPDU *pdu)
|
static const struct V9fsTransport virtio_9p_transport;
|
||||||
|
|
||||||
|
static void virtio_9p_push_and_notify(V9fsPDU *pdu)
|
||||||
{
|
{
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
||||||
@@ -126,6 +128,7 @@ static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
|
|||||||
v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag);
|
v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag);
|
||||||
virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
|
virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
|
||||||
v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
|
v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
|
||||||
|
v9fs_register_transport(s, &virtio_9p_transport);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return;
|
return;
|
||||||
@@ -148,8 +151,8 @@ static void virtio_9p_reset(VirtIODevice *vdev)
|
|||||||
v9fs_reset(&v->state);
|
v9fs_reset(&v->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset,
|
static ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset,
|
||||||
const char *fmt, va_list ap)
|
const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
||||||
@@ -158,8 +161,8 @@ ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset,
|
|||||||
return v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap);
|
return v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
|
static ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
|
||||||
const char *fmt, va_list ap)
|
const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
||||||
@@ -168,22 +171,37 @@ ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
|
|||||||
return v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap);
|
return v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
|
/* The size parameter is used by other transports. Do not drop it. */
|
||||||
unsigned int *pniov, bool is_write)
|
static void virtio_init_in_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
|
||||||
|
unsigned int *pniov, size_t size)
|
||||||
{
|
{
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
||||||
VirtQueueElement *elem = v->elems[pdu->idx];
|
VirtQueueElement *elem = v->elems[pdu->idx];
|
||||||
|
|
||||||
if (is_write) {
|
*piov = elem->in_sg;
|
||||||
*piov = elem->out_sg;
|
*pniov = elem->in_num;
|
||||||
*pniov = elem->out_num;
|
|
||||||
} else {
|
|
||||||
*piov = elem->in_sg;
|
|
||||||
*pniov = elem->in_num;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtio_init_out_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
|
||||||
|
unsigned int *pniov)
|
||||||
|
{
|
||||||
|
V9fsState *s = pdu->s;
|
||||||
|
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
||||||
|
VirtQueueElement *elem = v->elems[pdu->idx];
|
||||||
|
|
||||||
|
*piov = elem->out_sg;
|
||||||
|
*pniov = elem->out_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct V9fsTransport virtio_9p_transport = {
|
||||||
|
.pdu_vmarshal = virtio_pdu_vmarshal,
|
||||||
|
.pdu_vunmarshal = virtio_pdu_vunmarshal,
|
||||||
|
.init_in_iov_from_pdu = virtio_init_in_iov_from_pdu,
|
||||||
|
.init_out_iov_from_pdu = virtio_init_out_iov_from_pdu,
|
||||||
|
.push_and_notify = virtio_9p_push_and_notify,
|
||||||
|
};
|
||||||
|
|
||||||
/* virtio-9p device */
|
/* virtio-9p device */
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virtio_9p = {
|
static const VMStateDescription vmstate_virtio_9p = {
|
||||||
|
|||||||
@@ -10,20 +10,10 @@ typedef struct V9fsVirtioState
|
|||||||
VirtIODevice parent_obj;
|
VirtIODevice parent_obj;
|
||||||
VirtQueue *vq;
|
VirtQueue *vq;
|
||||||
size_t config_size;
|
size_t config_size;
|
||||||
V9fsPDU pdus[MAX_REQ];
|
|
||||||
VirtQueueElement *elems[MAX_REQ];
|
VirtQueueElement *elems[MAX_REQ];
|
||||||
V9fsState state;
|
V9fsState state;
|
||||||
} V9fsVirtioState;
|
} V9fsVirtioState;
|
||||||
|
|
||||||
void virtio_9p_push_and_notify(V9fsPDU *pdu);
|
|
||||||
|
|
||||||
ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset,
|
|
||||||
const char *fmt, va_list ap);
|
|
||||||
ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
|
|
||||||
const char *fmt, va_list ap);
|
|
||||||
void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
|
|
||||||
unsigned int *pniov, bool is_write);
|
|
||||||
|
|
||||||
#define TYPE_VIRTIO_9P "virtio-9p-device"
|
#define TYPE_VIRTIO_9P "virtio-9p-device"
|
||||||
#define VIRTIO_9P(obj) \
|
#define VIRTIO_9P(obj) \
|
||||||
OBJECT_CHECK(V9fsVirtioState, (obj), TYPE_VIRTIO_9P)
|
OBJECT_CHECK(V9fsVirtioState, (obj), TYPE_VIRTIO_9P)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#ifndef HW_ALPHA_SYS_H
|
#ifndef HW_ALPHA_SYS_H
|
||||||
#define HW_ALPHA_SYS_H
|
#define HW_ALPHA_SYS_H
|
||||||
|
|
||||||
#include "target-alpha/cpu-qom.h"
|
#include "target/alpha/cpu-qom.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "hw/pci/pci_host.h"
|
#include "hw/pci/pci_host.h"
|
||||||
#include "hw/ide.h"
|
#include "hw/ide.h"
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ static void cchip_write(void *opaque, hwaddr addr,
|
|||||||
break;
|
break;
|
||||||
case 0x0240: /* DIM1 */
|
case 0x0240: /* DIM1 */
|
||||||
/* DIM: Device Interrupt Mask Register, CPU1. */
|
/* DIM: Device Interrupt Mask Register, CPU1. */
|
||||||
s->cchip.dim[0] = val;
|
s->cchip.dim[1] = val;
|
||||||
cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
|
cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,18 @@ typedef struct AspeedBoardState {
|
|||||||
typedef struct AspeedBoardConfig {
|
typedef struct AspeedBoardConfig {
|
||||||
const char *soc_name;
|
const char *soc_name;
|
||||||
uint32_t hw_strap1;
|
uint32_t hw_strap1;
|
||||||
|
const char *fmc_model;
|
||||||
|
const char *spi_model;
|
||||||
|
uint32_t num_cs;
|
||||||
} AspeedBoardConfig;
|
} AspeedBoardConfig;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PALMETTO_BMC,
|
PALMETTO_BMC,
|
||||||
AST2500_EVB,
|
AST2500_EVB,
|
||||||
|
ROMULUS_BMC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Palmetto hardware value: 0x120CE416 */
|
||||||
#define PALMETTO_BMC_HW_STRAP1 ( \
|
#define PALMETTO_BMC_HW_STRAP1 ( \
|
||||||
SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) | \
|
SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) | \
|
||||||
SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
|
SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
|
||||||
@@ -54,6 +59,7 @@ enum {
|
|||||||
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
|
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
|
||||||
SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
|
SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
|
||||||
|
|
||||||
|
/* AST2500 evb hardware value: 0xF100C2E6 */
|
||||||
#define AST2500_EVB_HW_STRAP1 (( \
|
#define AST2500_EVB_HW_STRAP1 (( \
|
||||||
AST2500_HW_STRAP1_DEFAULTS | \
|
AST2500_HW_STRAP1_DEFAULTS | \
|
||||||
SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
|
SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
|
||||||
@@ -64,9 +70,38 @@ enum {
|
|||||||
SCU_HW_STRAP_MAC0_RGMII) & \
|
SCU_HW_STRAP_MAC0_RGMII) & \
|
||||||
~SCU_HW_STRAP_2ND_BOOT_WDT)
|
~SCU_HW_STRAP_2ND_BOOT_WDT)
|
||||||
|
|
||||||
|
/* Romulus hardware value: 0xF10AD206 */
|
||||||
|
#define ROMULUS_BMC_HW_STRAP1 ( \
|
||||||
|
AST2500_HW_STRAP1_DEFAULTS | \
|
||||||
|
SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
|
||||||
|
SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
|
||||||
|
SCU_AST2500_HW_STRAP_UART_DEBUG | \
|
||||||
|
SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
|
||||||
|
SCU_AST2500_HW_STRAP_ACPI_ENABLE | \
|
||||||
|
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
|
||||||
|
|
||||||
static const AspeedBoardConfig aspeed_boards[] = {
|
static const AspeedBoardConfig aspeed_boards[] = {
|
||||||
[PALMETTO_BMC] = { "ast2400-a0", PALMETTO_BMC_HW_STRAP1 },
|
[PALMETTO_BMC] = {
|
||||||
[AST2500_EVB] = { "ast2500-a1", AST2500_EVB_HW_STRAP1 },
|
.soc_name = "ast2400-a1",
|
||||||
|
.hw_strap1 = PALMETTO_BMC_HW_STRAP1,
|
||||||
|
.fmc_model = "n25q256a",
|
||||||
|
.spi_model = "mx25l25635e",
|
||||||
|
.num_cs = 1,
|
||||||
|
},
|
||||||
|
[AST2500_EVB] = {
|
||||||
|
.soc_name = "ast2500-a1",
|
||||||
|
.hw_strap1 = AST2500_EVB_HW_STRAP1,
|
||||||
|
.fmc_model = "n25q256a",
|
||||||
|
.spi_model = "mx25l25635e",
|
||||||
|
.num_cs = 1,
|
||||||
|
},
|
||||||
|
[ROMULUS_BMC] = {
|
||||||
|
.soc_name = "ast2500-a1",
|
||||||
|
.hw_strap1 = ROMULUS_BMC_HW_STRAP1,
|
||||||
|
.fmc_model = "n25q256a",
|
||||||
|
.spi_model = "mx66l1g45g",
|
||||||
|
.num_cs = 2,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
|
static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
|
||||||
@@ -112,6 +147,8 @@ static void aspeed_board_init(MachineState *machine,
|
|||||||
&error_abort);
|
&error_abort);
|
||||||
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
|
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
|
||||||
&error_abort);
|
&error_abort);
|
||||||
|
object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
|
||||||
|
&error_abort);
|
||||||
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
|
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
|
||||||
&error_abort);
|
&error_abort);
|
||||||
|
|
||||||
@@ -128,8 +165,8 @@ static void aspeed_board_init(MachineState *machine,
|
|||||||
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
|
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
|
||||||
&error_abort);
|
&error_abort);
|
||||||
|
|
||||||
aspeed_board_init_flashes(&bmc->soc.fmc, "n25q256a", &error_abort);
|
aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
|
||||||
aspeed_board_init_flashes(&bmc->soc.spi[0], "mx25l25635e", &error_abort);
|
aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
|
||||||
|
|
||||||
aspeed_board_binfo.kernel_filename = machine->kernel_filename;
|
aspeed_board_binfo.kernel_filename = machine->kernel_filename;
|
||||||
aspeed_board_binfo.initrd_filename = machine->initrd_filename;
|
aspeed_board_binfo.initrd_filename = machine->initrd_filename;
|
||||||
@@ -188,10 +225,35 @@ static const TypeInfo ast2500_evb_type = {
|
|||||||
.class_init = ast2500_evb_class_init,
|
.class_init = ast2500_evb_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void romulus_bmc_init(MachineState *machine)
|
||||||
|
{
|
||||||
|
aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void romulus_bmc_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
|
||||||
|
mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
|
||||||
|
mc->init = romulus_bmc_init;
|
||||||
|
mc->max_cpus = 1;
|
||||||
|
mc->no_sdcard = 1;
|
||||||
|
mc->no_floppy = 1;
|
||||||
|
mc->no_cdrom = 1;
|
||||||
|
mc->no_parallel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo romulus_bmc_type = {
|
||||||
|
.name = MACHINE_TYPE_NAME("romulus-bmc"),
|
||||||
|
.parent = TYPE_MACHINE,
|
||||||
|
.class_init = romulus_bmc_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
static void aspeed_machine_init(void)
|
static void aspeed_machine_init(void)
|
||||||
{
|
{
|
||||||
type_register_static(&palmetto_bmc_type);
|
type_register_static(&palmetto_bmc_type);
|
||||||
type_register_static(&ast2500_evb_type);
|
type_register_static(&ast2500_evb_type);
|
||||||
|
type_register_static(&romulus_bmc_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(aspeed_machine_init)
|
type_init(aspeed_machine_init)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#define ASPEED_SOC_VIC_BASE 0x1E6C0000
|
#define ASPEED_SOC_VIC_BASE 0x1E6C0000
|
||||||
#define ASPEED_SOC_SDMC_BASE 0x1E6E0000
|
#define ASPEED_SOC_SDMC_BASE 0x1E6E0000
|
||||||
#define ASPEED_SOC_SCU_BASE 0x1E6E2000
|
#define ASPEED_SOC_SCU_BASE 0x1E6E2000
|
||||||
|
#define ASPEED_SOC_SRAM_BASE 0x1E720000
|
||||||
#define ASPEED_SOC_TIMER_BASE 0x1E782000
|
#define ASPEED_SOC_TIMER_BASE 0x1E782000
|
||||||
#define ASPEED_SOC_I2C_BASE 0x1E78A000
|
#define ASPEED_SOC_I2C_BASE 0x1E78A000
|
||||||
|
|
||||||
@@ -47,15 +48,47 @@ static const char *aspeed_soc_ast2500_typenames[] = {
|
|||||||
"aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
|
"aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
|
||||||
|
|
||||||
static const AspeedSoCInfo aspeed_socs[] = {
|
static const AspeedSoCInfo aspeed_socs[] = {
|
||||||
{ "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
|
{
|
||||||
1, aspeed_soc_ast2400_spi_bases,
|
.name = "ast2400-a0",
|
||||||
"aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
|
.cpu_model = "arm926",
|
||||||
{ "ast2400", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
|
.silicon_rev = AST2400_A0_SILICON_REV,
|
||||||
1, aspeed_soc_ast2400_spi_bases,
|
.sdram_base = AST2400_SDRAM_BASE,
|
||||||
"aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
|
.sram_size = 0x8000,
|
||||||
{ "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE,
|
.spis_num = 1,
|
||||||
2, aspeed_soc_ast2500_spi_bases,
|
.spi_bases = aspeed_soc_ast2400_spi_bases,
|
||||||
"aspeed.smc.ast2500-fmc", aspeed_soc_ast2500_typenames },
|
.fmc_typename = "aspeed.smc.fmc",
|
||||||
|
.spi_typename = aspeed_soc_ast2400_typenames,
|
||||||
|
}, {
|
||||||
|
.name = "ast2400-a1",
|
||||||
|
.cpu_model = "arm926",
|
||||||
|
.silicon_rev = AST2400_A1_SILICON_REV,
|
||||||
|
.sdram_base = AST2400_SDRAM_BASE,
|
||||||
|
.sram_size = 0x8000,
|
||||||
|
.spis_num = 1,
|
||||||
|
.spi_bases = aspeed_soc_ast2400_spi_bases,
|
||||||
|
.fmc_typename = "aspeed.smc.fmc",
|
||||||
|
.spi_typename = aspeed_soc_ast2400_typenames,
|
||||||
|
}, {
|
||||||
|
.name = "ast2400",
|
||||||
|
.cpu_model = "arm926",
|
||||||
|
.silicon_rev = AST2400_A0_SILICON_REV,
|
||||||
|
.sdram_base = AST2400_SDRAM_BASE,
|
||||||
|
.sram_size = 0x8000,
|
||||||
|
.spis_num = 1,
|
||||||
|
.spi_bases = aspeed_soc_ast2400_spi_bases,
|
||||||
|
.fmc_typename = "aspeed.smc.fmc",
|
||||||
|
.spi_typename = aspeed_soc_ast2400_typenames,
|
||||||
|
}, {
|
||||||
|
.name = "ast2500-a1",
|
||||||
|
.cpu_model = "arm1176",
|
||||||
|
.silicon_rev = AST2500_A1_SILICON_REV,
|
||||||
|
.sdram_base = AST2500_SDRAM_BASE,
|
||||||
|
.sram_size = 0x9000,
|
||||||
|
.spis_num = 2,
|
||||||
|
.spi_bases = aspeed_soc_ast2500_spi_bases,
|
||||||
|
.fmc_typename = "aspeed.smc.ast2500-fmc",
|
||||||
|
.spi_typename = aspeed_soc_ast2500_typenames,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -87,9 +120,13 @@ static void aspeed_soc_init(Object *obj)
|
|||||||
{
|
{
|
||||||
AspeedSoCState *s = ASPEED_SOC(obj);
|
AspeedSoCState *s = ASPEED_SOC(obj);
|
||||||
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
||||||
|
char *cpu_typename;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
s->cpu = cpu_arm_init(sc->info->cpu_model);
|
cpu_typename = g_strdup_printf("%s-" TYPE_ARM_CPU, sc->info->cpu_model);
|
||||||
|
object_initialize(&s->cpu, sizeof(s->cpu), cpu_typename);
|
||||||
|
object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
|
||||||
|
g_free(cpu_typename);
|
||||||
|
|
||||||
object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
|
object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
|
||||||
object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
|
object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
|
||||||
@@ -116,11 +153,13 @@ static void aspeed_soc_init(Object *obj)
|
|||||||
object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
|
object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
|
||||||
object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
|
object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
|
||||||
qdev_set_parent_bus(DEVICE(&s->fmc), sysbus_get_default());
|
qdev_set_parent_bus(DEVICE(&s->fmc), sysbus_get_default());
|
||||||
|
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
for (i = 0; i < sc->info->spis_num; i++) {
|
for (i = 0; i < sc->info->spis_num; i++) {
|
||||||
object_initialize(&s->spi[i], sizeof(s->spi[i]),
|
object_initialize(&s->spi[i], sizeof(s->spi[i]),
|
||||||
sc->info->spi_typename[i]);
|
sc->info->spi_typename[i]);
|
||||||
object_property_add_child(obj, "spi", OBJECT(&s->spi[i]), NULL);
|
object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL);
|
||||||
qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
|
qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +185,24 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
memory_region_add_subregion_overlap(get_system_memory(),
|
memory_region_add_subregion_overlap(get_system_memory(),
|
||||||
ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
|
ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
|
||||||
|
|
||||||
|
/* CPU */
|
||||||
|
object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SRAM */
|
||||||
|
memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
|
||||||
|
sc->info->sram_size, &err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vmstate_register_ram_global(&s->sram);
|
||||||
|
memory_region_add_subregion(get_system_memory(), ASPEED_SOC_SRAM_BASE,
|
||||||
|
&s->sram);
|
||||||
|
|
||||||
/* VIC */
|
/* VIC */
|
||||||
object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -154,9 +211,9 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
}
|
}
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
|
||||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
|
||||||
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
|
qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
|
||||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
|
||||||
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
|
qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
|
||||||
|
|
||||||
/* Timer */
|
/* Timer */
|
||||||
object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
|
||||||
@@ -195,10 +252,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
|
||||||
qdev_get_gpio_in(DEVICE(&s->vic), 12));
|
qdev_get_gpio_in(DEVICE(&s->vic), 12));
|
||||||
|
|
||||||
/* FMC */
|
/* FMC, The number of CS is set at the board level */
|
||||||
object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
|
object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err);
|
||||||
object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
|
|
||||||
error_propagate(&err, local_err);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
return;
|
return;
|
||||||
@@ -240,12 +295,6 @@ static void aspeed_soc_class_init(ObjectClass *oc, void *data)
|
|||||||
|
|
||||||
sc->info = (AspeedSoCInfo *) data;
|
sc->info = (AspeedSoCInfo *) data;
|
||||||
dc->realize = aspeed_soc_realize;
|
dc->realize = aspeed_soc_realize;
|
||||||
|
|
||||||
/*
|
|
||||||
* Reason: creates an ARM CPU, thus use after free(), see
|
|
||||||
* arm_cpu_class_init()
|
|
||||||
*/
|
|
||||||
dc->cannot_destroy_with_object_finalize_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo aspeed_soc_type_info = {
|
static const TypeInfo aspeed_soc_type_info = {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
#include <libfdt.h>
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/arm/arm.h"
|
#include "hw/arm/arm.h"
|
||||||
#include "hw/arm/linux-boot-if.h"
|
#include "hw/arm/linux-boot-if.h"
|
||||||
@@ -486,6 +487,17 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
|
|||||||
g_free(nodename);
|
g_free(nodename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
rc = fdt_path_offset(fdt, "/memory");
|
||||||
|
if (rc < 0) {
|
||||||
|
qemu_fdt_add_subnode(fdt, "/memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qemu_fdt_getprop(fdt, "/memory", "device_type", NULL, &err)) {
|
||||||
|
qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
|
||||||
|
}
|
||||||
|
|
||||||
rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
|
rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
|
||||||
acells, binfo->loader_start,
|
acells, binfo->loader_start,
|
||||||
scells, binfo->ram_size);
|
scells, binfo->ram_size);
|
||||||
@@ -495,6 +507,11 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = fdt_path_offset(fdt, "/chosen");
|
||||||
|
if (rc < 0) {
|
||||||
|
qemu_fdt_add_subnode(fdt, "/chosen");
|
||||||
|
}
|
||||||
|
|
||||||
if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
|
if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
|
||||||
rc = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
|
rc = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
|
||||||
binfo->kernel_cmdline);
|
binfo->kernel_cmdline);
|
||||||
|
|||||||
@@ -1449,17 +1449,10 @@ static const VMStateDescription vmstate_pxa2xx_i2c = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pxa2xx_i2c_slave_init(I2CSlave *i2c)
|
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
|
static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
||||||
|
|
||||||
k->init = pxa2xx_i2c_slave_init;
|
|
||||||
k->event = pxa2xx_i2c_event;
|
k->event = pxa2xx_i2c_event;
|
||||||
k->recv = pxa2xx_i2c_rx;
|
k->recv = pxa2xx_i2c_rx;
|
||||||
k->send = pxa2xx_i2c_tx;
|
k->send = pxa2xx_i2c_tx;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#define STRONGARM_H
|
#define STRONGARM_H
|
||||||
|
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
#include "target-arm/cpu-qom.h"
|
#include "target/arm/cpu-qom.h"
|
||||||
|
|
||||||
#define SA_CS0 0x00000000
|
#define SA_CS0 0x00000000
|
||||||
#define SA_CS1 0x08000000
|
#define SA_CS1 0x08000000
|
||||||
|
|||||||
@@ -202,12 +202,6 @@ static int tosa_dac_recv(I2CSlave *s)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tosa_dac_init(I2CSlave *i2c)
|
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tosa_tg_init(PXA2xxState *cpu)
|
static void tosa_tg_init(PXA2xxState *cpu)
|
||||||
{
|
{
|
||||||
I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
|
I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
|
||||||
@@ -275,7 +269,6 @@ static void tosa_dac_class_init(ObjectClass *klass, void *data)
|
|||||||
{
|
{
|
||||||
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
||||||
|
|
||||||
k->init = tosa_dac_init;
|
|
||||||
k->event = tosa_dac_event;
|
k->event = tosa_dac_event;
|
||||||
k->recv = tosa_dac_recv;
|
k->recv = tosa_dac_recv;
|
||||||
k->send = tosa_dac_send;
|
k->send = tosa_dac_send;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include "qemu/bitmap.h"
|
#include "qemu/bitmap.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
#include "target-arm/cpu.h"
|
#include "target/arm/cpu.h"
|
||||||
#include "hw/acpi/acpi-defs.h"
|
#include "hw/acpi/acpi-defs.h"
|
||||||
#include "hw/acpi/acpi.h"
|
#include "hw/acpi/acpi.h"
|
||||||
#include "hw/nvram/fw_cfg.h"
|
#include "hw/nvram/fw_cfg.h"
|
||||||
@@ -809,7 +809,7 @@ static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state,
|
|||||||
uint64_t max_size)
|
uint64_t max_size)
|
||||||
{
|
{
|
||||||
return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
|
return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
|
||||||
name, virt_acpi_build_update, build_state);
|
name, virt_acpi_build_update, build_state, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virt_acpi_build = {
|
static const VMStateDescription vmstate_virt_acpi_build = {
|
||||||
|
|||||||
@@ -1525,7 +1525,7 @@ static void machvirt_machine_init(void)
|
|||||||
}
|
}
|
||||||
type_init(machvirt_machine_init);
|
type_init(machvirt_machine_init);
|
||||||
|
|
||||||
static void virt_2_8_instance_init(Object *obj)
|
static void virt_2_9_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||||
|
|
||||||
@@ -1558,10 +1558,25 @@ static void virt_2_8_instance_init(Object *obj)
|
|||||||
"Valid values are 2, 3 and host", NULL);
|
"Valid values are 2, 3 and host", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virt_machine_2_8_options(MachineClass *mc)
|
static void virt_machine_2_9_options(MachineClass *mc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
DEFINE_VIRT_MACHINE_AS_LATEST(2, 8)
|
DEFINE_VIRT_MACHINE_AS_LATEST(2, 9)
|
||||||
|
|
||||||
|
#define VIRT_COMPAT_2_8 \
|
||||||
|
HW_COMPAT_2_8
|
||||||
|
|
||||||
|
static void virt_2_8_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
virt_2_9_instance_init(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virt_machine_2_8_options(MachineClass *mc)
|
||||||
|
{
|
||||||
|
virt_machine_2_9_options(mc);
|
||||||
|
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8);
|
||||||
|
}
|
||||||
|
DEFINE_VIRT_MACHINE(2, 8)
|
||||||
|
|
||||||
#define VIRT_COMPAT_2_7 \
|
#define VIRT_COMPAT_2_7 \
|
||||||
HW_COMPAT_2_7
|
HW_COMPAT_2_7
|
||||||
|
|||||||
@@ -263,12 +263,6 @@ static int aer915_recv(I2CSlave *slave)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aer915_init(I2CSlave *i2c)
|
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VMStateDescription vmstate_aer915_state = {
|
static VMStateDescription vmstate_aer915_state = {
|
||||||
.name = "aer915",
|
.name = "aer915",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
@@ -285,7 +279,6 @@ static void aer915_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
||||||
|
|
||||||
k->init = aer915_init;
|
|
||||||
k->event = aer915_event;
|
k->event = aer915_event;
|
||||||
k->recv = aer915_recv;
|
k->recv = aer915_recv;
|
||||||
k->send = aer915_send;
|
k->send = aer915_send;
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ typedef struct {
|
|||||||
unsigned int play_pos;
|
unsigned int play_pos;
|
||||||
uint8_t data_on;
|
uint8_t data_on;
|
||||||
uint8_t dummy_refresh_clock;
|
uint8_t dummy_refresh_clock;
|
||||||
|
bool migrate;
|
||||||
} PCSpkState;
|
} PCSpkState;
|
||||||
|
|
||||||
static const char *s_spk = "pcspk";
|
static const char *s_spk = "pcspk";
|
||||||
@@ -187,11 +188,19 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
|
|||||||
pcspk_state = s;
|
pcspk_state = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool migrate_needed(void *opaque)
|
||||||
|
{
|
||||||
|
PCSpkState *s = opaque;
|
||||||
|
|
||||||
|
return s->migrate;
|
||||||
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_spk = {
|
static const VMStateDescription vmstate_spk = {
|
||||||
.name = "pcspk",
|
.name = "pcspk",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
.minimum_version_id_old = 1,
|
||||||
|
.needed = migrate_needed,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(data_on, PCSpkState),
|
VMSTATE_UINT8(data_on, PCSpkState),
|
||||||
VMSTATE_UINT8(dummy_refresh_clock, PCSpkState),
|
VMSTATE_UINT8(dummy_refresh_clock, PCSpkState),
|
||||||
@@ -201,6 +210,7 @@ static const VMStateDescription vmstate_spk = {
|
|||||||
|
|
||||||
static Property pcspk_properties[] = {
|
static Property pcspk_properties[] = {
|
||||||
DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1),
|
DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1),
|
||||||
|
DEFINE_PROP_BOOL("migrate", PCSpkState, migrate, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,7 @@ static const FlashPartInfo known_devices[] = {
|
|||||||
{ INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) },
|
{ INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) },
|
||||||
{ INFO("mx66u51235f", 0xc2253a, 0, 64 << 10, 1024, ER_4K | ER_32K) },
|
{ INFO("mx66u51235f", 0xc2253a, 0, 64 << 10, 1024, ER_4K | ER_32K) },
|
||||||
{ INFO("mx66u1g45g", 0xc2253b, 0, 64 << 10, 2048, ER_4K | ER_32K) },
|
{ INFO("mx66u1g45g", 0xc2253b, 0, 64 << 10, 2048, ER_4K | ER_32K) },
|
||||||
|
{ INFO("mx66l1g45g", 0xc2201b, 0, 64 << 10, 2048, ER_4K | ER_32K) },
|
||||||
|
|
||||||
/* Micron */
|
/* Micron */
|
||||||
{ INFO("n25q032a11", 0x20bb16, 0, 64 << 10, 64, ER_4K) },
|
{ INFO("n25q032a11", 0x20bb16, 0, 64 << 10, 64, ER_4K) },
|
||||||
|
|||||||
@@ -707,6 +707,19 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
|||||||
int num_devices;
|
int num_devices;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (pfl->sector_len == 0) {
|
||||||
|
error_setg(errp, "attribute \"sector-length\" not specified or zero.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pfl->nb_blocs == 0) {
|
||||||
|
error_setg(errp, "attribute \"num-blocks\" not specified or zero.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pfl->name == NULL) {
|
||||||
|
error_setg(errp, "attribute \"name\" not specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
total_len = pfl->sector_len * pfl->nb_blocs;
|
total_len = pfl->sector_len * pfl->nb_blocs;
|
||||||
|
|
||||||
/* These are only used to expose the parameters of each device
|
/* These are only used to expose the parameters of each device
|
||||||
|
|||||||
@@ -600,6 +600,19 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
|
|||||||
int ret;
|
int ret;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (pfl->sector_len == 0) {
|
||||||
|
error_setg(errp, "attribute \"sector-length\" not specified or zero.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pfl->nb_blocs == 0) {
|
||||||
|
error_setg(errp, "attribute \"num-blocks\" not specified or zero.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pfl->name == NULL) {
|
||||||
|
error_setg(errp, "attribute \"name\" not specified.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
chip_len = pfl->sector_len * pfl->nb_blocs;
|
chip_len = pfl->sector_len * pfl->nb_blocs;
|
||||||
/* XXX: to be fixed */
|
/* XXX: to be fixed */
|
||||||
#if 0
|
#if 0
|
||||||
|
|||||||
@@ -588,13 +588,19 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
|
|||||||
|
|
||||||
blk_io_plug(s->blk);
|
blk_io_plug(s->blk);
|
||||||
|
|
||||||
while ((req = virtio_blk_get_request(s, vq))) {
|
do {
|
||||||
if (virtio_blk_handle_request(req, &mrb)) {
|
virtio_queue_set_notification(vq, 0);
|
||||||
virtqueue_detach_element(req->vq, &req->elem, 0);
|
|
||||||
virtio_blk_free_request(req);
|
while ((req = virtio_blk_get_request(s, vq))) {
|
||||||
break;
|
if (virtio_blk_handle_request(req, &mrb)) {
|
||||||
|
virtqueue_detach_element(req->vq, &req->elem, 0);
|
||||||
|
virtio_blk_free_request(req);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
virtio_queue_set_notification(vq, 1);
|
||||||
|
} while (!virtio_queue_empty(vq));
|
||||||
|
|
||||||
if (mrb.num_reqs) {
|
if (mrb.num_reqs) {
|
||||||
virtio_blk_submit_multireq(s->blk, &mrb);
|
virtio_blk_submit_multireq(s->blk, &mrb);
|
||||||
|
|||||||
@@ -660,6 +660,38 @@ static void qemu_aio_complete(void *opaque, int ret)
|
|||||||
qemu_bh_schedule(ioreq->blkdev->bh);
|
qemu_bh_schedule(ioreq->blkdev->bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number,
|
||||||
|
uint64_t nr_sectors)
|
||||||
|
{
|
||||||
|
struct XenBlkDev *blkdev = ioreq->blkdev;
|
||||||
|
int64_t byte_offset;
|
||||||
|
int byte_chunk;
|
||||||
|
uint64_t byte_remaining, limit;
|
||||||
|
uint64_t sec_start = sector_number;
|
||||||
|
uint64_t sec_count = nr_sectors;
|
||||||
|
|
||||||
|
/* Wrap around, or overflowing byte limit? */
|
||||||
|
if (sec_start + sec_count < sec_count ||
|
||||||
|
sec_start + sec_count > INT64_MAX >> BDRV_SECTOR_BITS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
limit = BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS;
|
||||||
|
byte_offset = sec_start << BDRV_SECTOR_BITS;
|
||||||
|
byte_remaining = sec_count << BDRV_SECTOR_BITS;
|
||||||
|
|
||||||
|
do {
|
||||||
|
byte_chunk = byte_remaining > limit ? limit : byte_remaining;
|
||||||
|
ioreq->aio_inflight++;
|
||||||
|
blk_aio_pdiscard(blkdev->blk, byte_offset, byte_chunk,
|
||||||
|
qemu_aio_complete, ioreq);
|
||||||
|
byte_remaining -= byte_chunk;
|
||||||
|
byte_offset += byte_chunk;
|
||||||
|
} while (byte_remaining > 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
||||||
{
|
{
|
||||||
struct XenBlkDev *blkdev = ioreq->blkdev;
|
struct XenBlkDev *blkdev = ioreq->blkdev;
|
||||||
@@ -708,12 +740,10 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
|||||||
break;
|
break;
|
||||||
case BLKIF_OP_DISCARD:
|
case BLKIF_OP_DISCARD:
|
||||||
{
|
{
|
||||||
struct blkif_request_discard *discard_req = (void *)&ioreq->req;
|
struct blkif_request_discard *req = (void *)&ioreq->req;
|
||||||
ioreq->aio_inflight++;
|
if (!blk_split_discard(ioreq, req->sector_number, req->nr_sectors)) {
|
||||||
blk_aio_pdiscard(blkdev->blk,
|
goto err;
|
||||||
discard_req->sector_number << BDRV_SECTOR_BITS,
|
}
|
||||||
discard_req->nr_sectors << BDRV_SECTOR_BITS,
|
|
||||||
qemu_aio_complete, ioreq);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -138,9 +138,10 @@ static void fifo_trigger_update(void *opaque)
|
|||||||
{
|
{
|
||||||
CadenceUARTState *s = opaque;
|
CadenceUARTState *s = opaque;
|
||||||
|
|
||||||
s->r[R_CISR] |= UART_INTR_TIMEOUT;
|
if (s->r[R_RTOR]) {
|
||||||
|
s->r[R_CISR] |= UART_INTR_TIMEOUT;
|
||||||
uart_update_status(s);
|
uart_update_status(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uart_rx_reset(CadenceUARTState *s)
|
static void uart_rx_reset(CadenceUARTState *s)
|
||||||
@@ -502,6 +503,13 @@ static int cadence_uart_post_load(void *opaque, int version_id)
|
|||||||
{
|
{
|
||||||
CadenceUARTState *s = opaque;
|
CadenceUARTState *s = opaque;
|
||||||
|
|
||||||
|
/* Ensure these two aren't invalid numbers */
|
||||||
|
if (s->r[R_BRGR] < 1 || s->r[R_BRGR] & ~0xFFFF ||
|
||||||
|
s->r[R_BDIV] <= 3 || s->r[R_BDIV] & ~0xFF) {
|
||||||
|
/* Value is invalid, abort */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
uart_parameters_setup(s);
|
uart_parameters_setup(s);
|
||||||
uart_update_status(s);
|
uart_update_status(s);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ static int vty_can_receive(void *opaque)
|
|||||||
{
|
{
|
||||||
VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
|
VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
|
||||||
|
|
||||||
return (dev->in - dev->out) < VTERM_BUFSIZE;
|
return VTERM_BUFSIZE - (dev->in - dev->out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vty_receive(void *opaque, const uint8_t *buf, int size)
|
static void vty_receive(void *opaque, const uint8_t *buf, int size)
|
||||||
|
|||||||
@@ -93,7 +93,12 @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
|
|||||||
"image");
|
"image");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s->set_pc = true;
|
/* The user specified a file, only set the PC if they also specified
|
||||||
|
* a CPU to use.
|
||||||
|
*/
|
||||||
|
if (s->cpu_num != CPU_NONE) {
|
||||||
|
s->set_pc = true;
|
||||||
|
}
|
||||||
} else if (s->addr) {
|
} else if (s->addr) {
|
||||||
/* User is setting the PC */
|
/* User is setting the PC */
|
||||||
if (s->data || s->data_len || s->data_be) {
|
if (s->data || s->data_len || s->data_be) {
|
||||||
|
|||||||
@@ -818,7 +818,7 @@ static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
|
|||||||
|
|
||||||
static inline bool rom_order_compare(Rom *rom, Rom *item)
|
static inline bool rom_order_compare(Rom *rom, Rom *item)
|
||||||
{
|
{
|
||||||
return (rom->as > item->as) ||
|
return ((uintptr_t)(void *)rom->as > (uintptr_t)(void *)item->as) ||
|
||||||
(rom->as == item->as && rom->addr >= item->addr);
|
(rom->as == item->as && rom->addr >= item->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,7 +978,8 @@ err:
|
|||||||
|
|
||||||
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
|
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||||
size_t max_len, hwaddr addr, const char *fw_file_name,
|
size_t max_len, hwaddr addr, const char *fw_file_name,
|
||||||
FWCfgReadCallback fw_callback, void *callback_opaque)
|
FWCfgReadCallback fw_callback, void *callback_opaque,
|
||||||
|
AddressSpace *as)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||||
Rom *rom;
|
Rom *rom;
|
||||||
@@ -986,6 +987,7 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
|
|||||||
|
|
||||||
rom = g_malloc0(sizeof(*rom));
|
rom = g_malloc0(sizeof(*rom));
|
||||||
rom->name = g_strdup(name);
|
rom->name = g_strdup(name);
|
||||||
|
rom->as = as;
|
||||||
rom->addr = addr;
|
rom->addr = addr;
|
||||||
rom->romsize = max_len ? max_len : len;
|
rom->romsize = max_len ? max_len : len;
|
||||||
rom->datasize = len;
|
rom->datasize = len;
|
||||||
|
|||||||
@@ -272,6 +272,9 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
|
|||||||
static bool blit_region_is_unsafe(struct CirrusVGAState *s,
|
static bool blit_region_is_unsafe(struct CirrusVGAState *s,
|
||||||
int32_t pitch, int32_t addr)
|
int32_t pitch, int32_t addr)
|
||||||
{
|
{
|
||||||
|
if (!pitch) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (pitch < 0) {
|
if (pitch < 0) {
|
||||||
int64_t min = addr
|
int64_t min = addr
|
||||||
+ ((int64_t)s->cirrus_blt_height-1) * pitch;
|
+ ((int64_t)s->cirrus_blt_height-1) * pitch;
|
||||||
@@ -715,7 +718,7 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
|||||||
s->cirrus_addr_mask));
|
s->cirrus_addr_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
||||||
{
|
{
|
||||||
int sx = 0, sy = 0;
|
int sx = 0, sy = 0;
|
||||||
int dx = 0, dy = 0;
|
int dx = 0, dy = 0;
|
||||||
@@ -729,6 +732,9 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
|||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
depth = s->vga.get_bpp(&s->vga) / 8;
|
depth = s->vga.get_bpp(&s->vga) / 8;
|
||||||
|
if (!depth) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
s->vga.get_resolution(&s->vga, &width, &height);
|
s->vga.get_resolution(&s->vga, &width, &height);
|
||||||
|
|
||||||
/* extra x, y */
|
/* extra x, y */
|
||||||
@@ -783,6 +789,8 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
|||||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
||||||
s->cirrus_blt_dstpitch, s->cirrus_blt_width,
|
s->cirrus_blt_dstpitch, s->cirrus_blt_width,
|
||||||
s->cirrus_blt_height);
|
s->cirrus_blt_height);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
|
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
|
||||||
@@ -790,11 +798,9 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
|
|||||||
if (blit_is_unsafe(s))
|
if (blit_is_unsafe(s))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
|
return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
|
||||||
s->cirrus_blt_srcaddr - s->vga.start_addr,
|
s->cirrus_blt_srcaddr - s->vga.start_addr,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
|||||||
@@ -992,6 +992,34 @@ static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
|
|||||||
return crc32(0xffffffff, p, len) ^ 0xffffffff;
|
return crc32(0xffffffff, p, len) ^ 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool qxl_rom_monitors_config_changed(QXLRom *rom,
|
||||||
|
VDAgentMonitorsConfig *monitors_config,
|
||||||
|
unsigned int max_outputs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned int monitors_count;
|
||||||
|
|
||||||
|
monitors_count = MIN(monitors_config->num_of_monitors, max_outputs);
|
||||||
|
|
||||||
|
if (rom->client_monitors_config.count != monitors_count) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {
|
||||||
|
VDAgentMonConfig *monitor = &monitors_config->monitors[i];
|
||||||
|
QXLURect *rect = &rom->client_monitors_config.heads[i];
|
||||||
|
/* monitor->depth ignored */
|
||||||
|
if ((rect->left != monitor->x) ||
|
||||||
|
(rect->top != monitor->y) ||
|
||||||
|
(rect->right != monitor->x + monitor->width) ||
|
||||||
|
(rect->bottom != monitor->y + monitor->height)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* called from main context only */
|
/* called from main context only */
|
||||||
static int interface_client_monitors_config(QXLInstance *sin,
|
static int interface_client_monitors_config(QXLInstance *sin,
|
||||||
VDAgentMonitorsConfig *monitors_config)
|
VDAgentMonitorsConfig *monitors_config)
|
||||||
@@ -1000,6 +1028,7 @@ static int interface_client_monitors_config(QXLInstance *sin,
|
|||||||
QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
|
QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);
|
||||||
int i;
|
int i;
|
||||||
unsigned max_outputs = ARRAY_SIZE(rom->client_monitors_config.heads);
|
unsigned max_outputs = ARRAY_SIZE(rom->client_monitors_config.heads);
|
||||||
|
bool config_changed = false;
|
||||||
|
|
||||||
if (qxl->revision < 4) {
|
if (qxl->revision < 4) {
|
||||||
trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,
|
trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,
|
||||||
@@ -1030,6 +1059,10 @@ static int interface_client_monitors_config(QXLInstance *sin,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
config_changed = qxl_rom_monitors_config_changed(rom,
|
||||||
|
monitors_config,
|
||||||
|
max_outputs);
|
||||||
|
|
||||||
memset(&rom->client_monitors_config, 0,
|
memset(&rom->client_monitors_config, 0,
|
||||||
sizeof(rom->client_monitors_config));
|
sizeof(rom->client_monitors_config));
|
||||||
rom->client_monitors_config.count = monitors_config->num_of_monitors;
|
rom->client_monitors_config.count = monitors_config->num_of_monitors;
|
||||||
@@ -1059,7 +1092,9 @@ static int interface_client_monitors_config(QXLInstance *sin,
|
|||||||
trace_qxl_interrupt_client_monitors_config(qxl->id,
|
trace_qxl_interrupt_client_monitors_config(qxl->id,
|
||||||
rom->client_monitors_config.count,
|
rom->client_monitors_config.count,
|
||||||
rom->client_monitors_config.heads);
|
rom->client_monitors_config.heads);
|
||||||
qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
|
if (config_changed) {
|
||||||
|
qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -291,8 +291,11 @@ static void virgl_resource_attach_backing(VirtIOGPU *g,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virgl_renderer_resource_attach_iov(att_rb.resource_id,
|
ret = virgl_renderer_resource_attach_iov(att_rb.resource_id,
|
||||||
res_iovs, att_rb.nr_entries);
|
res_iovs, att_rb.nr_entries);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
virtio_gpu_cleanup_mapping_iov(res_iovs, att_rb.nr_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virgl_resource_detach_backing(VirtIOGPU *g,
|
static void virgl_resource_detach_backing(VirtIOGPU *g,
|
||||||
@@ -347,6 +350,7 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
|
|||||||
|
|
||||||
VIRTIO_GPU_FILL_CMD(info);
|
VIRTIO_GPU_FILL_CMD(info);
|
||||||
|
|
||||||
|
memset(&resp, 0, sizeof(resp));
|
||||||
if (info.capset_index == 0) {
|
if (info.capset_index == 0) {
|
||||||
resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
|
resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
|
||||||
virgl_renderer_get_cap_set(resp.capset_id,
|
virgl_renderer_get_cap_set(resp.capset_id,
|
||||||
@@ -370,8 +374,12 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
|
|||||||
|
|
||||||
virgl_renderer_get_cap_set(gc.capset_id, &max_ver,
|
virgl_renderer_get_cap_set(gc.capset_id, &max_ver,
|
||||||
&max_size);
|
&max_size);
|
||||||
resp = g_malloc(sizeof(*resp) + max_size);
|
if (!max_size) {
|
||||||
|
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = g_malloc(sizeof(*resp) + max_size);
|
||||||
resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET;
|
resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET;
|
||||||
virgl_renderer_fill_caps(gc.capset_id,
|
virgl_renderer_fill_caps(gc.capset_id,
|
||||||
gc.capset_version,
|
gc.capset_version,
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
static struct virtio_gpu_simple_resource*
|
static struct virtio_gpu_simple_resource*
|
||||||
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
|
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
|
||||||
|
|
||||||
|
static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res);
|
||||||
|
|
||||||
#ifdef CONFIG_VIRGL
|
#ifdef CONFIG_VIRGL
|
||||||
#include <virglrenderer.h>
|
#include <virglrenderer.h>
|
||||||
#define VIRGL(_g, _virgl, _simple, ...) \
|
#define VIRGL(_g, _virgl, _simple, ...) \
|
||||||
@@ -84,6 +86,7 @@ static void update_cursor_data_virgl(VirtIOGPU *g,
|
|||||||
|
|
||||||
if (width != s->current_cursor->width ||
|
if (width != s->current_cursor->width ||
|
||||||
height != s->current_cursor->height) {
|
height != s->current_cursor->height) {
|
||||||
|
free(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,10 +340,14 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
|
|||||||
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
|
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
res->image = pixman_image_create_bits(pformat,
|
|
||||||
c2d.width,
|
res->hostmem = PIXMAN_FORMAT_BPP(pformat) * c2d.width * c2d.height;
|
||||||
c2d.height,
|
if (res->hostmem + g->hostmem < g->conf.max_hostmem) {
|
||||||
NULL, 0);
|
res->image = pixman_image_create_bits(pformat,
|
||||||
|
c2d.width,
|
||||||
|
c2d.height,
|
||||||
|
NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!res->image) {
|
if (!res->image) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
@@ -352,13 +359,16 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
|
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
|
||||||
|
g->hostmem += res->hostmem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_gpu_resource_destroy(VirtIOGPU *g,
|
static void virtio_gpu_resource_destroy(VirtIOGPU *g,
|
||||||
struct virtio_gpu_simple_resource *res)
|
struct virtio_gpu_simple_resource *res)
|
||||||
{
|
{
|
||||||
pixman_image_unref(res->image);
|
pixman_image_unref(res->image);
|
||||||
|
virtio_gpu_cleanup_mapping(res);
|
||||||
QTAILQ_REMOVE(&g->reslist, res, next);
|
QTAILQ_REMOVE(&g->reslist, res, next);
|
||||||
|
g->hostmem -= res->hostmem;
|
||||||
g_free(res);
|
g_free(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,6 +714,11 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res->iov) {
|
||||||
|
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov);
|
ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
@@ -1240,6 +1255,8 @@ static const VMStateDescription vmstate_virtio_gpu = {
|
|||||||
|
|
||||||
static Property virtio_gpu_properties[] = {
|
static Property virtio_gpu_properties[] = {
|
||||||
DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1),
|
DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1),
|
||||||
|
DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf.max_hostmem,
|
||||||
|
256 * 1024 * 1024),
|
||||||
#ifdef CONFIG_VIRGL
|
#ifdef CONFIG_VIRGL
|
||||||
DEFINE_PROP_BIT("virgl", VirtIOGPU, conf.flags,
|
DEFINE_PROP_BIT("virgl", VirtIOGPU, conf.flags,
|
||||||
VIRTIO_GPU_FLAG_VIRGL_ENABLED, true),
|
VIRTIO_GPU_FLAG_VIRGL_ENABLED, true),
|
||||||
|
|||||||
@@ -260,7 +260,11 @@ static int i2c_slave_qdev_init(DeviceState *dev)
|
|||||||
I2CSlave *s = I2C_SLAVE(dev);
|
I2CSlave *s = I2C_SLAVE(dev);
|
||||||
I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(s);
|
I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(s);
|
||||||
|
|
||||||
return sc->init(s);
|
if (sc->init) {
|
||||||
|
return sc->init(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
|
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
#include "target-i386/cpu.h"
|
#include "target/i386/cpu.h"
|
||||||
#include "hw/timer/hpet.h"
|
#include "hw/timer/hpet.h"
|
||||||
#include "hw/acpi/acpi-defs.h"
|
#include "hw/acpi/acpi-defs.h"
|
||||||
#include "hw/acpi/acpi.h"
|
#include "hw/acpi/acpi.h"
|
||||||
@@ -2936,7 +2936,7 @@ static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state,
|
|||||||
uint64_t max_size)
|
uint64_t max_size)
|
||||||
{
|
{
|
||||||
return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
|
return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
|
||||||
name, acpi_build_update, build_state);
|
name, acpi_build_update, build_state, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_acpi_build = {
|
static const VMStateDescription vmstate_acpi_build = {
|
||||||
|
|||||||
@@ -988,6 +988,7 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
|
|||||||
mask = 7; /* Mask bit 2:0 in the SID field */
|
mask = 7; /* Mask bit 2:0 in the SID field */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mask = ~mask;
|
||||||
VTD_DPRINTF(INV, "device-selective invalidation source 0x%"PRIx16
|
VTD_DPRINTF(INV, "device-selective invalidation source 0x%"PRIx16
|
||||||
" mask %"PRIu16, source_id, mask);
|
" mask %"PRIu16, source_id, mask);
|
||||||
vtd_bus = vtd_find_as_from_bus_num(s, VTD_SID_TO_BUS(source_id));
|
vtd_bus = vtd_find_as_from_bus_num(s, VTD_SID_TO_BUS(source_id));
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "hw/i386/apic_internal.h"
|
#include "hw/i386/apic_internal.h"
|
||||||
#include "hw/pci/msi.h"
|
#include "hw/pci/msi.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "target-i386/kvm_i386.h"
|
#include "target/i386/kvm_i386.h"
|
||||||
|
|
||||||
static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic,
|
static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic,
|
||||||
int reg_id, uint32_t val)
|
int reg_id, uint32_t val)
|
||||||
|
|||||||
@@ -36,6 +36,13 @@ typedef struct KVMClockState {
|
|||||||
|
|
||||||
uint64_t clock;
|
uint64_t clock;
|
||||||
bool clock_valid;
|
bool clock_valid;
|
||||||
|
|
||||||
|
/* whether machine type supports reliable KVM_GET_CLOCK */
|
||||||
|
bool mach_use_reliable_get_clock;
|
||||||
|
|
||||||
|
/* whether the 'clock' value was obtained in a host with
|
||||||
|
* reliable KVM_GET_CLOCK */
|
||||||
|
bool clock_is_reliable;
|
||||||
} KVMClockState;
|
} KVMClockState;
|
||||||
|
|
||||||
struct pvclock_vcpu_time_info {
|
struct pvclock_vcpu_time_info {
|
||||||
@@ -81,6 +88,60 @@ static uint64_t kvmclock_current_nsec(KVMClockState *s)
|
|||||||
return nsec + time.system_time;
|
return nsec + time.system_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kvm_update_clock(KVMClockState *s)
|
||||||
|
{
|
||||||
|
struct kvm_clock_data data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
s->clock = data.clock;
|
||||||
|
|
||||||
|
/* If kvm_has_adjust_clock_stable() is false, KVM_GET_CLOCK returns
|
||||||
|
* essentially CLOCK_MONOTONIC plus a guest-specific adjustment. This
|
||||||
|
* can drift from the TSC-based value that is computed by the guest,
|
||||||
|
* so we need to go through kvmclock_current_nsec(). If
|
||||||
|
* kvm_has_adjust_clock_stable() is true, and the flags contain
|
||||||
|
* KVM_CLOCK_TSC_STABLE, then KVM_GET_CLOCK returns a TSC-based value
|
||||||
|
* and kvmclock_current_nsec() is not necessary.
|
||||||
|
*
|
||||||
|
* Here, however, we need not check KVM_CLOCK_TSC_STABLE. This is because:
|
||||||
|
*
|
||||||
|
* - if the host has disabled the kvmclock master clock, the guest already
|
||||||
|
* has protection against time going backwards. This "safety net" is only
|
||||||
|
* absent when kvmclock is stable;
|
||||||
|
*
|
||||||
|
* - therefore, we can replace a check like
|
||||||
|
*
|
||||||
|
* if last KVM_GET_CLOCK was not reliable then
|
||||||
|
* read from memory
|
||||||
|
*
|
||||||
|
* with
|
||||||
|
*
|
||||||
|
* if last KVM_GET_CLOCK was not reliable && masterclock is enabled
|
||||||
|
* read from memory
|
||||||
|
*
|
||||||
|
* However:
|
||||||
|
*
|
||||||
|
* - if kvm_has_adjust_clock_stable() returns false, the left side is
|
||||||
|
* always true (KVM_GET_CLOCK is never reliable), and the right side is
|
||||||
|
* unknown (because we don't have data.flags). We must assume it's true
|
||||||
|
* and read from memory.
|
||||||
|
*
|
||||||
|
* - if kvm_has_adjust_clock_stable() returns true, the result of the &&
|
||||||
|
* is always false (masterclock is enabled iff KVM_GET_CLOCK is reliable)
|
||||||
|
*
|
||||||
|
* So we can just use this instead:
|
||||||
|
*
|
||||||
|
* if !kvm_has_adjust_clock_stable() then
|
||||||
|
* read from memory
|
||||||
|
*/
|
||||||
|
s->clock_is_reliable = kvm_has_adjust_clock_stable();
|
||||||
|
}
|
||||||
|
|
||||||
static void kvmclock_vm_state_change(void *opaque, int running,
|
static void kvmclock_vm_state_change(void *opaque, int running,
|
||||||
RunState state)
|
RunState state)
|
||||||
{
|
{
|
||||||
@@ -91,15 +152,21 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
|||||||
|
|
||||||
if (running) {
|
if (running) {
|
||||||
struct kvm_clock_data data = {};
|
struct kvm_clock_data data = {};
|
||||||
uint64_t time_at_migration = kvmclock_current_nsec(s);
|
|
||||||
|
/*
|
||||||
|
* If the host where s->clock was read did not support reliable
|
||||||
|
* KVM_GET_CLOCK, read kvmclock value from memory.
|
||||||
|
*/
|
||||||
|
if (!s->clock_is_reliable) {
|
||||||
|
uint64_t pvclock_via_mem = kvmclock_current_nsec(s);
|
||||||
|
/* We can't rely on the saved clock value, just discard it */
|
||||||
|
if (pvclock_via_mem) {
|
||||||
|
s->clock = pvclock_via_mem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s->clock_valid = false;
|
s->clock_valid = false;
|
||||||
|
|
||||||
/* We can't rely on the migrated clock value, just discard it */
|
|
||||||
if (time_at_migration) {
|
|
||||||
s->clock = time_at_migration;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.clock = s->clock;
|
data.clock = s->clock;
|
||||||
ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
|
ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -120,8 +187,6 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct kvm_clock_data data;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (s->clock_valid) {
|
if (s->clock_valid) {
|
||||||
return;
|
return;
|
||||||
@@ -129,13 +194,7 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
|||||||
|
|
||||||
kvm_synchronize_all_tsc();
|
kvm_synchronize_all_tsc();
|
||||||
|
|
||||||
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
|
kvm_update_clock(s);
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
s->clock = data.clock;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the VM is stopped, declare the clock state valid to
|
* If the VM is stopped, declare the clock state valid to
|
||||||
* avoid re-reading it on next vmsave (which would return
|
* avoid re-reading it on next vmsave (which would return
|
||||||
@@ -149,25 +208,78 @@ static void kvmclock_realize(DeviceState *dev, Error **errp)
|
|||||||
{
|
{
|
||||||
KVMClockState *s = KVM_CLOCK(dev);
|
KVMClockState *s = KVM_CLOCK(dev);
|
||||||
|
|
||||||
|
kvm_update_clock(s);
|
||||||
|
|
||||||
qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
|
qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool kvmclock_clock_is_reliable_needed(void *opaque)
|
||||||
|
{
|
||||||
|
KVMClockState *s = opaque;
|
||||||
|
|
||||||
|
return s->mach_use_reliable_get_clock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription kvmclock_reliable_get_clock = {
|
||||||
|
.name = "kvmclock/clock_is_reliable",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.needed = kvmclock_clock_is_reliable_needed,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_BOOL(clock_is_reliable, KVMClockState),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When migrating, read the clock just before migration,
|
||||||
|
* so that the guest clock counts during the events
|
||||||
|
* between:
|
||||||
|
*
|
||||||
|
* * vm_stop()
|
||||||
|
* *
|
||||||
|
* * pre_save()
|
||||||
|
*
|
||||||
|
* This reduces kvmclock difference on migration from 5s
|
||||||
|
* to 0.1s (when max_downtime == 5s), because sending the
|
||||||
|
* final pages of memory (which happens between vm_stop()
|
||||||
|
* and pre_save()) takes max_downtime.
|
||||||
|
*/
|
||||||
|
static void kvmclock_pre_save(void *opaque)
|
||||||
|
{
|
||||||
|
KVMClockState *s = opaque;
|
||||||
|
|
||||||
|
kvm_update_clock(s);
|
||||||
|
}
|
||||||
|
|
||||||
static const VMStateDescription kvmclock_vmsd = {
|
static const VMStateDescription kvmclock_vmsd = {
|
||||||
.name = "kvmclock",
|
.name = "kvmclock",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
|
.pre_save = kvmclock_pre_save,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT64(clock, KVMClockState),
|
VMSTATE_UINT64(clock, KVMClockState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
|
},
|
||||||
|
.subsections = (const VMStateDescription * []) {
|
||||||
|
&kvmclock_reliable_get_clock,
|
||||||
|
NULL
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property kvmclock_properties[] = {
|
||||||
|
DEFINE_PROP_BOOL("x-mach-use-reliable-get-clock", KVMClockState,
|
||||||
|
mach_use_reliable_get_clock, true),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void kvmclock_class_init(ObjectClass *klass, void *data)
|
static void kvmclock_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->realize = kvmclock_realize;
|
dc->realize = kvmclock_realize;
|
||||||
dc->vmsd = &kvmclock_vmsd;
|
dc->vmsd = &kvmclock_vmsd;
|
||||||
|
dc->props = kvmclock_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo kvmclock_info = {
|
static const TypeInfo kvmclock_info = {
|
||||||
|
|||||||
@@ -1251,6 +1251,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
|
|||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
dev->dev.cap_present |= QEMU_PCI_CAP_MSI;
|
||||||
dev->cap.available |= ASSIGNED_DEVICE_CAP_MSI;
|
dev->cap.available |= ASSIGNED_DEVICE_CAP_MSI;
|
||||||
/* Only 32-bit/no-mask currently supported */
|
/* Only 32-bit/no-mask currently supported */
|
||||||
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_MSI, pos, 10,
|
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_MSI, pos, 10,
|
||||||
@@ -1285,6 +1286,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
|
|||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
dev->dev.cap_present |= QEMU_PCI_CAP_MSIX;
|
||||||
dev->cap.available |= ASSIGNED_DEVICE_CAP_MSIX;
|
dev->cap.available |= ASSIGNED_DEVICE_CAP_MSIX;
|
||||||
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_MSIX, pos, 12,
|
ret = pci_add_capability2(pci_dev, PCI_CAP_ID_MSIX, pos, 12,
|
||||||
&local_err);
|
&local_err);
|
||||||
@@ -1648,6 +1650,7 @@ static void assigned_dev_register_msix_mmio(AssignedDevice *dev, Error **errp)
|
|||||||
dev->msix_table = NULL;
|
dev->msix_table = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
dev->dev.msix_table = (uint8_t *)dev->msix_table;
|
||||||
|
|
||||||
assigned_dev_msix_reset(dev);
|
assigned_dev_msix_reset(dev);
|
||||||
|
|
||||||
@@ -1665,6 +1668,7 @@ static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev)
|
|||||||
error_report("error unmapping msix_table! %s", strerror(errno));
|
error_report("error unmapping msix_table! %s", strerror(errno));
|
||||||
}
|
}
|
||||||
dev->msix_table = NULL;
|
dev->msix_table = NULL;
|
||||||
|
dev->dev.msix_table = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_assigned_device = {
|
static const VMStateDescription vmstate_assigned_device = {
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline)
|
|||||||
hwaddr p = s->offset_cmdlines;
|
hwaddr p = s->offset_cmdlines;
|
||||||
char *b = (char *)s->mb_buf + p;
|
char *b = (char *)s->mb_buf + p;
|
||||||
|
|
||||||
get_opt_value(b, strlen(cmdline) + 1, cmdline);
|
memcpy(b, cmdline, strlen(cmdline) + 1);
|
||||||
s->offset_cmdlines += strlen(b) + 1;
|
s->offset_cmdlines += strlen(b) + 1;
|
||||||
return s->mb_buf_phys + p;
|
return s->mb_buf_phys + p;
|
||||||
}
|
}
|
||||||
@@ -287,7 +287,8 @@ int load_multiboot(FWCfgState *fw_cfg,
|
|||||||
mbs.offset_bootloader = mbs.offset_cmdlines + cmdline_len;
|
mbs.offset_bootloader = mbs.offset_cmdlines + cmdline_len;
|
||||||
|
|
||||||
if (initrd_filename) {
|
if (initrd_filename) {
|
||||||
char *next_initrd, not_last;
|
const char *next_initrd;
|
||||||
|
char not_last, tmpbuf[strlen(initrd_filename) + 1];
|
||||||
|
|
||||||
mbs.offset_mods = mbs.mb_buf_size;
|
mbs.offset_mods = mbs.mb_buf_size;
|
||||||
|
|
||||||
@@ -296,25 +297,24 @@ int load_multiboot(FWCfgState *fw_cfg,
|
|||||||
int mb_mod_length;
|
int mb_mod_length;
|
||||||
uint32_t offs = mbs.mb_buf_size;
|
uint32_t offs = mbs.mb_buf_size;
|
||||||
|
|
||||||
next_initrd = (char *)get_opt_value(NULL, 0, initrd_filename);
|
next_initrd = get_opt_value(tmpbuf, sizeof(tmpbuf), initrd_filename);
|
||||||
not_last = *next_initrd;
|
not_last = *next_initrd;
|
||||||
*next_initrd = '\0';
|
|
||||||
/* if a space comes after the module filename, treat everything
|
/* if a space comes after the module filename, treat everything
|
||||||
after that as parameters */
|
after that as parameters */
|
||||||
hwaddr c = mb_add_cmdline(&mbs, initrd_filename);
|
hwaddr c = mb_add_cmdline(&mbs, tmpbuf);
|
||||||
if ((next_space = strchr(initrd_filename, ' ')))
|
if ((next_space = strchr(tmpbuf, ' ')))
|
||||||
*next_space = '\0';
|
*next_space = '\0';
|
||||||
mb_debug("multiboot loading module: %s\n", initrd_filename);
|
mb_debug("multiboot loading module: %s\n", tmpbuf);
|
||||||
mb_mod_length = get_image_size(initrd_filename);
|
mb_mod_length = get_image_size(tmpbuf);
|
||||||
if (mb_mod_length < 0) {
|
if (mb_mod_length < 0) {
|
||||||
fprintf(stderr, "Failed to open file '%s'\n", initrd_filename);
|
fprintf(stderr, "Failed to open file '%s'\n", tmpbuf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
|
mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
|
||||||
mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
|
mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
|
||||||
|
|
||||||
load_image(initrd_filename, (unsigned char *)mbs.mb_buf + offs);
|
load_image(tmpbuf, (unsigned char *)mbs.mb_buf + offs);
|
||||||
mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
|
mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
|
||||||
mbs.mb_buf_phys + offs + mb_mod_length, c);
|
mbs.mb_buf_phys + offs + mb_mod_length, c);
|
||||||
|
|
||||||
|
|||||||
68
hw/i386/pc.c
68
hw/i386/pc.c
@@ -400,13 +400,13 @@ static void pc_cmos_init_late(void *opaque)
|
|||||||
int i, trans;
|
int i, trans;
|
||||||
|
|
||||||
val = 0;
|
val = 0;
|
||||||
if (ide_get_geometry(arg->idebus[0], 0,
|
if (arg->idebus[0] && ide_get_geometry(arg->idebus[0], 0,
|
||||||
&cylinders, &heads, §ors) >= 0) {
|
&cylinders, &heads, §ors) >= 0) {
|
||||||
cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
|
cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
|
||||||
val |= 0xf0;
|
val |= 0xf0;
|
||||||
}
|
}
|
||||||
if (ide_get_geometry(arg->idebus[0], 1,
|
if (arg->idebus[0] && ide_get_geometry(arg->idebus[0], 1,
|
||||||
&cylinders, &heads, §ors) >= 0) {
|
&cylinders, &heads, §ors) >= 0) {
|
||||||
cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
|
cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
|
||||||
val |= 0x0f;
|
val |= 0x0f;
|
||||||
}
|
}
|
||||||
@@ -418,7 +418,8 @@ static void pc_cmos_init_late(void *opaque)
|
|||||||
geometry. It is always such that: 1 <= sects <= 63, 1
|
geometry. It is always such that: 1 <= sects <= 63, 1
|
||||||
<= heads <= 16, 1 <= cylinders <= 16383. The BIOS
|
<= heads <= 16, 1 <= cylinders <= 16383. The BIOS
|
||||||
geometry can be different if a translation is done. */
|
geometry can be different if a translation is done. */
|
||||||
if (ide_get_geometry(arg->idebus[i / 2], i % 2,
|
if (arg->idebus[i / 2] &&
|
||||||
|
ide_get_geometry(arg->idebus[i / 2], i % 2,
|
||||||
&cylinders, &heads, §ors) >= 0) {
|
&cylinders, &heads, §ors) >= 0) {
|
||||||
trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
|
trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
|
||||||
assert((trans & ~3) == 0);
|
assert((trans & ~3) == 0);
|
||||||
@@ -1535,6 +1536,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
|||||||
ISADevice **rtc_state,
|
ISADevice **rtc_state,
|
||||||
bool create_fdctrl,
|
bool create_fdctrl,
|
||||||
bool no_vmport,
|
bool no_vmport,
|
||||||
|
bool has_pit,
|
||||||
uint32_t hpet_irqs)
|
uint32_t hpet_irqs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -1588,7 +1590,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
|||||||
|
|
||||||
qemu_register_boot_set(pc_boot_set, *rtc_state);
|
qemu_register_boot_set(pc_boot_set, *rtc_state);
|
||||||
|
|
||||||
if (!xen_enabled()) {
|
if (!xen_enabled() && has_pit) {
|
||||||
if (kvm_pit_in_kernel()) {
|
if (kvm_pit_in_kernel()) {
|
||||||
pit = kvm_pit_init(isa_bus, 0x40);
|
pit = kvm_pit_init(isa_bus, 0x40);
|
||||||
} else {
|
} else {
|
||||||
@@ -2158,6 +2160,48 @@ static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp)
|
|||||||
pcms->acpi_nvdimm_state.is_enabled = value;
|
pcms->acpi_nvdimm_state.is_enabled = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pc_machine_get_smbus(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
return pcms->smbus;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pc_machine_set_smbus(Object *obj, bool value, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
pcms->smbus = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pc_machine_get_sata(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
return pcms->sata;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pc_machine_set_sata(Object *obj, bool value, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
pcms->sata = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pc_machine_get_pit(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
return pcms->pit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pc_machine_set_pit(Object *obj, bool value, Error **errp)
|
||||||
|
{
|
||||||
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
|
|
||||||
|
pcms->pit = value;
|
||||||
|
}
|
||||||
|
|
||||||
static void pc_machine_initfn(Object *obj)
|
static void pc_machine_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
PCMachineState *pcms = PC_MACHINE(obj);
|
PCMachineState *pcms = PC_MACHINE(obj);
|
||||||
@@ -2169,6 +2213,9 @@ static void pc_machine_initfn(Object *obj)
|
|||||||
pcms->acpi_nvdimm_state.is_enabled = false;
|
pcms->acpi_nvdimm_state.is_enabled = false;
|
||||||
/* acpi build is enabled by default if machine supports it */
|
/* acpi build is enabled by default if machine supports it */
|
||||||
pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
|
pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
|
||||||
|
pcms->smbus = true;
|
||||||
|
pcms->sata = true;
|
||||||
|
pcms->pit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_machine_reset(void)
|
static void pc_machine_reset(void)
|
||||||
@@ -2329,6 +2376,15 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
|||||||
|
|
||||||
object_class_property_add_bool(oc, PC_MACHINE_NVDIMM,
|
object_class_property_add_bool(oc, PC_MACHINE_NVDIMM,
|
||||||
pc_machine_get_nvdimm, pc_machine_set_nvdimm, &error_abort);
|
pc_machine_get_nvdimm, pc_machine_set_nvdimm, &error_abort);
|
||||||
|
|
||||||
|
object_class_property_add_bool(oc, PC_MACHINE_SMBUS,
|
||||||
|
pc_machine_get_smbus, pc_machine_set_smbus, &error_abort);
|
||||||
|
|
||||||
|
object_class_property_add_bool(oc, PC_MACHINE_SATA,
|
||||||
|
pc_machine_get_sata, pc_machine_set_sata, &error_abort);
|
||||||
|
|
||||||
|
object_class_property_add_bool(oc, PC_MACHINE_PIT,
|
||||||
|
pc_machine_get_pit, pc_machine_set_pit, &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pc_machine_info = {
|
static const TypeInfo pc_machine_info = {
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ static void pc_init1(MachineState *machine,
|
|||||||
|
|
||||||
/* init basic PC hardware */
|
/* init basic PC hardware */
|
||||||
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, true,
|
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, true,
|
||||||
(pcms->vmport != ON_OFF_AUTO_ON), 0x4);
|
(pcms->vmport != ON_OFF_AUTO_ON), pcms->pit, 0x4);
|
||||||
|
|
||||||
pc_nic_init(isa_bus, pci_bus);
|
pc_nic_init(isa_bus, pci_bus);
|
||||||
|
|
||||||
|
|||||||
@@ -227,32 +227,39 @@ static void pc_q35_init(MachineState *machine)
|
|||||||
|
|
||||||
/* init basic PC hardware */
|
/* init basic PC hardware */
|
||||||
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, !mc->no_floppy,
|
pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, !mc->no_floppy,
|
||||||
(pcms->vmport != ON_OFF_AUTO_ON), 0xff0104);
|
(pcms->vmport != ON_OFF_AUTO_ON), pcms->pit,
|
||||||
|
0xff0104);
|
||||||
|
|
||||||
/* connect pm stuff to lpc */
|
/* connect pm stuff to lpc */
|
||||||
ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms));
|
ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms));
|
||||||
|
|
||||||
/* ahci and SATA device, for q35 1 ahci controller is built-in */
|
if (pcms->sata) {
|
||||||
ahci = pci_create_simple_multifunction(host_bus,
|
/* ahci and SATA device, for q35 1 ahci controller is built-in */
|
||||||
PCI_DEVFN(ICH9_SATA1_DEV,
|
ahci = pci_create_simple_multifunction(host_bus,
|
||||||
ICH9_SATA1_FUNC),
|
PCI_DEVFN(ICH9_SATA1_DEV,
|
||||||
true, "ich9-ahci");
|
ICH9_SATA1_FUNC),
|
||||||
idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
|
true, "ich9-ahci");
|
||||||
idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
|
idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
|
||||||
g_assert(MAX_SATA_PORTS == ICH_AHCI(ahci)->ahci.ports);
|
idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
|
||||||
ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
|
g_assert(MAX_SATA_PORTS == ICH_AHCI(ahci)->ahci.ports);
|
||||||
ahci_ide_create_devs(ahci, hd);
|
ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
|
||||||
|
ahci_ide_create_devs(ahci, hd);
|
||||||
|
} else {
|
||||||
|
idebus[0] = idebus[1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (machine_usb(machine)) {
|
if (machine_usb(machine)) {
|
||||||
/* Should we create 6 UHCI according to ich9 spec? */
|
/* Should we create 6 UHCI according to ich9 spec? */
|
||||||
ehci_create_ich9_with_companions(host_bus, 0x1d);
|
ehci_create_ich9_with_companions(host_bus, 0x1d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Populate SPD eeprom data. */
|
if (pcms->smbus) {
|
||||||
smbus_eeprom_init(ich9_smb_init(host_bus,
|
/* TODO: Populate SPD eeprom data. */
|
||||||
PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
|
smbus_eeprom_init(ich9_smb_init(host_bus,
|
||||||
0xb100),
|
PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
|
||||||
8, NULL, 0);
|
0xb100),
|
||||||
|
8, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
|
pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
|
||||||
|
|
||||||
|
|||||||
@@ -252,6 +252,9 @@ static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = {
|
|||||||
[Q_KEY_CODE_ASTERISK] = 0x37,
|
[Q_KEY_CODE_ASTERISK] = 0x37,
|
||||||
[Q_KEY_CODE_LESS] = 0x56,
|
[Q_KEY_CODE_LESS] = 0x56,
|
||||||
[Q_KEY_CODE_RO] = 0x73,
|
[Q_KEY_CODE_RO] = 0x73,
|
||||||
|
[Q_KEY_CODE_HIRAGANA] = 0x70,
|
||||||
|
[Q_KEY_CODE_HENKAN] = 0x79,
|
||||||
|
[Q_KEY_CODE_YEN] = 0x7d,
|
||||||
[Q_KEY_CODE_KP_COMMA] = 0x7e,
|
[Q_KEY_CODE_KP_COMMA] = 0x7e,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -394,6 +397,9 @@ static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = {
|
|||||||
[Q_KEY_CODE_LESS] = 0x61,
|
[Q_KEY_CODE_LESS] = 0x61,
|
||||||
[Q_KEY_CODE_SYSRQ] = 0x7f,
|
[Q_KEY_CODE_SYSRQ] = 0x7f,
|
||||||
[Q_KEY_CODE_RO] = 0x51,
|
[Q_KEY_CODE_RO] = 0x51,
|
||||||
|
[Q_KEY_CODE_HIRAGANA] = 0x13,
|
||||||
|
[Q_KEY_CODE_HENKAN] = 0x64,
|
||||||
|
[Q_KEY_CODE_YEN] = 0x6a,
|
||||||
[Q_KEY_CODE_KP_COMMA] = 0x6d,
|
[Q_KEY_CODE_KP_COMMA] = 0x6d,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -504,6 +510,10 @@ static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = {
|
|||||||
[Q_KEY_CODE_COMMA] = 0x41,
|
[Q_KEY_CODE_COMMA] = 0x41,
|
||||||
[Q_KEY_CODE_DOT] = 0x49,
|
[Q_KEY_CODE_DOT] = 0x49,
|
||||||
[Q_KEY_CODE_SLASH] = 0x4a,
|
[Q_KEY_CODE_SLASH] = 0x4a,
|
||||||
|
|
||||||
|
[Q_KEY_CODE_HIRAGANA] = 0x87,
|
||||||
|
[Q_KEY_CODE_HENKAN] = 0x86,
|
||||||
|
[Q_KEY_CODE_YEN] = 0x5d,
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t translate_table[256] = {
|
static uint8_t translate_table[256] = {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ static uint32_t gicd_int_pending(GICv3State *s, int irq)
|
|||||||
* + the PENDING latch is set OR it is level triggered and the input is 1
|
* + the PENDING latch is set OR it is level triggered and the input is 1
|
||||||
* + its ENABLE bit is set
|
* + its ENABLE bit is set
|
||||||
* + the GICD enable bit for its group is set
|
* + the GICD enable bit for its group is set
|
||||||
|
* + its ACTIVE bit is not set (otherwise it would be Active+Pending)
|
||||||
* Conveniently we can bulk-calculate this with bitwise operations.
|
* Conveniently we can bulk-calculate this with bitwise operations.
|
||||||
*/
|
*/
|
||||||
uint32_t pend, grpmask;
|
uint32_t pend, grpmask;
|
||||||
@@ -63,9 +64,11 @@ static uint32_t gicd_int_pending(GICv3State *s, int irq)
|
|||||||
uint32_t group = *gic_bmp_ptr32(s->group, irq);
|
uint32_t group = *gic_bmp_ptr32(s->group, irq);
|
||||||
uint32_t grpmod = *gic_bmp_ptr32(s->grpmod, irq);
|
uint32_t grpmod = *gic_bmp_ptr32(s->grpmod, irq);
|
||||||
uint32_t enable = *gic_bmp_ptr32(s->enabled, irq);
|
uint32_t enable = *gic_bmp_ptr32(s->enabled, irq);
|
||||||
|
uint32_t active = *gic_bmp_ptr32(s->active, irq);
|
||||||
|
|
||||||
pend = pending | (~edge_trigger & level);
|
pend = pending | (~edge_trigger & level);
|
||||||
pend &= enable;
|
pend &= enable;
|
||||||
|
pend &= ~active;
|
||||||
|
|
||||||
if (s->gicd_ctlr & GICD_CTLR_DS) {
|
if (s->gicd_ctlr & GICD_CTLR_DS) {
|
||||||
grpmod = 0;
|
grpmod = 0;
|
||||||
@@ -96,12 +99,14 @@ static uint32_t gicr_int_pending(GICv3CPUState *cs)
|
|||||||
* + the PENDING latch is set OR it is level triggered and the input is 1
|
* + the PENDING latch is set OR it is level triggered and the input is 1
|
||||||
* + its ENABLE bit is set
|
* + its ENABLE bit is set
|
||||||
* + the GICD enable bit for its group is set
|
* + the GICD enable bit for its group is set
|
||||||
|
* + its ACTIVE bit is not set (otherwise it would be Active+Pending)
|
||||||
* Conveniently we can bulk-calculate this with bitwise operations.
|
* Conveniently we can bulk-calculate this with bitwise operations.
|
||||||
*/
|
*/
|
||||||
uint32_t pend, grpmask, grpmod;
|
uint32_t pend, grpmask, grpmod;
|
||||||
|
|
||||||
pend = cs->gicr_ipendr0 | (~cs->edge_trigger & cs->level);
|
pend = cs->gicr_ipendr0 | (~cs->edge_trigger & cs->level);
|
||||||
pend &= cs->gicr_ienabler0;
|
pend &= cs->gicr_ienabler0;
|
||||||
|
pend &= ~cs->gicr_iactiver0;
|
||||||
|
|
||||||
if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
|
if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
|
||||||
grpmod = 0;
|
grpmod = 0;
|
||||||
|
|||||||
@@ -204,7 +204,8 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
|
|||||||
/* The CPU mp-affinity property is in MPIDR register format; squash
|
/* The CPU mp-affinity property is in MPIDR register format; squash
|
||||||
* the affinity bytes into 32 bits as the GICR_TYPER has them.
|
* the affinity bytes into 32 bits as the GICR_TYPER has them.
|
||||||
*/
|
*/
|
||||||
cpu_affid = (cpu_affid & 0xFF00000000ULL >> 8) | (cpu_affid & 0xFFFFFF);
|
cpu_affid = ((cpu_affid & 0xFF00000000ULL) >> 8) |
|
||||||
|
(cpu_affid & 0xFFFFFF);
|
||||||
s->cpu[i].gicr_typer = (cpu_affid << 32) |
|
s->cpu[i].gicr_typer = (cpu_affid << 32) |
|
||||||
(1 << 24) |
|
(1 << 24) |
|
||||||
(i << 8) |
|
(i << 8) |
|
||||||
|
|||||||
@@ -1118,35 +1118,35 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
|
|||||||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 3,
|
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 3,
|
||||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||||
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
||||||
.fieldoffset = offsetof(GICv3CPUState, icc_bpr[GICV3_G0]),
|
.readfn = icc_bpr_read,
|
||||||
.writefn = icc_bpr_write,
|
.writefn = icc_bpr_write,
|
||||||
},
|
},
|
||||||
{ .name = "ICC_AP0R0_EL1", .state = ARM_CP_STATE_BOTH,
|
{ .name = "ICC_AP0R0_EL1", .state = ARM_CP_STATE_BOTH,
|
||||||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 4,
|
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 4,
|
||||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||||
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
||||||
.fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][0]),
|
.readfn = icc_ap_read,
|
||||||
.writefn = icc_ap_write,
|
.writefn = icc_ap_write,
|
||||||
},
|
},
|
||||||
{ .name = "ICC_AP0R1_EL1", .state = ARM_CP_STATE_BOTH,
|
{ .name = "ICC_AP0R1_EL1", .state = ARM_CP_STATE_BOTH,
|
||||||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 5,
|
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 5,
|
||||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||||
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
||||||
.fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][1]),
|
.readfn = icc_ap_read,
|
||||||
.writefn = icc_ap_write,
|
.writefn = icc_ap_write,
|
||||||
},
|
},
|
||||||
{ .name = "ICC_AP0R2_EL1", .state = ARM_CP_STATE_BOTH,
|
{ .name = "ICC_AP0R2_EL1", .state = ARM_CP_STATE_BOTH,
|
||||||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 6,
|
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 6,
|
||||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||||
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
||||||
.fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][2]),
|
.readfn = icc_ap_read,
|
||||||
.writefn = icc_ap_write,
|
.writefn = icc_ap_write,
|
||||||
},
|
},
|
||||||
{ .name = "ICC_AP0R3_EL1", .state = ARM_CP_STATE_BOTH,
|
{ .name = "ICC_AP0R3_EL1", .state = ARM_CP_STATE_BOTH,
|
||||||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 7,
|
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 8, .opc2 = 7,
|
||||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||||
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
||||||
.fieldoffset = offsetof(GICv3CPUState, icc_apr[GICV3_G0][3]),
|
.readfn = icc_ap_read,
|
||||||
.writefn = icc_ap_write,
|
.writefn = icc_ap_write,
|
||||||
},
|
},
|
||||||
/* All the ICC_AP1R*_EL1 registers are banked */
|
/* All the ICC_AP1R*_EL1 registers are banked */
|
||||||
@@ -1275,7 +1275,7 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
|
|||||||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 6,
|
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 6,
|
||||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||||
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
||||||
.fieldoffset = offsetof(GICv3CPUState, icc_igrpen[GICV3_G0]),
|
.readfn = icc_igrpen_read,
|
||||||
.writefn = icc_igrpen_write,
|
.writefn = icc_igrpen_write,
|
||||||
},
|
},
|
||||||
/* This register is banked */
|
/* This register is banked */
|
||||||
@@ -1299,7 +1299,6 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
|
|||||||
.opc0 = 3, .opc1 = 6, .crn = 12, .crm = 12, .opc2 = 4,
|
.opc0 = 3, .opc1 = 6, .crn = 12, .crm = 12, .opc2 = 4,
|
||||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||||
.access = PL3_RW,
|
.access = PL3_RW,
|
||||||
.fieldoffset = offsetof(GICv3CPUState, icc_ctlr_el3),
|
|
||||||
.readfn = icc_ctlr_el3_read,
|
.readfn = icc_ctlr_el3_read,
|
||||||
.writefn = icc_ctlr_el3_write,
|
.writefn = icc_ctlr_el3_write,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include "hw/i386/ioapic_internal.h"
|
#include "hw/i386/ioapic_internal.h"
|
||||||
#include "include/hw/pci/msi.h"
|
#include "include/hw/pci/msi.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "target-i386/cpu.h"
|
#include "target/i386/cpu.h"
|
||||||
#include "hw/i386/apic-msidef.h"
|
#include "hw/i386/apic-msidef.h"
|
||||||
#include "hw/i386/x86-iommu.h"
|
#include "hw/i386/x86-iommu.h"
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ static inline void hwsetup_create_rom(HWSetup *hw,
|
|||||||
hwaddr base)
|
hwaddr base)
|
||||||
{
|
{
|
||||||
rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE,
|
rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE,
|
||||||
TARGET_PAGE_SIZE, base, NULL, NULL, NULL);
|
TARGET_PAGE_SIZE, base, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u)
|
static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
#define BMC_DEV_ID TO_REG(0x1A4)
|
#define BMC_DEV_ID TO_REG(0x1A4)
|
||||||
|
|
||||||
#define PROT_KEY_UNLOCK 0x1688A8A8
|
#define PROT_KEY_UNLOCK 0x1688A8A8
|
||||||
#define SCU_IO_REGION_SIZE 0x20000
|
#define SCU_IO_REGION_SIZE 0x1000
|
||||||
|
|
||||||
static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
|
static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
|
||||||
[SYS_RST_CTRL] = 0xFFCFFEDCU,
|
[SYS_RST_CTRL] = 0xFFCFFEDCU,
|
||||||
@@ -231,6 +231,7 @@ static void aspeed_scu_reset(DeviceState *dev)
|
|||||||
|
|
||||||
switch (s->silicon_rev) {
|
switch (s->silicon_rev) {
|
||||||
case AST2400_A0_SILICON_REV:
|
case AST2400_A0_SILICON_REV:
|
||||||
|
case AST2400_A1_SILICON_REV:
|
||||||
reset = ast2400_a0_resets;
|
reset = ast2400_a0_resets;
|
||||||
break;
|
break;
|
||||||
case AST2500_A0_SILICON_REV:
|
case AST2500_A0_SILICON_REV:
|
||||||
@@ -249,6 +250,7 @@ static void aspeed_scu_reset(DeviceState *dev)
|
|||||||
|
|
||||||
static uint32_t aspeed_silicon_revs[] = {
|
static uint32_t aspeed_silicon_revs[] = {
|
||||||
AST2400_A0_SILICON_REV,
|
AST2400_A0_SILICON_REV,
|
||||||
|
AST2400_A1_SILICON_REV,
|
||||||
AST2500_A0_SILICON_REV,
|
AST2500_A0_SILICON_REV,
|
||||||
AST2500_A1_SILICON_REV,
|
AST2500_A1_SILICON_REV,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
|
|||||||
/* Make sure readonly bits are kept */
|
/* Make sure readonly bits are kept */
|
||||||
switch (s->silicon_rev) {
|
switch (s->silicon_rev) {
|
||||||
case AST2400_A0_SILICON_REV:
|
case AST2400_A0_SILICON_REV:
|
||||||
|
case AST2400_A1_SILICON_REV:
|
||||||
data &= ~ASPEED_SDMC_READONLY_MASK;
|
data &= ~ASPEED_SDMC_READONLY_MASK;
|
||||||
break;
|
break;
|
||||||
case AST2500_A0_SILICON_REV:
|
case AST2500_A0_SILICON_REV:
|
||||||
@@ -193,6 +194,7 @@ static void aspeed_sdmc_reset(DeviceState *dev)
|
|||||||
/* Set ram size bit and defaults values */
|
/* Set ram size bit and defaults values */
|
||||||
switch (s->silicon_rev) {
|
switch (s->silicon_rev) {
|
||||||
case AST2400_A0_SILICON_REV:
|
case AST2400_A0_SILICON_REV:
|
||||||
|
case AST2400_A1_SILICON_REV:
|
||||||
s->regs[R_CONF] |=
|
s->regs[R_CONF] |=
|
||||||
ASPEED_SDMC_VGA_COMPAT |
|
ASPEED_SDMC_VGA_COMPAT |
|
||||||
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
|
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
|
||||||
@@ -224,6 +226,7 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
switch (s->silicon_rev) {
|
switch (s->silicon_rev) {
|
||||||
case AST2400_A0_SILICON_REV:
|
case AST2400_A0_SILICON_REV:
|
||||||
|
case AST2400_A1_SILICON_REV:
|
||||||
s->ram_bits = ast2400_rambits(s);
|
s->ram_bits = ast2400_rambits(s);
|
||||||
break;
|
break;
|
||||||
case AST2500_A0_SILICON_REV:
|
case AST2500_A0_SILICON_REV:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "hw/qdev.h"
|
#include "hw/qdev.h"
|
||||||
#include "hw/isa/isa.h"
|
#include "hw/isa/isa.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "target-i386/hyperv.h"
|
#include "target/i386/hyperv.h"
|
||||||
#include "kvm_i386.h"
|
#include "kvm_i386.h"
|
||||||
|
|
||||||
#define HV_TEST_DEV_MAX_SINT_ROUTES 64
|
#define HV_TEST_DEV_MAX_SINT_ROUTES 64
|
||||||
|
|||||||
@@ -348,8 +348,8 @@ static ssize_t etsec_receive(NetClientState *nc,
|
|||||||
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
eTSEC *etsec = qemu_get_nic_opaque(nc);
|
||||||
|
|
||||||
#if defined(HEX_DUMP)
|
#if defined(HEX_DUMP)
|
||||||
fprintf(stderr, "%s receive size:%d\n", etsec->nic->nc.name, size);
|
fprintf(stderr, "%s receive size:%zd\n", nc->name, size);
|
||||||
qemu_hexdump(buf, stderr, "", size);
|
qemu_hexdump((void *)buf, stderr, "", size);
|
||||||
#endif
|
#endif
|
||||||
/* Flush is unnecessary as are already in receiving path */
|
/* Flush is unnecessary as are already in receiving path */
|
||||||
etsec->need_flush = false;
|
etsec->need_flush = false;
|
||||||
|
|||||||
@@ -474,6 +474,14 @@ static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size)
|
|||||||
/* CRC padding (We don't have to compute the CRC) */
|
/* CRC padding (We don't have to compute the CRC) */
|
||||||
etsec->rx_padding = 4;
|
etsec->rx_padding = 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that payload length + CRC length is at least 802.3
|
||||||
|
* minimum MTU size bytes long (64)
|
||||||
|
*/
|
||||||
|
if (etsec->rx_buffer_len < 60) {
|
||||||
|
etsec->rx_padding += 60 - etsec->rx_buffer_len;
|
||||||
|
}
|
||||||
|
|
||||||
etsec->rx_first_in_frame = 1;
|
etsec->rx_first_in_frame = 1;
|
||||||
etsec->rx_remaining_data = etsec->rx_buffer_len;
|
etsec->rx_remaining_data = etsec->rx_buffer_len;
|
||||||
RING_DEBUG("%s: rx_buffer_len:%u rx_padding+crc:%u\n", __func__,
|
RING_DEBUG("%s: rx_buffer_len:%u rx_padding+crc:%u\n", __func__,
|
||||||
|
|||||||
@@ -393,7 +393,7 @@ static void mcf_fec_write(void *opaque, hwaddr addr,
|
|||||||
s->tx_descriptor = s->etdsr;
|
s->tx_descriptor = s->etdsr;
|
||||||
break;
|
break;
|
||||||
case 0x188:
|
case 0x188:
|
||||||
s->emrbr = value & 0x7f0;
|
s->emrbr = value > 0 ? value & 0x7F0 : 0x7F0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr);
|
hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr);
|
||||||
|
|||||||
@@ -62,9 +62,7 @@ typedef struct UNINState {
|
|||||||
|
|
||||||
static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
|
static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
|
||||||
{
|
{
|
||||||
int devfn = pci_dev->devfn & 0x00FFFFFF;
|
return (irq_num + (pci_dev->devfn >> 3)) & 3;
|
||||||
|
|
||||||
return (((devfn >> 11) & 0x1F) + irq_num) & 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_unin_set_irq(void *opaque, int irq_num, int level)
|
static void pci_unin_set_irq(void *opaque, int irq_num, int level)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "target-ppc/cpu.h"
|
#include "target/ppc/cpu.h"
|
||||||
|
|
||||||
#include "hw/ppc/fdt.h"
|
#include "hw/ppc/fdt.h"
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "sysemu/numa.h"
|
#include "sysemu/numa.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "target-ppc/cpu.h"
|
#include "target/ppc/cpu.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "hw/ppc/fdt.h"
|
#include "hw/ppc/fdt.h"
|
||||||
#include "hw/ppc/ppc.h"
|
#include "hw/ppc/ppc.h"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "target-ppc/cpu.h"
|
#include "target/ppc/cpu.h"
|
||||||
#include "hw/ppc/ppc.h"
|
#include "hw/ppc/ppc.h"
|
||||||
#include "hw/ppc/pnv.h"
|
#include "hw/ppc/pnv.h"
|
||||||
#include "hw/ppc/pnv_core.h"
|
#include "hw/ppc/pnv_core.h"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "target-ppc/cpu.h"
|
#include "target/ppc/cpu.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "target-ppc/cpu.h"
|
#include "target/ppc/cpu.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
|
|
||||||
#include "hw/ppc/fdt.h"
|
#include "hw/ppc/fdt.h"
|
||||||
|
|||||||
@@ -1267,6 +1267,68 @@ static bool version_before_3(void *opaque, int version_id)
|
|||||||
return version_id < 3;
|
return version_id < 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool spapr_ov5_cas_needed(void *opaque)
|
||||||
|
{
|
||||||
|
sPAPRMachineState *spapr = opaque;
|
||||||
|
sPAPROptionVector *ov5_mask = spapr_ovec_new();
|
||||||
|
sPAPROptionVector *ov5_legacy = spapr_ovec_new();
|
||||||
|
sPAPROptionVector *ov5_removed = spapr_ovec_new();
|
||||||
|
bool cas_needed;
|
||||||
|
|
||||||
|
/* Prior to the introduction of sPAPROptionVector, we had two option
|
||||||
|
* vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY.
|
||||||
|
* Both of these options encode machine topology into the device-tree
|
||||||
|
* in such a way that the now-booted OS should still be able to interact
|
||||||
|
* appropriately with QEMU regardless of what options were actually
|
||||||
|
* negotiatied on the source side.
|
||||||
|
*
|
||||||
|
* As such, we can avoid migrating the CAS-negotiated options if these
|
||||||
|
* are the only options available on the current machine/platform.
|
||||||
|
* Since these are the only options available for pseries-2.7 and
|
||||||
|
* earlier, this allows us to maintain old->new/new->old migration
|
||||||
|
* compatibility.
|
||||||
|
*
|
||||||
|
* For QEMU 2.8+, there are additional CAS-negotiatable options available
|
||||||
|
* via default pseries-2.8 machines and explicit command-line parameters.
|
||||||
|
* Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware
|
||||||
|
* of the actual CAS-negotiated values to continue working properly. For
|
||||||
|
* example, availability of memory unplug depends on knowing whether
|
||||||
|
* OV5_HP_EVT was negotiated via CAS.
|
||||||
|
*
|
||||||
|
* Thus, for any cases where the set of available CAS-negotiatable
|
||||||
|
* options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we
|
||||||
|
* include the CAS-negotiated options in the migration stream.
|
||||||
|
*/
|
||||||
|
spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY);
|
||||||
|
spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY);
|
||||||
|
|
||||||
|
/* spapr_ovec_diff returns true if bits were removed. we avoid using
|
||||||
|
* the mask itself since in the future it's possible "legacy" bits may be
|
||||||
|
* removed via machine options, which could generate a false positive
|
||||||
|
* that breaks migration.
|
||||||
|
*/
|
||||||
|
spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask);
|
||||||
|
cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy);
|
||||||
|
|
||||||
|
spapr_ovec_cleanup(ov5_mask);
|
||||||
|
spapr_ovec_cleanup(ov5_legacy);
|
||||||
|
spapr_ovec_cleanup(ov5_removed);
|
||||||
|
|
||||||
|
return cas_needed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_spapr_ov5_cas = {
|
||||||
|
.name = "spapr_option_vector_ov5_cas",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.needed = spapr_ov5_cas_needed,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1,
|
||||||
|
vmstate_spapr_ovec, sPAPROptionVector),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_spapr = {
|
static const VMStateDescription vmstate_spapr = {
|
||||||
.name = "spapr",
|
.name = "spapr",
|
||||||
.version_id = 3,
|
.version_id = 3,
|
||||||
@@ -1282,6 +1344,10 @@ static const VMStateDescription vmstate_spapr = {
|
|||||||
VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
|
VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
},
|
},
|
||||||
|
.subsections = (const VMStateDescription*[]) {
|
||||||
|
&vmstate_spapr_ov5_cas,
|
||||||
|
NULL
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int htab_save_setup(QEMUFile *f, void *opaque)
|
static int htab_save_setup(QEMUFile *f, void *opaque)
|
||||||
@@ -2224,6 +2290,11 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
|
|||||||
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||||
drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp);
|
drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp);
|
||||||
addr += SPAPR_MEMORY_BLOCK_SIZE;
|
addr += SPAPR_MEMORY_BLOCK_SIZE;
|
||||||
|
if (!dev->hotplugged) {
|
||||||
|
/* guests expect coldplugged LMBs to be pre-allocated */
|
||||||
|
drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE);
|
||||||
|
drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* send hotplug notification to the
|
/* send hotplug notification to the
|
||||||
* guest only in case of hotplugged memory
|
* guest only in case of hotplugged memory
|
||||||
@@ -2701,6 +2772,16 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", true);
|
|||||||
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
|
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
|
||||||
.property = "mem64_win_size", \
|
.property = "mem64_win_size", \
|
||||||
.value = "0", \
|
.value = "0", \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.driver = TYPE_POWERPC_CPU, \
|
||||||
|
.property = "pre-2.8-migration", \
|
||||||
|
.value = "on", \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
|
||||||
|
.property = "pre-2.8-migration", \
|
||||||
|
.value = "on", \
|
||||||
},
|
},
|
||||||
|
|
||||||
static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
|
static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
*/
|
*/
|
||||||
#include "hw/cpu/core.h"
|
#include "hw/cpu/core.h"
|
||||||
#include "hw/ppc/spapr_cpu_core.h"
|
#include "hw/ppc/spapr_cpu_core.h"
|
||||||
#include "target-ppc/cpu.h"
|
#include "target/ppc/cpu.h"
|
||||||
#include "hw/ppc/spapr.h"
|
#include "hw/ppc/spapr.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "sysemu/cpus.h"
|
#include "sysemu/cpus.h"
|
||||||
#include "target-ppc/kvm_ppc.h"
|
#include "target/ppc/kvm_ppc.h"
|
||||||
#include "hw/ppc/ppc.h"
|
#include "hw/ppc/ppc.h"
|
||||||
#include "target-ppc/mmu-hash64.h"
|
#include "target/ppc/mmu-hash64.h"
|
||||||
#include "sysemu/numa.h"
|
#include "sysemu/numa.h"
|
||||||
|
|
||||||
static void spapr_cpu_reset(void *opaque)
|
static void spapr_cpu_reset(void *opaque)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user