Compare commits
457 Commits
pull-conso
...
pull-gtk-2
Author | SHA1 | Date | |
---|---|---|---|
|
fa7a1e5219 | ||
|
f50def915e | ||
|
0a337ed067 | ||
|
932f2d7e0f | ||
|
b780bf8eff | ||
|
1a2858995d | ||
|
e2bb4ae746 | ||
|
4380be0e99 | ||
|
fec0da9cbf | ||
|
ec15993d9d | ||
|
6b1dd54b6a | ||
|
a10678b08e | ||
|
6998b6c11b | ||
|
d1180c1e57 | ||
|
89218c218f | ||
|
fc4bde9025 | ||
|
029ad4bcf3 | ||
|
e3a17ef6cc | ||
|
f46b9cc71c | ||
|
c1d7572793 | ||
|
a1fa7992a9 | ||
|
f9b5426fd5 | ||
|
7179585688 | ||
|
831f4d27b6 | ||
|
49bba868df | ||
|
2a802aaf63 | ||
|
ef18c2f54e | ||
|
3048ed6aac | ||
|
fa15286a75 | ||
|
6ab57a6b80 | ||
|
3334e929ae | ||
|
333cb18ff4 | ||
|
a1d2db08d8 | ||
|
7b0140e49b | ||
|
bbd8bb8e32 | ||
|
de13d21614 | ||
|
66ad0893f0 | ||
|
79afc36d91 | ||
|
bcb2b582f3 | ||
|
6449a41a4d | ||
|
a2689242b1 | ||
|
4cb88c3c37 | ||
|
08da527fd0 | ||
|
f068d320de | ||
|
7721a30442 | ||
|
14ac573392 | ||
|
3b1a413812 | ||
|
d3afacc726 | ||
|
f6fe04d566 | ||
|
be56f04eea | ||
|
5acc765c04 | ||
|
aa633469ed | ||
|
130f2e7dcb | ||
|
da5141fc45 | ||
|
25f748e37a | ||
|
fb8ad9f2c1 | ||
|
46d9dfdad6 | ||
|
411bdc7837 | ||
|
4e624edaeb | ||
|
526d0096e5 | ||
|
f1ecb913d8 | ||
|
d615efac7c | ||
|
8d5c773e32 | ||
|
bf01601764 | ||
|
61e9924149 | ||
|
4a331bb33b | ||
|
a35d9be622 | ||
|
5b808275f3 | ||
|
82432638eb | ||
|
80ff35cd3f | ||
|
26896cbf35 | ||
|
7efea76377 | ||
|
b167383ffb | ||
|
8597f2e19e | ||
|
b44672849a | ||
|
40e76f736d | ||
|
5dfc05cb1d | ||
|
959e41473f | ||
|
37654d9e6a | ||
|
08397c4b29 | ||
|
a373cdb5ce | ||
|
aa0f607f61 | ||
|
95faaa73df | ||
|
e8198f6ea0 | ||
|
8c6d96728d | ||
|
04bb4d86f1 | ||
|
2e95fa1719 | ||
|
1ad166b612 | ||
|
5db15096d0 | ||
|
d34bda716a | ||
|
5d039baba4 | ||
|
b544c1aba8 | ||
|
405a27640b | ||
|
50809c8b92 | ||
|
4e627aeef8 | ||
|
26edf8cc08 | ||
|
31e25e3e57 | ||
|
ae74bbe7c5 | ||
|
f38b161203 | ||
|
fd7fbc8ff7 | ||
|
ea9a6606b1 | ||
|
01b91ac2be | ||
|
d4ad9dec14 | ||
|
366d4f7e00 | ||
|
e09c49f40d | ||
|
9d48d3f01c | ||
|
9f0355b590 | ||
|
d4f005db9b | ||
|
711e2f1e9e | ||
|
9f9260a3be | ||
|
16b96f82cd | ||
|
b09481de91 | ||
|
de431a655a | ||
|
eaad03e472 | ||
|
e2a32ebbfe | ||
|
e7e898a76a | ||
|
e8f6d00c30 | ||
|
b728464ae8 | ||
|
c1eb2fa3fd | ||
|
77549a7809 | ||
|
b052e4509b | ||
|
870a706735 | ||
|
7c82256006 | ||
|
487cad8853 | ||
|
00cc3e1d70 | ||
|
843408b3cf | ||
|
f57584dc87 | ||
|
8a201bd47e | ||
|
81cf8d8adc | ||
|
43773ed369 | ||
|
c773828aa9 | ||
|
f08b617018 | ||
|
1d854765df | ||
|
58ed270df9 | ||
|
0f590e749f | ||
|
d94f0a8ecb | ||
|
93e22326d6 | ||
|
ca0aa40816 | ||
|
a6c9eac0d5 | ||
|
859d76120b | ||
|
0983979b3a | ||
|
fddbd80cc9 | ||
|
7e4e88656c | ||
|
e3eb9806c7 | ||
|
3d1b2ff62c | ||
|
76782fab1c | ||
|
0b91966730 | ||
|
d6635c4dbb | ||
|
1ac362cdbd | ||
|
b15446fdbf | ||
|
22524f7262 | ||
|
13af91ebf0 | ||
|
c9f87b20b9 | ||
|
5a05cbeeaa | ||
|
6d7e73d62f | ||
|
db519cba87 | ||
|
76ef2cf549 | ||
|
8d242f0ed5 | ||
|
0d6ecec252 | ||
|
580b6b2aa2 | ||
|
c75f3bdf46 | ||
|
2af0b20056 | ||
|
84390bed59 | ||
|
ea80019149 | ||
|
85ebd381fd | ||
|
99cc598924 | ||
|
abd269b7cf | ||
|
c2f3426c9b | ||
|
e3625d3d6a | ||
|
a8c868c386 | ||
|
471799d135 | ||
|
69447cd8f3 | ||
|
80cf625766 | ||
|
6ee50af24b | ||
|
63f0f45f2e | ||
|
9d94020bc6 | ||
|
7e1efdf0a3 | ||
|
dcd042282d | ||
|
9b536adcbe | ||
|
ed78cda3de | ||
|
2572b37a47 | ||
|
924fe1293c | ||
|
79b6f2f651 | ||
|
2082bac151 | ||
|
90525fe279 | ||
|
3503206a90 | ||
|
2deb4acc7c | ||
|
5a165668e7 | ||
|
2e377f1730 | ||
|
be1a717624 | ||
|
374044f08f | ||
|
9b1786829a | ||
|
f522d2acc5 | ||
|
e00fcfeab3 | ||
|
278073ba29 | ||
|
82ea61c6da | ||
|
1673e89e93 | ||
|
3257fc8383 | ||
|
36f5db59cf | ||
|
7bafd8889e | ||
|
b52991537c | ||
|
4006617552 | ||
|
cf864569cd | ||
|
7bd3055ffd | ||
|
b791c3b38c | ||
|
322fd1f4f7 | ||
|
b88a3e01f5 | ||
|
d81d410635 | ||
|
381626a969 | ||
|
95dd1c4d7a | ||
|
9a1d111e70 | ||
|
ad489e9346 | ||
|
f2335791fd | ||
|
363f59d9e4 | ||
|
bdef972474 | ||
|
50ef467923 | ||
|
f72b49398f | ||
|
9bb931802e | ||
|
55d492d760 | ||
|
0e1dac6c41 | ||
|
5e70018b00 | ||
|
0688448b71 | ||
|
3df3e0a587 | ||
|
279a35ab4a | ||
|
7532d3cbf1 | ||
|
12e1129b80 | ||
|
078c44f48e | ||
|
4cb47d281a | ||
|
c13959c745 | ||
|
675036e4da | ||
|
bb9cd2ee99 | ||
|
2df5fee2db | ||
|
b122c3b6d0 | ||
|
6262bbd363 | ||
|
f25391c2a6 | ||
|
3cb0e25c4b | ||
|
6376f95223 | ||
|
543f7bef13 | ||
|
29f2601aa6 | ||
|
443422fde7 | ||
|
b20e61e0d5 | ||
|
a1904e48c4 | ||
|
75e347d66a | ||
|
ebee92b4fe | ||
|
d7d3d6092c | ||
|
66226ffd05 | ||
|
24666baf1f | ||
|
a62f6f5600 | ||
|
ae18b28dd1 | ||
|
d2e16f2ce1 | ||
|
1695974187 | ||
|
3d9bddb30b | ||
|
e9a9a5b605 | ||
|
2c90784abf | ||
|
011209e19f | ||
|
bbb8a1b455 | ||
|
afb49896fa | ||
|
72866e823e | ||
|
a5ed2de10a | ||
|
836d6ed96e | ||
|
c017230d9b | ||
|
944eea962b | ||
|
2ef6175aa7 | ||
|
a763551ad5 | ||
|
de77914e50 | ||
|
a5f54290ce | ||
|
6b1b144019 | ||
|
a199b2b6a5 | ||
|
1d10b44546 | ||
|
13d7adf92a | ||
|
3ef9622182 | ||
|
0380aef323 | ||
|
3ee933c9d4 | ||
|
052367ba85 | ||
|
adbfc34103 | ||
|
972b09c219 | ||
|
fbab9ccbdb | ||
|
efde4b6252 | ||
|
e67c399363 | ||
|
dc83cd427b | ||
|
7d2d3e74e5 | ||
|
318df29e10 | ||
|
356b4ca2bb | ||
|
dfb12bf86e | ||
|
d11c8917b2 | ||
|
68c70af16d | ||
|
5496fb1aeb | ||
|
5f0c39e598 | ||
|
4618e658e6 | ||
|
01c2b265fc | ||
|
04bc7c0e38 | ||
|
d61563b235 | ||
|
3775ec6f5a | ||
|
b1422f2040 | ||
|
e8817e7b0e | ||
|
6815bce542 | ||
|
ce782938b8 | ||
|
826b6ca0b0 | ||
|
920beae103 | ||
|
8d24cce1e3 | ||
|
628ff68303 | ||
|
3718d8ab65 | ||
|
fbe40ff780 | ||
|
8574575f90 | ||
|
0bf7488afb | ||
|
271c0f68b4 | ||
|
bd60436936 | ||
|
4ba6fabfb4 | ||
|
7cf6376ae8 | ||
|
53651ec26b | ||
|
109519fd32 | ||
|
4aa23452e3 | ||
|
9474ab1487 | ||
|
2f21ff25c0 | ||
|
eb386aaccc | ||
|
501f28ca9d | ||
|
27aa948502 | ||
|
a1ba125c0c | ||
|
d42e3c26cd | ||
|
855ea66dd5 | ||
|
61d4b215d1 | ||
|
db6c3cd0e7 | ||
|
14c521d45e | ||
|
7ab6c10d00 | ||
|
81547d6630 | ||
|
3b685ba7bf | ||
|
1fe8141ed4 | ||
|
cca7c2f523 | ||
|
2a923c4dde | ||
|
28c9457df0 | ||
|
1b1742386c | ||
|
73fb3b764b | ||
|
68fdb6c5b0 | ||
|
d81c519c40 | ||
|
6947f05978 | ||
|
f79fbf39e2 | ||
|
6ce2faf43c | ||
|
c119779543 | ||
|
a99caa48d8 | ||
|
9d4c4e872e | ||
|
f0aff25570 | ||
|
fc37b7a0b0 | ||
|
9ef137cad6 | ||
|
93f94f9018 | ||
|
00d0f7cb66 | ||
|
57a740514d | ||
|
ca3164df4d | ||
|
433d33c555 | ||
|
8977bd111f | ||
|
f85d28316a | ||
|
ee8c0b622c | ||
|
6f5943cf45 | ||
|
8b84286f4c | ||
|
1ff5eedd1d | ||
|
86846bfe64 | ||
|
2386a90730 | ||
|
11c7fa7fa6 | ||
|
f5c0ab1312 | ||
|
1687a089f1 | ||
|
116d554601 | ||
|
1fba509527 | ||
|
69e995040c | ||
|
8d1bd3c901 | ||
|
56a9f18051 | ||
|
b664b80f19 | ||
|
19e8393170 | ||
|
22513a9b44 | ||
|
68206d7342 | ||
|
36084d7e31 | ||
|
f995523582 | ||
|
058fdcf52c | ||
|
463c534db5 | ||
|
6fa2769751 | ||
|
82fc18099a | ||
|
0f61a61df3 | ||
|
3158a3482b | ||
|
aa0a55d42d | ||
|
0c77a37f11 | ||
|
99623c90d1 | ||
|
2884cf5b93 | ||
|
4eeaa3a885 | ||
|
746b867030 | ||
|
4c638e2e4b | ||
|
1c856da57b | ||
|
74444bc198 | ||
|
cdeb7090ee | ||
|
d3ef575080 | ||
|
6a24ced5ca | ||
|
ed1132e41a | ||
|
e3500d1f5f | ||
|
271a25c0b6 | ||
|
832189c9b1 | ||
|
0fb20d1c39 | ||
|
ee5f31e48b | ||
|
6fe83074d7 | ||
|
fd07d07ba9 | ||
|
d09b8fa161 | ||
|
38dbd48b24 | ||
|
25156d1061 | ||
|
4e7d30a22a | ||
|
f7bbcfb5c3 | ||
|
a946ce8020 | ||
|
b6bfeea92a | ||
|
33fac20bb2 | ||
|
3401fd259e | ||
|
1db1c4d7d9 | ||
|
9a2f0bfe32 | ||
|
c068896f7f | ||
|
fd1cf66630 | ||
|
4f048535cd | ||
|
741f117d9a | ||
|
22ee3a987d | ||
|
070603f62b | ||
|
ac0f3b1263 | ||
|
1c4182687e | ||
|
f216a35f36 | ||
|
6c530e32f4 | ||
|
418839044e | ||
|
fbef2cc80f | ||
|
ce0236cfbd | ||
|
9d8bf2d125 | ||
|
f9a716325f | ||
|
7dae901d2d | ||
|
f8c9eddb2b | ||
|
483c76e140 | ||
|
479eb12108 | ||
|
42119fa356 | ||
|
26b78f4d3c | ||
|
f33a984d51 | ||
|
fa5912a17b | ||
|
124fe7fb1b | ||
|
d357e3d9d2 | ||
|
5b9d313e3f | ||
|
8cd05ab65a | ||
|
9c132c7f64 | ||
|
0971f1bed2 | ||
|
b645000e1a | ||
|
e35f29ded3 | ||
|
1a3de8dbec | ||
|
9e04c683fc | ||
|
5672ee54d5 | ||
|
36af599417 | ||
|
aef553fdca | ||
|
78a4b8d205 | ||
|
a3abb29292 | ||
|
28fb26f19f | ||
|
7125c937c9 | ||
|
d3b5491897 | ||
|
b98dbc9095 | ||
|
87446327cc | ||
|
b763adf1a6 | ||
|
7c8b724826 | ||
|
0d73394ad9 | ||
|
84351843eb | ||
|
fb5be2e833 | ||
|
13cc2c3e86 | ||
|
a096b3a673 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@
|
||||
/config-host.*
|
||||
/config-target.*
|
||||
/config.status
|
||||
/config-temp
|
||||
/trace/generated-tracers.h
|
||||
/trace/generated-tracers.c
|
||||
/trace/generated-tracers-dtrace.h
|
||||
|
@@ -66,16 +66,16 @@ matrix:
|
||||
compiler: gcc
|
||||
# All the trace backends (apart from dtrace)
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_CONFIG="--enable-trace-backend=stderr"
|
||||
EXTRA_CONFIG="--enable-trace-backends=stderr"
|
||||
compiler: gcc
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_CONFIG="--enable-trace-backend=simple"
|
||||
EXTRA_CONFIG="--enable-trace-backends=simple"
|
||||
compiler: gcc
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_CONFIG="--enable-trace-backend=ftrace"
|
||||
EXTRA_CONFIG="--enable-trace-backends=ftrace"
|
||||
TEST_CMD=""
|
||||
compiler: gcc
|
||||
- env: TARGETS=i386-softmmu,x86_64-softmmu
|
||||
EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
|
||||
EXTRA_CONFIG="--enable-trace-backend=ust"
|
||||
EXTRA_CONFIG="--enable-trace-backends=ust"
|
||||
compiler: gcc
|
||||
|
@@ -243,8 +243,8 @@ S: Maintained
|
||||
F: hw/*/exynos*
|
||||
|
||||
Calxeda Highbank
|
||||
M: Mark Langsdorf <mark.langsdorf@calxeda.com>
|
||||
S: Supported
|
||||
M: Rob Herring <robh@kernel.org>
|
||||
S: Maintained
|
||||
F: hw/arm/highbank.c
|
||||
F: hw/net/xgmac.c
|
||||
|
||||
|
4
Makefile
4
Makefile
@@ -52,12 +52,12 @@ GENERATED_HEADERS += trace/generated-events.h
|
||||
GENERATED_SOURCES += trace/generated-events.c
|
||||
|
||||
GENERATED_HEADERS += trace/generated-tracers.h
|
||||
ifeq ($(TRACE_BACKEND),dtrace)
|
||||
ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
|
||||
GENERATED_HEADERS += trace/generated-tracers-dtrace.h
|
||||
endif
|
||||
GENERATED_SOURCES += trace/generated-tracers.c
|
||||
|
||||
ifeq ($(TRACE_BACKEND),ust)
|
||||
ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
|
||||
GENERATED_HEADERS += trace/generated-ust-provider.h
|
||||
GENERATED_SOURCES += trace/generated-ust.c
|
||||
endif
|
||||
|
@@ -49,7 +49,7 @@ endif
|
||||
$(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
|
||||
$(call quiet-command,$(TRACETOOL) \
|
||||
--format=stap \
|
||||
--backend=$(TRACE_BACKEND) \
|
||||
--backends=$(TRACE_BACKENDS) \
|
||||
--binary=$(bindir)/$(QEMU_PROG) \
|
||||
--target-name=$(TARGET_NAME) \
|
||||
--target-type=$(TARGET_TYPE) \
|
||||
@@ -58,7 +58,7 @@ $(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
|
||||
$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
|
||||
$(call quiet-command,$(TRACETOOL) \
|
||||
--format=stap \
|
||||
--backend=$(TRACE_BACKEND) \
|
||||
--backends=$(TRACE_BACKENDS) \
|
||||
--binary=$(realpath .)/$(QEMU_PROG) \
|
||||
--target-name=$(TARGET_NAME) \
|
||||
--target-type=$(TARGET_TYPE) \
|
||||
|
33
arch_init.c
33
arch_init.c
@@ -739,7 +739,6 @@ static void migration_end(void)
|
||||
XBZRLE_cache_lock();
|
||||
if (XBZRLE.cache) {
|
||||
cache_fini(XBZRLE.cache);
|
||||
g_free(XBZRLE.cache);
|
||||
g_free(XBZRLE.encoded_buf);
|
||||
g_free(XBZRLE.current_buf);
|
||||
XBZRLE.cache = NULL;
|
||||
@@ -975,12 +974,12 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
|
||||
xh_len = qemu_get_be16(f);
|
||||
|
||||
if (xh_flags != ENCODING_FLAG_XBZRLE) {
|
||||
fprintf(stderr, "Failed to load XBZRLE page - wrong compression!\n");
|
||||
error_report("Failed to load XBZRLE page - wrong compression!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xh_len > TARGET_PAGE_SIZE) {
|
||||
fprintf(stderr, "Failed to load XBZRLE page - len overflow!\n");
|
||||
error_report("Failed to load XBZRLE page - len overflow!");
|
||||
return -1;
|
||||
}
|
||||
/* load data and decode */
|
||||
@@ -989,7 +988,7 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
|
||||
/* decode RLE */
|
||||
if (xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host,
|
||||
TARGET_PAGE_SIZE) == -1) {
|
||||
fprintf(stderr, "Failed to load XBZRLE page - decode error!\n");
|
||||
error_report("Failed to load XBZRLE page - decode error!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1006,7 +1005,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
|
||||
|
||||
if (flags & RAM_SAVE_FLAG_CONTINUE) {
|
||||
if (!block) {
|
||||
fprintf(stderr, "Ack, bad migration stream!\n");
|
||||
error_report("Ack, bad migration stream!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1022,7 +1021,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
|
||||
return memory_region_get_ram_ptr(block->mr) + offset;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Can't find block %s!\n", id);
|
||||
error_report("Can't find block %s!", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1075,10 +1074,9 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
|
||||
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
|
||||
if (!strncmp(id, block->idstr, sizeof(id))) {
|
||||
if (block->length != length) {
|
||||
fprintf(stderr,
|
||||
"Length mismatch: %s: " RAM_ADDR_FMT
|
||||
" in != " RAM_ADDR_FMT "\n", id, length,
|
||||
block->length);
|
||||
error_report("Length mismatch: %s: " RAM_ADDR_FMT
|
||||
" in != " RAM_ADDR_FMT, id, length,
|
||||
block->length);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
@@ -1087,8 +1085,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
|
||||
}
|
||||
|
||||
if (!block) {
|
||||
fprintf(stderr, "Unknown ramblock \"%s\", cannot "
|
||||
"accept migration\n", id);
|
||||
error_report("Unknown ramblock \"%s\", cannot "
|
||||
"accept migration", id);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
@@ -1243,12 +1241,11 @@ void select_soundhw(const char *optarg)
|
||||
|
||||
if (!c->name) {
|
||||
if (l > 80) {
|
||||
fprintf(stderr,
|
||||
"Unknown sound card name (too big to show)\n");
|
||||
error_report("Unknown sound card name (too big to show)");
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Unknown sound card name `%.*s'\n",
|
||||
(int) l, p);
|
||||
error_report("Unknown sound card name `%.*s'",
|
||||
(int) l, p);
|
||||
}
|
||||
bad_card = 1;
|
||||
}
|
||||
@@ -1271,13 +1268,13 @@ void audio_init(void)
|
||||
if (c->enabled) {
|
||||
if (c->isa) {
|
||||
if (!isa_bus) {
|
||||
fprintf(stderr, "ISA bus not available for %s\n", c->name);
|
||||
error_report("ISA bus not available for %s", c->name);
|
||||
exit(1);
|
||||
}
|
||||
c->init.init_isa(isa_bus);
|
||||
} else {
|
||||
if (!pci_bus) {
|
||||
fprintf(stderr, "PCI bus not available for %s\n", c->name);
|
||||
error_report("PCI bus not available for %s", c->name);
|
||||
exit(1);
|
||||
}
|
||||
c->init.init_pci(pci_bus);
|
||||
|
14
async.c
14
async.c
@@ -117,15 +117,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
|
||||
|
||||
void qemu_bh_schedule(QEMUBH *bh)
|
||||
{
|
||||
AioContext *ctx;
|
||||
|
||||
if (bh->scheduled)
|
||||
return;
|
||||
ctx = bh->ctx;
|
||||
bh->idle = 0;
|
||||
/* Make sure that idle & any writes needed by the callback are done
|
||||
* before the locations are read in the aio_bh_poll.
|
||||
/* Make sure that:
|
||||
* 1. idle & any writes needed by the callback are done before the
|
||||
* locations are read in the aio_bh_poll.
|
||||
* 2. ctx is loaded before scheduled is set and the callback has a chance
|
||||
* to execute.
|
||||
*/
|
||||
smp_wmb();
|
||||
smp_mb();
|
||||
bh->scheduled = 1;
|
||||
aio_notify(bh->ctx);
|
||||
aio_notify(ctx);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -105,7 +105,7 @@ static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
|
||||
bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
|
||||
samples = (bytes - rate->bytes_sent) >> info->shift;
|
||||
if (samples < 0 || samples > 65536) {
|
||||
fprintf (stderr, "Resetting rate control (%" PRId64 " samples)\n", samples);
|
||||
error_report("Resetting rate control (%" PRId64 " samples)", samples);
|
||||
rate_start (rate);
|
||||
samples = 0;
|
||||
}
|
||||
|
@@ -63,8 +63,7 @@ static void wav_destroy (void *opaque)
|
||||
}
|
||||
doclose:
|
||||
if (fclose (wav->f)) {
|
||||
fprintf (stderr, "wav_destroy: fclose failed: %s",
|
||||
strerror (errno));
|
||||
error_report("wav_destroy: fclose failed: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -59,6 +59,7 @@ typedef struct BlkMigDevState {
|
||||
unsigned long *aio_bitmap;
|
||||
int64_t completed_sectors;
|
||||
BdrvDirtyBitmap *dirty_bitmap;
|
||||
Error *blocker;
|
||||
} BlkMigDevState;
|
||||
|
||||
typedef struct BlkMigBlock {
|
||||
@@ -361,7 +362,8 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
|
||||
bmds->completed_sectors = 0;
|
||||
bmds->shared_base = block_mig_state.shared_base;
|
||||
alloc_aio_bitmap(bmds);
|
||||
bdrv_set_in_use(bs, 1);
|
||||
error_setg(&bmds->blocker, "block device is in use by migration");
|
||||
bdrv_op_block_all(bs, bmds->blocker);
|
||||
bdrv_ref(bs);
|
||||
|
||||
block_mig_state.total_sector_sum += sectors;
|
||||
@@ -599,7 +601,8 @@ static void blk_mig_cleanup(void)
|
||||
blk_mig_lock();
|
||||
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
|
||||
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
|
||||
bdrv_set_in_use(bmds->bs, 0);
|
||||
bdrv_op_unblock_all(bmds->bs, bmds->blocker);
|
||||
error_free(bmds->blocker);
|
||||
bdrv_unref(bmds->bs);
|
||||
g_free(bmds->aio_bitmap);
|
||||
g_free(bmds);
|
||||
@@ -626,6 +629,7 @@ static int block_save_setup(QEMUFile *f, void *opaque)
|
||||
block_mig_state.submitted, block_mig_state.transferred);
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
init_blk_migration(f);
|
||||
|
||||
/* start track dirty blocks */
|
||||
ret = set_dirty_tracking();
|
||||
@@ -635,8 +639,6 @@ static int block_save_setup(QEMUFile *f, void *opaque)
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_blk_migration(f);
|
||||
|
||||
qemu_mutex_unlock_iothread();
|
||||
|
||||
ret = flush_blks(f);
|
||||
|
297
block.c
297
block.c
@@ -179,6 +179,7 @@ void bdrv_io_limits_enable(BlockDriverState *bs)
|
||||
{
|
||||
assert(!bs->io_limits_enabled);
|
||||
throttle_init(&bs->throttle_state,
|
||||
bdrv_get_aio_context(bs),
|
||||
QEMU_CLOCK_VIRTUAL,
|
||||
bdrv_throttle_read_timer_cb,
|
||||
bdrv_throttle_write_timer_cb,
|
||||
@@ -335,6 +336,7 @@ void bdrv_register(BlockDriver *bdrv)
|
||||
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int i;
|
||||
|
||||
if (bdrv_find(device_name)) {
|
||||
error_setg(errp, "Device with id '%s' already exists",
|
||||
@@ -353,12 +355,16 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||
if (device_name[0] != '\0') {
|
||||
QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
|
||||
}
|
||||
for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
|
||||
QLIST_INIT(&bs->op_blockers[i]);
|
||||
}
|
||||
bdrv_iostatus_disable(bs);
|
||||
notifier_list_init(&bs->close_notifiers);
|
||||
notifier_with_return_list_init(&bs->before_write_notifiers);
|
||||
qemu_co_queue_init(&bs->throttled_reqs[0]);
|
||||
qemu_co_queue_init(&bs->throttled_reqs[1]);
|
||||
bs->refcnt = 1;
|
||||
bs->aio_context = qemu_get_aio_context();
|
||||
|
||||
return bs;
|
||||
}
|
||||
@@ -1090,6 +1096,37 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
|
||||
{
|
||||
|
||||
if (bs->backing_hd) {
|
||||
assert(bs->backing_blocker);
|
||||
bdrv_op_unblock_all(bs->backing_hd, bs->backing_blocker);
|
||||
} else if (backing_hd) {
|
||||
error_setg(&bs->backing_blocker,
|
||||
"device is used as backing hd of '%s'",
|
||||
bs->device_name);
|
||||
}
|
||||
|
||||
bs->backing_hd = backing_hd;
|
||||
if (!backing_hd) {
|
||||
error_free(bs->backing_blocker);
|
||||
bs->backing_blocker = NULL;
|
||||
goto out;
|
||||
}
|
||||
bs->open_flags &= ~BDRV_O_NO_BACKING;
|
||||
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_hd->filename);
|
||||
pstrcpy(bs->backing_format, sizeof(bs->backing_format),
|
||||
backing_hd->drv ? backing_hd->drv->format_name : "");
|
||||
|
||||
bdrv_op_block_all(bs->backing_hd, bs->backing_blocker);
|
||||
/* Otherwise we won't be able to commit due to check in bdrv_commit */
|
||||
bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT,
|
||||
bs->backing_blocker);
|
||||
out:
|
||||
bdrv_refresh_limits(bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens the backing file for a BlockDriverState if not yet open
|
||||
*
|
||||
@@ -1103,6 +1140,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
char *backing_filename = g_malloc0(PATH_MAX);
|
||||
int ret = 0;
|
||||
BlockDriver *back_drv = NULL;
|
||||
BlockDriverState *backing_hd;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (bs->backing_hd != NULL) {
|
||||
@@ -1125,30 +1163,26 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
|
||||
}
|
||||
|
||||
backing_hd = bdrv_new("", errp);
|
||||
|
||||
if (bs->backing_format[0] != '\0') {
|
||||
back_drv = bdrv_find_format(bs->backing_format);
|
||||
}
|
||||
|
||||
assert(bs->backing_hd == NULL);
|
||||
ret = bdrv_open(&bs->backing_hd,
|
||||
ret = bdrv_open(&backing_hd,
|
||||
*backing_filename ? backing_filename : NULL, NULL, options,
|
||||
bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
|
||||
if (ret < 0) {
|
||||
bs->backing_hd = NULL;
|
||||
bdrv_unref(backing_hd);
|
||||
backing_hd = NULL;
|
||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||
error_setg(errp, "Could not open backing file: %s",
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
goto free_exit;
|
||||
}
|
||||
|
||||
if (bs->backing_hd->file) {
|
||||
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
|
||||
bs->backing_hd->file->filename);
|
||||
}
|
||||
|
||||
/* Recalculate the BlockLimits with the backing file */
|
||||
bdrv_refresh_limits(bs);
|
||||
bdrv_set_backing_hd(bs, backing_hd);
|
||||
|
||||
free_exit:
|
||||
g_free(backing_filename);
|
||||
@@ -1196,6 +1230,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
||||
bdref_key);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
QDECREF(image_options);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1784,8 +1819,9 @@ void bdrv_close(BlockDriverState *bs)
|
||||
|
||||
if (bs->drv) {
|
||||
if (bs->backing_hd) {
|
||||
bdrv_unref(bs->backing_hd);
|
||||
bs->backing_hd = NULL;
|
||||
BlockDriverState *backing_hd = bs->backing_hd;
|
||||
bdrv_set_backing_hd(bs, NULL);
|
||||
bdrv_unref(backing_hd);
|
||||
}
|
||||
bs->drv->bdrv_close(bs);
|
||||
g_free(bs->opaque);
|
||||
@@ -1822,7 +1858,11 @@ void bdrv_close_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_close(bs);
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1847,17 +1887,6 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool bdrv_requests_pending_all(void)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
if (bdrv_requests_pending(bs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for pending requests to complete across all BlockDriverStates
|
||||
*
|
||||
@@ -1877,12 +1906,20 @@ void bdrv_drain_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
while (busy) {
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
bdrv_start_throttled_reqs(bs);
|
||||
}
|
||||
busy = false;
|
||||
|
||||
busy = bdrv_requests_pending_all();
|
||||
busy |= aio_poll(qemu_get_aio_context(), busy);
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
bool bs_busy;
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_start_throttled_reqs(bs);
|
||||
bs_busy = bdrv_requests_pending(bs);
|
||||
bs_busy |= aio_poll(aio_context, bs_busy);
|
||||
aio_context_release(aio_context);
|
||||
|
||||
busy |= bs_busy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1945,13 +1982,14 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
|
||||
bs_dest->refcnt = bs_src->refcnt;
|
||||
|
||||
/* job */
|
||||
bs_dest->in_use = bs_src->in_use;
|
||||
bs_dest->job = bs_src->job;
|
||||
|
||||
/* keep the same entry in bdrv_states */
|
||||
pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
|
||||
bs_src->device_name);
|
||||
bs_dest->device_list = bs_src->device_list;
|
||||
memcpy(bs_dest->op_blockers, bs_src->op_blockers,
|
||||
sizeof(bs_dest->op_blockers));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1986,7 +2024,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
|
||||
assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
|
||||
assert(bs_new->job == NULL);
|
||||
assert(bs_new->dev == NULL);
|
||||
assert(bs_new->in_use == 0);
|
||||
assert(bs_new->io_limits_enabled == false);
|
||||
assert(!throttle_have_timer(&bs_new->throttle_state));
|
||||
|
||||
@@ -2005,7 +2042,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
|
||||
/* Check a few fields that should remain attached to the device */
|
||||
assert(bs_new->dev == NULL);
|
||||
assert(bs_new->job == NULL);
|
||||
assert(bs_new->in_use == 0);
|
||||
assert(bs_new->io_limits_enabled == false);
|
||||
assert(!throttle_have_timer(&bs_new->throttle_state));
|
||||
|
||||
@@ -2038,19 +2074,14 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
|
||||
|
||||
/* The contents of 'tmp' will become bs_top, as we are
|
||||
* swapping bs_new and bs_top contents. */
|
||||
bs_top->backing_hd = bs_new;
|
||||
bs_top->open_flags &= ~BDRV_O_NO_BACKING;
|
||||
pstrcpy(bs_top->backing_file, sizeof(bs_top->backing_file),
|
||||
bs_new->filename);
|
||||
pstrcpy(bs_top->backing_format, sizeof(bs_top->backing_format),
|
||||
bs_new->drv ? bs_new->drv->format_name : "");
|
||||
bdrv_set_backing_hd(bs_top, bs_new);
|
||||
}
|
||||
|
||||
static void bdrv_delete(BlockDriverState *bs)
|
||||
{
|
||||
assert(!bs->dev);
|
||||
assert(!bs->job);
|
||||
assert(!bs->in_use);
|
||||
assert(bdrv_op_blocker_is_empty(bs));
|
||||
assert(!bs->refcnt);
|
||||
assert(QLIST_EMPTY(&bs->dirty_bitmaps));
|
||||
|
||||
@@ -2232,7 +2263,8 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) {
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT, NULL) ||
|
||||
bdrv_op_is_blocked(bs->backing_hd, BLOCK_OP_TYPE_COMMIT, NULL)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@@ -2323,12 +2355,17 @@ int bdrv_commit_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
if (bs->drv && bs->backing_hd) {
|
||||
int ret = bdrv_commit(bs);
|
||||
if (ret < 0) {
|
||||
aio_context_release(aio_context);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2636,13 +2673,11 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
|
||||
if (ret) {
|
||||
goto exit;
|
||||
}
|
||||
new_top_bs->backing_hd = base_bs;
|
||||
|
||||
bdrv_refresh_limits(new_top_bs);
|
||||
bdrv_set_backing_hd(new_top_bs, base_bs);
|
||||
|
||||
QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) {
|
||||
/* so that bdrv_close() does not recursively close the chain */
|
||||
intermediate_state->bs->backing_hd = NULL;
|
||||
bdrv_set_backing_hd(intermediate_state->bs, NULL);
|
||||
bdrv_unref(intermediate_state->bs);
|
||||
}
|
||||
ret = 0;
|
||||
@@ -2748,10 +2783,12 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset,
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_rw_co_entry(&rwco);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_rw_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
while (rwco.ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
return rwco.ret;
|
||||
@@ -3494,8 +3531,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
|
||||
return -ENOTSUP;
|
||||
if (bs->read_only)
|
||||
return -EACCES;
|
||||
if (bdrv_in_use(bs))
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
ret = drv->bdrv_truncate(bs, offset);
|
||||
if (ret == 0) {
|
||||
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
||||
@@ -3803,10 +3841,15 @@ int bdrv_flush_all(void)
|
||||
int result = 0;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
int ret = bdrv_flush(bs);
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
int ret;
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
ret = bdrv_flush(bs);
|
||||
if (ret < 0 && !result) {
|
||||
result = ret;
|
||||
}
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -3997,10 +4040,12 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_get_block_status_co_entry(&data);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_get_block_status_co_entry);
|
||||
qemu_coroutine_enter(co, &data);
|
||||
while (!data.done) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
return data.ret;
|
||||
@@ -4593,7 +4638,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
acb->is_write = is_write;
|
||||
acb->qiov = qiov;
|
||||
acb->bounce = qemu_blockalign(bs, qiov->size);
|
||||
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_aio_bh_cb, acb);
|
||||
|
||||
if (is_write) {
|
||||
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
|
||||
@@ -4632,13 +4677,14 @@ typedef struct BlockDriverAIOCBCoroutine {
|
||||
|
||||
static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
|
||||
BlockDriverAIOCBCoroutine *acb =
|
||||
container_of(blockacb, BlockDriverAIOCBCoroutine, common);
|
||||
bool done = false;
|
||||
|
||||
acb->done = &done;
|
||||
while (!done) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4675,7 +4721,7 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
|
||||
acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -4711,7 +4757,7 @@ static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
|
||||
BlockDriverState *bs = acb->common.bs;
|
||||
|
||||
acb->req.error = bdrv_co_flush(bs);
|
||||
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -4738,7 +4784,7 @@ static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
|
||||
BlockDriverState *bs = acb->common.bs;
|
||||
|
||||
acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors);
|
||||
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -4949,7 +4995,11 @@ void bdrv_invalidate_cache_all(Error **errp)
|
||||
Error *local_err = NULL;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_invalidate_cache(bs, &local_err);
|
||||
aio_context_release(aio_context);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@@ -4962,7 +5012,11 @@ void bdrv_clear_incoming_migration_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bs->open_flags = bs->open_flags & ~(BDRV_O_INCOMING);
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4978,10 +5032,12 @@ int bdrv_flush(BlockDriverState *bs)
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_flush_co_entry(&rwco);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_flush_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
while (rwco.ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5091,10 +5147,12 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_discard_co_entry(&rwco);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_discard_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
while (rwco.ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5325,15 +5383,74 @@ void bdrv_unref(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_set_in_use(BlockDriverState *bs, int in_use)
|
||||
struct BdrvOpBlocker {
|
||||
Error *reason;
|
||||
QLIST_ENTRY(BdrvOpBlocker) list;
|
||||
};
|
||||
|
||||
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
|
||||
{
|
||||
assert(bs->in_use != in_use);
|
||||
bs->in_use = in_use;
|
||||
BdrvOpBlocker *blocker;
|
||||
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
|
||||
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
|
||||
blocker = QLIST_FIRST(&bs->op_blockers[op]);
|
||||
if (errp) {
|
||||
error_setg(errp, "Device '%s' is busy: %s",
|
||||
bs->device_name, error_get_pretty(blocker->reason));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int bdrv_in_use(BlockDriverState *bs)
|
||||
void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason)
|
||||
{
|
||||
return bs->in_use;
|
||||
BdrvOpBlocker *blocker;
|
||||
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
|
||||
|
||||
blocker = g_malloc0(sizeof(BdrvOpBlocker));
|
||||
blocker->reason = reason;
|
||||
QLIST_INSERT_HEAD(&bs->op_blockers[op], blocker, list);
|
||||
}
|
||||
|
||||
void bdrv_op_unblock(BlockDriverState *bs, BlockOpType op, Error *reason)
|
||||
{
|
||||
BdrvOpBlocker *blocker, *next;
|
||||
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
|
||||
QLIST_FOREACH_SAFE(blocker, &bs->op_blockers[op], list, next) {
|
||||
if (blocker->reason == reason) {
|
||||
QLIST_REMOVE(blocker, list);
|
||||
g_free(blocker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_op_block_all(BlockDriverState *bs, Error *reason)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
|
||||
bdrv_op_block(bs, i, reason);
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
|
||||
bdrv_op_unblock(bs, i, reason);
|
||||
}
|
||||
}
|
||||
|
||||
bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
|
||||
if (!QLIST_EMPTY(&bs->op_blockers[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void bdrv_iostatus_enable(BlockDriverState *bs)
|
||||
@@ -5546,8 +5663,66 @@ out:
|
||||
|
||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
/* Currently BlockDriverState always uses the main loop AioContext */
|
||||
return qemu_get_aio_context();
|
||||
return bs->aio_context;
|
||||
}
|
||||
|
||||
void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
if (!bs->drv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bs->io_limits_enabled) {
|
||||
throttle_detach_aio_context(&bs->throttle_state);
|
||||
}
|
||||
if (bs->drv->bdrv_detach_aio_context) {
|
||||
bs->drv->bdrv_detach_aio_context(bs);
|
||||
}
|
||||
if (bs->file) {
|
||||
bdrv_detach_aio_context(bs->file);
|
||||
}
|
||||
if (bs->backing_hd) {
|
||||
bdrv_detach_aio_context(bs->backing_hd);
|
||||
}
|
||||
|
||||
bs->aio_context = NULL;
|
||||
}
|
||||
|
||||
void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
if (!bs->drv) {
|
||||
return;
|
||||
}
|
||||
|
||||
bs->aio_context = new_context;
|
||||
|
||||
if (bs->backing_hd) {
|
||||
bdrv_attach_aio_context(bs->backing_hd, new_context);
|
||||
}
|
||||
if (bs->file) {
|
||||
bdrv_attach_aio_context(bs->file, new_context);
|
||||
}
|
||||
if (bs->drv->bdrv_attach_aio_context) {
|
||||
bs->drv->bdrv_attach_aio_context(bs, new_context);
|
||||
}
|
||||
if (bs->io_limits_enabled) {
|
||||
throttle_attach_aio_context(&bs->throttle_state, new_context);
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
|
||||
{
|
||||
bdrv_drain_all(); /* ensure there are no in-flight requests */
|
||||
|
||||
bdrv_detach_aio_context(bs);
|
||||
|
||||
/* This function executes in the old AioContext so acquire the new one in
|
||||
* case it runs in a different thread.
|
||||
*/
|
||||
aio_context_acquire(new_context);
|
||||
bdrv_attach_aio_context(bs, new_context);
|
||||
aio_context_release(new_context);
|
||||
}
|
||||
|
||||
void bdrv_add_before_write_notifier(BlockDriverState *bs,
|
||||
|
@@ -471,7 +471,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
|
||||
acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
|
||||
acb->ret = -error;
|
||||
|
||||
bh = qemu_bh_new(error_callback_bh, acb);
|
||||
bh = aio_bh_new(bdrv_get_aio_context(bs), error_callback_bh, acb);
|
||||
acb->bh = bh;
|
||||
qemu_bh_schedule(bh);
|
||||
|
||||
|
@@ -39,12 +39,13 @@ struct BlkverifyAIOCB {
|
||||
static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
|
||||
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
|
||||
bool finished = false;
|
||||
|
||||
/* Wait until request completes, invokes its callback, and frees itself */
|
||||
acb->finished = &finished;
|
||||
while (!finished) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +229,8 @@ static void blkverify_aio_cb(void *opaque, int ret)
|
||||
acb->verify(acb);
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(blkverify_aio_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
|
||||
blkverify_aio_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
break;
|
||||
}
|
||||
@@ -302,21 +304,40 @@ static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
|
||||
return bdrv_recurse_is_first_non_filter(s->test_file, candidate);
|
||||
}
|
||||
|
||||
/* Propagate AioContext changes to ->test_file */
|
||||
static void blkverify_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkverifyState *s = bs->opaque;
|
||||
|
||||
bdrv_detach_aio_context(s->test_file);
|
||||
}
|
||||
|
||||
static void blkverify_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVBlkverifyState *s = bs->opaque;
|
||||
|
||||
bdrv_attach_aio_context(s->test_file, new_context);
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_blkverify = {
|
||||
.format_name = "blkverify",
|
||||
.protocol_name = "blkverify",
|
||||
.instance_size = sizeof(BDRVBlkverifyState),
|
||||
.format_name = "blkverify",
|
||||
.protocol_name = "blkverify",
|
||||
.instance_size = sizeof(BDRVBlkverifyState),
|
||||
|
||||
.bdrv_parse_filename = blkverify_parse_filename,
|
||||
.bdrv_file_open = blkverify_open,
|
||||
.bdrv_close = blkverify_close,
|
||||
.bdrv_getlength = blkverify_getlength,
|
||||
.bdrv_parse_filename = blkverify_parse_filename,
|
||||
.bdrv_file_open = blkverify_open,
|
||||
.bdrv_close = blkverify_close,
|
||||
.bdrv_getlength = blkverify_getlength,
|
||||
|
||||
.bdrv_aio_readv = blkverify_aio_readv,
|
||||
.bdrv_aio_writev = blkverify_aio_writev,
|
||||
.bdrv_aio_flush = blkverify_aio_flush,
|
||||
.bdrv_aio_readv = blkverify_aio_readv,
|
||||
.bdrv_aio_writev = blkverify_aio_writev,
|
||||
.bdrv_aio_flush = blkverify_aio_flush,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_attach_aio_context = blkverify_attach_aio_context,
|
||||
.bdrv_detach_aio_context = blkverify_detach_aio_context,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_recurse_is_first_non_filter = blkverify_recurse_is_first_non_filter,
|
||||
};
|
||||
|
||||
|
192
block/curl.c
192
block/curl.c
@@ -110,6 +110,7 @@ typedef struct BDRVCURLState {
|
||||
size_t readahead_size;
|
||||
bool sslverify;
|
||||
bool accept_range;
|
||||
AioContext *aio_context;
|
||||
} BDRVCURLState;
|
||||
|
||||
static void curl_clean_state(CURLState *s);
|
||||
@@ -134,25 +135,29 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
|
||||
#endif
|
||||
|
||||
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
||||
void *s, void *sp)
|
||||
void *userp, void *sp)
|
||||
{
|
||||
BDRVCURLState *s;
|
||||
CURLState *state = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
|
||||
state->sock_fd = fd;
|
||||
s = state->s;
|
||||
|
||||
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
|
||||
switch (action) {
|
||||
case CURL_POLL_IN:
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
|
||||
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
|
||||
NULL, state);
|
||||
break;
|
||||
case CURL_POLL_OUT:
|
||||
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
|
||||
aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, state);
|
||||
break;
|
||||
case CURL_POLL_INOUT:
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
|
||||
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
|
||||
curl_multi_do, state);
|
||||
break;
|
||||
case CURL_POLL_REMOVE:
|
||||
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
|
||||
aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -365,7 +370,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
|
||||
break;
|
||||
}
|
||||
if (!state) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(state->s->aio_context, true);
|
||||
}
|
||||
} while(!state);
|
||||
|
||||
@@ -422,6 +427,51 @@ static void curl_parse_filename(const char *filename, QDict *options,
|
||||
qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
|
||||
}
|
||||
|
||||
static void curl_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVCURLState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CURL_NUM_STATES; i++) {
|
||||
if (s->states[i].in_use) {
|
||||
curl_clean_state(&s->states[i]);
|
||||
}
|
||||
if (s->states[i].curl) {
|
||||
curl_easy_cleanup(s->states[i].curl);
|
||||
s->states[i].curl = NULL;
|
||||
}
|
||||
if (s->states[i].orig_buf) {
|
||||
g_free(s->states[i].orig_buf);
|
||||
s->states[i].orig_buf = NULL;
|
||||
}
|
||||
}
|
||||
if (s->multi) {
|
||||
curl_multi_cleanup(s->multi);
|
||||
s->multi = NULL;
|
||||
}
|
||||
|
||||
timer_del(&s->timer);
|
||||
}
|
||||
|
||||
static void curl_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVCURLState *s = bs->opaque;
|
||||
|
||||
aio_timer_init(new_context, &s->timer,
|
||||
QEMU_CLOCK_REALTIME, SCALE_NS,
|
||||
curl_multi_timeout_do, s);
|
||||
|
||||
assert(!s->multi);
|
||||
s->multi = curl_multi_init();
|
||||
s->aio_context = new_context;
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
||||
#endif
|
||||
}
|
||||
|
||||
static QemuOptsList runtime_opts = {
|
||||
.name = "curl",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
||||
@@ -491,6 +541,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
DPRINTF("CURL: Opening %s\n", file);
|
||||
s->aio_context = bdrv_get_aio_context(bs);
|
||||
s->url = g_strdup(file);
|
||||
state = curl_init_state(s);
|
||||
if (!state)
|
||||
@@ -523,19 +574,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
curl_easy_cleanup(state->curl);
|
||||
state->curl = NULL;
|
||||
|
||||
aio_timer_init(bdrv_get_aio_context(bs), &s->timer,
|
||||
QEMU_CLOCK_REALTIME, SCALE_NS,
|
||||
curl_multi_timeout_do, s);
|
||||
|
||||
// Now we know the file exists and its size, so let's
|
||||
// initialize the multi interface!
|
||||
|
||||
s->multi = curl_multi_init();
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
||||
#endif
|
||||
curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
|
||||
|
||||
qemu_opts_del(opts);
|
||||
return 0;
|
||||
@@ -630,7 +669,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
||||
acb->sector_num = sector_num;
|
||||
acb->nb_sectors = nb_sectors;
|
||||
|
||||
acb->bh = qemu_bh_new(curl_readv_bh_cb, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
return &acb->common;
|
||||
}
|
||||
@@ -638,25 +677,9 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
||||
static void curl_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVCURLState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
DPRINTF("CURL: Close\n");
|
||||
for (i=0; i<CURL_NUM_STATES; i++) {
|
||||
if (s->states[i].in_use)
|
||||
curl_clean_state(&s->states[i]);
|
||||
if (s->states[i].curl) {
|
||||
curl_easy_cleanup(s->states[i].curl);
|
||||
s->states[i].curl = NULL;
|
||||
}
|
||||
if (s->states[i].orig_buf) {
|
||||
g_free(s->states[i].orig_buf);
|
||||
s->states[i].orig_buf = NULL;
|
||||
}
|
||||
}
|
||||
if (s->multi)
|
||||
curl_multi_cleanup(s->multi);
|
||||
|
||||
timer_del(&s->timer);
|
||||
curl_detach_aio_context(bs);
|
||||
|
||||
g_free(s->url);
|
||||
}
|
||||
@@ -668,68 +691,83 @@ static int64_t curl_getlength(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_http = {
|
||||
.format_name = "http",
|
||||
.protocol_name = "http",
|
||||
.format_name = "http",
|
||||
.protocol_name = "http",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_https = {
|
||||
.format_name = "https",
|
||||
.protocol_name = "https",
|
||||
.format_name = "https",
|
||||
.protocol_name = "https",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_ftp = {
|
||||
.format_name = "ftp",
|
||||
.protocol_name = "ftp",
|
||||
.format_name = "ftp",
|
||||
.protocol_name = "ftp",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_ftps = {
|
||||
.format_name = "ftps",
|
||||
.protocol_name = "ftps",
|
||||
.format_name = "ftps",
|
||||
.protocol_name = "ftps",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_tftp = {
|
||||
.format_name = "tftp",
|
||||
.protocol_name = "tftp",
|
||||
.format_name = "tftp",
|
||||
.protocol_name = "tftp",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static void curl_block_init(void)
|
||||
|
@@ -16,6 +16,7 @@ typedef struct GlusterAIOCB {
|
||||
int ret;
|
||||
QEMUBH *bh;
|
||||
Coroutine *coroutine;
|
||||
AioContext *aio_context;
|
||||
} GlusterAIOCB;
|
||||
|
||||
typedef struct BDRVGlusterState {
|
||||
@@ -249,7 +250,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
|
||||
acb->ret = -EIO; /* Partial read/write - fail it */
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
|
||||
acb->bh = aio_bh_new(acb->aio_context, qemu_gluster_complete_aio, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -436,6 +437,7 @@ static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
|
||||
acb->size = size;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
ret = glfs_zerofill_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
|
||||
if (ret < 0) {
|
||||
@@ -549,6 +551,7 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
|
||||
acb->size = size;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
if (write) {
|
||||
ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
|
||||
@@ -605,6 +608,7 @@ static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
|
||||
acb->size = 0;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
|
||||
if (ret < 0) {
|
||||
@@ -633,6 +637,7 @@ static coroutine_fn int qemu_gluster_co_discard(BlockDriverState *bs,
|
||||
acb->size = 0;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
|
||||
if (ret < 0) {
|
||||
|
@@ -49,6 +49,7 @@
|
||||
|
||||
typedef struct IscsiLun {
|
||||
struct iscsi_context *iscsi;
|
||||
AioContext *aio_context;
|
||||
int lun;
|
||||
enum scsi_inquiry_peripheral_device_type type;
|
||||
int block_size;
|
||||
@@ -73,6 +74,7 @@ typedef struct IscsiTask {
|
||||
struct scsi_task *task;
|
||||
Coroutine *co;
|
||||
QEMUBH *bh;
|
||||
IscsiLun *iscsilun;
|
||||
} IscsiTask;
|
||||
|
||||
typedef struct IscsiAIOCB {
|
||||
@@ -133,7 +135,7 @@ iscsi_schedule_bh(IscsiAIOCB *acb)
|
||||
if (acb->bh) {
|
||||
return;
|
||||
}
|
||||
acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
|
||||
acb->bh = aio_bh_new(acb->iscsilun->aio_context, iscsi_bh_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -169,7 +171,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
out:
|
||||
if (iTask->co) {
|
||||
iTask->bh = qemu_bh_new(iscsi_co_generic_bh_cb, iTask);
|
||||
iTask->bh = aio_bh_new(iTask->iscsilun->aio_context,
|
||||
iscsi_co_generic_bh_cb, iTask);
|
||||
qemu_bh_schedule(iTask->bh);
|
||||
}
|
||||
}
|
||||
@@ -177,8 +180,9 @@ out:
|
||||
static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
|
||||
{
|
||||
*iTask = (struct IscsiTask) {
|
||||
.co = qemu_coroutine_self(),
|
||||
.retries = ISCSI_CMD_RETRIES,
|
||||
.co = qemu_coroutine_self(),
|
||||
.retries = ISCSI_CMD_RETRIES,
|
||||
.iscsilun = iscsilun,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -209,7 +213,7 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
iscsi_abort_task_cb, acb);
|
||||
|
||||
while (acb->status == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(iscsilun->aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,10 +236,11 @@ iscsi_set_events(IscsiLun *iscsilun)
|
||||
ev = POLLIN;
|
||||
ev |= iscsi_which_events(iscsi);
|
||||
if (ev != iscsilun->events) {
|
||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
|
||||
iscsi_process_read,
|
||||
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
||||
iscsilun);
|
||||
aio_set_fd_handler(iscsilun->aio_context,
|
||||
iscsi_get_fd(iscsi),
|
||||
iscsi_process_read,
|
||||
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
||||
iscsilun);
|
||||
|
||||
}
|
||||
|
||||
@@ -791,7 +796,7 @@ static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
|
||||
iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
|
||||
|
||||
while (status == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(iscsilun->aio_context, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1195,6 +1200,40 @@ fail_with_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void iscsi_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
|
||||
aio_set_fd_handler(iscsilun->aio_context,
|
||||
iscsi_get_fd(iscsilun->iscsi),
|
||||
NULL, NULL, NULL);
|
||||
iscsilun->events = 0;
|
||||
|
||||
if (iscsilun->nop_timer) {
|
||||
timer_del(iscsilun->nop_timer);
|
||||
timer_free(iscsilun->nop_timer);
|
||||
iscsilun->nop_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void iscsi_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
|
||||
iscsilun->aio_context = new_context;
|
||||
iscsi_set_events(iscsilun);
|
||||
|
||||
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
|
||||
/* Set up a timer for sending out iSCSI NOPs */
|
||||
iscsilun->nop_timer = aio_timer_new(iscsilun->aio_context,
|
||||
QEMU_CLOCK_REALTIME, SCALE_MS,
|
||||
iscsi_nop_timed_event, iscsilun);
|
||||
timer_mod(iscsilun->nop_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* We support iscsi url's on the form
|
||||
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
|
||||
@@ -1301,6 +1340,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
iscsilun->iscsi = iscsi;
|
||||
iscsilun->aio_context = bdrv_get_aio_context(bs);
|
||||
iscsilun->lun = iscsi_url->lun;
|
||||
iscsilun->has_write_same = true;
|
||||
|
||||
@@ -1374,11 +1414,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
|
||||
/* Set up a timer for sending out iSCSI NOPs */
|
||||
iscsilun->nop_timer = timer_new_ms(QEMU_CLOCK_REALTIME, iscsi_nop_timed_event, iscsilun);
|
||||
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||
#endif
|
||||
iscsi_attach_aio_context(bs, iscsilun->aio_context);
|
||||
|
||||
/* Guess the internal cluster (page) size of the iscsi target by the means
|
||||
* of opt_unmap_gran. Transfer the unmap granularity only if it has a
|
||||
@@ -1422,11 +1458,7 @@ static void iscsi_close(BlockDriverState *bs)
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
struct iscsi_context *iscsi = iscsilun->iscsi;
|
||||
|
||||
if (iscsilun->nop_timer) {
|
||||
timer_del(iscsilun->nop_timer);
|
||||
timer_free(iscsilun->nop_timer);
|
||||
}
|
||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
|
||||
iscsi_detach_aio_context(bs);
|
||||
iscsi_destroy_context(iscsi);
|
||||
g_free(iscsilun->zeroblock);
|
||||
g_free(iscsilun->allocationmap);
|
||||
@@ -1530,10 +1562,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
if (iscsilun->nop_timer) {
|
||||
timer_del(iscsilun->nop_timer);
|
||||
timer_free(iscsilun->nop_timer);
|
||||
}
|
||||
iscsi_detach_aio_context(bs);
|
||||
if (iscsilun->type != TYPE_DISK) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
@@ -1604,6 +1633,9 @@ static BlockDriver bdrv_iscsi = {
|
||||
.bdrv_ioctl = iscsi_ioctl,
|
||||
.bdrv_aio_ioctl = iscsi_aio_ioctl,
|
||||
#endif
|
||||
|
||||
.bdrv_detach_aio_context = iscsi_detach_aio_context,
|
||||
.bdrv_attach_aio_context = iscsi_attach_aio_context,
|
||||
};
|
||||
|
||||
static QemuOptsList qemu_iscsi_opts = {
|
||||
|
@@ -177,6 +177,20 @@ out_free_aiocb:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void laio_detach_aio_context(void *s_, AioContext *old_context)
|
||||
{
|
||||
struct qemu_laio_state *s = s_;
|
||||
|
||||
aio_set_event_notifier(old_context, &s->e, NULL);
|
||||
}
|
||||
|
||||
void laio_attach_aio_context(void *s_, AioContext *new_context)
|
||||
{
|
||||
struct qemu_laio_state *s = s_;
|
||||
|
||||
aio_set_event_notifier(new_context, &s->e, qemu_laio_completion_cb);
|
||||
}
|
||||
|
||||
void *laio_init(void)
|
||||
{
|
||||
struct qemu_laio_state *s;
|
||||
@@ -190,8 +204,6 @@ void *laio_init(void)
|
||||
goto out_close_efd;
|
||||
}
|
||||
|
||||
qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb);
|
||||
|
||||
return s;
|
||||
|
||||
out_close_efd:
|
||||
@@ -200,3 +212,11 @@ out_free_state:
|
||||
g_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void laio_cleanup(void *s_)
|
||||
{
|
||||
struct qemu_laio_state *s = s_;
|
||||
|
||||
event_notifier_cleanup(&s->e);
|
||||
g_free(s);
|
||||
}
|
||||
|
@@ -498,7 +498,7 @@ immediate_exit:
|
||||
/* drop the bs loop chain formed by the swap: break the loop then
|
||||
* trigger the unref from the top one */
|
||||
BlockDriverState *p = s->base->backing_hd;
|
||||
s->base->backing_hd = NULL;
|
||||
bdrv_set_backing_hd(s->base, NULL);
|
||||
bdrv_unref(p);
|
||||
}
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@ static void nbd_teardown_connection(NbdClientSession *client)
|
||||
shutdown(client->sock, 2);
|
||||
nbd_recv_coroutines_enter_all(client);
|
||||
|
||||
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
||||
nbd_client_session_detach_aio_context(client);
|
||||
closesocket(client->sock);
|
||||
client->sock = -1;
|
||||
}
|
||||
@@ -103,11 +103,14 @@ static int nbd_co_send_request(NbdClientSession *s,
|
||||
struct nbd_request *request,
|
||||
QEMUIOVector *qiov, int offset)
|
||||
{
|
||||
AioContext *aio_context;
|
||||
int rc, ret;
|
||||
|
||||
qemu_co_mutex_lock(&s->send_mutex);
|
||||
s->send_coroutine = qemu_coroutine_self();
|
||||
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, s);
|
||||
aio_context = bdrv_get_aio_context(s->bs);
|
||||
aio_set_fd_handler(aio_context, s->sock,
|
||||
nbd_reply_ready, nbd_restart_write, s);
|
||||
if (qiov) {
|
||||
if (!s->is_unix) {
|
||||
socket_set_cork(s->sock, 1);
|
||||
@@ -126,7 +129,7 @@ static int nbd_co_send_request(NbdClientSession *s,
|
||||
} else {
|
||||
rc = nbd_send_request(s->sock, request);
|
||||
}
|
||||
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, s);
|
||||
aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, s);
|
||||
s->send_coroutine = NULL;
|
||||
qemu_co_mutex_unlock(&s->send_mutex);
|
||||
return rc;
|
||||
@@ -335,6 +338,19 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
|
||||
|
||||
}
|
||||
|
||||
void nbd_client_session_detach_aio_context(NbdClientSession *client)
|
||||
{
|
||||
aio_set_fd_handler(bdrv_get_aio_context(client->bs), client->sock,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void nbd_client_session_attach_aio_context(NbdClientSession *client,
|
||||
AioContext *new_context)
|
||||
{
|
||||
aio_set_fd_handler(new_context, client->sock,
|
||||
nbd_reply_ready, NULL, client);
|
||||
}
|
||||
|
||||
void nbd_client_session_close(NbdClientSession *client)
|
||||
{
|
||||
struct nbd_request request = {
|
||||
@@ -381,7 +397,7 @@ int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
|
||||
/* Now that we're connected, set the socket to be non-blocking and
|
||||
* kick the reply mechanism. */
|
||||
qemu_set_nonblock(sock);
|
||||
qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, client);
|
||||
nbd_client_session_attach_aio_context(client, bdrv_get_aio_context(bs));
|
||||
|
||||
logout("Established connection with NBD server\n");
|
||||
return 0;
|
||||
|
@@ -47,4 +47,8 @@ int nbd_client_session_co_writev(NbdClientSession *client, int64_t sector_num,
|
||||
int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num,
|
||||
int nb_sectors, QEMUIOVector *qiov);
|
||||
|
||||
void nbd_client_session_detach_aio_context(NbdClientSession *client);
|
||||
void nbd_client_session_attach_aio_context(NbdClientSession *client,
|
||||
AioContext *new_context);
|
||||
|
||||
#endif /* NBD_CLIENT_H */
|
||||
|
87
block/nbd.c
87
block/nbd.c
@@ -323,46 +323,67 @@ static int64_t nbd_getlength(BlockDriverState *bs)
|
||||
return s->client.size;
|
||||
}
|
||||
|
||||
static void nbd_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
|
||||
nbd_client_session_detach_aio_context(&s->client);
|
||||
}
|
||||
|
||||
static void nbd_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
|
||||
nbd_client_session_attach_aio_context(&s->client, new_context);
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_nbd = {
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_nbd_tcp = {
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+tcp",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+tcp",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_nbd_unix = {
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+unix",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+unix",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
};
|
||||
|
||||
static void bdrv_nbd_init(void)
|
||||
|
75
block/nfs.c
75
block/nfs.c
@@ -40,6 +40,7 @@ typedef struct NFSClient {
|
||||
struct nfsfh *fh;
|
||||
int events;
|
||||
bool has_zero_init;
|
||||
AioContext *aio_context;
|
||||
} NFSClient;
|
||||
|
||||
typedef struct NFSRPC {
|
||||
@@ -49,6 +50,7 @@ typedef struct NFSRPC {
|
||||
struct stat *st;
|
||||
Coroutine *co;
|
||||
QEMUBH *bh;
|
||||
NFSClient *client;
|
||||
} NFSRPC;
|
||||
|
||||
static void nfs_process_read(void *arg);
|
||||
@@ -58,10 +60,11 @@ static void nfs_set_events(NFSClient *client)
|
||||
{
|
||||
int ev = nfs_which_events(client->context);
|
||||
if (ev != client->events) {
|
||||
qemu_aio_set_fd_handler(nfs_get_fd(client->context),
|
||||
(ev & POLLIN) ? nfs_process_read : NULL,
|
||||
(ev & POLLOUT) ? nfs_process_write : NULL,
|
||||
client);
|
||||
aio_set_fd_handler(client->aio_context,
|
||||
nfs_get_fd(client->context),
|
||||
(ev & POLLIN) ? nfs_process_read : NULL,
|
||||
(ev & POLLOUT) ? nfs_process_write : NULL,
|
||||
client);
|
||||
|
||||
}
|
||||
client->events = ev;
|
||||
@@ -84,7 +87,8 @@ static void nfs_process_write(void *arg)
|
||||
static void nfs_co_init_task(NFSClient *client, NFSRPC *task)
|
||||
{
|
||||
*task = (NFSRPC) {
|
||||
.co = qemu_coroutine_self(),
|
||||
.co = qemu_coroutine_self(),
|
||||
.client = client,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -116,7 +120,8 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
|
||||
error_report("NFS Error: %s", nfs_get_error(nfs));
|
||||
}
|
||||
if (task->co) {
|
||||
task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task);
|
||||
task->bh = aio_bh_new(task->client->aio_context,
|
||||
nfs_co_generic_bh_cb, task);
|
||||
qemu_bh_schedule(task->bh);
|
||||
}
|
||||
}
|
||||
@@ -224,13 +229,34 @@ static QemuOptsList runtime_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
static void nfs_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
NFSClient *client = bs->opaque;
|
||||
|
||||
aio_set_fd_handler(client->aio_context,
|
||||
nfs_get_fd(client->context),
|
||||
NULL, NULL, NULL);
|
||||
client->events = 0;
|
||||
}
|
||||
|
||||
static void nfs_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
NFSClient *client = bs->opaque;
|
||||
|
||||
client->aio_context = new_context;
|
||||
nfs_set_events(client);
|
||||
}
|
||||
|
||||
static void nfs_client_close(NFSClient *client)
|
||||
{
|
||||
if (client->context) {
|
||||
if (client->fh) {
|
||||
nfs_close(client->context, client->fh);
|
||||
}
|
||||
qemu_aio_set_fd_handler(nfs_get_fd(client->context), NULL, NULL, NULL);
|
||||
aio_set_fd_handler(client->aio_context,
|
||||
nfs_get_fd(client->context),
|
||||
NULL, NULL, NULL);
|
||||
nfs_destroy_context(client->context);
|
||||
}
|
||||
memset(client, 0, sizeof(NFSClient));
|
||||
@@ -345,6 +371,8 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
|
||||
client->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (local_err) {
|
||||
@@ -368,6 +396,8 @@ static int nfs_file_create(const char *url, QEMUOptionParameter *options,
|
||||
int64_t total_size = 0;
|
||||
NFSClient *client = g_malloc0(sizeof(NFSClient));
|
||||
|
||||
client->aio_context = qemu_get_aio_context();
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, "size")) {
|
||||
@@ -407,7 +437,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
|
||||
|
||||
while (!task.complete) {
|
||||
nfs_set_events(client);
|
||||
qemu_aio_wait();
|
||||
aio_poll(client->aio_context, true);
|
||||
}
|
||||
|
||||
return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize);
|
||||
@@ -420,22 +450,25 @@ static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_nfs = {
|
||||
.format_name = "nfs",
|
||||
.protocol_name = "nfs",
|
||||
.format_name = "nfs",
|
||||
.protocol_name = "nfs",
|
||||
|
||||
.instance_size = sizeof(NFSClient),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_has_zero_init = nfs_has_zero_init,
|
||||
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
|
||||
.bdrv_truncate = nfs_file_truncate,
|
||||
.instance_size = sizeof(NFSClient),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_has_zero_init = nfs_has_zero_init,
|
||||
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
|
||||
.bdrv_truncate = nfs_file_truncate,
|
||||
|
||||
.bdrv_file_open = nfs_file_open,
|
||||
.bdrv_close = nfs_file_close,
|
||||
.bdrv_create = nfs_file_create,
|
||||
.bdrv_file_open = nfs_file_open,
|
||||
.bdrv_close = nfs_file_close,
|
||||
.bdrv_create = nfs_file_create,
|
||||
|
||||
.bdrv_co_readv = nfs_co_readv,
|
||||
.bdrv_co_writev = nfs_co_writev,
|
||||
.bdrv_co_flush_to_disk = nfs_co_flush,
|
||||
.bdrv_co_readv = nfs_co_readv,
|
||||
.bdrv_co_writev = nfs_co_writev,
|
||||
.bdrv_co_flush_to_disk = nfs_co_flush,
|
||||
|
||||
.bdrv_detach_aio_context = nfs_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nfs_attach_aio_context,
|
||||
};
|
||||
|
||||
static void nfs_block_init(void)
|
||||
|
@@ -475,6 +475,7 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
|
||||
case QTYPE_QERROR: {
|
||||
QString *value = qerror_human((QError *)obj);
|
||||
func_fprintf(f, "%s", qstring_get_str(value));
|
||||
QDECREF(value);
|
||||
break;
|
||||
}
|
||||
case QTYPE_NONE:
|
||||
|
@@ -379,7 +379,8 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
|
||||
|
||||
if (!bs->drv) {
|
||||
return -ENOMEDIUM;
|
||||
ret = -ENOMEDIUM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Call .bdrv_co_readv() directly instead of using the public block-layer
|
||||
|
@@ -1308,6 +1308,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||
options = qdict_clone_shallow(bs->options);
|
||||
|
||||
ret = qcow2_open(bs, options, flags, &local_err);
|
||||
QDECREF(options);
|
||||
if (local_err) {
|
||||
error_setg(errp, "Could not reopen qcow2 layer: %s",
|
||||
error_get_pretty(local_err));
|
||||
@@ -1318,8 +1319,6 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
QDECREF(options);
|
||||
|
||||
if (crypt_method) {
|
||||
s->crypt_method = crypt_method;
|
||||
memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
|
||||
|
@@ -173,7 +173,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
|
||||
qed_read_table(s, s->header.l1_table_offset,
|
||||
s->l1_table, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -194,7 +194,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
|
||||
|
||||
qed_write_l1_table(s, index, n, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -267,7 +267,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
|
||||
|
||||
qed_read_l2_table(s, request, offset, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -289,7 +289,7 @@ int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
|
||||
|
||||
qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
35
block/qed.c
35
block/qed.c
@@ -21,12 +21,13 @@
|
||||
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
QEDAIOCB *acb = (QEDAIOCB *)blockacb;
|
||||
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
|
||||
bool finished = false;
|
||||
|
||||
/* Wait for the request to finish */
|
||||
acb->finished = &finished;
|
||||
while (!finished) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +374,27 @@ static void bdrv_qed_rebind(BlockDriverState *bs)
|
||||
s->bs = bs;
|
||||
}
|
||||
|
||||
static void bdrv_qed_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
qed_cancel_need_check_timer(s);
|
||||
timer_free(s->need_check_timer);
|
||||
}
|
||||
|
||||
static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
s->need_check_timer = aio_timer_new(new_context,
|
||||
QEMU_CLOCK_VIRTUAL, SCALE_NS,
|
||||
qed_need_check_timer_cb, s);
|
||||
if (s->header.features & QED_F_NEED_CHECK) {
|
||||
qed_start_need_check_timer(s);
|
||||
}
|
||||
}
|
||||
|
||||
static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -496,8 +518,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
}
|
||||
|
||||
s->need_check_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
qed_need_check_timer_cb, s);
|
||||
bdrv_qed_attach_aio_context(bs, bdrv_get_aio_context(bs));
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
@@ -528,8 +549,7 @@ static void bdrv_qed_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
qed_cancel_need_check_timer(s);
|
||||
timer_free(s->need_check_timer);
|
||||
bdrv_qed_detach_aio_context(bs);
|
||||
|
||||
/* Ensure writes reach stable storage */
|
||||
bdrv_flush(bs->file);
|
||||
@@ -919,7 +939,8 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
|
||||
|
||||
/* Arrange for a bh to invoke the completion function */
|
||||
acb->bh_ret = ret;
|
||||
acb->bh = qemu_bh_new(qed_aio_complete_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
|
||||
qed_aio_complete_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
|
||||
/* Start next allocating write request waiting behind this one. Note that
|
||||
@@ -1644,6 +1665,8 @@ static BlockDriver bdrv_qed = {
|
||||
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
|
||||
.bdrv_invalidate_cache = bdrv_qed_invalidate_cache,
|
||||
.bdrv_check = bdrv_qed_check,
|
||||
.bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
|
||||
.bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
|
||||
};
|
||||
|
||||
static void bdrv_qed_init(void)
|
||||
|
@@ -848,25 +848,49 @@ static void quorum_close(BlockDriverState *bs)
|
||||
g_free(s->bs);
|
||||
}
|
||||
|
||||
static void quorum_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_detach_aio_context(s->bs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void quorum_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_attach_aio_context(s->bs[i], new_context);
|
||||
}
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_quorum = {
|
||||
.format_name = "quorum",
|
||||
.protocol_name = "quorum",
|
||||
.format_name = "quorum",
|
||||
.protocol_name = "quorum",
|
||||
|
||||
.instance_size = sizeof(BDRVQuorumState),
|
||||
.instance_size = sizeof(BDRVQuorumState),
|
||||
|
||||
.bdrv_file_open = quorum_open,
|
||||
.bdrv_close = quorum_close,
|
||||
.bdrv_file_open = quorum_open,
|
||||
.bdrv_close = quorum_close,
|
||||
|
||||
.bdrv_co_flush_to_disk = quorum_co_flush,
|
||||
.bdrv_co_flush_to_disk = quorum_co_flush,
|
||||
|
||||
.bdrv_getlength = quorum_getlength,
|
||||
.bdrv_getlength = quorum_getlength,
|
||||
|
||||
.bdrv_aio_readv = quorum_aio_readv,
|
||||
.bdrv_aio_writev = quorum_aio_writev,
|
||||
.bdrv_invalidate_cache = quorum_invalidate_cache,
|
||||
.bdrv_aio_readv = quorum_aio_readv,
|
||||
.bdrv_aio_writev = quorum_aio_writev,
|
||||
.bdrv_invalidate_cache = quorum_invalidate_cache,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
||||
.bdrv_detach_aio_context = quorum_detach_aio_context,
|
||||
.bdrv_attach_aio_context = quorum_attach_aio_context,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
||||
};
|
||||
|
||||
static void bdrv_quorum_init(void)
|
||||
|
@@ -34,19 +34,27 @@
|
||||
/* linux-aio.c - Linux native implementation */
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
void *laio_init(void);
|
||||
void laio_cleanup(void *s);
|
||||
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque, int type);
|
||||
void laio_detach_aio_context(void *s, AioContext *old_context);
|
||||
void laio_attach_aio_context(void *s, AioContext *new_context);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef struct QEMUWin32AIOState QEMUWin32AIOState;
|
||||
QEMUWin32AIOState *win32_aio_init(void);
|
||||
void win32_aio_cleanup(QEMUWin32AIOState *aio);
|
||||
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
|
||||
BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
|
||||
QEMUWin32AIOState *aio, HANDLE hfile,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque, int type);
|
||||
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *old_context);
|
||||
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *new_context);
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_RAW_AIO_H */
|
||||
|
@@ -307,6 +307,29 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->use_aio) {
|
||||
laio_detach_aio_context(s->aio_ctx, bdrv_get_aio_context(bs));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void raw_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->use_aio) {
|
||||
laio_attach_aio_context(s->aio_ctx, new_context);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags)
|
||||
{
|
||||
@@ -447,6 +470,8 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
}
|
||||
#endif
|
||||
|
||||
raw_attach_aio_context(bs, bdrv_get_aio_context(bs));
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
|
||||
@@ -1059,6 +1084,14 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
raw_detach_aio_context(bs);
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
if (s->use_aio) {
|
||||
laio_cleanup(s->aio_ctx);
|
||||
}
|
||||
#endif
|
||||
if (s->fd >= 0) {
|
||||
qemu_close(s->fd);
|
||||
s->fd = -1;
|
||||
@@ -1192,7 +1225,7 @@ again:
|
||||
if (size == 0)
|
||||
#endif
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
size = LONG_LONG_MAX;
|
||||
size = LLONG_MAX;
|
||||
#else
|
||||
size = lseek(fd, 0LL, SEEK_END);
|
||||
#endif
|
||||
@@ -1478,6 +1511,9 @@ static BlockDriver bdrv_file = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
};
|
||||
|
||||
@@ -1878,6 +1914,9 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* generic scsi device */
|
||||
#ifdef __linux__
|
||||
.bdrv_ioctl = hdev_ioctl,
|
||||
@@ -2020,6 +2059,9 @@ static BlockDriver bdrv_host_floppy = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = floppy_is_inserted,
|
||||
.bdrv_media_changed = floppy_media_changed,
|
||||
@@ -2145,6 +2187,9 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
.bdrv_eject = cdrom_eject,
|
||||
@@ -2276,6 +2321,9 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
.bdrv_eject = cdrom_eject,
|
||||
@@ -2283,40 +2331,6 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
};
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
/**
|
||||
* Return the file descriptor for Linux AIO
|
||||
*
|
||||
* This function is a layering violation and should be removed when it becomes
|
||||
* possible to call the block layer outside the global mutex. It allows the
|
||||
* caller to hijack the file descriptor so I/O can be performed outside the
|
||||
* block layer.
|
||||
*/
|
||||
int raw_get_aio_fd(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s;
|
||||
|
||||
if (!bs->drv) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
if (bs->drv == bdrv_find_format("raw")) {
|
||||
bs = bs->file;
|
||||
}
|
||||
|
||||
/* raw-posix has several protocols so just check for raw_aio_readv */
|
||||
if (bs->drv->bdrv_aio_readv != raw_aio_readv) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
s = bs->opaque;
|
||||
if (!s->use_aio) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return s->fd;
|
||||
}
|
||||
#endif /* CONFIG_LINUX_AIO */
|
||||
|
||||
static void bdrv_file_init(void)
|
||||
{
|
||||
/*
|
||||
|
@@ -36,8 +36,6 @@
|
||||
#define FTYPE_CD 1
|
||||
#define FTYPE_HARDDISK 2
|
||||
|
||||
static QEMUWin32AIOState *aio;
|
||||
|
||||
typedef struct RawWin32AIOData {
|
||||
BlockDriverState *bs;
|
||||
HANDLE hfile;
|
||||
@@ -202,6 +200,25 @@ static int set_sparse(int fd)
|
||||
NULL, 0, NULL, 0, &returned, NULL);
|
||||
}
|
||||
|
||||
static void raw_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->aio) {
|
||||
win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->aio) {
|
||||
win32_aio_attach_aio_context(s->aio, new_context);
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_probe_alignment(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
@@ -300,15 +317,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
raw_parse_flags(flags, &access_flags, &overlapped);
|
||||
|
||||
if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
|
||||
aio = win32_aio_init();
|
||||
if (aio == NULL) {
|
||||
error_setg(errp, "Could not initialize AIO");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (filename[0] && filename[1] == ':') {
|
||||
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
|
||||
} else if (filename[0] == '\\' && filename[1] == '\\') {
|
||||
@@ -335,13 +343,23 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
if (flags & BDRV_O_NATIVE_AIO) {
|
||||
ret = win32_aio_attach(aio, s->hfile);
|
||||
s->aio = win32_aio_init();
|
||||
if (s->aio == NULL) {
|
||||
CloseHandle(s->hfile);
|
||||
error_setg(errp, "Could not initialize AIO");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = win32_aio_attach(s->aio, s->hfile);
|
||||
if (ret < 0) {
|
||||
win32_aio_cleanup(s->aio);
|
||||
CloseHandle(s->hfile);
|
||||
error_setg_errno(errp, -ret, "Could not enable AIO");
|
||||
goto fail;
|
||||
}
|
||||
s->aio = aio;
|
||||
|
||||
win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
|
||||
}
|
||||
|
||||
raw_probe_alignment(bs);
|
||||
@@ -389,6 +407,13 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->aio) {
|
||||
win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
|
||||
win32_aio_cleanup(s->aio);
|
||||
s->aio = NULL;
|
||||
}
|
||||
|
||||
CloseHandle(s->hfile);
|
||||
if (bs->open_flags & BDRV_O_TEMPORARY) {
|
||||
unlink(bs->filename);
|
||||
@@ -684,6 +709,9 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
.bdrv_aio_flush = raw_aio_flush,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.has_variable_length = true,
|
||||
|
||||
|
81
block/rbd.c
81
block/rbd.c
@@ -105,7 +105,7 @@ typedef struct BDRVRBDState {
|
||||
static int qemu_rbd_next_tok(char *dst, int dst_len,
|
||||
char *src, char delim,
|
||||
const char *name,
|
||||
char **p)
|
||||
char **p, Error **errp)
|
||||
{
|
||||
int l;
|
||||
char *end;
|
||||
@@ -128,10 +128,10 @@ static int qemu_rbd_next_tok(char *dst, int dst_len,
|
||||
}
|
||||
l = strlen(src);
|
||||
if (l >= dst_len) {
|
||||
error_report("%s too long", name);
|
||||
error_setg(errp, "%s too long", name);
|
||||
return -EINVAL;
|
||||
} else if (l == 0) {
|
||||
error_report("%s too short", name);
|
||||
error_setg(errp, "%s too short", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -157,13 +157,15 @@ static int qemu_rbd_parsename(const char *filename,
|
||||
char *pool, int pool_len,
|
||||
char *snap, int snap_len,
|
||||
char *name, int name_len,
|
||||
char *conf, int conf_len)
|
||||
char *conf, int conf_len,
|
||||
Error **errp)
|
||||
{
|
||||
const char *start;
|
||||
char *p, *buf;
|
||||
int ret;
|
||||
|
||||
if (!strstart(filename, "rbd:", &start)) {
|
||||
error_setg(errp, "File name must start with 'rbd:'");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -172,7 +174,8 @@ static int qemu_rbd_parsename(const char *filename,
|
||||
*snap = '\0';
|
||||
*conf = '\0';
|
||||
|
||||
ret = qemu_rbd_next_tok(pool, pool_len, p, '/', "pool name", &p);
|
||||
ret = qemu_rbd_next_tok(pool, pool_len, p,
|
||||
'/', "pool name", &p, errp);
|
||||
if (ret < 0 || !p) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
@@ -180,21 +183,25 @@ static int qemu_rbd_parsename(const char *filename,
|
||||
qemu_rbd_unescape(pool);
|
||||
|
||||
if (strchr(p, '@')) {
|
||||
ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p);
|
||||
ret = qemu_rbd_next_tok(name, name_len, p,
|
||||
'@', "object name", &p, errp);
|
||||
if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
ret = qemu_rbd_next_tok(snap, snap_len, p, ':', "snap name", &p);
|
||||
ret = qemu_rbd_next_tok(snap, snap_len, p,
|
||||
':', "snap name", &p, errp);
|
||||
qemu_rbd_unescape(snap);
|
||||
} else {
|
||||
ret = qemu_rbd_next_tok(name, name_len, p, ':', "object name", &p);
|
||||
ret = qemu_rbd_next_tok(name, name_len, p,
|
||||
':', "object name", &p, errp);
|
||||
}
|
||||
qemu_rbd_unescape(name);
|
||||
if (ret < 0 || !p) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = qemu_rbd_next_tok(conf, conf_len, p, '\0', "configuration", &p);
|
||||
ret = qemu_rbd_next_tok(conf, conf_len, p,
|
||||
'\0', "configuration", &p, errp);
|
||||
|
||||
done:
|
||||
g_free(buf);
|
||||
@@ -229,7 +236,7 @@ static char *qemu_rbd_parse_clientname(const char *conf, char *clientname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
|
||||
static int qemu_rbd_set_conf(rados_t cluster, const char *conf, Error **errp)
|
||||
{
|
||||
char *p, *buf;
|
||||
char name[RBD_MAX_CONF_NAME_SIZE];
|
||||
@@ -241,20 +248,20 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
|
||||
|
||||
while (p) {
|
||||
ret = qemu_rbd_next_tok(name, sizeof(name), p,
|
||||
'=', "conf option name", &p);
|
||||
'=', "conf option name", &p, errp);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
qemu_rbd_unescape(name);
|
||||
|
||||
if (!p) {
|
||||
error_report("conf option %s has no value", name);
|
||||
error_setg(errp, "conf option %s has no value", name);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = qemu_rbd_next_tok(value, sizeof(value), p,
|
||||
':', "conf option value", &p);
|
||||
':', "conf option value", &p, errp);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
@@ -263,7 +270,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
|
||||
if (strcmp(name, "conf") == 0) {
|
||||
ret = rados_conf_read_file(cluster, value);
|
||||
if (ret < 0) {
|
||||
error_report("error reading conf file %s", value);
|
||||
error_setg(errp, "error reading conf file %s", value);
|
||||
break;
|
||||
}
|
||||
} else if (strcmp(name, "id") == 0) {
|
||||
@@ -271,7 +278,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
|
||||
} else {
|
||||
ret = rados_conf_set(cluster, name, value);
|
||||
if (ret < 0) {
|
||||
error_report("invalid conf option %s", name);
|
||||
error_setg(errp, "invalid conf option %s", name);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@@ -285,6 +292,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
|
||||
static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int64_t bytes = 0;
|
||||
int64_t objsize;
|
||||
int obj_order = 0;
|
||||
@@ -301,7 +309,8 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (qemu_rbd_parsename(filename, pool, sizeof(pool),
|
||||
snap_buf, sizeof(snap_buf),
|
||||
name, sizeof(name),
|
||||
conf, sizeof(conf)) < 0) {
|
||||
conf, sizeof(conf), &local_err) < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -313,11 +322,11 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (options->value.n) {
|
||||
objsize = options->value.n;
|
||||
if ((objsize - 1) & objsize) { /* not a power of 2? */
|
||||
error_report("obj size needs to be power of 2");
|
||||
error_setg(errp, "obj size needs to be power of 2");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (objsize < 4096) {
|
||||
error_report("obj size too small");
|
||||
error_setg(errp, "obj size too small");
|
||||
return -EINVAL;
|
||||
}
|
||||
obj_order = ffs(objsize) - 1;
|
||||
@@ -328,7 +337,7 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||
|
||||
clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
|
||||
if (rados_create(&cluster, clientname) < 0) {
|
||||
error_report("error initializing");
|
||||
error_setg(errp, "error initializing");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -338,20 +347,20 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
|
||||
if (conf[0] != '\0' &&
|
||||
qemu_rbd_set_conf(cluster, conf) < 0) {
|
||||
error_report("error setting config options");
|
||||
qemu_rbd_set_conf(cluster, conf, &local_err) < 0) {
|
||||
rados_shutdown(cluster);
|
||||
error_propagate(errp, local_err);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (rados_connect(cluster) < 0) {
|
||||
error_report("error connecting");
|
||||
error_setg(errp, "error connecting");
|
||||
rados_shutdown(cluster);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) {
|
||||
error_report("error opening pool %s", pool);
|
||||
error_setg(errp, "error opening pool %s", pool);
|
||||
rados_shutdown(cluster);
|
||||
return -EIO;
|
||||
}
|
||||
@@ -441,8 +450,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
error_propagate(errp, local_err);
|
||||
qemu_opts_del(opts);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -452,7 +460,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
if (qemu_rbd_parsename(filename, pool, sizeof(pool),
|
||||
snap_buf, sizeof(snap_buf),
|
||||
s->name, sizeof(s->name),
|
||||
conf, sizeof(conf)) < 0) {
|
||||
conf, sizeof(conf), errp) < 0) {
|
||||
r = -EINVAL;
|
||||
goto failed_opts;
|
||||
}
|
||||
@@ -460,7 +468,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
|
||||
r = rados_create(&s->cluster, clientname);
|
||||
if (r < 0) {
|
||||
error_report("error initializing");
|
||||
error_setg(&local_err, "error initializing");
|
||||
goto failed_opts;
|
||||
}
|
||||
|
||||
@@ -488,28 +496,27 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
if (conf[0] != '\0') {
|
||||
r = qemu_rbd_set_conf(s->cluster, conf);
|
||||
r = qemu_rbd_set_conf(s->cluster, conf, errp);
|
||||
if (r < 0) {
|
||||
error_report("error setting config options");
|
||||
goto failed_shutdown;
|
||||
}
|
||||
}
|
||||
|
||||
r = rados_connect(s->cluster);
|
||||
if (r < 0) {
|
||||
error_report("error connecting");
|
||||
error_setg(&local_err, "error connecting");
|
||||
goto failed_shutdown;
|
||||
}
|
||||
|
||||
r = rados_ioctx_create(s->cluster, pool, &s->io_ctx);
|
||||
if (r < 0) {
|
||||
error_report("error opening pool %s", pool);
|
||||
error_setg(&local_err, "error opening pool %s", pool);
|
||||
goto failed_shutdown;
|
||||
}
|
||||
|
||||
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
|
||||
if (r < 0) {
|
||||
error_report("error reading header from %s", s->name);
|
||||
error_setg(&local_err, "error reading header from %s", s->name);
|
||||
goto failed_open;
|
||||
}
|
||||
|
||||
@@ -548,7 +555,7 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
acb->cancelled = 1;
|
||||
|
||||
while (acb->status == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(acb->common.bs), true);
|
||||
}
|
||||
|
||||
qemu_aio_release(acb);
|
||||
@@ -581,7 +588,8 @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb)
|
||||
rcb->ret = rbd_aio_get_return_value(c);
|
||||
rbd_aio_release(c);
|
||||
|
||||
acb->bh = qemu_bh_new(rbd_finish_bh, rcb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
|
||||
rbd_finish_bh, rcb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -677,13 +685,16 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
goto failed;
|
||||
goto failed_completion;
|
||||
}
|
||||
|
||||
return &acb->common;
|
||||
|
||||
failed_completion:
|
||||
rbd_aio_release(c);
|
||||
failed:
|
||||
g_free(rcb);
|
||||
qemu_vfree(acb->bounce);
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
320
block/sheepdog.c
320
block/sheepdog.c
@@ -200,6 +200,8 @@ typedef struct SheepdogInode {
|
||||
uint32_t data_vdi_id[MAX_DATA_OBJS];
|
||||
} SheepdogInode;
|
||||
|
||||
#define SD_INODE_HEADER_SIZE offsetof(SheepdogInode, data_vdi_id)
|
||||
|
||||
/*
|
||||
* 64 bit FNV-1a non-zero initial basis
|
||||
*/
|
||||
@@ -282,6 +284,7 @@ typedef struct AIOReq {
|
||||
unsigned int data_len;
|
||||
uint8_t flags;
|
||||
uint32_t id;
|
||||
bool create;
|
||||
|
||||
QLIST_ENTRY(AIOReq) aio_siblings;
|
||||
} AIOReq;
|
||||
@@ -314,6 +317,7 @@ struct SheepdogAIOCB {
|
||||
|
||||
typedef struct BDRVSheepdogState {
|
||||
BlockDriverState *bs;
|
||||
AioContext *aio_context;
|
||||
|
||||
SheepdogInode inode;
|
||||
|
||||
@@ -404,7 +408,7 @@ static const char * sd_strerror(int err)
|
||||
|
||||
static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
|
||||
uint64_t oid, unsigned int data_len,
|
||||
uint64_t offset, uint8_t flags,
|
||||
uint64_t offset, uint8_t flags, bool create,
|
||||
uint64_t base_oid, unsigned int iov_offset)
|
||||
{
|
||||
AIOReq *aio_req;
|
||||
@@ -418,6 +422,7 @@ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
|
||||
aio_req->data_len = data_len;
|
||||
aio_req->flags = flags;
|
||||
aio_req->id = s->aioreq_seq_num++;
|
||||
aio_req->create = create;
|
||||
|
||||
acb->nr_pending++;
|
||||
return aio_req;
|
||||
@@ -496,7 +501,7 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
sd_finish_aiocb(acb);
|
||||
return;
|
||||
}
|
||||
qemu_aio_wait();
|
||||
aio_poll(s->aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,17 +531,16 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
|
||||
return acb;
|
||||
}
|
||||
|
||||
static int connect_to_sdog(BDRVSheepdogState *s)
|
||||
static int connect_to_sdog(BDRVSheepdogState *s, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
Error *err = NULL;
|
||||
|
||||
if (s->is_unix) {
|
||||
fd = unix_connect(s->host_spec, &err);
|
||||
fd = unix_connect(s->host_spec, errp);
|
||||
} else {
|
||||
fd = inet_connect(s->host_spec, &err);
|
||||
fd = inet_connect(s->host_spec, errp);
|
||||
|
||||
if (err == NULL) {
|
||||
if (fd >= 0) {
|
||||
int ret = socket_set_nodelay(fd);
|
||||
if (ret < 0) {
|
||||
error_report("%s", strerror(errno));
|
||||
@@ -544,10 +548,7 @@ static int connect_to_sdog(BDRVSheepdogState *s)
|
||||
}
|
||||
}
|
||||
|
||||
if (err != NULL) {
|
||||
qerror_report_err(err);
|
||||
error_free(err);
|
||||
} else {
|
||||
if (fd >= 0) {
|
||||
qemu_set_nonblock(fd);
|
||||
}
|
||||
|
||||
@@ -582,6 +583,7 @@ static void restart_co_req(void *opaque)
|
||||
|
||||
typedef struct SheepdogReqCo {
|
||||
int sockfd;
|
||||
AioContext *aio_context;
|
||||
SheepdogReq *hdr;
|
||||
void *data;
|
||||
unsigned int *wlen;
|
||||
@@ -602,14 +604,14 @@ static coroutine_fn void do_co_req(void *opaque)
|
||||
unsigned int *rlen = srco->rlen;
|
||||
|
||||
co = qemu_coroutine_self();
|
||||
qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, co);
|
||||
aio_set_fd_handler(srco->aio_context, sockfd, NULL, restart_co_req, co);
|
||||
|
||||
ret = send_co_req(sockfd, hdr, data, wlen);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, co);
|
||||
aio_set_fd_handler(srco->aio_context, sockfd, restart_co_req, NULL, co);
|
||||
|
||||
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
|
||||
if (ret != sizeof(*hdr)) {
|
||||
@@ -634,18 +636,19 @@ static coroutine_fn void do_co_req(void *opaque)
|
||||
out:
|
||||
/* there is at most one request for this sockfd, so it is safe to
|
||||
* set each handler to NULL. */
|
||||
qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL);
|
||||
aio_set_fd_handler(srco->aio_context, sockfd, NULL, NULL, NULL);
|
||||
|
||||
srco->ret = ret;
|
||||
srco->finished = true;
|
||||
}
|
||||
|
||||
static int do_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
unsigned int *wlen, unsigned int *rlen)
|
||||
static int do_req(int sockfd, AioContext *aio_context, SheepdogReq *hdr,
|
||||
void *data, unsigned int *wlen, unsigned int *rlen)
|
||||
{
|
||||
Coroutine *co;
|
||||
SheepdogReqCo srco = {
|
||||
.sockfd = sockfd,
|
||||
.aio_context = aio_context,
|
||||
.hdr = hdr,
|
||||
.data = data,
|
||||
.wlen = wlen,
|
||||
@@ -660,7 +663,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
co = qemu_coroutine_create(do_co_req);
|
||||
qemu_coroutine_enter(co, &srco);
|
||||
while (!srco.finished) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,11 +671,11 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
}
|
||||
|
||||
static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
struct iovec *iov, int niov, bool create,
|
||||
enum AIOCBState aiocb_type);
|
||||
struct iovec *iov, int niov,
|
||||
enum AIOCBState aiocb_type);
|
||||
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req);
|
||||
static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag);
|
||||
static int get_sheep_fd(BDRVSheepdogState *s);
|
||||
static int get_sheep_fd(BDRVSheepdogState *s, Error **errp);
|
||||
static void co_write_request(void *opaque);
|
||||
|
||||
static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid)
|
||||
@@ -702,17 +705,18 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid)
|
||||
/* move aio_req from pending list to inflight one */
|
||||
QLIST_REMOVE(aio_req, aio_siblings);
|
||||
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
|
||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, false,
|
||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
|
||||
acb->aiocb_type);
|
||||
}
|
||||
}
|
||||
|
||||
static coroutine_fn void reconnect_to_sdog(void *opaque)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BDRVSheepdogState *s = opaque;
|
||||
AIOReq *aio_req, *next;
|
||||
|
||||
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
|
||||
close(s->fd);
|
||||
s->fd = -1;
|
||||
|
||||
@@ -723,9 +727,11 @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
|
||||
|
||||
/* Try to reconnect the sheepdog server every one second. */
|
||||
while (s->fd < 0) {
|
||||
s->fd = get_sheep_fd(s);
|
||||
s->fd = get_sheep_fd(s, &local_err);
|
||||
if (s->fd < 0) {
|
||||
DPRINTF("Wait for connection to be established\n");
|
||||
error_report("%s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME,
|
||||
1000000000ULL);
|
||||
}
|
||||
@@ -798,7 +804,7 @@ static void coroutine_fn aio_read_response(void *opaque)
|
||||
}
|
||||
idx = data_oid_to_idx(aio_req->oid);
|
||||
|
||||
if (s->inode.data_vdi_id[idx] != s->inode.vdi_id) {
|
||||
if (aio_req->create) {
|
||||
/*
|
||||
* If the object is newly created one, we need to update
|
||||
* the vdi object (metadata object). min_dirty_data_idx
|
||||
@@ -914,16 +920,16 @@ static void co_write_request(void *opaque)
|
||||
* We cannot use this descriptor for other operations because
|
||||
* the block driver may be on waiting response from the server.
|
||||
*/
|
||||
static int get_sheep_fd(BDRVSheepdogState *s)
|
||||
static int get_sheep_fd(BDRVSheepdogState *s, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, errp);
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
qemu_aio_set_fd_handler(fd, co_read_response, NULL, s);
|
||||
aio_set_fd_handler(s->aio_context, fd, co_read_response, NULL, s);
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -1061,7 +1067,7 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
|
||||
|
||||
static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
||||
uint32_t snapid, const char *tag, uint32_t *vid,
|
||||
bool lock)
|
||||
bool lock, Error **errp)
|
||||
{
|
||||
int ret, fd;
|
||||
SheepdogVdiReq hdr;
|
||||
@@ -1069,7 +1075,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
||||
unsigned int wlen, rlen = 0;
|
||||
char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN];
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, errp);
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
@@ -1093,14 +1099,15 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
||||
hdr.snapid = snapid;
|
||||
hdr.flags = SD_FLAG_CMD_WRITE;
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, -ret, "cannot get vdi info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rsp->result != SD_RES_SUCCESS) {
|
||||
error_report("cannot get vdi info, %s, %s %" PRIu32 " %s",
|
||||
sd_strerror(rsp->result), filename, snapid, tag);
|
||||
error_setg(errp, "cannot get vdi info, %s, %s %" PRIu32 " %s",
|
||||
sd_strerror(rsp->result), filename, snapid, tag);
|
||||
if (rsp->result == SD_RES_NO_VDI) {
|
||||
ret = -ENOENT;
|
||||
} else {
|
||||
@@ -1117,8 +1124,8 @@ out:
|
||||
}
|
||||
|
||||
static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
struct iovec *iov, int niov, bool create,
|
||||
enum AIOCBState aiocb_type)
|
||||
struct iovec *iov, int niov,
|
||||
enum AIOCBState aiocb_type)
|
||||
{
|
||||
int nr_copies = s->inode.nr_copies;
|
||||
SheepdogObjReq hdr;
|
||||
@@ -1129,6 +1136,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
uint64_t offset = aio_req->offset;
|
||||
uint8_t flags = aio_req->flags;
|
||||
uint64_t old_oid = aio_req->base_oid;
|
||||
bool create = aio_req->create;
|
||||
|
||||
if (!nr_copies) {
|
||||
error_report("bug");
|
||||
@@ -1173,7 +1181,8 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
s->co_send = qemu_coroutine_self();
|
||||
qemu_aio_set_fd_handler(s->fd, co_read_response, co_write_request, s);
|
||||
aio_set_fd_handler(s->aio_context, s->fd,
|
||||
co_read_response, co_write_request, s);
|
||||
socket_set_cork(s->fd, 1);
|
||||
|
||||
/* send a header */
|
||||
@@ -1191,12 +1200,13 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
}
|
||||
out:
|
||||
socket_set_cork(s->fd, 0);
|
||||
qemu_aio_set_fd_handler(s->fd, co_read_response, NULL, s);
|
||||
aio_set_fd_handler(s->aio_context, s->fd, co_read_response, NULL, s);
|
||||
s->co_send = NULL;
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
}
|
||||
|
||||
static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
|
||||
static int read_write_object(int fd, AioContext *aio_context, char *buf,
|
||||
uint64_t oid, uint8_t copies,
|
||||
unsigned int datalen, uint64_t offset,
|
||||
bool write, bool create, uint32_t cache_flags)
|
||||
{
|
||||
@@ -1229,7 +1239,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
|
||||
hdr.offset = offset;
|
||||
hdr.copies = copies;
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
ret = do_req(fd, aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
if (ret) {
|
||||
error_report("failed to send a request to the sheep");
|
||||
return ret;
|
||||
@@ -1244,49 +1254,59 @@ static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
|
||||
}
|
||||
}
|
||||
|
||||
static int read_object(int fd, char *buf, uint64_t oid, uint8_t copies,
|
||||
static int read_object(int fd, AioContext *aio_context, char *buf,
|
||||
uint64_t oid, uint8_t copies,
|
||||
unsigned int datalen, uint64_t offset,
|
||||
uint32_t cache_flags)
|
||||
{
|
||||
return read_write_object(fd, buf, oid, copies, datalen, offset, false,
|
||||
return read_write_object(fd, aio_context, buf, oid, copies,
|
||||
datalen, offset, false,
|
||||
false, cache_flags);
|
||||
}
|
||||
|
||||
static int write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
|
||||
static int write_object(int fd, AioContext *aio_context, char *buf,
|
||||
uint64_t oid, uint8_t copies,
|
||||
unsigned int datalen, uint64_t offset, bool create,
|
||||
uint32_t cache_flags)
|
||||
{
|
||||
return read_write_object(fd, buf, oid, copies, datalen, offset, true,
|
||||
return read_write_object(fd, aio_context, buf, oid, copies,
|
||||
datalen, offset, true,
|
||||
create, cache_flags);
|
||||
}
|
||||
|
||||
/* update inode with the latest state */
|
||||
static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
SheepdogInode *inode;
|
||||
int ret = 0, fd;
|
||||
uint32_t vid = 0;
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
inode = g_malloc(sizeof(s->inode));
|
||||
inode = g_malloc(SD_INODE_HEADER_SIZE);
|
||||
|
||||
ret = find_vdi_name(s, s->name, snapid, tag, &vid, false);
|
||||
ret = find_vdi_name(s, s->name, snapid, tag, &vid, false, &local_err);
|
||||
if (ret) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(vid),
|
||||
s->inode.nr_copies, sizeof(*inode), 0, s->cache_flags);
|
||||
ret = read_object(fd, s->aio_context, (char *)inode, vid_to_vdi_oid(vid),
|
||||
s->inode.nr_copies, SD_INODE_HEADER_SIZE, 0,
|
||||
s->cache_flags);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (inode->vdi_id != s->inode.vdi_id) {
|
||||
memcpy(&s->inode, inode, sizeof(s->inode));
|
||||
memcpy(&s->inode, inode, SD_INODE_HEADER_SIZE);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -1310,6 +1330,7 @@ static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
|
||||
DPRINTF("simultaneous create to %" PRIx64 "\n", aio_req->oid);
|
||||
aio_req->flags = 0;
|
||||
aio_req->base_oid = 0;
|
||||
aio_req->create = false;
|
||||
QLIST_REMOVE(aio_req, aio_siblings);
|
||||
QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
|
||||
return true;
|
||||
@@ -1322,7 +1343,8 @@ static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
|
||||
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
|
||||
{
|
||||
SheepdogAIOCB *acb = aio_req->aiocb;
|
||||
bool create = false;
|
||||
|
||||
aio_req->create = false;
|
||||
|
||||
/* check whether this request becomes a CoW one */
|
||||
if (acb->aiocb_type == AIOCB_WRITE_UDATA && is_data_obj(aio_req->oid)) {
|
||||
@@ -1340,20 +1362,36 @@ static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
|
||||
aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
|
||||
aio_req->flags |= SD_FLAG_CMD_COW;
|
||||
}
|
||||
create = true;
|
||||
aio_req->create = true;
|
||||
}
|
||||
out:
|
||||
if (is_data_obj(aio_req->oid)) {
|
||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
|
||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
|
||||
acb->aiocb_type);
|
||||
} else {
|
||||
struct iovec iov;
|
||||
iov.iov_base = &s->inode;
|
||||
iov.iov_len = sizeof(s->inode);
|
||||
add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
|
||||
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
|
||||
aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void sd_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
|
||||
s->aio_context = new_context;
|
||||
aio_set_fd_handler(new_context, s->fd, co_read_response, NULL, s);
|
||||
}
|
||||
|
||||
/* TODO Convert to fine grained options */
|
||||
static QemuOptsList runtime_opts = {
|
||||
.name = "sheepdog",
|
||||
@@ -1382,12 +1420,12 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
const char *filename;
|
||||
|
||||
s->bs = bs;
|
||||
s->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1408,15 +1446,16 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = parse_vdiname(s, filename, vdi, &snapid, tag);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Can't parse filename");
|
||||
goto out;
|
||||
}
|
||||
s->fd = get_sheep_fd(s);
|
||||
s->fd = get_sheep_fd(s, errp);
|
||||
if (s->fd < 0) {
|
||||
ret = s->fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = find_vdi_name(s, vdi, snapid, tag, &vid, true);
|
||||
ret = find_vdi_name(s, vdi, snapid, tag, &vid, true, errp);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
@@ -1436,19 +1475,20 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->is_snapshot = true;
|
||||
}
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, errp);
|
||||
if (fd < 0) {
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = g_malloc(SD_INODE_SIZE);
|
||||
ret = read_object(fd, buf, vid_to_vdi_oid(vid), 0, SD_INODE_SIZE, 0,
|
||||
s->cache_flags);
|
||||
ret = read_object(fd, s->aio_context, buf, vid_to_vdi_oid(vid),
|
||||
0, SD_INODE_SIZE, 0, s->cache_flags);
|
||||
|
||||
closesocket(fd);
|
||||
|
||||
if (ret) {
|
||||
error_setg(errp, "Can't read snapshot inode");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1463,7 +1503,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
g_free(buf);
|
||||
return 0;
|
||||
out:
|
||||
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
|
||||
if (s->fd >= 0) {
|
||||
closesocket(s->fd);
|
||||
}
|
||||
@@ -1472,7 +1512,8 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
|
||||
static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot,
|
||||
Error **errp)
|
||||
{
|
||||
SheepdogVdiReq hdr;
|
||||
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
||||
@@ -1480,7 +1521,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
|
||||
unsigned int wlen, rlen = 0;
|
||||
char buf[SD_MAX_VDI_LEN];
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, errp);
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
@@ -1505,16 +1546,17 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
|
||||
hdr.copy_policy = s->inode.copy_policy;
|
||||
hdr.copies = s->inode.nr_copies;
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
|
||||
closesocket(fd);
|
||||
|
||||
if (ret) {
|
||||
error_setg_errno(errp, -ret, "create failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rsp->result != SD_RES_SUCCESS) {
|
||||
error_report("%s, %s", sd_strerror(rsp->result), s->inode.name);
|
||||
error_setg(errp, "%s, %s", sd_strerror(rsp->result), s->inode.name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1525,21 +1567,18 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_prealloc(const char *filename)
|
||||
static int sd_prealloc(const char *filename, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
uint32_t idx, max_idx;
|
||||
int64_t vdi_size;
|
||||
void *buf = g_malloc0(SD_DATA_OBJ_SIZE);
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
|
||||
NULL, &local_err);
|
||||
NULL, errp);
|
||||
if (ret < 0) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
goto out;
|
||||
goto out_with_err_set;
|
||||
}
|
||||
|
||||
vdi_size = bdrv_getlength(bs);
|
||||
@@ -1563,7 +1602,12 @@ static int sd_prealloc(const char *filename)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Can't pre-allocate");
|
||||
}
|
||||
out_with_err_set:
|
||||
if (bs) {
|
||||
bdrv_unref(bs);
|
||||
}
|
||||
@@ -1636,7 +1680,6 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
char tag[SD_MAX_VDI_TAG_LEN];
|
||||
uint32_t snapid;
|
||||
bool prealloc = false;
|
||||
Error *local_err = NULL;
|
||||
|
||||
s = g_malloc0(sizeof(BDRVSheepdogState));
|
||||
|
||||
@@ -1647,6 +1690,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
ret = parse_vdiname(s, filename, s->name, &snapid, tag);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Can't parse filename");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1661,8 +1705,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
} else if (!strcmp(options->value.s, "full")) {
|
||||
prealloc = true;
|
||||
} else {
|
||||
error_report("Invalid preallocation mode: '%s'",
|
||||
options->value.s);
|
||||
error_setg(errp, "Invalid preallocation mode: '%s'",
|
||||
options->value.s);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1670,6 +1714,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (options->value.s) {
|
||||
ret = parse_redundancy(s, options->value.s);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Invalid redundancy mode: '%s'",
|
||||
options->value.s);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -1678,7 +1724,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
|
||||
if (s->inode.vdi_size > SD_MAX_VDI_SIZE) {
|
||||
error_report("too big image size");
|
||||
error_setg(errp, "too big image size");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1691,24 +1737,22 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
/* Currently, only Sheepdog backing image is supported. */
|
||||
drv = bdrv_find_protocol(backing_file, true);
|
||||
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
|
||||
error_report("backing_file must be a sheepdog image");
|
||||
error_setg(errp, "backing_file must be a sheepdog image");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bs = NULL;
|
||||
ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_PROTOCOL, NULL,
|
||||
&local_err);
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
base = bs->opaque;
|
||||
|
||||
if (!is_snapshot(&base->inode)) {
|
||||
error_report("cannot clone from a non snapshot vdi");
|
||||
error_setg(errp, "cannot clone from a non snapshot vdi");
|
||||
bdrv_unref(bs);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
@@ -1717,12 +1761,14 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
||||
bdrv_unref(bs);
|
||||
}
|
||||
|
||||
ret = do_sd_create(s, &vid, 0);
|
||||
if (!prealloc || ret) {
|
||||
ret = do_sd_create(s, &vid, 0, errp);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sd_prealloc(filename);
|
||||
if (prealloc) {
|
||||
ret = sd_prealloc(filename, errp);
|
||||
}
|
||||
out:
|
||||
g_free(s);
|
||||
return ret;
|
||||
@@ -1730,6 +1776,7 @@ out:
|
||||
|
||||
static void sd_close(BlockDriverState *bs)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
SheepdogVdiReq hdr;
|
||||
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
||||
@@ -1738,8 +1785,10 @@ static void sd_close(BlockDriverState *bs)
|
||||
|
||||
DPRINTF("%s\n", s->name);
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1751,7 +1800,8 @@ static void sd_close(BlockDriverState *bs)
|
||||
hdr.data_length = wlen;
|
||||
hdr.flags = SD_FLAG_CMD_WRITE;
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, s->name, &wlen, &rlen);
|
||||
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr,
|
||||
s->name, &wlen, &rlen);
|
||||
|
||||
closesocket(fd);
|
||||
|
||||
@@ -1760,7 +1810,7 @@ static void sd_close(BlockDriverState *bs)
|
||||
error_report("%s, %s", sd_strerror(rsp->result), s->name);
|
||||
}
|
||||
|
||||
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
|
||||
closesocket(s->fd);
|
||||
g_free(s->host_spec);
|
||||
}
|
||||
@@ -1774,6 +1824,7 @@ static int64_t sd_getlength(BlockDriverState *bs)
|
||||
|
||||
static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
int ret, fd;
|
||||
unsigned int datalen;
|
||||
@@ -1786,16 +1837,19 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* we don't need to update entire object */
|
||||
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
|
||||
s->inode.vdi_size = offset;
|
||||
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
|
||||
s->inode.nr_copies, datalen, 0, false, s->cache_flags);
|
||||
ret = write_object(fd, s->aio_context, (char *)&s->inode,
|
||||
vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies,
|
||||
datalen, 0, false, s->cache_flags);
|
||||
close(fd);
|
||||
|
||||
if (ret < 0) {
|
||||
@@ -1831,9 +1885,9 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
|
||||
iov.iov_base = &s->inode;
|
||||
iov.iov_len = sizeof(s->inode);
|
||||
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
|
||||
data_len, offset, 0, 0, offset);
|
||||
data_len, offset, 0, false, 0, offset);
|
||||
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
|
||||
add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
|
||||
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
|
||||
|
||||
acb->aio_done_func = sd_finish_aiocb;
|
||||
acb->aiocb_type = AIOCB_WRITE_UDATA;
|
||||
@@ -1846,6 +1900,7 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
|
||||
/* Delete current working VDI on the snapshot chain */
|
||||
static bool sd_delete(BDRVSheepdogState *s)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0;
|
||||
SheepdogVdiReq hdr = {
|
||||
.opcode = SD_OP_DEL_VDI,
|
||||
@@ -1856,12 +1911,15 @@ static bool sd_delete(BDRVSheepdogState *s)
|
||||
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
||||
int fd, ret;
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, s->name, &wlen, &rlen);
|
||||
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr,
|
||||
s->name, &wlen, &rlen);
|
||||
closesocket(fd);
|
||||
if (ret) {
|
||||
return false;
|
||||
@@ -1885,6 +1943,7 @@ static bool sd_delete(BDRVSheepdogState *s)
|
||||
*/
|
||||
static int sd_create_branch(BDRVSheepdogState *s)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int ret, fd;
|
||||
uint32_t vid;
|
||||
char *buf;
|
||||
@@ -1900,21 +1959,25 @@ static int sd_create_branch(BDRVSheepdogState *s)
|
||||
* false bail out.
|
||||
*/
|
||||
deleted = sd_delete(s);
|
||||
ret = do_sd_create(s, &vid, !deleted);
|
||||
ret = do_sd_create(s, &vid, !deleted, &local_err);
|
||||
if (ret) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
DPRINTF("%" PRIx32 " is created.\n", vid);
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = read_object(fd, buf, vid_to_vdi_oid(vid), s->inode.nr_copies,
|
||||
SD_INODE_SIZE, 0, s->cache_flags);
|
||||
ret = read_object(fd, s->aio_context, buf, vid_to_vdi_oid(vid),
|
||||
s->inode.nr_copies, SD_INODE_SIZE, 0, s->cache_flags);
|
||||
|
||||
closesocket(fd);
|
||||
|
||||
@@ -2023,7 +2086,8 @@ static int coroutine_fn sd_co_rw_vector(void *p)
|
||||
DPRINTF("new oid %" PRIx64 "\n", oid);
|
||||
}
|
||||
|
||||
aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, old_oid, done);
|
||||
aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, create,
|
||||
old_oid, done);
|
||||
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
|
||||
|
||||
if (create) {
|
||||
@@ -2032,7 +2096,7 @@ static int coroutine_fn sd_co_rw_vector(void *p)
|
||||
}
|
||||
}
|
||||
|
||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
|
||||
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
|
||||
acb->aiocb_type);
|
||||
done:
|
||||
offset = 0;
|
||||
@@ -2112,9 +2176,9 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
|
||||
acb->aio_done_func = sd_finish_aiocb;
|
||||
|
||||
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
|
||||
0, 0, 0, 0, 0);
|
||||
0, 0, 0, false, 0, 0);
|
||||
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
|
||||
add_aio_request(s, aio_req, NULL, 0, false, acb->aiocb_type);
|
||||
add_aio_request(s, aio_req, NULL, 0, acb->aiocb_type);
|
||||
|
||||
qemu_coroutine_yield();
|
||||
return acb->ret;
|
||||
@@ -2122,6 +2186,7 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
|
||||
|
||||
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
int ret, fd;
|
||||
uint32_t new_vid;
|
||||
@@ -2149,32 +2214,37 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
|
||||
/* we don't need to update entire object */
|
||||
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
|
||||
inode = g_malloc(datalen);
|
||||
|
||||
/* refresh inode. */
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
ret = fd;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
|
||||
s->inode.nr_copies, datalen, 0, false, s->cache_flags);
|
||||
ret = write_object(fd, s->aio_context, (char *)&s->inode,
|
||||
vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies,
|
||||
datalen, 0, false, s->cache_flags);
|
||||
if (ret < 0) {
|
||||
error_report("failed to write snapshot's inode.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = do_sd_create(s, &new_vid, 1);
|
||||
ret = do_sd_create(s, &new_vid, 1, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
error_report("failed to create inode for snapshot. %s",
|
||||
strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
inode = (SheepdogInode *)g_malloc(datalen);
|
||||
|
||||
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
|
||||
s->inode.nr_copies, datalen, 0, s->cache_flags);
|
||||
ret = read_object(fd, s->aio_context, (char *)inode,
|
||||
vid_to_vdi_oid(new_vid), s->inode.nr_copies, datalen, 0,
|
||||
s->cache_flags);
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to read new inode info. %s", strerror(errno));
|
||||
@@ -2186,6 +2256,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
s->inode.name, s->inode.snap_id, s->inode.vdi_id);
|
||||
|
||||
cleanup:
|
||||
g_free(inode);
|
||||
closesocket(fd);
|
||||
return ret;
|
||||
}
|
||||
@@ -2249,6 +2320,7 @@ static int sd_snapshot_delete(BlockDriverState *bs,
|
||||
|
||||
static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
SheepdogReq req;
|
||||
int fd, nr = 1024, ret, max = BITS_TO_LONGS(SD_NR_VDIS) * sizeof(long);
|
||||
@@ -2263,8 +2335,10 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
|
||||
vdi_inuse = g_malloc(max);
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
@@ -2277,7 +2351,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
req.opcode = SD_OP_READ_VDIS;
|
||||
req.data_length = max;
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&req, vdi_inuse, &wlen, &rlen);
|
||||
ret = do_req(fd, s->aio_context, (SheepdogReq *)&req,
|
||||
vdi_inuse, &wlen, &rlen);
|
||||
|
||||
closesocket(fd);
|
||||
if (ret) {
|
||||
@@ -2290,8 +2365,10 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT);
|
||||
start_nr = hval & (SD_NR_VDIS - 1);
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
@@ -2302,7 +2379,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
}
|
||||
|
||||
/* we don't need to read entire object */
|
||||
ret = read_object(fd, (char *)&inode, vid_to_vdi_oid(vid),
|
||||
ret = read_object(fd, s->aio_context, (char *)&inode,
|
||||
vid_to_vdi_oid(vid),
|
||||
0, SD_INODE_SIZE - sizeof(inode.data_vdi_id), 0,
|
||||
s->cache_flags);
|
||||
|
||||
@@ -2341,6 +2419,7 @@ out:
|
||||
static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
int64_t pos, int size, int load)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
bool create;
|
||||
int fd, ret = 0, remaining = size;
|
||||
unsigned int data_len;
|
||||
@@ -2349,8 +2428,10 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
uint32_t vdi_index;
|
||||
uint32_t vdi_id = load ? s->inode.parent_vdi_id : s->inode.vdi_id;
|
||||
|
||||
fd = connect_to_sdog(s);
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report("%s", error_get_pretty(local_err));;
|
||||
error_free(local_err);
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -2364,11 +2445,11 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
|
||||
create = (offset == 0);
|
||||
if (load) {
|
||||
ret = read_object(fd, (char *)data, vmstate_oid,
|
||||
ret = read_object(fd, s->aio_context, (char *)data, vmstate_oid,
|
||||
s->inode.nr_copies, data_len, offset,
|
||||
s->cache_flags);
|
||||
} else {
|
||||
ret = write_object(fd, (char *)data, vmstate_oid,
|
||||
ret = write_object(fd, s->aio_context, (char *)data, vmstate_oid,
|
||||
s->inode.nr_copies, data_len, offset, create,
|
||||
s->cache_flags);
|
||||
}
|
||||
@@ -2541,6 +2622,9 @@ static BlockDriver bdrv_sheepdog = {
|
||||
.bdrv_save_vmstate = sd_save_vmstate,
|
||||
.bdrv_load_vmstate = sd_load_vmstate,
|
||||
|
||||
.bdrv_detach_aio_context = sd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = sd_attach_aio_context,
|
||||
|
||||
.create_options = sd_create_options,
|
||||
};
|
||||
|
||||
@@ -2571,6 +2655,9 @@ static BlockDriver bdrv_sheepdog_tcp = {
|
||||
.bdrv_save_vmstate = sd_save_vmstate,
|
||||
.bdrv_load_vmstate = sd_load_vmstate,
|
||||
|
||||
.bdrv_detach_aio_context = sd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = sd_attach_aio_context,
|
||||
|
||||
.create_options = sd_create_options,
|
||||
};
|
||||
|
||||
@@ -2601,6 +2688,9 @@ static BlockDriver bdrv_sheepdog_unix = {
|
||||
.bdrv_save_vmstate = sd_save_vmstate,
|
||||
.bdrv_load_vmstate = sd_load_vmstate,
|
||||
|
||||
.bdrv_detach_aio_context = sd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = sd_attach_aio_context,
|
||||
|
||||
.create_options = sd_create_options,
|
||||
};
|
||||
|
||||
|
187
block/ssh.c
187
block/ssh.c
@@ -106,30 +106,59 @@ static void ssh_state_free(BDRVSSHState *s)
|
||||
}
|
||||
}
|
||||
|
||||
/* Wrappers around error_report which make sure to dump as much
|
||||
* information from libssh2 as possible.
|
||||
*/
|
||||
static void GCC_FMT_ATTR(2, 3)
|
||||
session_error_report(BDRVSSHState *s, const char *fs, ...)
|
||||
static void GCC_FMT_ATTR(3, 4)
|
||||
session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *msg;
|
||||
|
||||
va_start(args, fs);
|
||||
error_vprintf(fs, args);
|
||||
msg = g_strdup_vprintf(fs, args);
|
||||
va_end(args);
|
||||
|
||||
if ((s)->session) {
|
||||
if (s->session) {
|
||||
char *ssh_err;
|
||||
int ssh_err_code;
|
||||
|
||||
libssh2_session_last_error((s)->session, &ssh_err, NULL, 0);
|
||||
/* This is not an errno. See <libssh2.h>. */
|
||||
ssh_err_code = libssh2_session_last_errno((s)->session);
|
||||
|
||||
error_printf(": %s (libssh2 error code: %d)", ssh_err, ssh_err_code);
|
||||
ssh_err_code = libssh2_session_last_error(s->session,
|
||||
&ssh_err, NULL, 0);
|
||||
error_setg(errp, "%s: %s (libssh2 error code: %d)",
|
||||
msg, ssh_err, ssh_err_code);
|
||||
} else {
|
||||
error_setg(errp, "%s", msg);
|
||||
}
|
||||
g_free(msg);
|
||||
}
|
||||
|
||||
static void GCC_FMT_ATTR(3, 4)
|
||||
sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *msg;
|
||||
|
||||
va_start(args, fs);
|
||||
msg = g_strdup_vprintf(fs, args);
|
||||
va_end(args);
|
||||
error_printf("\n");
|
||||
|
||||
if (s->sftp) {
|
||||
char *ssh_err;
|
||||
int ssh_err_code;
|
||||
unsigned long sftp_err_code;
|
||||
|
||||
/* This is not an errno. See <libssh2.h>. */
|
||||
ssh_err_code = libssh2_session_last_error(s->session,
|
||||
&ssh_err, NULL, 0);
|
||||
/* See <libssh2_sftp.h>. */
|
||||
sftp_err_code = libssh2_sftp_last_error((s)->sftp);
|
||||
|
||||
error_setg(errp,
|
||||
"%s: %s (libssh2 error code: %d, sftp error code: %lu)",
|
||||
msg, ssh_err, ssh_err_code, sftp_err_code);
|
||||
} else {
|
||||
error_setg(errp, "%s", msg);
|
||||
}
|
||||
g_free(msg);
|
||||
}
|
||||
|
||||
static void GCC_FMT_ATTR(2, 3)
|
||||
@@ -145,9 +174,9 @@ sftp_error_report(BDRVSSHState *s, const char *fs, ...)
|
||||
int ssh_err_code;
|
||||
unsigned long sftp_err_code;
|
||||
|
||||
libssh2_session_last_error((s)->session, &ssh_err, NULL, 0);
|
||||
/* This is not an errno. See <libssh2.h>. */
|
||||
ssh_err_code = libssh2_session_last_errno((s)->session);
|
||||
ssh_err_code = libssh2_session_last_error(s->session,
|
||||
&ssh_err, NULL, 0);
|
||||
/* See <libssh2_sftp.h>. */
|
||||
sftp_err_code = libssh2_sftp_last_error((s)->sftp);
|
||||
|
||||
@@ -243,7 +272,7 @@ static void ssh_parse_filename(const char *filename, QDict *options,
|
||||
}
|
||||
|
||||
static int check_host_key_knownhosts(BDRVSSHState *s,
|
||||
const char *host, int port)
|
||||
const char *host, int port, Error **errp)
|
||||
{
|
||||
const char *home;
|
||||
char *knh_file = NULL;
|
||||
@@ -257,14 +286,15 @@ static int check_host_key_knownhosts(BDRVSSHState *s,
|
||||
hostkey = libssh2_session_hostkey(s->session, &len, &type);
|
||||
if (!hostkey) {
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failed to read remote host key");
|
||||
session_error_setg(errp, s, "failed to read remote host key");
|
||||
goto out;
|
||||
}
|
||||
|
||||
knh = libssh2_knownhost_init(s->session);
|
||||
if (!knh) {
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failed to initialize known hosts support");
|
||||
session_error_setg(errp, s,
|
||||
"failed to initialize known hosts support");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -289,21 +319,23 @@ static int check_host_key_knownhosts(BDRVSSHState *s,
|
||||
break;
|
||||
case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "host key does not match the one in known_hosts (found key %s)",
|
||||
found->key);
|
||||
session_error_setg(errp, s,
|
||||
"host key does not match the one in known_hosts"
|
||||
" (found key %s)", found->key);
|
||||
goto out;
|
||||
case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "no host key was found in known_hosts");
|
||||
session_error_setg(errp, s, "no host key was found in known_hosts");
|
||||
goto out;
|
||||
case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failure matching the host key with known_hosts");
|
||||
session_error_setg(errp, s,
|
||||
"failure matching the host key with known_hosts");
|
||||
goto out;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "unknown error matching the host key with known_hosts (%d)",
|
||||
r);
|
||||
session_error_setg(errp, s, "unknown error matching the host key"
|
||||
" with known_hosts (%d)", r);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -358,20 +390,20 @@ static int compare_fingerprint(const unsigned char *fingerprint, size_t len,
|
||||
|
||||
static int
|
||||
check_host_key_hash(BDRVSSHState *s, const char *hash,
|
||||
int hash_type, size_t fingerprint_len)
|
||||
int hash_type, size_t fingerprint_len, Error **errp)
|
||||
{
|
||||
const char *fingerprint;
|
||||
|
||||
fingerprint = libssh2_hostkey_hash(s->session, hash_type);
|
||||
if (!fingerprint) {
|
||||
session_error_report(s, "failed to read remote host key");
|
||||
session_error_setg(errp, s, "failed to read remote host key");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len,
|
||||
hash) != 0) {
|
||||
error_report("remote host key does not match host_key_check '%s'",
|
||||
hash);
|
||||
error_setg(errp, "remote host key does not match host_key_check '%s'",
|
||||
hash);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@@ -379,7 +411,7 @@ check_host_key_hash(BDRVSSHState *s, const char *hash,
|
||||
}
|
||||
|
||||
static int check_host_key(BDRVSSHState *s, const char *host, int port,
|
||||
const char *host_key_check)
|
||||
const char *host_key_check, Error **errp)
|
||||
{
|
||||
/* host_key_check=no */
|
||||
if (strcmp(host_key_check, "no") == 0) {
|
||||
@@ -389,25 +421,25 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port,
|
||||
/* host_key_check=md5:xx:yy:zz:... */
|
||||
if (strncmp(host_key_check, "md5:", 4) == 0) {
|
||||
return check_host_key_hash(s, &host_key_check[4],
|
||||
LIBSSH2_HOSTKEY_HASH_MD5, 16);
|
||||
LIBSSH2_HOSTKEY_HASH_MD5, 16, errp);
|
||||
}
|
||||
|
||||
/* host_key_check=sha1:xx:yy:zz:... */
|
||||
if (strncmp(host_key_check, "sha1:", 5) == 0) {
|
||||
return check_host_key_hash(s, &host_key_check[5],
|
||||
LIBSSH2_HOSTKEY_HASH_SHA1, 20);
|
||||
LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp);
|
||||
}
|
||||
|
||||
/* host_key_check=yes */
|
||||
if (strcmp(host_key_check, "yes") == 0) {
|
||||
return check_host_key_knownhosts(s, host, port);
|
||||
return check_host_key_knownhosts(s, host, port, errp);
|
||||
}
|
||||
|
||||
error_report("unknown host_key_check setting (%s)", host_key_check);
|
||||
error_setg(errp, "unknown host_key_check setting (%s)", host_key_check);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int authenticate(BDRVSSHState *s, const char *user)
|
||||
static int authenticate(BDRVSSHState *s, const char *user, Error **errp)
|
||||
{
|
||||
int r, ret;
|
||||
const char *userauthlist;
|
||||
@@ -418,7 +450,8 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
||||
userauthlist = libssh2_userauth_list(s->session, user, strlen(user));
|
||||
if (strstr(userauthlist, "publickey") == NULL) {
|
||||
ret = -EPERM;
|
||||
error_report("remote server does not support \"publickey\" authentication");
|
||||
error_setg(errp,
|
||||
"remote server does not support \"publickey\" authentication");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -426,17 +459,18 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
||||
agent = libssh2_agent_init(s->session);
|
||||
if (!agent) {
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failed to initialize ssh-agent support");
|
||||
session_error_setg(errp, s, "failed to initialize ssh-agent support");
|
||||
goto out;
|
||||
}
|
||||
if (libssh2_agent_connect(agent)) {
|
||||
ret = -ECONNREFUSED;
|
||||
session_error_report(s, "failed to connect to ssh-agent");
|
||||
session_error_setg(errp, s, "failed to connect to ssh-agent");
|
||||
goto out;
|
||||
}
|
||||
if (libssh2_agent_list_identities(agent)) {
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failed requesting identities from ssh-agent");
|
||||
session_error_setg(errp, s,
|
||||
"failed requesting identities from ssh-agent");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -447,7 +481,8 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
||||
}
|
||||
if (r < 0) {
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failed to obtain identity from ssh-agent");
|
||||
session_error_setg(errp, s,
|
||||
"failed to obtain identity from ssh-agent");
|
||||
goto out;
|
||||
}
|
||||
r = libssh2_agent_userauth(agent, user, identity);
|
||||
@@ -461,8 +496,8 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
||||
}
|
||||
|
||||
ret = -EPERM;
|
||||
error_report("failed to authenticate using publickey authentication "
|
||||
"and the identities held by your ssh-agent");
|
||||
error_setg(errp, "failed to authenticate using publickey authentication "
|
||||
"and the identities held by your ssh-agent");
|
||||
|
||||
out:
|
||||
if (agent != NULL) {
|
||||
@@ -476,10 +511,9 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
||||
}
|
||||
|
||||
static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
int ssh_flags, int creat_mode)
|
||||
int ssh_flags, int creat_mode, Error **errp)
|
||||
{
|
||||
int r, ret;
|
||||
Error *err = NULL;
|
||||
const char *host, *user, *path, *host_key_check;
|
||||
int port;
|
||||
|
||||
@@ -498,6 +532,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
} else {
|
||||
user = g_get_user_name();
|
||||
if (!user) {
|
||||
error_setg_errno(errp, errno, "Can't get user name");
|
||||
ret = -errno;
|
||||
goto err;
|
||||
}
|
||||
@@ -514,11 +549,9 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
s->hostport = g_strdup_printf("%s:%d", host, port);
|
||||
|
||||
/* Open the socket and connect. */
|
||||
s->sock = inet_connect(s->hostport, &err);
|
||||
if (err != NULL) {
|
||||
s->sock = inet_connect(s->hostport, errp);
|
||||
if (s->sock < 0) {
|
||||
ret = -errno;
|
||||
qerror_report_err(err);
|
||||
error_free(err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -526,7 +559,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
s->session = libssh2_session_init();
|
||||
if (!s->session) {
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failed to initialize libssh2 session");
|
||||
session_error_setg(errp, s, "failed to initialize libssh2 session");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -537,18 +570,18 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
r = libssh2_session_handshake(s->session, s->sock);
|
||||
if (r != 0) {
|
||||
ret = -EINVAL;
|
||||
session_error_report(s, "failed to establish SSH session");
|
||||
session_error_setg(errp, s, "failed to establish SSH session");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check the remote host's key against known_hosts. */
|
||||
ret = check_host_key(s, host, port, host_key_check);
|
||||
ret = check_host_key(s, host, port, host_key_check, errp);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Authenticate. */
|
||||
ret = authenticate(s, user);
|
||||
ret = authenticate(s, user, errp);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
@@ -556,7 +589,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
/* Start SFTP. */
|
||||
s->sftp = libssh2_sftp_init(s->session);
|
||||
if (!s->sftp) {
|
||||
session_error_report(s, "failed to initialize sftp handle");
|
||||
session_error_setg(errp, s, "failed to initialize sftp handle");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -566,14 +599,14 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
path, ssh_flags, creat_mode);
|
||||
s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode);
|
||||
if (!s->sftp_handle) {
|
||||
session_error_report(s, "failed to open remote file '%s'", path);
|
||||
session_error_setg(errp, s, "failed to open remote file '%s'", path);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);
|
||||
if (r < 0) {
|
||||
sftp_error_report(s, "failed to read file attributes");
|
||||
sftp_error_setg(errp, s, "failed to read file attributes");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -623,7 +656,7 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
|
||||
}
|
||||
|
||||
/* Start up SSH. */
|
||||
ret = connect_to_ssh(s, options, ssh_flags, 0);
|
||||
ret = connect_to_ssh(s, options, ssh_flags, 0, errp);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
@@ -655,7 +688,6 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
{
|
||||
int r, ret;
|
||||
Error *local_err = NULL;
|
||||
int64_t total_size = 0;
|
||||
QDict *uri_options = NULL;
|
||||
BDRVSSHState s;
|
||||
@@ -674,17 +706,16 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
||||
DPRINTF("total_size=%" PRIi64, total_size);
|
||||
|
||||
uri_options = qdict_new();
|
||||
r = parse_uri(filename, uri_options, &local_err);
|
||||
r = parse_uri(filename, uri_options, errp);
|
||||
if (r < 0) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
ret = r;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = connect_to_ssh(&s, uri_options,
|
||||
LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|
|
||||
LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0644);
|
||||
LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
|
||||
0644, errp);
|
||||
if (r < 0) {
|
||||
ret = r;
|
||||
goto out;
|
||||
@@ -694,7 +725,7 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
||||
libssh2_sftp_seek64(s.sftp_handle, total_size-1);
|
||||
r2 = libssh2_sftp_write(s.sftp_handle, c, 1);
|
||||
if (r2 < 0) {
|
||||
sftp_error_report(&s, "truncate failed");
|
||||
sftp_error_setg(errp, &s, "truncate failed");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -742,7 +773,7 @@ static void restart_coroutine(void *opaque)
|
||||
qemu_coroutine_enter(co, NULL);
|
||||
}
|
||||
|
||||
static coroutine_fn void set_fd_handler(BDRVSSHState *s)
|
||||
static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
|
||||
{
|
||||
int r;
|
||||
IOHandler *rd_handler = NULL, *wr_handler = NULL;
|
||||
@@ -760,24 +791,26 @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s)
|
||||
DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock,
|
||||
rd_handler, wr_handler);
|
||||
|
||||
qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, co);
|
||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
|
||||
rd_handler, wr_handler, co);
|
||||
}
|
||||
|
||||
static coroutine_fn void clear_fd_handler(BDRVSSHState *s)
|
||||
static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
|
||||
BlockDriverState *bs)
|
||||
{
|
||||
DPRINTF("s->sock=%d", s->sock);
|
||||
qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL);
|
||||
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* A non-blocking call returned EAGAIN, so yield, ensuring the
|
||||
* handlers are set up so that we'll be rescheduled when there is an
|
||||
* interesting event on the socket.
|
||||
*/
|
||||
static coroutine_fn void co_yield(BDRVSSHState *s)
|
||||
static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
|
||||
{
|
||||
set_fd_handler(s);
|
||||
set_fd_handler(s, bs);
|
||||
qemu_coroutine_yield();
|
||||
clear_fd_handler(s);
|
||||
clear_fd_handler(s, bs);
|
||||
}
|
||||
|
||||
/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
|
||||
@@ -807,7 +840,7 @@ static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
static coroutine_fn int ssh_read(BDRVSSHState *s,
|
||||
static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
|
||||
int64_t offset, size_t size,
|
||||
QEMUIOVector *qiov)
|
||||
{
|
||||
@@ -840,7 +873,7 @@ static coroutine_fn int ssh_read(BDRVSSHState *s,
|
||||
DPRINTF("sftp_read returned %zd", r);
|
||||
|
||||
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
|
||||
co_yield(s);
|
||||
co_yield(s, bs);
|
||||
goto again;
|
||||
}
|
||||
if (r < 0) {
|
||||
@@ -875,14 +908,14 @@ static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
|
||||
int ret;
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
ret = ssh_read(s, sector_num * BDRV_SECTOR_SIZE,
|
||||
ret = ssh_read(s, bs, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE, qiov);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ssh_write(BDRVSSHState *s,
|
||||
static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
|
||||
int64_t offset, size_t size,
|
||||
QEMUIOVector *qiov)
|
||||
{
|
||||
@@ -910,7 +943,7 @@ static int ssh_write(BDRVSSHState *s,
|
||||
DPRINTF("sftp_write returned %zd", r);
|
||||
|
||||
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
|
||||
co_yield(s);
|
||||
co_yield(s, bs);
|
||||
goto again;
|
||||
}
|
||||
if (r < 0) {
|
||||
@@ -929,7 +962,7 @@ static int ssh_write(BDRVSSHState *s,
|
||||
*/
|
||||
if (r == 0) {
|
||||
ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE);
|
||||
co_yield(s);
|
||||
co_yield(s, bs);
|
||||
goto again;
|
||||
}
|
||||
|
||||
@@ -957,7 +990,7 @@ static coroutine_fn int ssh_co_writev(BlockDriverState *bs,
|
||||
int ret;
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
ret = ssh_write(s, sector_num * BDRV_SECTOR_SIZE,
|
||||
ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE, qiov);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
|
||||
@@ -978,7 +1011,7 @@ static void unsafe_flush_warning(BDRVSSHState *s, const char *what)
|
||||
|
||||
#ifdef HAS_LIBSSH2_SFTP_FSYNC
|
||||
|
||||
static coroutine_fn int ssh_flush(BDRVSSHState *s)
|
||||
static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs)
|
||||
{
|
||||
int r;
|
||||
|
||||
@@ -986,7 +1019,7 @@ static coroutine_fn int ssh_flush(BDRVSSHState *s)
|
||||
again:
|
||||
r = libssh2_sftp_fsync(s->sftp_handle);
|
||||
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
|
||||
co_yield(s);
|
||||
co_yield(s, bs);
|
||||
goto again;
|
||||
}
|
||||
if (r == LIBSSH2_ERROR_SFTP_PROTOCOL &&
|
||||
@@ -1008,7 +1041,7 @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
|
||||
int ret;
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
ret = ssh_flush(s);
|
||||
ret = ssh_flush(s, bs);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
|
||||
return ret;
|
||||
|
@@ -60,7 +60,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
|
||||
/* Must assign before bdrv_delete() to prevent traversing dangling pointer
|
||||
* while we delete backing image instances.
|
||||
*/
|
||||
top->backing_hd = base;
|
||||
bdrv_set_backing_hd(top, base);
|
||||
|
||||
while (intermediate) {
|
||||
BlockDriverState *unused;
|
||||
@@ -72,7 +72,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
|
||||
|
||||
unused = intermediate;
|
||||
intermediate = intermediate->backing_hd;
|
||||
unused->backing_hd = NULL;
|
||||
bdrv_set_backing_hd(unused, NULL);
|
||||
bdrv_unref(unused);
|
||||
}
|
||||
|
||||
|
@@ -239,7 +239,6 @@ static void vdi_header_to_le(VdiHeader *header)
|
||||
cpu_to_le32s(&header->block_extra);
|
||||
cpu_to_le32s(&header->blocks_in_image);
|
||||
cpu_to_le32s(&header->blocks_allocated);
|
||||
cpu_to_le32s(&header->blocks_allocated);
|
||||
uuid_convert(header->uuid_image);
|
||||
uuid_convert(header->uuid_last_snap);
|
||||
uuid_convert(header->uuid_link);
|
||||
|
31
block/vmdk.c
31
block/vmdk.c
@@ -1534,7 +1534,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
|
||||
int ret, i;
|
||||
BlockDriverState *bs = NULL;
|
||||
VMDK4Header header;
|
||||
Error *local_err;
|
||||
Error *local_err = NULL;
|
||||
uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count;
|
||||
uint32_t *gd_buf = NULL;
|
||||
int gd_buf_size;
|
||||
@@ -1700,7 +1700,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
{
|
||||
int idx = 0;
|
||||
BlockDriverState *new_bs = NULL;
|
||||
Error *local_err;
|
||||
Error *local_err = NULL;
|
||||
char *desc = NULL;
|
||||
int64_t total_size = 0, filesize;
|
||||
const char *adapter_type = NULL;
|
||||
@@ -1881,7 +1881,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
} else {
|
||||
ret = bdrv_create_file(filename, options, &local_err);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not create image file");
|
||||
error_propagate(errp, local_err);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
@@ -1889,7 +1889,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
ret = bdrv_open(&new_bs, filename, NULL, NULL,
|
||||
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not write description");
|
||||
error_propagate(errp, local_err);
|
||||
goto exit;
|
||||
}
|
||||
ret = bdrv_pwrite(new_bs, desc_offset, desc, desc_len);
|
||||
@@ -2096,6 +2096,27 @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmdk_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_extents; i++) {
|
||||
bdrv_detach_aio_context(s->extents[i].file);
|
||||
}
|
||||
}
|
||||
|
||||
static void vmdk_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_extents; i++) {
|
||||
bdrv_attach_aio_context(s->extents[i].file, new_context);
|
||||
}
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vmdk_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_SIZE,
|
||||
@@ -2153,6 +2174,8 @@ static BlockDriver bdrv_vmdk = {
|
||||
.bdrv_get_specific_info = vmdk_get_specific_info,
|
||||
.bdrv_refresh_limits = vmdk_refresh_limits,
|
||||
.bdrv_get_info = vmdk_get_info,
|
||||
.bdrv_detach_aio_context = vmdk_detach_aio_context,
|
||||
.bdrv_attach_aio_context = vmdk_attach_aio_context,
|
||||
|
||||
.create_options = vmdk_create_options,
|
||||
};
|
||||
|
@@ -787,7 +787,9 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
s->current_mapping->path=buffer;
|
||||
s->current_mapping->read_only =
|
||||
(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
|
||||
}
|
||||
} else {
|
||||
g_free(buffer);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
@@ -831,7 +833,8 @@ static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
|
||||
}
|
||||
|
||||
static int init_directories(BDRVVVFATState* s,
|
||||
const char *dirname, int heads, int secs)
|
||||
const char *dirname, int heads, int secs,
|
||||
Error **errp)
|
||||
{
|
||||
bootsector_t* bootsector;
|
||||
mapping_t* mapping;
|
||||
@@ -892,8 +895,8 @@ static int init_directories(BDRVVVFATState* s,
|
||||
if (mapping->mode & MODE_DIRECTORY) {
|
||||
mapping->begin = cluster;
|
||||
if(read_directory(s, i)) {
|
||||
fprintf(stderr, "Could not read directory %s\n",
|
||||
mapping->path);
|
||||
error_setg(errp, "Could not read directory %s",
|
||||
mapping->path);
|
||||
return -1;
|
||||
}
|
||||
mapping = array_get(&(s->mapping), i);
|
||||
@@ -919,9 +922,10 @@ static int init_directories(BDRVVVFATState* s,
|
||||
cluster = mapping->end;
|
||||
|
||||
if(cluster > s->cluster_count) {
|
||||
fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
|
||||
s->fat_type, s->sector_count / 2000.0);
|
||||
return -EINVAL;
|
||||
error_setg(errp,
|
||||
"Directory does not fit in FAT%d (capacity %.2f MB)",
|
||||
s->fat_type, s->sector_count / 2000.0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fix fat for entry */
|
||||
@@ -979,7 +983,7 @@ static int init_directories(BDRVVVFATState* s,
|
||||
static BDRVVVFATState *vvv = NULL;
|
||||
#endif
|
||||
|
||||
static int enable_write_target(BDRVVVFATState *s);
|
||||
static int enable_write_target(BDRVVVFATState *s, Error **errp);
|
||||
static int is_consistent(BDRVVVFATState *s);
|
||||
|
||||
static void vvfat_rebind(BlockDriverState *bs)
|
||||
@@ -1160,7 +1164,7 @@ DLOG(if (stderr == NULL) {
|
||||
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
|
||||
|
||||
if (qemu_opt_get_bool(opts, "rw", false)) {
|
||||
ret = enable_write_target(s);
|
||||
ret = enable_write_target(s, errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1169,7 +1173,7 @@ DLOG(if (stderr == NULL) {
|
||||
|
||||
bs->total_sectors = cyls * heads * secs;
|
||||
|
||||
if (init_directories(s, dirname, heads, secs)) {
|
||||
if (init_directories(s, dirname, heads, secs, errp)) {
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
@@ -1864,7 +1868,7 @@ static int check_directory_consistency(BDRVVVFATState *s,
|
||||
|
||||
if (s->used_clusters[cluster_num] & USED_ANY) {
|
||||
fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
s->used_clusters[cluster_num] = USED_DIRECTORY;
|
||||
|
||||
@@ -2904,11 +2908,10 @@ static BlockDriver vvfat_write_target = {
|
||||
.bdrv_close = write_target_close,
|
||||
};
|
||||
|
||||
static int enable_write_target(BDRVVVFATState *s)
|
||||
static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
||||
{
|
||||
BlockDriver *bdrv_qcow;
|
||||
QEMUOptionParameter *options;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
int size = sector2cluster(s, s->sector_count);
|
||||
s->used_clusters = calloc(size, 1);
|
||||
@@ -2918,6 +2921,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
s->qcow_filename = g_malloc(1024);
|
||||
ret = get_tmp_filename(s->qcow_filename, 1024);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "can't create temporary file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2926,20 +2930,17 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
|
||||
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
|
||||
|
||||
ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, &local_err);
|
||||
ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, errp);
|
||||
free_option_parameters(options);
|
||||
if (ret < 0) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->qcow = NULL;
|
||||
ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL,
|
||||
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow,
|
||||
&local_err);
|
||||
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH,
|
||||
bdrv_qcow, errp);
|
||||
if (ret < 0) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2947,7 +2948,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
unlink(s->qcow_filename);
|
||||
#endif
|
||||
|
||||
s->bs->backing_hd = bdrv_new("", &error_abort);
|
||||
bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
|
||||
s->bs->backing_hd->drv = &vvfat_write_target;
|
||||
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
|
||||
*(void**)s->bs->backing_hd->opaque = s;
|
||||
|
@@ -40,6 +40,7 @@ struct QEMUWin32AIOState {
|
||||
HANDLE hIOCP;
|
||||
EventNotifier e;
|
||||
int count;
|
||||
bool is_aio_context_attached;
|
||||
};
|
||||
|
||||
typedef struct QEMUWin32AIOCB {
|
||||
@@ -114,7 +115,7 @@ static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
* wait for completion.
|
||||
*/
|
||||
while (!HasOverlappedIoCompleted(&waiocb->ov)) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(blockacb->bs), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +181,20 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
|
||||
}
|
||||
}
|
||||
|
||||
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *old_context)
|
||||
{
|
||||
aio_set_event_notifier(old_context, &aio->e, NULL);
|
||||
aio->is_aio_context_attached = false;
|
||||
}
|
||||
|
||||
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *new_context)
|
||||
{
|
||||
aio->is_aio_context_attached = true;
|
||||
aio_set_event_notifier(new_context, &aio->e, win32_aio_completion_cb);
|
||||
}
|
||||
|
||||
QEMUWin32AIOState *win32_aio_init(void)
|
||||
{
|
||||
QEMUWin32AIOState *s;
|
||||
@@ -194,8 +209,6 @@ QEMUWin32AIOState *win32_aio_init(void)
|
||||
goto out_close_efd;
|
||||
}
|
||||
|
||||
qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb);
|
||||
|
||||
return s;
|
||||
|
||||
out_close_efd:
|
||||
@@ -204,3 +217,11 @@ out_free_state:
|
||||
g_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void win32_aio_cleanup(QEMUWin32AIOState *aio)
|
||||
{
|
||||
assert(!aio->is_aio_context_attached);
|
||||
CloseHandle(aio->hIOCP);
|
||||
event_notifier_cleanup(&aio->e);
|
||||
g_free(aio);
|
||||
}
|
||||
|
@@ -27,8 +27,8 @@ static void nbd_accept(void *opaque)
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
||||
if (fd >= 0) {
|
||||
nbd_client_new(NULL, fd, nbd_client_put);
|
||||
if (fd >= 0 && !nbd_client_new(NULL, fd, nbd_client_put)) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
47
blockdev.c
47
blockdev.c
@@ -34,7 +34,6 @@
|
||||
#include "hw/block/block.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
@@ -352,7 +351,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
||||
opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
return NULL;
|
||||
goto err_no_opts;
|
||||
}
|
||||
|
||||
qemu_opts_absorb_qdict(opts, bs_opts, &error);
|
||||
@@ -565,8 +564,9 @@ bdrv_new_err:
|
||||
g_free(dinfo->id);
|
||||
g_free(dinfo);
|
||||
early_err:
|
||||
QDECREF(bs_opts);
|
||||
qemu_opts_del(opts);
|
||||
err_no_opts:
|
||||
QDECREF(bs_opts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -730,7 +730,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
&error_abort);
|
||||
qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_report("%s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
goto fail;
|
||||
}
|
||||
@@ -940,9 +940,10 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
|
||||
/* Actual block device init: Functionality shared with blockdev-add */
|
||||
dinfo = blockdev_init(filename, bs_opts, &local_err);
|
||||
bs_opts = NULL;
|
||||
if (dinfo == NULL) {
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_report("%s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
}
|
||||
goto fail;
|
||||
@@ -977,6 +978,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
|
||||
fail:
|
||||
qemu_opts_del(legacy_opts);
|
||||
QDECREF(bs_opts);
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
@@ -1334,8 +1336,8 @@ static void external_snapshot_prepare(BlkTransactionState *common,
|
||||
return;
|
||||
}
|
||||
|
||||
if (bdrv_in_use(state->old_bs)) {
|
||||
error_set(errp, QERR_DEVICE_IN_USE, device);
|
||||
if (bdrv_op_is_blocked(state->old_bs,
|
||||
BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1557,8 +1559,7 @@ exit:
|
||||
|
||||
static void eject_device(BlockDriverState *bs, int force, Error **errp)
|
||||
{
|
||||
if (bdrv_in_use(bs)) {
|
||||
error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
|
||||
return;
|
||||
}
|
||||
if (!bdrv_dev_has_removable_media(bs)) {
|
||||
@@ -1702,6 +1703,7 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
|
||||
{
|
||||
ThrottleConfig cfg;
|
||||
BlockDriverState *bs;
|
||||
AioContext *aio_context;
|
||||
|
||||
bs = bdrv_find(device);
|
||||
if (!bs) {
|
||||
@@ -1745,6 +1747,9 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
|
||||
return;
|
||||
}
|
||||
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
if (!bs->io_limits_enabled && throttle_enabled(&cfg)) {
|
||||
bdrv_io_limits_enable(bs);
|
||||
} else if (bs->io_limits_enabled && !throttle_enabled(&cfg)) {
|
||||
@@ -1754,20 +1759,24 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
|
||||
if (bs->io_limits_enabled) {
|
||||
bdrv_set_io_limits(bs, &cfg);
|
||||
}
|
||||
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
const char *id = qdict_get_str(qdict, "id");
|
||||
BlockDriverState *bs;
|
||||
Error *local_err = NULL;
|
||||
|
||||
bs = bdrv_find(id);
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, id);
|
||||
error_report("Device '%s' not found", id);
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_in_use(bs)) {
|
||||
qerror_report(QERR_DEVICE_IN_USE, id);
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
|
||||
error_report("%s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1888,6 +1897,10 @@ void qmp_block_stream(const char *device, bool has_base,
|
||||
return;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (base) {
|
||||
base_bs = bdrv_find_backing_image(bs, base);
|
||||
if (base_bs == NULL) {
|
||||
@@ -1932,6 +1945,10 @@ void qmp_block_commit(const char *device,
|
||||
return;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* default top_bs is the active layer */
|
||||
top_bs = bs;
|
||||
|
||||
@@ -2023,8 +2040,7 @@ void qmp_drive_backup(const char *device, const char *target,
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_in_use(bs)) {
|
||||
error_set(errp, QERR_DEVICE_IN_USE, device);
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2157,8 +2173,7 @@ void qmp_drive_mirror(const char *device, const char *target,
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_in_use(bs)) {
|
||||
error_set(errp, QERR_DEVICE_IN_USE, device);
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
14
blockjob.c
14
blockjob.c
@@ -41,14 +41,16 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
|
||||
{
|
||||
BlockJob *job;
|
||||
|
||||
if (bs->job || bdrv_in_use(bs)) {
|
||||
if (bs->job) {
|
||||
error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
||||
return NULL;
|
||||
}
|
||||
bdrv_ref(bs);
|
||||
bdrv_set_in_use(bs, 1);
|
||||
|
||||
job = g_malloc0(driver->instance_size);
|
||||
error_setg(&job->blocker, "block device is in use by block job: %s",
|
||||
BlockJobType_lookup[driver->job_type]);
|
||||
bdrv_op_block_all(bs, job->blocker);
|
||||
|
||||
job->driver = driver;
|
||||
job->bs = bs;
|
||||
job->cb = cb;
|
||||
@@ -63,8 +65,9 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
|
||||
block_job_set_speed(job, speed, &local_err);
|
||||
if (local_err) {
|
||||
bs->job = NULL;
|
||||
bdrv_op_unblock_all(bs, job->blocker);
|
||||
error_free(job->blocker);
|
||||
g_free(job);
|
||||
bdrv_set_in_use(bs, 0);
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
}
|
||||
@@ -79,8 +82,9 @@ void block_job_completed(BlockJob *job, int ret)
|
||||
assert(bs->job == job);
|
||||
job->cb(job->opaque, ret);
|
||||
bs->job = NULL;
|
||||
bdrv_op_unblock_all(bs, job->blocker);
|
||||
error_free(job->blocker);
|
||||
g_free(job);
|
||||
bdrv_set_in_use(bs, 0);
|
||||
}
|
||||
|
||||
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
|
||||
|
@@ -1004,7 +1004,7 @@ int main(int argc, char **argv)
|
||||
|
||||
#if defined(TARGET_I386)
|
||||
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
|
||||
env->hflags |= HF_PE_MASK;
|
||||
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
|
||||
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
|
||||
env->cr[4] |= CR4_OSFXSR_MASK;
|
||||
env->hflags |= HF_OSFXSR_MASK;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
|
||||
#undef DEBUG_REMAP
|
||||
#ifdef DEBUG_REMAP
|
||||
|
109
configure
vendored
109
configure
vendored
@@ -2,26 +2,28 @@
|
||||
#
|
||||
# qemu configure script (c) 2003 Fabrice Bellard
|
||||
#
|
||||
# set temporary file name
|
||||
if test ! -z "$TMPDIR" ; then
|
||||
TMPDIR1="${TMPDIR}"
|
||||
elif test ! -z "$TEMPDIR" ; then
|
||||
TMPDIR1="${TEMPDIR}"
|
||||
else
|
||||
TMPDIR1="/tmp"
|
||||
|
||||
# Temporary directory used for files created while
|
||||
# configure runs. Since it is in the build directory
|
||||
# we can safely blow away any previous version of it
|
||||
# (and we need not jump through hoops to try to delete
|
||||
# it when configure exits.)
|
||||
TMPDIR1="config-temp"
|
||||
rm -rf "${TMPDIR1}"
|
||||
mkdir -p "${TMPDIR1}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: failed to create temporary directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
|
||||
TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}"
|
||||
TMPB="qemu-conf"
|
||||
TMPC="${TMPDIR1}/${TMPB}.c"
|
||||
TMPO="${TMPDIR1}/${TMPB}.o"
|
||||
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
|
||||
TMPL="${TMPDIR1}/${TMPB}.lo"
|
||||
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
||||
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
|
||||
TMPE="${TMPDIR1}/${TMPB}.exe"
|
||||
|
||||
# NB: do not call "exit" in the trap handler; this is buggy with some shells;
|
||||
# see <1285349658-3122-1-git-send-email-loic.minier@linaro.org>
|
||||
trap "rm -f $TMPC $TMPO $TMPCXX $TMPE" EXIT INT QUIT TERM
|
||||
rm -f config.log
|
||||
|
||||
# Print a helpful header at the top of config.log
|
||||
@@ -180,6 +182,10 @@ path_of() {
|
||||
return 1
|
||||
}
|
||||
|
||||
have_backend () {
|
||||
echo "$trace_backends" | grep "$1" >/dev/null
|
||||
}
|
||||
|
||||
# default parameters
|
||||
source_path=`dirname "$0"`
|
||||
cpu=""
|
||||
@@ -291,7 +297,7 @@ pkgversion=""
|
||||
pie=""
|
||||
zero_malloc=""
|
||||
qom_cast_debug="yes"
|
||||
trace_backend="nop"
|
||||
trace_backends="nop"
|
||||
trace_file="trace"
|
||||
spice=""
|
||||
rbd=""
|
||||
@@ -317,7 +323,7 @@ glusterfs_discard="no"
|
||||
glusterfs_zerofill="no"
|
||||
virtio_blk_data_plane=""
|
||||
gtk=""
|
||||
gtkabi="2.0"
|
||||
gtkabi=""
|
||||
vte=""
|
||||
tpm="no"
|
||||
libssh2=""
|
||||
@@ -751,7 +757,10 @@ for opt do
|
||||
;;
|
||||
--target-list=*) target_list="$optarg"
|
||||
;;
|
||||
--enable-trace-backend=*) trace_backend="$optarg"
|
||||
--enable-trace-backends=*) trace_backends="$optarg"
|
||||
;;
|
||||
# XXX: backwards compatibility
|
||||
--enable-trace-backend=*) trace_backends="$optarg"
|
||||
;;
|
||||
--with-trace-file=*) trace_file="$optarg"
|
||||
;;
|
||||
@@ -1318,7 +1327,7 @@ Advanced options (experts only):
|
||||
--disable-docs disable documentation build
|
||||
--disable-vhost-net disable vhost-net acceleration support
|
||||
--enable-vhost-net enable vhost-net acceleration support
|
||||
--enable-trace-backend=B Set trace backend
|
||||
--enable-trace-backends=B Set trace backend
|
||||
Available backends: $($python $source_path/scripts/tracetool.py --list-backends)
|
||||
--with-trace-file=NAME Full PATH,NAME of file to store traces
|
||||
Default:trace-<pid>
|
||||
@@ -1970,8 +1979,21 @@ fi
|
||||
##########################################
|
||||
# GTK probe
|
||||
|
||||
if test "$gtkabi" = ""; then
|
||||
# The GTK ABI was not specified explicitly, so try whether 2.0 is available.
|
||||
# Use 3.0 as a fallback if that is available.
|
||||
if $pkg_config --exists "gtk+-2.0 >= 2.18.0"; then
|
||||
gtkabi=2.0
|
||||
elif $pkg_config --exists "gtk+-3.0 >= 3.0.0"; then
|
||||
gtkabi=3.0
|
||||
else
|
||||
gtkabi=2.0
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$gtk" != "no"; then
|
||||
gtkpackage="gtk+-$gtkabi"
|
||||
gtkx11package="gtk+-x11-$gtkabi"
|
||||
if test "$gtkabi" = "3.0" ; then
|
||||
gtkversion="3.0.0"
|
||||
else
|
||||
@@ -1980,10 +2002,13 @@ if test "$gtk" != "no"; then
|
||||
if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
|
||||
gtk_cflags=`$pkg_config --cflags $gtkpackage`
|
||||
gtk_libs=`$pkg_config --libs $gtkpackage`
|
||||
if $pkg_config --exists "$gtkx11package >= $gtkversion"; then
|
||||
gtk_libs="$gtk_libs -lX11"
|
||||
fi
|
||||
libs_softmmu="$gtk_libs $libs_softmmu"
|
||||
gtk="yes"
|
||||
elif test "$gtk" = "yes"; then
|
||||
feature_not_found "gtk" "Install gtk2 or gtk3 (requires --with-gtkabi=3.0 option to configure) devel"
|
||||
feature_not_found "gtk" "Install gtk2 or gtk3 devel"
|
||||
else
|
||||
gtk="no"
|
||||
fi
|
||||
@@ -2006,7 +2031,11 @@ if test "$vte" != "no"; then
|
||||
libs_softmmu="$vte_libs $libs_softmmu"
|
||||
vte="yes"
|
||||
elif test "$vte" = "yes"; then
|
||||
feature_not_found "vte" "Install libvte or libvte-2.90 (requires --with-gtkabi=3.0 option to configure) devel"
|
||||
if test "$gtkabi" = "3.0"; then
|
||||
feature_not_found "vte" "Install libvte-2.90 devel"
|
||||
else
|
||||
feature_not_found "vte" "Install libvte devel"
|
||||
fi
|
||||
else
|
||||
vte="no"
|
||||
fi
|
||||
@@ -3648,15 +3677,15 @@ fi
|
||||
##########################################
|
||||
# check if trace backend exists
|
||||
|
||||
$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend > /dev/null 2> /dev/null
|
||||
$python "$source_path/scripts/tracetool.py" "--backends=$trace_backends" --check-backends > /dev/null 2> /dev/null
|
||||
if test "$?" -ne 0 ; then
|
||||
error_exit "invalid trace backend" \
|
||||
"Please choose a supported trace backend."
|
||||
error_exit "invalid trace backends" \
|
||||
"Please choose supported trace backends."
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# For 'ust' backend, test if ust headers are present
|
||||
if test "$trace_backend" = "ust"; then
|
||||
if have_backend "ust"; then
|
||||
cat > $TMPC << EOF
|
||||
#include <lttng/tracepoint.h>
|
||||
int main(void) { return 0; }
|
||||
@@ -3682,7 +3711,7 @@ fi
|
||||
|
||||
##########################################
|
||||
# For 'dtrace' backend, test if 'dtrace' command is present
|
||||
if test "$trace_backend" = "dtrace"; then
|
||||
if have_backend "dtrace"; then
|
||||
if ! has 'dtrace' ; then
|
||||
error_exit "dtrace command is not found in PATH $PATH"
|
||||
fi
|
||||
@@ -4029,11 +4058,14 @@ fi
|
||||
if test "$pie" = "no" ; then
|
||||
textseg_addr=
|
||||
case "$cpu" in
|
||||
arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64 | x32)
|
||||
arm | i386 | ppc* | s390* | sparc* | x86_64 | x32)
|
||||
# ??? Rationale for choosing this address
|
||||
textseg_addr=0x60000000
|
||||
;;
|
||||
mips)
|
||||
textseg_addr=0x400000
|
||||
# A 256M aligned address, high in the address space, with enough
|
||||
# room for the code_gen_buffer above it before the stack.
|
||||
textseg_addr=0x60000000
|
||||
;;
|
||||
esac
|
||||
if [ -n "$textseg_addr" ]; then
|
||||
@@ -4149,7 +4181,7 @@ echo "uuid support $uuid"
|
||||
echo "libcap-ng support $cap_ng"
|
||||
echo "vhost-net support $vhost_net"
|
||||
echo "vhost-scsi support $vhost_scsi"
|
||||
echo "Trace backend $trace_backend"
|
||||
echo "Trace backends $trace_backends"
|
||||
if test "$trace_backend" = "simple"; then
|
||||
echo "Trace output file $trace_file-<pid>"
|
||||
fi
|
||||
@@ -4643,43 +4675,35 @@ if test "$tpm" = "yes"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# use default implementation for tracing backend-specific routines
|
||||
trace_default=yes
|
||||
echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
|
||||
if test "$trace_backend" = "nop"; then
|
||||
echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
|
||||
if have_backend "nop"; then
|
||||
echo "CONFIG_TRACE_NOP=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$trace_backend" = "simple"; then
|
||||
if have_backend "simple"; then
|
||||
echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak
|
||||
trace_default=no
|
||||
# Set the appropriate trace file.
|
||||
trace_file="\"$trace_file-\" FMT_pid"
|
||||
fi
|
||||
if test "$trace_backend" = "stderr"; then
|
||||
if have_backend "stderr"; then
|
||||
echo "CONFIG_TRACE_STDERR=y" >> $config_host_mak
|
||||
trace_default=no
|
||||
fi
|
||||
if test "$trace_backend" = "ust"; then
|
||||
if have_backend "ust"; then
|
||||
echo "CONFIG_TRACE_UST=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$trace_backend" = "dtrace"; then
|
||||
if have_backend "dtrace"; then
|
||||
echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak
|
||||
if test "$trace_backend_stap" = "yes" ; then
|
||||
echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak
|
||||
fi
|
||||
fi
|
||||
if test "$trace_backend" = "ftrace"; then
|
||||
if have_backend "ftrace"; then
|
||||
if test "$linux" = "yes" ; then
|
||||
echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
|
||||
trace_default=no
|
||||
else
|
||||
feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
|
||||
fi
|
||||
fi
|
||||
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
|
||||
if test "$trace_default" = "yes"; then
|
||||
echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$rdma" = "yes" ; then
|
||||
echo "CONFIG_RDMA=y" >> $config_host_mak
|
||||
@@ -5219,3 +5243,4 @@ printf " '%s'" "$0" "$@" >>config.status
|
||||
echo >>config.status
|
||||
chmod +x config.status
|
||||
|
||||
rm -r "$TMPDIR1"
|
||||
|
33
cputlb.c
33
cputlb.c
@@ -22,11 +22,13 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
|
||||
#include "exec/cputlb.h"
|
||||
|
||||
#include "exec/memory-internal.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
//#define DEBUG_TLB
|
||||
//#define DEBUG_TLB_CHECK
|
||||
@@ -330,21 +332,36 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
||||
return qemu_ram_addr_from_host_nofail(p);
|
||||
}
|
||||
|
||||
#define MMUSUFFIX _mmu
|
||||
|
||||
#define SHIFT 0
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 1
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 2
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 3
|
||||
#include "softmmu_template.h"
|
||||
#undef MMUSUFFIX
|
||||
|
||||
#define MMUSUFFIX _cmmu
|
||||
#undef GETPC
|
||||
#define GETPC() ((uintptr_t)0)
|
||||
#undef GETPC_ADJ
|
||||
#define GETPC_ADJ 0
|
||||
#undef GETRA
|
||||
#define GETRA() ((uintptr_t)0)
|
||||
#define SOFTMMU_CODE_ACCESS
|
||||
|
||||
#define SHIFT 0
|
||||
#include "exec/softmmu_template.h"
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 1
|
||||
#include "exec/softmmu_template.h"
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 2
|
||||
#include "exec/softmmu_template.h"
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 3
|
||||
#include "exec/softmmu_template.h"
|
||||
|
||||
#undef env
|
||||
#include "softmmu_template.h"
|
||||
|
@@ -143,12 +143,12 @@ static void dma_bdrv_cb(void *opaque, int ret)
|
||||
|
||||
dbs->acb = NULL;
|
||||
dbs->sector_num += dbs->iov.size / 512;
|
||||
dma_bdrv_unmap(dbs);
|
||||
|
||||
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
|
||||
dma_complete(dbs, ret);
|
||||
return;
|
||||
}
|
||||
dma_bdrv_unmap(dbs);
|
||||
|
||||
while (dbs->sg_cur_index < dbs->sg->nsg) {
|
||||
cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
|
||||
|
102
docs/multiseat.txt
Normal file
102
docs/multiseat.txt
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
multiseat howto (with some multihead coverage)
|
||||
==============================================
|
||||
|
||||
host side
|
||||
---------
|
||||
|
||||
First you must compile qemu with a user interface supporting
|
||||
multihead/multiseat and input event routing. Right now this
|
||||
list includes sdl2 and gtk (both 2+3):
|
||||
|
||||
./configure --enable-sdl --with-sdlabi=2.0
|
||||
|
||||
or
|
||||
|
||||
./configure --enable-gtk
|
||||
|
||||
|
||||
Next put together the qemu command line:
|
||||
|
||||
qemu -enable-kvm -usb $memory $disk $whatever \
|
||||
-display [ sdl | gtk ] \
|
||||
-vga std \
|
||||
-device usb-tablet
|
||||
|
||||
That is it for the first head, which will use the standard vga, the
|
||||
standard ps/2 keyboard (implicitly there) and the usb-tablet. Now the
|
||||
additional switches for the second head:
|
||||
|
||||
-device pci-bridge,addr=12.0,chassis_nr=2,id=head.2 \
|
||||
-device secondary-vga,bus=head.2,addr=02.0,id=video.2 \
|
||||
-device nec-usb-xhci,bus=head.2,addr=0f.0,id=usb.2 \
|
||||
-device usb-kbd,bus=usb.2.0,port=1,display=video.2 \
|
||||
-device usb-tablet,bus=usb.2.0,port=2,display=video.2
|
||||
|
||||
This places a pci bridge in slot 12, connects a display adapter and
|
||||
xhci (usb) controller to the bridge. Then it adds a usb keyboard and
|
||||
usb mouse, both connected to the xhci and linked to the display.
|
||||
|
||||
The "display=video2" sets up the input routing. Any input coming from
|
||||
the window which belongs to the video.2 display adapter will be routed
|
||||
to these input devices.
|
||||
|
||||
The sdl2 ui will start up with two windows, one for each display
|
||||
device. The gtk ui will start with a single window and each display
|
||||
in a separate tab. You can either simply switch tabs to switch heads,
|
||||
or use the "View / Detach tab" menu item to move one of the displays
|
||||
to its own window so you can see both display devices side-by-side.
|
||||
|
||||
Note on spice: Spice handles multihead just fine. But it can't do
|
||||
multiseat. For tablet events the event source is sent to the spice
|
||||
agent. But qemu can't figure it, so it can't do input routing.
|
||||
Fixing this needs a new or extended input interface between
|
||||
libspice-server and qemu. For keyboard events it is even worse: The
|
||||
event source isn't included in the spice protocol, so the wire
|
||||
protocol must be extended to support this.
|
||||
|
||||
|
||||
guest side
|
||||
----------
|
||||
|
||||
You need a pretty recent linux guest. systemd with loginctl. kernel
|
||||
3.14+ with CONFIG_DRM_BOCHS enabled. Fedora 20 will do. Must be
|
||||
fully updated for the new kernel though, i.e. the live iso doesn't cut
|
||||
it.
|
||||
|
||||
Now we'll have to configure the guest. Boot and login. "lspci -vt"
|
||||
should list the pci bridge with the display adapter and usb controller:
|
||||
|
||||
[root@fedora ~]# lspci -vt
|
||||
-[0000:00]-+-00.0 Intel Corporation 440FX - 82441FX PMC [Natoma]
|
||||
[ ... ]
|
||||
\-12.0-[01]--+-02.0 Device 1234:1111
|
||||
\-0f.0 NEC Corporation USB 3.0 Host Controller
|
||||
|
||||
Good. Now lets tell the system that the pci bridge and all devices
|
||||
below it belong to a separate seat by dropping a file into
|
||||
/etc/udev/rules.d:
|
||||
|
||||
[root@fedora ~]# cat /etc/udev/rules.d/70-qemu-autoseat.rules
|
||||
SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:12.0", TAG+="seat", ENV{ID_AUTOSEAT}="1"
|
||||
|
||||
Reboot. System should come up with two seats. With loginctl you can
|
||||
check the configuration:
|
||||
|
||||
[root@fedora ~]# loginctl list-seats
|
||||
SEAT
|
||||
seat0
|
||||
seat-pci-pci-0000_00_12_0
|
||||
|
||||
2 seats listed.
|
||||
|
||||
You can use "loginctl seat-status seat-pci-pci-0000_00_12_0" to list
|
||||
the devices attached to the seat.
|
||||
|
||||
Background info is here:
|
||||
http://www.freedesktop.org/wiki/Software/systemd/multiseat/
|
||||
|
||||
Enjoy!
|
||||
|
||||
--
|
||||
Gerd Hoffmann <kraxel@redhat.com>
|
@@ -107,8 +107,9 @@ in the description of a field.
|
||||
|
||||
96 - 99: refcount_order
|
||||
Describes the width of a reference count block entry (width
|
||||
in bits = 1 << refcount_order). For version 2 images, the
|
||||
order is always assumed to be 4 (i.e. the width is 16 bits).
|
||||
in bits: refcount_bits = 1 << refcount_order). For version 2
|
||||
images, the order is always assumed to be 4
|
||||
(i.e. refcount_bits = 16).
|
||||
|
||||
100 - 103: header_length
|
||||
Length of the header structure in bytes. For version 2
|
||||
|
@@ -9,7 +9,7 @@ for debugging, profiling, and observing execution.
|
||||
|
||||
1. Build with the 'simple' trace backend:
|
||||
|
||||
./configure --enable-trace-backend=simple
|
||||
./configure --enable-trace-backends=simple
|
||||
make
|
||||
|
||||
2. Create a file with the events you want to trace:
|
||||
@@ -142,7 +142,7 @@ script.
|
||||
The trace backend is chosen at configure time and only one trace backend can
|
||||
be built into the binary:
|
||||
|
||||
./configure --trace-backend=simple
|
||||
./configure --trace-backends=simple
|
||||
|
||||
For a list of supported trace backends, try ./configure --help or see below.
|
||||
|
||||
|
@@ -35,7 +35,8 @@ which will return a dictionary containing:
|
||||
|
||||
o A key named last-update, which contains the last stats update
|
||||
timestamp in seconds. Since this timestamp is generated by the host,
|
||||
a buggy guest can't influence its value
|
||||
a buggy guest can't influence its value. The value is 0 if the guest
|
||||
has not updated the stats (yet).
|
||||
|
||||
It's also important to note the following:
|
||||
|
||||
@@ -49,7 +50,7 @@ It's also important to note the following:
|
||||
|
||||
- Polling can be enabled even if the guest doesn't have stats support
|
||||
or the balloon driver wasn't loaded in the guest. If this is the case
|
||||
and stats are queried, an error will be returned
|
||||
and stats are queried, last-update will be 0.
|
||||
|
||||
- The polling timer is only re-armed when the guest responds to the
|
||||
statistics request. This means that if a (buggy) guest doesn't ever
|
||||
|
@@ -34,7 +34,7 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
|
||||
|
||||
len = strlen(s->tag);
|
||||
cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
|
||||
stw_raw(&cfg->tag_len, len);
|
||||
stw_p(&cfg->tag_len, len);
|
||||
/* We don't copy the terminating null to config space */
|
||||
memcpy(cfg->tag, s->tag, len);
|
||||
memcpy(config, cfg, s->config_size);
|
||||
|
@@ -43,13 +43,13 @@ static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
|
||||
return (slot + 1) * 4 + irq_num;
|
||||
}
|
||||
|
||||
static void clipper_init(QEMUMachineInitArgs *args)
|
||||
static void clipper_init(MachineState *machine)
|
||||
{
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
AlphaCPU *cpus[4];
|
||||
PCIBus *pci_bus;
|
||||
ISABus *isa_bus;
|
||||
|
@@ -23,12 +23,12 @@ static struct arm_boot_info collie_binfo = {
|
||||
.ram_size = 0x20000000,
|
||||
};
|
||||
|
||||
static void collie_init(QEMUMachineInitArgs *args)
|
||||
static void collie_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
StrongARMState *s;
|
||||
DriveInfo *dinfo;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
|
@@ -30,7 +30,7 @@ typedef struct CubieBoardState {
|
||||
MemoryRegion sdram;
|
||||
} CubieBoardState;
|
||||
|
||||
static void cubieboard_init(QEMUMachineInitArgs *args)
|
||||
static void cubieboard_init(MachineState *machine)
|
||||
{
|
||||
CubieBoardState *s = g_new(CubieBoardState, 1);
|
||||
Error *err = NULL;
|
||||
@@ -63,14 +63,15 @@ static void cubieboard_init(QEMUMachineInitArgs *args)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memory_region_init_ram(&s->sdram, NULL, "cubieboard.ram", args->ram_size);
|
||||
memory_region_init_ram(&s->sdram, NULL, "cubieboard.ram",
|
||||
machine->ram_size);
|
||||
vmstate_register_ram_global(&s->sdram);
|
||||
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
|
||||
&s->sdram);
|
||||
|
||||
cubieboard_binfo.ram_size = args->ram_size;
|
||||
cubieboard_binfo.kernel_filename = args->kernel_filename;
|
||||
cubieboard_binfo.kernel_cmdline = args->kernel_cmdline;
|
||||
cubieboard_binfo.ram_size = machine->ram_size;
|
||||
cubieboard_binfo.kernel_filename = machine->kernel_filename;
|
||||
cubieboard_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
arm_load_kernel(&s->a10->cpu, &cubieboard_binfo);
|
||||
}
|
||||
|
||||
|
@@ -143,7 +143,7 @@ static DigicBoard digic4_board_canon_a1100 = {
|
||||
.rom1_def_filename = "canon-a1100-rom1.bin",
|
||||
};
|
||||
|
||||
static void canon_a1100_init(QEMUMachineInitArgs *args)
|
||||
static void canon_a1100_init(MachineState *machine)
|
||||
{
|
||||
digic4_board_init(&digic4_board_canon_a1100);
|
||||
}
|
||||
|
@@ -94,7 +94,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
|
||||
}
|
||||
}
|
||||
|
||||
static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
|
||||
static Exynos4210State *exynos4_boards_init_common(MachineState *machine,
|
||||
Exynos4BoardType board_type)
|
||||
{
|
||||
if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
|
||||
@@ -108,9 +108,9 @@ static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
|
||||
exynos4_board_binfo.board_id = exynos4_board_id[board_type];
|
||||
exynos4_board_binfo.smp_bootreg_addr =
|
||||
exynos4_board_smp_bootreg_addr[board_type];
|
||||
exynos4_board_binfo.kernel_filename = args->kernel_filename;
|
||||
exynos4_board_binfo.initrd_filename = args->initrd_filename;
|
||||
exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
|
||||
exynos4_board_binfo.kernel_filename = machine->kernel_filename;
|
||||
exynos4_board_binfo.initrd_filename = machine->initrd_filename;
|
||||
exynos4_board_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
exynos4_board_binfo.gic_cpu_if_addr =
|
||||
EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
|
||||
|
||||
@@ -120,24 +120,24 @@ static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
|
||||
" initrd_filename: %s\n",
|
||||
exynos4_board_ram_size[board_type] / 1048576,
|
||||
exynos4_board_ram_size[board_type],
|
||||
args->kernel_filename,
|
||||
args->kernel_cmdline,
|
||||
args->initrd_filename);
|
||||
machine->kernel_filename,
|
||||
machine->kernel_cmdline,
|
||||
machine->initrd_filename);
|
||||
|
||||
return exynos4210_init(get_system_memory(),
|
||||
exynos4_board_ram_size[board_type]);
|
||||
}
|
||||
|
||||
static void nuri_init(QEMUMachineInitArgs *args)
|
||||
static void nuri_init(MachineState *machine)
|
||||
{
|
||||
exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
|
||||
exynos4_boards_init_common(machine, EXYNOS4_BOARD_NURI);
|
||||
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo);
|
||||
}
|
||||
|
||||
static void smdkc210_init(QEMUMachineInitArgs *args)
|
||||
static void smdkc210_init(MachineState *machine)
|
||||
{
|
||||
Exynos4210State *s = exynos4_boards_init_common(args,
|
||||
Exynos4210State *s = exynos4_boards_init_common(machine,
|
||||
EXYNOS4_BOARD_SMDKC210);
|
||||
|
||||
lan9215_init(SMDK_LAN9118_BASE_ADDR,
|
||||
|
@@ -46,7 +46,7 @@
|
||||
|
||||
static const int sector_len = 128 * 1024;
|
||||
|
||||
static void connex_init(QEMUMachineInitArgs *args)
|
||||
static void connex_init(MachineState *machine)
|
||||
{
|
||||
PXA2xxState *cpu;
|
||||
DriveInfo *dinfo;
|
||||
@@ -83,9 +83,9 @@ static void connex_init(QEMUMachineInitArgs *args)
|
||||
qdev_get_gpio_in(cpu->gpio, 36));
|
||||
}
|
||||
|
||||
static void verdex_init(QEMUMachineInitArgs *args)
|
||||
static void verdex_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
PXA2xxState *cpu;
|
||||
DriveInfo *dinfo;
|
||||
int be;
|
||||
|
@@ -199,13 +199,13 @@ enum cxmachines {
|
||||
* 32-bit host, set the reg value of memory to 0xf7ff00000 in the
|
||||
* device tree and pass -m 2047 to QEMU.
|
||||
*/
|
||||
static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
||||
static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
{
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
DeviceState *dev = NULL;
|
||||
SysBusDevice *busdev;
|
||||
qemu_irq pic[128];
|
||||
@@ -217,7 +217,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
||||
char *sysboot_filename;
|
||||
|
||||
if (!cpu_model) {
|
||||
switch (machine) {
|
||||
switch (machine_id) {
|
||||
case CALXEDA_HIGHBANK:
|
||||
cpu_model = "cortex-a9";
|
||||
break;
|
||||
@@ -274,7 +274,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
||||
}
|
||||
}
|
||||
|
||||
switch (machine) {
|
||||
switch (machine_id) {
|
||||
case CALXEDA_HIGHBANK:
|
||||
dev = qdev_create(NULL, "l2x0");
|
||||
qdev_init_nofail(dev);
|
||||
@@ -359,14 +359,14 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo);
|
||||
}
|
||||
|
||||
static void highbank_init(QEMUMachineInitArgs *args)
|
||||
static void highbank_init(MachineState *machine)
|
||||
{
|
||||
calxeda_init(args, CALXEDA_HIGHBANK);
|
||||
calxeda_init(machine, CALXEDA_HIGHBANK);
|
||||
}
|
||||
|
||||
static void midway_init(QEMUMachineInitArgs *args)
|
||||
static void midway_init(MachineState *machine)
|
||||
{
|
||||
calxeda_init(args, CALXEDA_MIDWAY);
|
||||
calxeda_init(machine, CALXEDA_MIDWAY);
|
||||
}
|
||||
|
||||
static QEMUMachine highbank_machine = {
|
||||
|
@@ -461,13 +461,13 @@ static struct arm_boot_info integrator_binfo = {
|
||||
.board_id = 0x113,
|
||||
};
|
||||
|
||||
static void integratorcp_init(QEMUMachineInitArgs *args)
|
||||
static void integratorcp_init(MachineState *machine)
|
||||
{
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
ARMCPU *cpu;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
|
12
hw/arm/kzm.c
12
hw/arm/kzm.c
@@ -70,13 +70,13 @@ static struct arm_boot_info kzm_binfo = {
|
||||
.board_id = 1722,
|
||||
};
|
||||
|
||||
static void kzm_init(QEMUMachineInitArgs *args)
|
||||
static void kzm_init(MachineState *machine)
|
||||
{
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
ARMCPU *cpu;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
|
@@ -105,7 +105,7 @@ static struct arm_boot_info mainstone_binfo = {
|
||||
};
|
||||
|
||||
static void mainstone_common_init(MemoryRegion *address_space_mem,
|
||||
QEMUMachineInitArgs *args,
|
||||
MachineState *machine,
|
||||
enum mainstone_model_e model, int arm_id)
|
||||
{
|
||||
uint32_t sector_len = 256 * 1024;
|
||||
@@ -116,7 +116,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
|
||||
int i;
|
||||
int be;
|
||||
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
|
||||
if (!cpu_model)
|
||||
cpu_model = "pxa270-c5";
|
||||
@@ -175,16 +175,16 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
|
||||
smc91c111_init(&nd_table[0], MST_ETH_PHYS,
|
||||
qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
|
||||
|
||||
mainstone_binfo.kernel_filename = args->kernel_filename;
|
||||
mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
|
||||
mainstone_binfo.initrd_filename = args->initrd_filename;
|
||||
mainstone_binfo.kernel_filename = machine->kernel_filename;
|
||||
mainstone_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
mainstone_binfo.initrd_filename = machine->initrd_filename;
|
||||
mainstone_binfo.board_id = arm_id;
|
||||
arm_load_kernel(mpu->cpu, &mainstone_binfo);
|
||||
}
|
||||
|
||||
static void mainstone_init(QEMUMachineInitArgs *args)
|
||||
static void mainstone_init(MachineState *machine)
|
||||
{
|
||||
mainstone_common_init(get_system_memory(), args, mainstone, 0x196);
|
||||
mainstone_common_init(get_system_memory(), machine, mainstone, 0x196);
|
||||
}
|
||||
|
||||
static QEMUMachine mainstone2_machine = {
|
||||
|
@@ -1569,12 +1569,12 @@ static struct arm_boot_info musicpal_binfo = {
|
||||
.board_id = 0x20e,
|
||||
};
|
||||
|
||||
static void musicpal_init(QEMUMachineInitArgs *args)
|
||||
static void musicpal_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
ARMCPU *cpu;
|
||||
qemu_irq pic[32];
|
||||
DeviceState *dev;
|
||||
|
338
hw/arm/nseries.c
338
hw/arm/nseries.c
@@ -239,8 +239,9 @@ static void n800_key_event(void *opaque, int keycode)
|
||||
int code = s->keymap[keycode & 0x7f];
|
||||
|
||||
if (code == -1) {
|
||||
if ((keycode & 0x7f) == RETU_KEYCODE)
|
||||
if ((keycode & 0x7f) == RETU_KEYCODE) {
|
||||
retu_key_event(s->retu, !(keycode & 0x80));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -280,11 +281,14 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
|
||||
s->ts.opaque = s->ts.chip->opaque;
|
||||
s->ts.txrx = tsc210x_txrx;
|
||||
|
||||
for (i = 0; i < 0x80; i ++)
|
||||
for (i = 0; i < 0x80; i++) {
|
||||
s->keymap[i] = -1;
|
||||
for (i = 0; i < 0x10; i ++)
|
||||
if (n800_keys[i] >= 0)
|
||||
}
|
||||
for (i = 0; i < 0x10; i++) {
|
||||
if (n800_keys[i] >= 0) {
|
||||
s->keymap[n800_keys[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_add_kbd_event_handler(n800_key_event, s);
|
||||
|
||||
@@ -308,8 +312,9 @@ static void n810_key_event(void *opaque, int keycode)
|
||||
int code = s->keymap[keycode & 0x7f];
|
||||
|
||||
if (code == -1) {
|
||||
if ((keycode & 0x7f) == RETU_KEYCODE)
|
||||
if ((keycode & 0x7f) == RETU_KEYCODE) {
|
||||
retu_key_event(s->retu, !(keycode & 0x80));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -388,11 +393,14 @@ static void n810_kbd_setup(struct n800_s *s)
|
||||
qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 0x80; i ++)
|
||||
for (i = 0; i < 0x80; i++) {
|
||||
s->keymap[i] = -1;
|
||||
for (i = 0; i < 0x80; i ++)
|
||||
if (n810_keys[i] > 0)
|
||||
}
|
||||
for (i = 0; i < 0x80; i++) {
|
||||
if (n810_keys[i] > 0) {
|
||||
s->keymap[n810_keys[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_add_kbd_event_handler(n810_key_event, s);
|
||||
|
||||
@@ -449,17 +457,20 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
|
||||
struct mipid_s *s = (struct mipid_s *) opaque;
|
||||
uint8_t ret;
|
||||
|
||||
if (len > 9)
|
||||
if (len > 9) {
|
||||
hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
|
||||
}
|
||||
|
||||
if (s->p >= ARRAY_SIZE(s->resp))
|
||||
if (s->p >= ARRAY_SIZE(s->resp)) {
|
||||
ret = 0;
|
||||
else
|
||||
ret = s->resp[s->p ++];
|
||||
if (s->pm --> 0)
|
||||
} else {
|
||||
ret = s->resp[s->p++];
|
||||
}
|
||||
if (s->pm-- > 0) {
|
||||
s->param[s->pm] = cmd;
|
||||
else
|
||||
} else {
|
||||
s->cmd = cmd;
|
||||
}
|
||||
|
||||
switch (s->cmd) {
|
||||
case 0x00: /* NOP */
|
||||
@@ -560,15 +571,17 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
|
||||
goto bad_cmd;
|
||||
|
||||
case 0x25: /* WRCNTR */
|
||||
if (s->pm < 0)
|
||||
if (s->pm < 0) {
|
||||
s->pm = 1;
|
||||
}
|
||||
goto bad_cmd;
|
||||
|
||||
case 0x26: /* GAMSET */
|
||||
if (!s->pm)
|
||||
if (!s->pm) {
|
||||
s->gamma = ffs(s->param[0] & 0xf) - 1;
|
||||
else if (s->pm < 0)
|
||||
} else if (s->pm < 0) {
|
||||
s->pm = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x28: /* DISPOFF */
|
||||
@@ -591,10 +604,11 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
|
||||
s->te = 0;
|
||||
break;
|
||||
case 0x35: /* TEON */
|
||||
if (!s->pm)
|
||||
if (!s->pm) {
|
||||
s->te = 1;
|
||||
else if (s->pm < 0)
|
||||
} else if (s->pm < 0) {
|
||||
s->pm = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x36: /* MADCTR */
|
||||
@@ -613,8 +627,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
|
||||
|
||||
case 0xb0: /* CLKINT / DISCTL */
|
||||
case 0xb1: /* CLKEXT */
|
||||
if (s->pm < 0)
|
||||
if (s->pm < 0) {
|
||||
s->pm = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb4: /* FRMSEL */
|
||||
@@ -635,8 +650,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
|
||||
break;
|
||||
|
||||
case 0xc2: /* IFMOD */
|
||||
if (s->pm < 0)
|
||||
if (s->pm < 0) {
|
||||
s->pm = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc6: /* PWRCTL */
|
||||
@@ -834,118 +850,119 @@ static void n800_setup_nolo_tags(void *sram_base)
|
||||
|
||||
strcpy((void *) (p + 8), "F5");
|
||||
|
||||
stl_raw(p + 10, 0x04f70000);
|
||||
stl_p(p + 10, 0x04f70000);
|
||||
strcpy((void *) (p + 9), "RX-34");
|
||||
|
||||
/* RAM size in MB? */
|
||||
stl_raw(p + 12, 0x80);
|
||||
stl_p(p + 12, 0x80);
|
||||
|
||||
/* Pointer to the list of tags */
|
||||
stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
|
||||
stl_p(p + 13, OMAP2_SRAM_BASE + 0x9000);
|
||||
|
||||
/* The NOLO tags start here */
|
||||
p = sram_base + 0x9000;
|
||||
#define ADD_TAG(tag, len) \
|
||||
stw_raw((uint16_t *) p + 0, tag); \
|
||||
stw_raw((uint16_t *) p + 1, len); p ++; \
|
||||
stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
|
||||
stw_p((uint16_t *) p + 0, tag); \
|
||||
stw_p((uint16_t *) p + 1, len); p++; \
|
||||
stl_p(p++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
|
||||
|
||||
/* OMAP STI console? Pin out settings? */
|
||||
ADD_TAG(0x6e01, 414);
|
||||
for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
|
||||
stl_raw(v ++, n800_pinout[i]);
|
||||
for (i = 0; i < ARRAY_SIZE(n800_pinout); i++) {
|
||||
stl_p(v++, n800_pinout[i]);
|
||||
}
|
||||
|
||||
/* Kernel memsize? */
|
||||
ADD_TAG(0x6e05, 1);
|
||||
stl_raw(v ++, 2);
|
||||
stl_p(v++, 2);
|
||||
|
||||
/* NOLO serial console */
|
||||
ADD_TAG(0x6e02, 4);
|
||||
stl_raw(v ++, XLDR_LL_UART); /* UART number (1 - 3) */
|
||||
stl_p(v++, XLDR_LL_UART); /* UART number (1 - 3) */
|
||||
|
||||
#if 0
|
||||
/* CBUS settings (Retu/AVilma) */
|
||||
ADD_TAG(0x6e03, 6);
|
||||
stw_raw((uint16_t *) v + 0, 65); /* CBUS GPIO0 */
|
||||
stw_raw((uint16_t *) v + 1, 66); /* CBUS GPIO1 */
|
||||
stw_raw((uint16_t *) v + 2, 64); /* CBUS GPIO2 */
|
||||
stw_p((uint16_t *) v + 0, 65); /* CBUS GPIO0 */
|
||||
stw_p((uint16_t *) v + 1, 66); /* CBUS GPIO1 */
|
||||
stw_p((uint16_t *) v + 2, 64); /* CBUS GPIO2 */
|
||||
v += 2;
|
||||
#endif
|
||||
|
||||
/* Nokia ASIC BB5 (Retu/Tahvo) */
|
||||
ADD_TAG(0x6e0a, 4);
|
||||
stw_raw((uint16_t *) v + 0, 111); /* "Retu" interrupt GPIO */
|
||||
stw_raw((uint16_t *) v + 1, 108); /* "Tahvo" interrupt GPIO */
|
||||
v ++;
|
||||
stw_p((uint16_t *) v + 0, 111); /* "Retu" interrupt GPIO */
|
||||
stw_p((uint16_t *) v + 1, 108); /* "Tahvo" interrupt GPIO */
|
||||
v++;
|
||||
|
||||
/* LCD console? */
|
||||
ADD_TAG(0x6e04, 4);
|
||||
stw_raw((uint16_t *) v + 0, 30); /* ??? */
|
||||
stw_raw((uint16_t *) v + 1, 24); /* ??? */
|
||||
v ++;
|
||||
stw_p((uint16_t *) v + 0, 30); /* ??? */
|
||||
stw_p((uint16_t *) v + 1, 24); /* ??? */
|
||||
v++;
|
||||
|
||||
#if 0
|
||||
/* LCD settings */
|
||||
ADD_TAG(0x6e06, 2);
|
||||
stw_raw((uint16_t *) (v ++), 15); /* ??? */
|
||||
stw_p((uint16_t *) (v++), 15); /* ??? */
|
||||
#endif
|
||||
|
||||
/* I^2C (Menelaus) */
|
||||
ADD_TAG(0x6e07, 4);
|
||||
stl_raw(v ++, 0x00720000); /* ??? */
|
||||
stl_p(v++, 0x00720000); /* ??? */
|
||||
|
||||
/* Unknown */
|
||||
ADD_TAG(0x6e0b, 6);
|
||||
stw_raw((uint16_t *) v + 0, 94); /* ??? */
|
||||
stw_raw((uint16_t *) v + 1, 23); /* ??? */
|
||||
stw_raw((uint16_t *) v + 2, 0); /* ??? */
|
||||
stw_p((uint16_t *) v + 0, 94); /* ??? */
|
||||
stw_p((uint16_t *) v + 1, 23); /* ??? */
|
||||
stw_p((uint16_t *) v + 2, 0); /* ??? */
|
||||
v += 2;
|
||||
|
||||
/* OMAP gpio switch info */
|
||||
ADD_TAG(0x6e0c, 80);
|
||||
strcpy((void *) v, "bat_cover"); v += 3;
|
||||
stw_raw((uint16_t *) v + 0, 110); /* GPIO num ??? */
|
||||
stw_raw((uint16_t *) v + 1, 1); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 0, 110); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 1, 1); /* GPIO num ??? */
|
||||
v += 2;
|
||||
strcpy((void *) v, "cam_act"); v += 3;
|
||||
stw_raw((uint16_t *) v + 0, 95); /* GPIO num ??? */
|
||||
stw_raw((uint16_t *) v + 1, 32); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 0, 95); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 1, 32); /* GPIO num ??? */
|
||||
v += 2;
|
||||
strcpy((void *) v, "cam_turn"); v += 3;
|
||||
stw_raw((uint16_t *) v + 0, 12); /* GPIO num ??? */
|
||||
stw_raw((uint16_t *) v + 1, 33); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 0, 12); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 1, 33); /* GPIO num ??? */
|
||||
v += 2;
|
||||
strcpy((void *) v, "headphone"); v += 3;
|
||||
stw_raw((uint16_t *) v + 0, 107); /* GPIO num ??? */
|
||||
stw_raw((uint16_t *) v + 1, 17); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 0, 107); /* GPIO num ??? */
|
||||
stw_p((uint16_t *) v + 1, 17); /* GPIO num ??? */
|
||||
v += 2;
|
||||
|
||||
/* Bluetooth */
|
||||
ADD_TAG(0x6e0e, 12);
|
||||
stl_raw(v ++, 0x5c623d01); /* ??? */
|
||||
stl_raw(v ++, 0x00000201); /* ??? */
|
||||
stl_raw(v ++, 0x00000000); /* ??? */
|
||||
stl_p(v++, 0x5c623d01); /* ??? */
|
||||
stl_p(v++, 0x00000201); /* ??? */
|
||||
stl_p(v++, 0x00000000); /* ??? */
|
||||
|
||||
/* CX3110x WLAN settings */
|
||||
ADD_TAG(0x6e0f, 8);
|
||||
stl_raw(v ++, 0x00610025); /* ??? */
|
||||
stl_raw(v ++, 0xffff0057); /* ??? */
|
||||
stl_p(v++, 0x00610025); /* ??? */
|
||||
stl_p(v++, 0xffff0057); /* ??? */
|
||||
|
||||
/* MMC host settings */
|
||||
ADD_TAG(0x6e10, 12);
|
||||
stl_raw(v ++, 0xffff000f); /* ??? */
|
||||
stl_raw(v ++, 0xffffffff); /* ??? */
|
||||
stl_raw(v ++, 0x00000060); /* ??? */
|
||||
stl_p(v++, 0xffff000f); /* ??? */
|
||||
stl_p(v++, 0xffffffff); /* ??? */
|
||||
stl_p(v++, 0x00000060); /* ??? */
|
||||
|
||||
/* OneNAND chip select */
|
||||
ADD_TAG(0x6e11, 10);
|
||||
stl_raw(v ++, 0x00000401); /* ??? */
|
||||
stl_raw(v ++, 0x0002003a); /* ??? */
|
||||
stl_raw(v ++, 0x00000002); /* ??? */
|
||||
stl_p(v++, 0x00000401); /* ??? */
|
||||
stl_p(v++, 0x0002003a); /* ??? */
|
||||
stl_p(v++, 0x00000002); /* ??? */
|
||||
|
||||
/* TEA5761 sensor settings */
|
||||
ADD_TAG(0x6e12, 2);
|
||||
stl_raw(v ++, 93); /* GPIO num ??? */
|
||||
stl_p(v++, 93); /* GPIO num ??? */
|
||||
|
||||
#if 0
|
||||
/* Unknown tag */
|
||||
@@ -956,8 +973,8 @@ static void n800_setup_nolo_tags(void *sram_base)
|
||||
#endif
|
||||
|
||||
/* End of the list */
|
||||
stl_raw(p ++, 0x00000000);
|
||||
stl_raw(p ++, 0x00000000);
|
||||
stl_p(p++, 0x00000000);
|
||||
stl_p(p++, 0x00000000);
|
||||
}
|
||||
|
||||
/* This task is normally performed by the bootloader. If we're loading
|
||||
@@ -1032,8 +1049,9 @@ static void n8x0_boot_init(void *opaque)
|
||||
s->mpu->cpu->env.GE = 0x5;
|
||||
|
||||
/* If the machine has a slided keyboard, open it */
|
||||
if (s->kbd)
|
||||
if (s->kbd) {
|
||||
qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
|
||||
}
|
||||
}
|
||||
|
||||
#define OMAP_TAG_NOKIA_BT 0x4e01
|
||||
@@ -1119,112 +1137,112 @@ static int n8x0_atag_setup(void *p, int model)
|
||||
|
||||
w = p;
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_UART); /* u16 tag */
|
||||
stw_raw(w ++, 4); /* u16 len */
|
||||
stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
|
||||
w ++;
|
||||
stw_p(w++, OMAP_TAG_UART); /* u16 tag */
|
||||
stw_p(w++, 4); /* u16 len */
|
||||
stw_p(w++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
|
||||
w++;
|
||||
|
||||
#if 0
|
||||
stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE); /* u16 tag */
|
||||
stw_raw(w ++, 4); /* u16 len */
|
||||
stw_raw(w ++, XLDR_LL_UART + 1); /* u8 console_uart */
|
||||
stw_raw(w ++, 115200); /* u32 console_speed */
|
||||
stw_p(w++, OMAP_TAG_SERIAL_CONSOLE); /* u16 tag */
|
||||
stw_p(w++, 4); /* u16 len */
|
||||
stw_p(w++, XLDR_LL_UART + 1); /* u8 console_uart */
|
||||
stw_p(w++, 115200); /* u32 console_speed */
|
||||
#endif
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_LCD); /* u16 tag */
|
||||
stw_raw(w ++, 36); /* u16 len */
|
||||
stw_p(w++, OMAP_TAG_LCD); /* u16 tag */
|
||||
stw_p(w++, 36); /* u16 len */
|
||||
strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */
|
||||
w += 8;
|
||||
strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */
|
||||
w += 8;
|
||||
stw_raw(w ++, N810_BLIZZARD_RESET_GPIO); /* TODO: n800 s16 nreset_gpio */
|
||||
stw_raw(w ++, 24); /* u8 data_lines */
|
||||
stw_p(w++, N810_BLIZZARD_RESET_GPIO); /* TODO: n800 s16 nreset_gpio */
|
||||
stw_p(w++, 24); /* u8 data_lines */
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_CBUS); /* u16 tag */
|
||||
stw_raw(w ++, 8); /* u16 len */
|
||||
stw_raw(w ++, N8X0_CBUS_CLK_GPIO); /* s16 clk_gpio */
|
||||
stw_raw(w ++, N8X0_CBUS_DAT_GPIO); /* s16 dat_gpio */
|
||||
stw_raw(w ++, N8X0_CBUS_SEL_GPIO); /* s16 sel_gpio */
|
||||
w ++;
|
||||
stw_p(w++, OMAP_TAG_CBUS); /* u16 tag */
|
||||
stw_p(w++, 8); /* u16 len */
|
||||
stw_p(w++, N8X0_CBUS_CLK_GPIO); /* s16 clk_gpio */
|
||||
stw_p(w++, N8X0_CBUS_DAT_GPIO); /* s16 dat_gpio */
|
||||
stw_p(w++, N8X0_CBUS_SEL_GPIO); /* s16 sel_gpio */
|
||||
w++;
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */
|
||||
stw_raw(w ++, 4); /* u16 len */
|
||||
stw_raw(w ++, N8X0_RETU_GPIO); /* s16 retu_irq_gpio */
|
||||
stw_raw(w ++, N8X0_TAHVO_GPIO); /* s16 tahvo_irq_gpio */
|
||||
stw_p(w++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */
|
||||
stw_p(w++, 4); /* u16 len */
|
||||
stw_p(w++, N8X0_RETU_GPIO); /* s16 retu_irq_gpio */
|
||||
stw_p(w++, N8X0_TAHVO_GPIO); /* s16 tahvo_irq_gpio */
|
||||
|
||||
gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
|
||||
for (; gpiosw->name; gpiosw ++) {
|
||||
stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
|
||||
stw_raw(w ++, 20); /* u16 len */
|
||||
for (; gpiosw->name; gpiosw++) {
|
||||
stw_p(w++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
|
||||
stw_p(w++, 20); /* u16 len */
|
||||
strcpy((void *) w, gpiosw->name); /* char name[12] */
|
||||
w += 6;
|
||||
stw_raw(w ++, gpiosw->line); /* u16 gpio */
|
||||
stw_raw(w ++, gpiosw->type);
|
||||
stw_raw(w ++, 0);
|
||||
stw_raw(w ++, 0);
|
||||
stw_p(w++, gpiosw->line); /* u16 gpio */
|
||||
stw_p(w++, gpiosw->type);
|
||||
stw_p(w++, 0);
|
||||
stw_p(w++, 0);
|
||||
}
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_NOKIA_BT); /* u16 tag */
|
||||
stw_raw(w ++, 12); /* u16 len */
|
||||
stw_p(w++, OMAP_TAG_NOKIA_BT); /* u16 tag */
|
||||
stw_p(w++, 12); /* u16 len */
|
||||
b = (void *) w;
|
||||
stb_raw(b ++, 0x01); /* u8 chip_type (CSR) */
|
||||
stb_raw(b ++, N8X0_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */
|
||||
stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */
|
||||
stb_raw(b ++, N8X0_BT_RESET_GPIO); /* u8 reset_gpio */
|
||||
stb_raw(b ++, BT_UART + 1); /* u8 bt_uart */
|
||||
stb_p(b++, 0x01); /* u8 chip_type (CSR) */
|
||||
stb_p(b++, N8X0_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */
|
||||
stb_p(b++, N8X0_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */
|
||||
stb_p(b++, N8X0_BT_RESET_GPIO); /* u8 reset_gpio */
|
||||
stb_p(b++, BT_UART + 1); /* u8 bt_uart */
|
||||
memcpy(b, &n8x0_bd_addr, 6); /* u8 bd_addr[6] */
|
||||
b += 6;
|
||||
stb_raw(b ++, 0x02); /* u8 bt_sysclk (38.4) */
|
||||
stb_p(b++, 0x02); /* u8 bt_sysclk (38.4) */
|
||||
w = (void *) b;
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */
|
||||
stw_raw(w ++, 8); /* u16 len */
|
||||
stw_raw(w ++, 0x25); /* u8 chip_type */
|
||||
stw_raw(w ++, N8X0_WLAN_PWR_GPIO); /* s16 power_gpio */
|
||||
stw_raw(w ++, N8X0_WLAN_IRQ_GPIO); /* s16 irq_gpio */
|
||||
stw_raw(w ++, -1); /* s16 spi_cs_gpio */
|
||||
stw_p(w++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */
|
||||
stw_p(w++, 8); /* u16 len */
|
||||
stw_p(w++, 0x25); /* u8 chip_type */
|
||||
stw_p(w++, N8X0_WLAN_PWR_GPIO); /* s16 power_gpio */
|
||||
stw_p(w++, N8X0_WLAN_IRQ_GPIO); /* s16 irq_gpio */
|
||||
stw_p(w++, -1); /* s16 spi_cs_gpio */
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_MMC); /* u16 tag */
|
||||
stw_raw(w ++, 16); /* u16 len */
|
||||
stw_p(w++, OMAP_TAG_MMC); /* u16 tag */
|
||||
stw_p(w++, 16); /* u16 len */
|
||||
if (model == 810) {
|
||||
stw_raw(w ++, 0x23f); /* unsigned flags */
|
||||
stw_raw(w ++, -1); /* s16 power_pin */
|
||||
stw_raw(w ++, -1); /* s16 switch_pin */
|
||||
stw_raw(w ++, -1); /* s16 wp_pin */
|
||||
stw_raw(w ++, 0x240); /* unsigned flags */
|
||||
stw_raw(w ++, 0xc000); /* s16 power_pin */
|
||||
stw_raw(w ++, 0x0248); /* s16 switch_pin */
|
||||
stw_raw(w ++, 0xc000); /* s16 wp_pin */
|
||||
stw_p(w++, 0x23f); /* unsigned flags */
|
||||
stw_p(w++, -1); /* s16 power_pin */
|
||||
stw_p(w++, -1); /* s16 switch_pin */
|
||||
stw_p(w++, -1); /* s16 wp_pin */
|
||||
stw_p(w++, 0x240); /* unsigned flags */
|
||||
stw_p(w++, 0xc000); /* s16 power_pin */
|
||||
stw_p(w++, 0x0248); /* s16 switch_pin */
|
||||
stw_p(w++, 0xc000); /* s16 wp_pin */
|
||||
} else {
|
||||
stw_raw(w ++, 0xf); /* unsigned flags */
|
||||
stw_raw(w ++, -1); /* s16 power_pin */
|
||||
stw_raw(w ++, -1); /* s16 switch_pin */
|
||||
stw_raw(w ++, -1); /* s16 wp_pin */
|
||||
stw_raw(w ++, 0); /* unsigned flags */
|
||||
stw_raw(w ++, 0); /* s16 power_pin */
|
||||
stw_raw(w ++, 0); /* s16 switch_pin */
|
||||
stw_raw(w ++, 0); /* s16 wp_pin */
|
||||
stw_p(w++, 0xf); /* unsigned flags */
|
||||
stw_p(w++, -1); /* s16 power_pin */
|
||||
stw_p(w++, -1); /* s16 switch_pin */
|
||||
stw_p(w++, -1); /* s16 wp_pin */
|
||||
stw_p(w++, 0); /* unsigned flags */
|
||||
stw_p(w++, 0); /* s16 power_pin */
|
||||
stw_p(w++, 0); /* s16 switch_pin */
|
||||
stw_p(w++, 0); /* s16 wp_pin */
|
||||
}
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_TEA5761); /* u16 tag */
|
||||
stw_raw(w ++, 4); /* u16 len */
|
||||
stw_raw(w ++, N8X0_TEA5761_CS_GPIO); /* u16 enable_gpio */
|
||||
w ++;
|
||||
stw_p(w++, OMAP_TAG_TEA5761); /* u16 tag */
|
||||
stw_p(w++, 4); /* u16 len */
|
||||
stw_p(w++, N8X0_TEA5761_CS_GPIO); /* u16 enable_gpio */
|
||||
w++;
|
||||
|
||||
partition = (model == 810) ? n810_part_info : n800_part_info;
|
||||
for (; partition->name; partition ++) {
|
||||
stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */
|
||||
stw_raw(w ++, 28); /* u16 len */
|
||||
for (; partition->name; partition++) {
|
||||
stw_p(w++, OMAP_TAG_PARTITION); /* u16 tag */
|
||||
stw_p(w++, 28); /* u16 len */
|
||||
strcpy((void *) w, partition->name); /* char name[16] */
|
||||
l = (void *) (w + 8);
|
||||
stl_raw(l ++, partition->size); /* unsigned int size */
|
||||
stl_raw(l ++, partition->offset); /* unsigned int offset */
|
||||
stl_raw(l ++, partition->mask); /* unsigned int mask_flags */
|
||||
stl_p(l++, partition->size); /* unsigned int size */
|
||||
stl_p(l++, partition->offset); /* unsigned int offset */
|
||||
stl_p(l++, partition->mask); /* unsigned int mask_flags */
|
||||
w = (void *) l;
|
||||
}
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_BOOT_REASON); /* u16 tag */
|
||||
stw_raw(w ++, 12); /* u16 len */
|
||||
stw_p(w++, OMAP_TAG_BOOT_REASON); /* u16 tag */
|
||||
stw_p(w++, 12); /* u16 len */
|
||||
#if 0
|
||||
strcpy((void *) w, "por"); /* char reason_str[12] */
|
||||
strcpy((void *) w, "charger"); /* char reason_str[12] */
|
||||
@@ -1242,15 +1260,15 @@ static int n8x0_atag_setup(void *p, int model)
|
||||
w += 6;
|
||||
|
||||
tag = (model == 810) ? "RX-44" : "RX-34";
|
||||
stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
|
||||
stw_raw(w ++, 24); /* u16 len */
|
||||
stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
|
||||
stw_p(w++, 24); /* u16 len */
|
||||
strcpy((void *) w, "product"); /* char component[12] */
|
||||
w += 6;
|
||||
strcpy((void *) w, tag); /* char version[12] */
|
||||
w += 6;
|
||||
|
||||
stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
|
||||
stw_raw(w ++, 24); /* u16 len */
|
||||
stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
|
||||
stw_p(w++, 24); /* u16 len */
|
||||
strcpy((void *) w, "hw-build"); /* char component[12] */
|
||||
w += 6;
|
||||
strcpy((void *) w, "QEMU ");
|
||||
@@ -1258,8 +1276,8 @@ static int n8x0_atag_setup(void *p, int model)
|
||||
w += 6;
|
||||
|
||||
tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
|
||||
stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
|
||||
stw_raw(w ++, 24); /* u16 len */
|
||||
stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
|
||||
stw_p(w++, 24); /* u16 len */
|
||||
strcpy((void *) w, "nolo"); /* char component[12] */
|
||||
w += 6;
|
||||
strcpy((void *) w, tag); /* char version[12] */
|
||||
@@ -1278,14 +1296,14 @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p)
|
||||
return n8x0_atag_setup(p, 810);
|
||||
}
|
||||
|
||||
static void n8x0_init(QEMUMachineInitArgs *args,
|
||||
static void n8x0_init(MachineState *machine,
|
||||
struct arm_boot_info *binfo, int model)
|
||||
{
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
|
||||
int sdram_size = binfo->ram_size;
|
||||
|
||||
s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
|
||||
s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_model);
|
||||
|
||||
/* Setup peripherals
|
||||
*
|
||||
@@ -1315,9 +1333,9 @@ static void n8x0_init(QEMUMachineInitArgs *args,
|
||||
n8x0_gpio_setup(s);
|
||||
n8x0_nand_setup(s);
|
||||
n8x0_i2c_setup(s);
|
||||
if (model == 800)
|
||||
if (model == 800) {
|
||||
n800_tsc_kbd_setup(s);
|
||||
else if (model == 810) {
|
||||
} else if (model == 810) {
|
||||
n810_tsc_setup(s);
|
||||
n810_kbd_setup(s);
|
||||
}
|
||||
@@ -1329,18 +1347,18 @@ static void n8x0_init(QEMUMachineInitArgs *args,
|
||||
n8x0_usb_setup(s);
|
||||
}
|
||||
|
||||
if (args->kernel_filename) {
|
||||
if (machine->kernel_filename) {
|
||||
/* Or at the linux loader. */
|
||||
binfo->kernel_filename = args->kernel_filename;
|
||||
binfo->kernel_cmdline = args->kernel_cmdline;
|
||||
binfo->initrd_filename = args->initrd_filename;
|
||||
binfo->kernel_filename = machine->kernel_filename;
|
||||
binfo->kernel_cmdline = machine->kernel_cmdline;
|
||||
binfo->initrd_filename = machine->initrd_filename;
|
||||
arm_load_kernel(s->mpu->cpu, binfo);
|
||||
|
||||
qemu_register_reset(n8x0_boot_init, s);
|
||||
}
|
||||
|
||||
if (option_rom[0].name &&
|
||||
(args->boot_order[0] == 'n' || !args->kernel_filename)) {
|
||||
(machine->boot_order[0] == 'n' || !machine->kernel_filename)) {
|
||||
uint8_t nolo_tags[0x10000];
|
||||
/* No, wait, better start at the ROM. */
|
||||
s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
|
||||
@@ -1382,14 +1400,14 @@ static struct arm_boot_info n810_binfo = {
|
||||
.atag_board = n810_atag_setup,
|
||||
};
|
||||
|
||||
static void n800_init(QEMUMachineInitArgs *args)
|
||||
static void n800_init(MachineState *machine)
|
||||
{
|
||||
return n8x0_init(args, &n800_binfo, 800);
|
||||
return n8x0_init(machine, &n800_binfo, 800);
|
||||
}
|
||||
|
||||
static void n810_init(QEMUMachineInitArgs *args)
|
||||
static void n810_init(MachineState *machine)
|
||||
{
|
||||
return n8x0_init(args, &n810_binfo, 810);
|
||||
return n8x0_init(machine, &n810_binfo, 810);
|
||||
}
|
||||
|
||||
static QEMUMachine n800_machine = {
|
||||
|
@@ -98,7 +98,7 @@ static struct arm_boot_info sx1_binfo = {
|
||||
.board_id = 0x265,
|
||||
};
|
||||
|
||||
static void sx1_init(QEMUMachineInitArgs *args, const int version)
|
||||
static void sx1_init(MachineState *machine, const int version)
|
||||
{
|
||||
struct omap_mpu_state_s *mpu;
|
||||
MemoryRegion *address_space = get_system_memory();
|
||||
@@ -118,7 +118,8 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version)
|
||||
flash_size = flash2_size;
|
||||
}
|
||||
|
||||
mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
|
||||
mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size,
|
||||
machine->cpu_model);
|
||||
|
||||
/* External Flash (EMIFS) */
|
||||
memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size);
|
||||
@@ -189,29 +190,29 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version)
|
||||
OMAP_CS1_BASE, &cs[1]);
|
||||
}
|
||||
|
||||
if (!args->kernel_filename && !fl_idx && !qtest_enabled()) {
|
||||
if (!machine->kernel_filename && !fl_idx && !qtest_enabled()) {
|
||||
fprintf(stderr, "Kernel or Flash image must be specified\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Load the kernel. */
|
||||
sx1_binfo.kernel_filename = args->kernel_filename;
|
||||
sx1_binfo.kernel_cmdline = args->kernel_cmdline;
|
||||
sx1_binfo.initrd_filename = args->initrd_filename;
|
||||
sx1_binfo.kernel_filename = machine->kernel_filename;
|
||||
sx1_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
sx1_binfo.initrd_filename = machine->initrd_filename;
|
||||
arm_load_kernel(mpu->cpu, &sx1_binfo);
|
||||
|
||||
/* TODO: fix next line */
|
||||
//~ qemu_console_resize(ds, 640, 480);
|
||||
}
|
||||
|
||||
static void sx1_init_v1(QEMUMachineInitArgs *args)
|
||||
static void sx1_init_v1(MachineState *machine)
|
||||
{
|
||||
sx1_init(args, 1);
|
||||
sx1_init(machine, 1);
|
||||
}
|
||||
|
||||
static void sx1_init_v2(QEMUMachineInitArgs *args)
|
||||
static void sx1_init_v2(MachineState *machine)
|
||||
{
|
||||
sx1_init(args, 2);
|
||||
sx1_init(machine, 2);
|
||||
}
|
||||
|
||||
static QEMUMachine sx1_machine_v2 = {
|
||||
|
@@ -191,12 +191,12 @@ static struct arm_boot_info palmte_binfo = {
|
||||
.board_id = 0x331,
|
||||
};
|
||||
|
||||
static void palmte_init(QEMUMachineInitArgs *args)
|
||||
static void palmte_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
struct omap_mpu_state_s *mpu;
|
||||
int flash_size = 0x00800000;
|
||||
|
@@ -45,7 +45,7 @@ static const int realview_board_id[] = {
|
||||
0x76d
|
||||
};
|
||||
|
||||
static void realview_init(QEMUMachineInitArgs *args,
|
||||
static void realview_init(MachineState *machine,
|
||||
enum realview_board_type board_type)
|
||||
{
|
||||
ARMCPU *cpu = NULL;
|
||||
@@ -71,7 +71,7 @@ static void realview_init(QEMUMachineInitArgs *args,
|
||||
uint32_t proc_id = 0;
|
||||
uint32_t sys_id;
|
||||
ram_addr_t low_ram_size;
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
hwaddr periphbase = 0;
|
||||
|
||||
switch (board_type) {
|
||||
@@ -91,7 +91,7 @@ static void realview_init(QEMUMachineInitArgs *args,
|
||||
break;
|
||||
}
|
||||
|
||||
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, args->cpu_model);
|
||||
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, machine->cpu_model);
|
||||
if (!cpu_oc) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
exit(1);
|
||||
@@ -342,45 +342,45 @@ static void realview_init(QEMUMachineInitArgs *args,
|
||||
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
|
||||
|
||||
realview_binfo.ram_size = ram_size;
|
||||
realview_binfo.kernel_filename = args->kernel_filename;
|
||||
realview_binfo.kernel_cmdline = args->kernel_cmdline;
|
||||
realview_binfo.initrd_filename = args->initrd_filename;
|
||||
realview_binfo.kernel_filename = machine->kernel_filename;
|
||||
realview_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
realview_binfo.initrd_filename = machine->initrd_filename;
|
||||
realview_binfo.nb_cpus = smp_cpus;
|
||||
realview_binfo.board_id = realview_board_id[board_type];
|
||||
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo);
|
||||
}
|
||||
|
||||
static void realview_eb_init(QEMUMachineInitArgs *args)
|
||||
static void realview_eb_init(MachineState *machine)
|
||||
{
|
||||
if (!args->cpu_model) {
|
||||
args->cpu_model = "arm926";
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "arm926";
|
||||
}
|
||||
realview_init(args, BOARD_EB);
|
||||
realview_init(machine, BOARD_EB);
|
||||
}
|
||||
|
||||
static void realview_eb_mpcore_init(QEMUMachineInitArgs *args)
|
||||
static void realview_eb_mpcore_init(MachineState *machine)
|
||||
{
|
||||
if (!args->cpu_model) {
|
||||
args->cpu_model = "arm11mpcore";
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "arm11mpcore";
|
||||
}
|
||||
realview_init(args, BOARD_EB_MPCORE);
|
||||
realview_init(machine, BOARD_EB_MPCORE);
|
||||
}
|
||||
|
||||
static void realview_pb_a8_init(QEMUMachineInitArgs *args)
|
||||
static void realview_pb_a8_init(MachineState *machine)
|
||||
{
|
||||
if (!args->cpu_model) {
|
||||
args->cpu_model = "cortex-a8";
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "cortex-a8";
|
||||
}
|
||||
realview_init(args, BOARD_PB_A8);
|
||||
realview_init(machine, BOARD_PB_A8);
|
||||
}
|
||||
|
||||
static void realview_pbx_a9_init(QEMUMachineInitArgs *args)
|
||||
static void realview_pbx_a9_init(MachineState *machine)
|
||||
{
|
||||
if (!args->cpu_model) {
|
||||
args->cpu_model = "cortex-a9";
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "cortex-a9";
|
||||
}
|
||||
realview_init(args, BOARD_PBX_A9);
|
||||
realview_init(machine, BOARD_PBX_A9);
|
||||
}
|
||||
|
||||
static QEMUMachine realview_eb_machine = {
|
||||
|
@@ -887,14 +887,14 @@ static struct arm_boot_info spitz_binfo = {
|
||||
.ram_size = 0x04000000,
|
||||
};
|
||||
|
||||
static void spitz_common_init(QEMUMachineInitArgs *args,
|
||||
static void spitz_common_init(MachineState *machine,
|
||||
enum spitz_model_e model, int arm_id)
|
||||
{
|
||||
PXA2xxState *mpu;
|
||||
DeviceState *scp0, *scp1 = NULL;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
|
||||
if (!cpu_model)
|
||||
cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
|
||||
@@ -935,32 +935,32 @@ static void spitz_common_init(QEMUMachineInitArgs *args,
|
||||
/* A 4.0 GB microdrive is permanently sitting in CF slot 0. */
|
||||
spitz_microdrive_attach(mpu, 0);
|
||||
|
||||
spitz_binfo.kernel_filename = args->kernel_filename;
|
||||
spitz_binfo.kernel_cmdline = args->kernel_cmdline;
|
||||
spitz_binfo.initrd_filename = args->initrd_filename;
|
||||
spitz_binfo.kernel_filename = machine->kernel_filename;
|
||||
spitz_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
spitz_binfo.initrd_filename = machine->initrd_filename;
|
||||
spitz_binfo.board_id = arm_id;
|
||||
arm_load_kernel(mpu->cpu, &spitz_binfo);
|
||||
sl_bootparam_write(SL_PXA_PARAM_BASE);
|
||||
}
|
||||
|
||||
static void spitz_init(QEMUMachineInitArgs *args)
|
||||
static void spitz_init(MachineState *machine)
|
||||
{
|
||||
spitz_common_init(args, spitz, 0x2c9);
|
||||
spitz_common_init(machine, spitz, 0x2c9);
|
||||
}
|
||||
|
||||
static void borzoi_init(QEMUMachineInitArgs *args)
|
||||
static void borzoi_init(MachineState *machine)
|
||||
{
|
||||
spitz_common_init(args, borzoi, 0x33f);
|
||||
spitz_common_init(machine, borzoi, 0x33f);
|
||||
}
|
||||
|
||||
static void akita_init(QEMUMachineInitArgs *args)
|
||||
static void akita_init(MachineState *machine)
|
||||
{
|
||||
spitz_common_init(args, akita, 0x2e8);
|
||||
spitz_common_init(machine, akita, 0x2e8);
|
||||
}
|
||||
|
||||
static void terrier_init(QEMUMachineInitArgs *args)
|
||||
static void terrier_init(MachineState *machine)
|
||||
{
|
||||
spitz_common_init(args, terrier, 0x33f);
|
||||
spitz_common_init(machine, terrier, 0x33f);
|
||||
}
|
||||
|
||||
static QEMUMachine akitapda_machine = {
|
||||
|
@@ -1290,9 +1290,10 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
||||
|
||||
sddev = ssi_create_slave(bus, "ssi-sd");
|
||||
ssddev = ssi_create_slave(bus, "ssd0323");
|
||||
gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0),
|
||||
qdev_get_gpio_in(ssddev, 0));
|
||||
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1);
|
||||
gpio_out[GPIO_D][0] = qemu_irq_split(
|
||||
qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
|
||||
qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0));
|
||||
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
|
||||
|
||||
/* Make sure the select pin is high. */
|
||||
qemu_irq_raise(gpio_out[GPIO_D][0]);
|
||||
@@ -1333,17 +1334,17 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
||||
}
|
||||
|
||||
/* FIXME: Figure out how to generate these from stellaris_boards. */
|
||||
static void lm3s811evb_init(QEMUMachineInitArgs *args)
|
||||
static void lm3s811evb_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
|
||||
}
|
||||
|
||||
static void lm3s6965evb_init(QEMUMachineInitArgs *args)
|
||||
static void lm3s6965evb_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
|
||||
}
|
||||
|
||||
|
@@ -211,12 +211,12 @@ static struct arm_boot_info tosa_binfo = {
|
||||
.ram_size = 0x04000000,
|
||||
};
|
||||
|
||||
static void tosa_init(QEMUMachineInitArgs *args)
|
||||
static void tosa_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
||||
PXA2xxState *mpu;
|
||||
|
@@ -173,7 +173,7 @@ static int vpb_sic_init(SysBusDevice *sbd)
|
||||
|
||||
static struct arm_boot_info versatile_binfo;
|
||||
|
||||
static void versatile_init(QEMUMachineInitArgs *args, int board_id)
|
||||
static void versatile_init(MachineState *machine, int board_id)
|
||||
{
|
||||
ARMCPU *cpu;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
@@ -190,15 +190,15 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
|
||||
int done_smc = 0;
|
||||
DriveInfo *dinfo;
|
||||
|
||||
if (!args->cpu_model) {
|
||||
args->cpu_model = "arm926";
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "arm926";
|
||||
}
|
||||
cpu = cpu_arm_init(args->cpu_model);
|
||||
cpu = cpu_arm_init(machine->cpu_model);
|
||||
if (!cpu) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
exit(1);
|
||||
}
|
||||
memory_region_init_ram(ram, NULL, "versatile.ram", args->ram_size);
|
||||
memory_region_init_ram(ram, NULL, "versatile.ram", machine->ram_size);
|
||||
vmstate_register_ram_global(ram);
|
||||
/* ??? RAM should repeat to fill physical memory space. */
|
||||
/* SDRAM at address zero. */
|
||||
@@ -344,22 +344,22 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
|
||||
fprintf(stderr, "qemu: Error registering flash memory.\n");
|
||||
}
|
||||
|
||||
versatile_binfo.ram_size = args->ram_size;
|
||||
versatile_binfo.kernel_filename = args->kernel_filename;
|
||||
versatile_binfo.kernel_cmdline = args->kernel_cmdline;
|
||||
versatile_binfo.initrd_filename = args->initrd_filename;
|
||||
versatile_binfo.ram_size = machine->ram_size;
|
||||
versatile_binfo.kernel_filename = machine->kernel_filename;
|
||||
versatile_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
versatile_binfo.initrd_filename = machine->initrd_filename;
|
||||
versatile_binfo.board_id = board_id;
|
||||
arm_load_kernel(cpu, &versatile_binfo);
|
||||
}
|
||||
|
||||
static void vpb_init(QEMUMachineInitArgs *args)
|
||||
static void vpb_init(MachineState *machine)
|
||||
{
|
||||
versatile_init(args, 0x183);
|
||||
versatile_init(machine, 0x183);
|
||||
}
|
||||
|
||||
static void vab_init(QEMUMachineInitArgs *args)
|
||||
static void vab_init(MachineState *machine)
|
||||
{
|
||||
versatile_init(args, 0x25e);
|
||||
versatile_init(machine, 0x25e);
|
||||
}
|
||||
|
||||
static QEMUMachine versatilepb_machine = {
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "net/net.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/block/flash.h"
|
||||
@@ -509,7 +510,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
|
||||
}
|
||||
|
||||
static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||
QEMUMachineInitArgs *args)
|
||||
MachineState *machine)
|
||||
{
|
||||
DeviceState *dev, *sysctl, *pl041;
|
||||
qemu_irq pic[64];
|
||||
@@ -525,7 +526,20 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||
const hwaddr *map = daughterboard->motherboard_map;
|
||||
int i;
|
||||
|
||||
daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic);
|
||||
daughterboard->init(daughterboard, machine->ram_size, machine->cpu_model,
|
||||
pic);
|
||||
|
||||
/*
|
||||
* If a bios file was provided, attempt to map it into memory
|
||||
*/
|
||||
if (bios_name) {
|
||||
const char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
if (!fn || load_image_targphys(fn, map[VE_NORFLASH0],
|
||||
VEXPRESS_FLASH_SIZE) < 0) {
|
||||
error_report("Could not load ROM image '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Motherboard peripherals: the wiring is the same but the
|
||||
* addresses vary between the legacy and A-Series memory maps.
|
||||
@@ -639,10 +653,10 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||
pic[40 + i]);
|
||||
}
|
||||
|
||||
daughterboard->bootinfo.ram_size = args->ram_size;
|
||||
daughterboard->bootinfo.kernel_filename = args->kernel_filename;
|
||||
daughterboard->bootinfo.kernel_cmdline = args->kernel_cmdline;
|
||||
daughterboard->bootinfo.initrd_filename = args->initrd_filename;
|
||||
daughterboard->bootinfo.ram_size = machine->ram_size;
|
||||
daughterboard->bootinfo.kernel_filename = machine->kernel_filename;
|
||||
daughterboard->bootinfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
daughterboard->bootinfo.initrd_filename = machine->initrd_filename;
|
||||
daughterboard->bootinfo.nb_cpus = smp_cpus;
|
||||
daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID;
|
||||
daughterboard->bootinfo.loader_start = daughterboard->loader_start;
|
||||
@@ -653,14 +667,14 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo);
|
||||
}
|
||||
|
||||
static void vexpress_a9_init(QEMUMachineInitArgs *args)
|
||||
static void vexpress_a9_init(MachineState *machine)
|
||||
{
|
||||
vexpress_common_init(&a9_daughterboard, args);
|
||||
vexpress_common_init(&a9_daughterboard, machine);
|
||||
}
|
||||
|
||||
static void vexpress_a15_init(QEMUMachineInitArgs *args)
|
||||
static void vexpress_a15_init(MachineState *machine)
|
||||
{
|
||||
vexpress_common_init(&a15_daughterboard, args);
|
||||
vexpress_common_init(&a15_daughterboard, machine);
|
||||
}
|
||||
|
||||
static QEMUMachine vexpress_a9_machine = {
|
||||
|
@@ -383,13 +383,13 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
|
||||
return board->fdt;
|
||||
}
|
||||
|
||||
static void machvirt_init(QEMUMachineInitArgs *args)
|
||||
static void machvirt_init(MachineState *machine)
|
||||
{
|
||||
qemu_irq pic[NUM_IRQS];
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
int n;
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
VirtBoardInfo *vbi;
|
||||
|
||||
if (!cpu_model) {
|
||||
@@ -415,7 +415,7 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (args->ram_size > vbi->memmap[VIRT_MEM].size) {
|
||||
if (machine->ram_size > vbi->memmap[VIRT_MEM].size) {
|
||||
error_report("mach-virt: cannot model more than 30GB RAM");
|
||||
exit(1);
|
||||
}
|
||||
@@ -447,7 +447,7 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
||||
}
|
||||
fdt_add_cpu_nodes(vbi);
|
||||
|
||||
memory_region_init_ram(ram, NULL, "mach-virt.ram", args->ram_size);
|
||||
memory_region_init_ram(ram, NULL, "mach-virt.ram", machine->ram_size);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
|
||||
|
||||
@@ -461,10 +461,10 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
||||
*/
|
||||
create_virtio_devices(vbi, pic);
|
||||
|
||||
vbi->bootinfo.ram_size = args->ram_size;
|
||||
vbi->bootinfo.kernel_filename = args->kernel_filename;
|
||||
vbi->bootinfo.kernel_cmdline = args->kernel_cmdline;
|
||||
vbi->bootinfo.initrd_filename = args->initrd_filename;
|
||||
vbi->bootinfo.ram_size = machine->ram_size;
|
||||
vbi->bootinfo.kernel_filename = machine->kernel_filename;
|
||||
vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline;
|
||||
vbi->bootinfo.initrd_filename = machine->initrd_filename;
|
||||
vbi->bootinfo.nb_cpus = smp_cpus;
|
||||
vbi->bootinfo.board_id = -1;
|
||||
vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
|
||||
|
@@ -94,20 +94,20 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
|
||||
for (j = 0; j < num_ss; ++j) {
|
||||
flash_dev = ssi_create_slave(spi, "n25q128");
|
||||
|
||||
cs_line = qdev_get_gpio_in(flash_dev, 0);
|
||||
cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
|
||||
sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void zynq_init(QEMUMachineInitArgs *args)
|
||||
static void zynq_init(MachineState *machine)
|
||||
{
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
ObjectClass *cpu_oc;
|
||||
ARMCPU *cpu;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
|
10
hw/arm/z2.c
10
hw/arm/z2.c
@@ -300,12 +300,12 @@ static const TypeInfo aer915_info = {
|
||||
.class_init = aer915_class_init,
|
||||
};
|
||||
|
||||
static void z2_init(QEMUMachineInitArgs *args)
|
||||
static void z2_init(MachineState *machine)
|
||||
{
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
uint32_t sector_len = 0x10000;
|
||||
PXA2xxState *mpu;
|
||||
|
@@ -1 +1 @@
|
||||
obj-y += ioq.o virtio-blk.o
|
||||
obj-y += virtio-blk.o
|
||||
|
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Linux AIO request queue
|
||||
*
|
||||
* Copyright 2012 IBM, Corp.
|
||||
* Copyright 2012 Red Hat, Inc. and/or its affiliates
|
||||
*
|
||||
* Authors:
|
||||
* Stefan Hajnoczi <stefanha@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ioq.h"
|
||||
|
||||
void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs)
|
||||
{
|
||||
int rc;
|
||||
|
||||
ioq->fd = fd;
|
||||
ioq->max_reqs = max_reqs;
|
||||
|
||||
memset(&ioq->io_ctx, 0, sizeof ioq->io_ctx);
|
||||
rc = io_setup(max_reqs, &ioq->io_ctx);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "ioq io_setup failed %d\n", rc);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rc = event_notifier_init(&ioq->io_notifier, 0);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "ioq io event notifier creation failed %d\n", rc);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ioq->freelist = g_malloc0(sizeof ioq->freelist[0] * max_reqs);
|
||||
ioq->freelist_idx = 0;
|
||||
|
||||
ioq->queue = g_malloc0(sizeof ioq->queue[0] * max_reqs);
|
||||
ioq->queue_idx = 0;
|
||||
}
|
||||
|
||||
void ioq_cleanup(IOQueue *ioq)
|
||||
{
|
||||
g_free(ioq->freelist);
|
||||
g_free(ioq->queue);
|
||||
|
||||
event_notifier_cleanup(&ioq->io_notifier);
|
||||
io_destroy(ioq->io_ctx);
|
||||
}
|
||||
|
||||
EventNotifier *ioq_get_notifier(IOQueue *ioq)
|
||||
{
|
||||
return &ioq->io_notifier;
|
||||
}
|
||||
|
||||
struct iocb *ioq_get_iocb(IOQueue *ioq)
|
||||
{
|
||||
/* Underflow cannot happen since ioq is sized for max_reqs */
|
||||
assert(ioq->freelist_idx != 0);
|
||||
|
||||
struct iocb *iocb = ioq->freelist[--ioq->freelist_idx];
|
||||
ioq->queue[ioq->queue_idx++] = iocb;
|
||||
return iocb;
|
||||
}
|
||||
|
||||
void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb)
|
||||
{
|
||||
/* Overflow cannot happen since ioq is sized for max_reqs */
|
||||
assert(ioq->freelist_idx != ioq->max_reqs);
|
||||
|
||||
ioq->freelist[ioq->freelist_idx++] = iocb;
|
||||
}
|
||||
|
||||
struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov,
|
||||
unsigned int count, long long offset)
|
||||
{
|
||||
struct iocb *iocb = ioq_get_iocb(ioq);
|
||||
|
||||
if (read) {
|
||||
io_prep_preadv(iocb, ioq->fd, iov, count, offset);
|
||||
} else {
|
||||
io_prep_pwritev(iocb, ioq->fd, iov, count, offset);
|
||||
}
|
||||
io_set_eventfd(iocb, event_notifier_get_fd(&ioq->io_notifier));
|
||||
return iocb;
|
||||
}
|
||||
|
||||
int ioq_submit(IOQueue *ioq)
|
||||
{
|
||||
int rc = io_submit(ioq->io_ctx, ioq->queue_idx, ioq->queue);
|
||||
ioq->queue_idx = 0; /* reset */
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion,
|
||||
void *opaque)
|
||||
{
|
||||
struct io_event events[ioq->max_reqs];
|
||||
int nevents, i;
|
||||
|
||||
do {
|
||||
nevents = io_getevents(ioq->io_ctx, 0, ioq->max_reqs, events, NULL);
|
||||
} while (nevents < 0 && errno == EINTR);
|
||||
if (nevents < 0) {
|
||||
return nevents;
|
||||
}
|
||||
|
||||
for (i = 0; i < nevents; i++) {
|
||||
ssize_t ret = ((uint64_t)events[i].res2 << 32) | events[i].res;
|
||||
|
||||
completion(events[i].obj, ret, opaque);
|
||||
ioq_put_iocb(ioq, events[i].obj);
|
||||
}
|
||||
return nevents;
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Linux AIO request queue
|
||||
*
|
||||
* Copyright 2012 IBM, Corp.
|
||||
* Copyright 2012 Red Hat, Inc. and/or its affiliates
|
||||
*
|
||||
* Authors:
|
||||
* Stefan Hajnoczi <stefanha@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IOQ_H
|
||||
#define IOQ_H
|
||||
|
||||
#include <libaio.h>
|
||||
#include "qemu/event_notifier.h"
|
||||
|
||||
typedef struct {
|
||||
int fd; /* file descriptor */
|
||||
unsigned int max_reqs; /* max length of freelist and queue */
|
||||
|
||||
io_context_t io_ctx; /* Linux AIO context */
|
||||
EventNotifier io_notifier; /* Linux AIO eventfd */
|
||||
|
||||
/* Requests can complete in any order so a free list is necessary to manage
|
||||
* available iocbs.
|
||||
*/
|
||||
struct iocb **freelist; /* free iocbs */
|
||||
unsigned int freelist_idx;
|
||||
|
||||
/* Multiple requests are queued up before submitting them all in one go */
|
||||
struct iocb **queue; /* queued iocbs */
|
||||
unsigned int queue_idx;
|
||||
} IOQueue;
|
||||
|
||||
void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs);
|
||||
void ioq_cleanup(IOQueue *ioq);
|
||||
EventNotifier *ioq_get_notifier(IOQueue *ioq);
|
||||
struct iocb *ioq_get_iocb(IOQueue *ioq);
|
||||
void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb);
|
||||
struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov,
|
||||
unsigned int count, long long offset);
|
||||
int ioq_submit(IOQueue *ioq);
|
||||
|
||||
static inline unsigned int ioq_num_queued(IOQueue *ioq)
|
||||
{
|
||||
return ioq->queue_idx;
|
||||
}
|
||||
|
||||
typedef void IOQueueCompletion(struct iocb *iocb, ssize_t ret, void *opaque);
|
||||
int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion,
|
||||
void *opaque);
|
||||
|
||||
#endif /* IOQ_H */
|
@@ -17,7 +17,6 @@
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/virtio/dataplane/vring.h"
|
||||
#include "ioq.h"
|
||||
#include "block/block.h"
|
||||
#include "hw/virtio/virtio-blk.h"
|
||||
#include "virtio-blk.h"
|
||||
@@ -25,20 +24,14 @@
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
||||
enum {
|
||||
SEG_MAX = 126, /* maximum number of I/O segments */
|
||||
VRING_MAX = SEG_MAX + 2, /* maximum number of vring descriptors */
|
||||
REQ_MAX = VRING_MAX, /* maximum number of requests in the vring,
|
||||
* is VRING_MAX / 2 with traditional and
|
||||
* VRING_MAX with indirect descriptors */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct iocb iocb; /* Linux AIO control block */
|
||||
VirtIOBlockDataPlane *s;
|
||||
QEMUIOVector *inhdr; /* iovecs for virtio_blk_inhdr */
|
||||
VirtQueueElement *elem; /* saved data from the virtqueue */
|
||||
struct iovec *bounce_iov; /* used if guest buffers are unaligned */
|
||||
QEMUIOVector *read_qiov; /* for read completion /w bounce buffer */
|
||||
QEMUIOVector qiov; /* original request iovecs */
|
||||
struct iovec bounce_iov; /* used if guest buffers are unaligned */
|
||||
QEMUIOVector bounce_qiov; /* bounce buffer iovecs */
|
||||
bool read; /* read or write? */
|
||||
} VirtIOBlockRequest;
|
||||
|
||||
struct VirtIOBlockDataPlane {
|
||||
@@ -47,7 +40,6 @@ struct VirtIOBlockDataPlane {
|
||||
bool stopping;
|
||||
|
||||
VirtIOBlkConf *blk;
|
||||
int fd; /* image file descriptor */
|
||||
|
||||
VirtIODevice *vdev;
|
||||
Vring vring; /* virtqueue vring */
|
||||
@@ -61,15 +53,10 @@ struct VirtIOBlockDataPlane {
|
||||
IOThread *iothread;
|
||||
IOThread internal_iothread_obj;
|
||||
AioContext *ctx;
|
||||
EventNotifier io_notifier; /* Linux AIO completion */
|
||||
EventNotifier host_notifier; /* doorbell */
|
||||
|
||||
IOQueue ioqueue; /* Linux AIO queue (should really be per
|
||||
IOThread) */
|
||||
VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the
|
||||
queue */
|
||||
|
||||
unsigned int num_reqs;
|
||||
/* Operation blocker on BDS */
|
||||
Error *blocker;
|
||||
};
|
||||
|
||||
/* Raise an interrupt to signal guest, if necessary */
|
||||
@@ -82,33 +69,28 @@ static void notify_guest(VirtIOBlockDataPlane *s)
|
||||
event_notifier_set(s->guest_notifier);
|
||||
}
|
||||
|
||||
static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque)
|
||||
static void complete_rdwr(void *opaque, int ret)
|
||||
{
|
||||
VirtIOBlockDataPlane *s = opaque;
|
||||
VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb);
|
||||
VirtIOBlockRequest *req = opaque;
|
||||
struct virtio_blk_inhdr hdr;
|
||||
int len;
|
||||
|
||||
if (likely(ret >= 0)) {
|
||||
if (likely(ret == 0)) {
|
||||
hdr.status = VIRTIO_BLK_S_OK;
|
||||
len = ret;
|
||||
len = req->qiov.size;
|
||||
} else {
|
||||
hdr.status = VIRTIO_BLK_S_IOERR;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
trace_virtio_blk_data_plane_complete_request(s, req->elem->index, ret);
|
||||
trace_virtio_blk_data_plane_complete_request(req->s, req->elem->index, ret);
|
||||
|
||||
if (req->read_qiov) {
|
||||
assert(req->bounce_iov);
|
||||
qemu_iovec_from_buf(req->read_qiov, 0, req->bounce_iov->iov_base, len);
|
||||
qemu_iovec_destroy(req->read_qiov);
|
||||
g_slice_free(QEMUIOVector, req->read_qiov);
|
||||
if (req->read && req->bounce_iov.iov_base) {
|
||||
qemu_iovec_from_buf(&req->qiov, 0, req->bounce_iov.iov_base, len);
|
||||
}
|
||||
|
||||
if (req->bounce_iov) {
|
||||
qemu_vfree(req->bounce_iov->iov_base);
|
||||
g_slice_free(struct iovec, req->bounce_iov);
|
||||
if (req->bounce_iov.iov_base) {
|
||||
qemu_vfree(req->bounce_iov.iov_base);
|
||||
}
|
||||
|
||||
qemu_iovec_from_buf(req->inhdr, 0, &hdr, sizeof(hdr));
|
||||
@@ -119,9 +101,9 @@ static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque)
|
||||
* written to, but for virtio-blk it seems to be the number of bytes
|
||||
* transferred plus the status bytes.
|
||||
*/
|
||||
vring_push(&s->vring, req->elem, len + sizeof(hdr));
|
||||
req->elem = NULL;
|
||||
s->num_reqs--;
|
||||
vring_push(&req->s->vring, req->elem, len + sizeof(hdr));
|
||||
notify_guest(req->s);
|
||||
g_slice_free(VirtIOBlockRequest, req);
|
||||
}
|
||||
|
||||
static void complete_request_early(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
|
||||
@@ -152,51 +134,87 @@ static void do_get_id_cmd(VirtIOBlockDataPlane *s,
|
||||
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK);
|
||||
}
|
||||
|
||||
static int do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read,
|
||||
struct iovec *iov, unsigned iov_cnt,
|
||||
long long offset, VirtQueueElement *elem,
|
||||
QEMUIOVector *inhdr)
|
||||
static void do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read,
|
||||
struct iovec *iov, unsigned iov_cnt,
|
||||
int64_t sector_num, VirtQueueElement *elem,
|
||||
QEMUIOVector *inhdr)
|
||||
{
|
||||
struct iocb *iocb;
|
||||
QEMUIOVector qiov;
|
||||
struct iovec *bounce_iov = NULL;
|
||||
QEMUIOVector *read_qiov = NULL;
|
||||
VirtIOBlockRequest *req = g_slice_new0(VirtIOBlockRequest);
|
||||
QEMUIOVector *qiov;
|
||||
int nb_sectors;
|
||||
|
||||
qemu_iovec_init_external(&qiov, iov, iov_cnt);
|
||||
if (!bdrv_qiov_is_aligned(s->blk->conf.bs, &qiov)) {
|
||||
void *bounce_buffer = qemu_blockalign(s->blk->conf.bs, qiov.size);
|
||||
/* Fill in virtio block metadata needed for completion */
|
||||
req->s = s;
|
||||
req->elem = elem;
|
||||
req->inhdr = inhdr;
|
||||
req->read = read;
|
||||
qemu_iovec_init_external(&req->qiov, iov, iov_cnt);
|
||||
|
||||
if (read) {
|
||||
/* Need to copy back from bounce buffer on completion */
|
||||
read_qiov = g_slice_new(QEMUIOVector);
|
||||
qemu_iovec_init(read_qiov, iov_cnt);
|
||||
qemu_iovec_concat_iov(read_qiov, iov, iov_cnt, 0, qiov.size);
|
||||
} else {
|
||||
qemu_iovec_to_buf(&qiov, 0, bounce_buffer, qiov.size);
|
||||
qiov = &req->qiov;
|
||||
|
||||
if (!bdrv_qiov_is_aligned(s->blk->conf.bs, qiov)) {
|
||||
void *bounce_buffer = qemu_blockalign(s->blk->conf.bs, qiov->size);
|
||||
|
||||
/* Populate bounce buffer with data for writes */
|
||||
if (!read) {
|
||||
qemu_iovec_to_buf(qiov, 0, bounce_buffer, qiov->size);
|
||||
}
|
||||
|
||||
/* Redirect I/O to aligned bounce buffer */
|
||||
bounce_iov = g_slice_new(struct iovec);
|
||||
bounce_iov->iov_base = bounce_buffer;
|
||||
bounce_iov->iov_len = qiov.size;
|
||||
iov = bounce_iov;
|
||||
iov_cnt = 1;
|
||||
req->bounce_iov.iov_base = bounce_buffer;
|
||||
req->bounce_iov.iov_len = qiov->size;
|
||||
qemu_iovec_init_external(&req->bounce_qiov, &req->bounce_iov, 1);
|
||||
qiov = &req->bounce_qiov;
|
||||
}
|
||||
|
||||
iocb = ioq_rdwr(&s->ioqueue, read, iov, iov_cnt, offset);
|
||||
nb_sectors = qiov->size / BDRV_SECTOR_SIZE;
|
||||
|
||||
/* Fill in virtio block metadata needed for completion */
|
||||
VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb);
|
||||
req->elem = elem;
|
||||
req->inhdr = inhdr;
|
||||
req->bounce_iov = bounce_iov;
|
||||
req->read_qiov = read_qiov;
|
||||
return 0;
|
||||
if (read) {
|
||||
bdrv_aio_readv(s->blk->conf.bs, sector_num, qiov, nb_sectors,
|
||||
complete_rdwr, req);
|
||||
} else {
|
||||
bdrv_aio_writev(s->blk->conf.bs, sector_num, qiov, nb_sectors,
|
||||
complete_rdwr, req);
|
||||
}
|
||||
}
|
||||
|
||||
static int process_request(IOQueue *ioq, VirtQueueElement *elem)
|
||||
static void complete_flush(void *opaque, int ret)
|
||||
{
|
||||
VirtIOBlockRequest *req = opaque;
|
||||
unsigned char status;
|
||||
|
||||
if (ret == 0) {
|
||||
status = VIRTIO_BLK_S_OK;
|
||||
} else {
|
||||
status = VIRTIO_BLK_S_IOERR;
|
||||
}
|
||||
|
||||
complete_request_early(req->s, req->elem, req->inhdr, status);
|
||||
g_slice_free(VirtIOBlockRequest, req);
|
||||
}
|
||||
|
||||
static void do_flush_cmd(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
|
||||
QEMUIOVector *inhdr)
|
||||
{
|
||||
VirtIOBlockRequest *req = g_slice_new(VirtIOBlockRequest);
|
||||
req->s = s;
|
||||
req->elem = elem;
|
||||
req->inhdr = inhdr;
|
||||
|
||||
bdrv_aio_flush(s->blk->conf.bs, complete_flush, req);
|
||||
}
|
||||
|
||||
static void do_scsi_cmd(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
|
||||
QEMUIOVector *inhdr)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = virtio_blk_handle_scsi_req(VIRTIO_BLK(s->vdev), elem);
|
||||
complete_request_early(s, elem, inhdr, status);
|
||||
}
|
||||
|
||||
static int process_request(VirtIOBlockDataPlane *s, VirtQueueElement *elem)
|
||||
{
|
||||
VirtIOBlockDataPlane *s = container_of(ioq, VirtIOBlockDataPlane, ioqueue);
|
||||
struct iovec *iov = elem->out_sg;
|
||||
struct iovec *in_iov = elem->in_sg;
|
||||
unsigned out_num = elem->out_num;
|
||||
@@ -231,25 +249,23 @@ static int process_request(IOQueue *ioq, VirtQueueElement *elem)
|
||||
|
||||
switch (outhdr.type) {
|
||||
case VIRTIO_BLK_T_IN:
|
||||
do_rdwr_cmd(s, true, in_iov, in_num, outhdr.sector * 512, elem, inhdr);
|
||||
do_rdwr_cmd(s, true, in_iov, in_num,
|
||||
outhdr.sector * 512 / BDRV_SECTOR_SIZE,
|
||||
elem, inhdr);
|
||||
return 0;
|
||||
|
||||
case VIRTIO_BLK_T_OUT:
|
||||
do_rdwr_cmd(s, false, iov, out_num, outhdr.sector * 512, elem, inhdr);
|
||||
do_rdwr_cmd(s, false, iov, out_num,
|
||||
outhdr.sector * 512 / BDRV_SECTOR_SIZE,
|
||||
elem, inhdr);
|
||||
return 0;
|
||||
|
||||
case VIRTIO_BLK_T_SCSI_CMD:
|
||||
/* TODO support SCSI commands */
|
||||
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_UNSUPP);
|
||||
do_scsi_cmd(s, elem, inhdr);
|
||||
return 0;
|
||||
|
||||
case VIRTIO_BLK_T_FLUSH:
|
||||
/* TODO fdsync not supported by Linux AIO, do it synchronously here! */
|
||||
if (qemu_fdatasync(s->fd) < 0) {
|
||||
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_IOERR);
|
||||
} else {
|
||||
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK);
|
||||
}
|
||||
do_flush_cmd(s, elem, inhdr);
|
||||
return 0;
|
||||
|
||||
case VIRTIO_BLK_T_GET_ID:
|
||||
@@ -271,7 +287,6 @@ static void handle_notify(EventNotifier *e)
|
||||
|
||||
VirtQueueElement *elem;
|
||||
int ret;
|
||||
unsigned int num_queued;
|
||||
|
||||
event_notifier_test_and_clear(&s->host_notifier);
|
||||
for (;;) {
|
||||
@@ -288,7 +303,7 @@ static void handle_notify(EventNotifier *e)
|
||||
trace_virtio_blk_data_plane_process_request(s, elem->out_num,
|
||||
elem->in_num, elem->index);
|
||||
|
||||
if (process_request(&s->ioqueue, elem) < 0) {
|
||||
if (process_request(s, elem) < 0) {
|
||||
vring_set_broken(&s->vring);
|
||||
vring_free_element(elem);
|
||||
ret = -EFAULT;
|
||||
@@ -303,44 +318,10 @@ static void handle_notify(EventNotifier *e)
|
||||
if (vring_enable_notification(s->vdev, &s->vring)) {
|
||||
break;
|
||||
}
|
||||
} else { /* ret == -ENOBUFS or fatal error, iovecs[] is depleted */
|
||||
/* Since there are no iovecs[] left, stop processing for now. Do
|
||||
* not re-enable guest->host notifies since the I/O completion
|
||||
* handler knows to check for more vring descriptors anyway.
|
||||
*/
|
||||
} else { /* fatal error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
num_queued = ioq_num_queued(&s->ioqueue);
|
||||
if (num_queued > 0) {
|
||||
s->num_reqs += num_queued;
|
||||
|
||||
int rc = ioq_submit(&s->ioqueue);
|
||||
if (unlikely(rc < 0)) {
|
||||
fprintf(stderr, "ioq_submit failed %d\n", rc);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_io(EventNotifier *e)
|
||||
{
|
||||
VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
|
||||
io_notifier);
|
||||
|
||||
event_notifier_test_and_clear(&s->io_notifier);
|
||||
if (ioq_run_completion(&s->ioqueue, complete_request, s) > 0) {
|
||||
notify_guest(s);
|
||||
}
|
||||
|
||||
/* If there were more requests than iovecs, the vring will not be empty yet
|
||||
* so check again. There should now be enough resources to process more
|
||||
* requests.
|
||||
*/
|
||||
if (unlikely(vring_more_avail(&s->vring))) {
|
||||
handle_notify(&s->host_notifier);
|
||||
}
|
||||
}
|
||||
|
||||
/* Context: QEMU global mutex held */
|
||||
@@ -349,7 +330,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
||||
Error **errp)
|
||||
{
|
||||
VirtIOBlockDataPlane *s;
|
||||
int fd;
|
||||
Error *local_err = NULL;
|
||||
|
||||
*dataplane = NULL;
|
||||
|
||||
@@ -357,37 +338,18 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
||||
return;
|
||||
}
|
||||
|
||||
if (blk->scsi) {
|
||||
error_setg(errp,
|
||||
"device is incompatible with x-data-plane, use scsi=off");
|
||||
return;
|
||||
}
|
||||
|
||||
if (blk->config_wce) {
|
||||
error_setg(errp, "device is incompatible with x-data-plane, "
|
||||
"use config-wce=off");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If dataplane is (re-)enabled while the guest is running there could be
|
||||
* block jobs that can conflict.
|
||||
*/
|
||||
if (bdrv_in_use(blk->conf.bs)) {
|
||||
error_setg(errp,
|
||||
"cannot start dataplane thread while device is in use");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = raw_get_aio_fd(blk->conf.bs);
|
||||
if (fd < 0) {
|
||||
error_setg(errp, "drive is incompatible with x-data-plane, "
|
||||
"use format=raw,cache=none,aio=native");
|
||||
if (bdrv_op_is_blocked(blk->conf.bs, BLOCK_OP_TYPE_DATAPLANE, &local_err)) {
|
||||
error_report("cannot start dataplane thread: %s",
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
s = g_new0(VirtIOBlockDataPlane, 1);
|
||||
s->vdev = vdev;
|
||||
s->fd = fd;
|
||||
s->blk = blk;
|
||||
|
||||
if (blk->iothread) {
|
||||
@@ -406,8 +368,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
||||
}
|
||||
s->ctx = iothread_get_aio_context(s->iothread);
|
||||
|
||||
/* Prevent block operations that conflict with data plane thread */
|
||||
bdrv_set_in_use(blk->conf.bs, 1);
|
||||
error_setg(&s->blocker, "block device is in use by data plane");
|
||||
bdrv_op_block_all(blk->conf.bs, s->blocker);
|
||||
|
||||
*dataplane = s;
|
||||
}
|
||||
@@ -420,7 +382,8 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
||||
}
|
||||
|
||||
virtio_blk_data_plane_stop(s);
|
||||
bdrv_set_in_use(s->blk->conf.bs, 0);
|
||||
bdrv_op_unblock_all(s->blk->conf.bs, s->blocker);
|
||||
error_free(s->blocker);
|
||||
object_unref(OBJECT(s->iothread));
|
||||
g_free(s);
|
||||
}
|
||||
@@ -431,7 +394,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtQueue *vq;
|
||||
int i;
|
||||
|
||||
if (s->started) {
|
||||
return;
|
||||
@@ -464,24 +426,18 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
|
||||
}
|
||||
s->host_notifier = *virtio_queue_get_host_notifier(vq);
|
||||
|
||||
/* Set up ioqueue */
|
||||
ioq_init(&s->ioqueue, s->fd, REQ_MAX);
|
||||
for (i = 0; i < ARRAY_SIZE(s->requests); i++) {
|
||||
ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
|
||||
}
|
||||
s->io_notifier = *ioq_get_notifier(&s->ioqueue);
|
||||
|
||||
s->starting = false;
|
||||
s->started = true;
|
||||
trace_virtio_blk_data_plane_start(s);
|
||||
|
||||
bdrv_set_aio_context(s->blk->conf.bs, s->ctx);
|
||||
|
||||
/* Kick right away to begin processing requests already in vring */
|
||||
event_notifier_set(virtio_queue_get_host_notifier(vq));
|
||||
|
||||
/* Get this show started by hooking up our callbacks */
|
||||
aio_context_acquire(s->ctx);
|
||||
aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify);
|
||||
aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io);
|
||||
aio_context_release(s->ctx);
|
||||
}
|
||||
|
||||
@@ -501,13 +457,8 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
|
||||
/* Stop notifications for new requests from guest */
|
||||
aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
|
||||
|
||||
/* Complete pending requests */
|
||||
while (s->num_reqs > 0) {
|
||||
aio_poll(s->ctx, true);
|
||||
}
|
||||
|
||||
/* Stop ioq callbacks (there are no pending requests left) */
|
||||
aio_set_event_notifier(s->ctx, &s->io_notifier, NULL);
|
||||
/* Drain and switch bs back to the QEMU main loop */
|
||||
bdrv_set_aio_context(s->blk->conf.bs, qemu_get_aio_context());
|
||||
|
||||
aio_context_release(s->ctx);
|
||||
|
||||
@@ -516,7 +467,6 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
|
||||
*/
|
||||
vring_teardown(&s->vring, s->vdev, 0);
|
||||
|
||||
ioq_cleanup(&s->ioqueue);
|
||||
k->set_host_notifier(qbus->parent, 0, false);
|
||||
|
||||
/* Clean up guest notifier (irq) */
|
||||
|
@@ -33,7 +33,6 @@ typedef struct VirtIOBlockReq
|
||||
VirtQueueElement elem;
|
||||
struct virtio_blk_inhdr *in;
|
||||
struct virtio_blk_outhdr *out;
|
||||
struct virtio_scsi_inhdr *scsi;
|
||||
QEMUIOVector qiov;
|
||||
struct VirtIOBlockReq *next;
|
||||
BlockAcctCookie acct;
|
||||
@@ -125,13 +124,15 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
|
||||
return req;
|
||||
}
|
||||
|
||||
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
|
||||
VirtQueueElement *elem)
|
||||
{
|
||||
#ifdef __linux__
|
||||
int ret;
|
||||
int i;
|
||||
#endif
|
||||
int status = VIRTIO_BLK_S_OK;
|
||||
struct virtio_scsi_inhdr *scsi = NULL;
|
||||
#ifdef __linux__
|
||||
int i;
|
||||
struct sg_io_hdr hdr;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We require at least one output segment each for the virtio_blk_outhdr
|
||||
@@ -140,19 +141,18 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
* We also at least require the virtio_blk_inhdr, the virtio_scsi_inhdr
|
||||
* and the sense buffer pointer in the input segments.
|
||||
*/
|
||||
if (req->elem.out_num < 2 || req->elem.in_num < 3) {
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
|
||||
g_free(req);
|
||||
return;
|
||||
if (elem->out_num < 2 || elem->in_num < 3) {
|
||||
status = VIRTIO_BLK_S_IOERR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* The scsi inhdr is placed in the second-to-last input segment, just
|
||||
* before the regular inhdr.
|
||||
*/
|
||||
req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
|
||||
scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
|
||||
|
||||
if (!req->dev->blk.scsi) {
|
||||
if (!blk->blk.scsi) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
goto fail;
|
||||
}
|
||||
@@ -160,43 +160,42 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
/*
|
||||
* No support for bidirection commands yet.
|
||||
*/
|
||||
if (req->elem.out_num > 2 && req->elem.in_num > 3) {
|
||||
if (elem->out_num > 2 && elem->in_num > 3) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
struct sg_io_hdr hdr;
|
||||
memset(&hdr, 0, sizeof(struct sg_io_hdr));
|
||||
hdr.interface_id = 'S';
|
||||
hdr.cmd_len = req->elem.out_sg[1].iov_len;
|
||||
hdr.cmdp = req->elem.out_sg[1].iov_base;
|
||||
hdr.cmd_len = elem->out_sg[1].iov_len;
|
||||
hdr.cmdp = elem->out_sg[1].iov_base;
|
||||
hdr.dxfer_len = 0;
|
||||
|
||||
if (req->elem.out_num > 2) {
|
||||
if (elem->out_num > 2) {
|
||||
/*
|
||||
* If there are more than the minimally required 2 output segments
|
||||
* there is write payload starting from the third iovec.
|
||||
*/
|
||||
hdr.dxfer_direction = SG_DXFER_TO_DEV;
|
||||
hdr.iovec_count = req->elem.out_num - 2;
|
||||
hdr.iovec_count = elem->out_num - 2;
|
||||
|
||||
for (i = 0; i < hdr.iovec_count; i++)
|
||||
hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len;
|
||||
hdr.dxfer_len += elem->out_sg[i + 2].iov_len;
|
||||
|
||||
hdr.dxferp = req->elem.out_sg + 2;
|
||||
hdr.dxferp = elem->out_sg + 2;
|
||||
|
||||
} else if (req->elem.in_num > 3) {
|
||||
} else if (elem->in_num > 3) {
|
||||
/*
|
||||
* If we have more than 3 input segments the guest wants to actually
|
||||
* read data.
|
||||
*/
|
||||
hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
hdr.iovec_count = req->elem.in_num - 3;
|
||||
hdr.iovec_count = elem->in_num - 3;
|
||||
for (i = 0; i < hdr.iovec_count; i++)
|
||||
hdr.dxfer_len += req->elem.in_sg[i].iov_len;
|
||||
hdr.dxfer_len += elem->in_sg[i].iov_len;
|
||||
|
||||
hdr.dxferp = req->elem.in_sg;
|
||||
hdr.dxferp = elem->in_sg;
|
||||
} else {
|
||||
/*
|
||||
* Some SCSI commands don't actually transfer any data.
|
||||
@@ -204,11 +203,11 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
hdr.dxfer_direction = SG_DXFER_NONE;
|
||||
}
|
||||
|
||||
hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base;
|
||||
hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len;
|
||||
hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base;
|
||||
hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len;
|
||||
|
||||
ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
|
||||
if (ret) {
|
||||
status = bdrv_ioctl(blk->bs, SG_IO, &hdr);
|
||||
if (status) {
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
goto fail;
|
||||
}
|
||||
@@ -224,23 +223,31 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
hdr.status = CHECK_CONDITION;
|
||||
}
|
||||
|
||||
stl_p(&req->scsi->errors,
|
||||
stl_p(&scsi->errors,
|
||||
hdr.status | (hdr.msg_status << 8) |
|
||||
(hdr.host_status << 16) | (hdr.driver_status << 24));
|
||||
stl_p(&req->scsi->residual, hdr.resid);
|
||||
stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
|
||||
stl_p(&req->scsi->data_len, hdr.dxfer_len);
|
||||
stl_p(&scsi->residual, hdr.resid);
|
||||
stl_p(&scsi->sense_len, hdr.sb_len_wr);
|
||||
stl_p(&scsi->data_len, hdr.dxfer_len);
|
||||
|
||||
virtio_blk_req_complete(req, status);
|
||||
g_free(req);
|
||||
return;
|
||||
return status;
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
|
||||
fail:
|
||||
/* Just put anything nonzero so that the ioctl fails in the guest. */
|
||||
stl_p(&req->scsi->errors, 255);
|
||||
if (scsi) {
|
||||
stl_p(&scsi->errors, 255);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = virtio_blk_handle_scsi_req(req->dev, &req->elem);
|
||||
virtio_blk_req_complete(req, status);
|
||||
g_free(req);
|
||||
}
|
||||
@@ -487,12 +494,12 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
|
||||
|
||||
bdrv_get_geometry(s->bs, &capacity);
|
||||
memset(&blkcfg, 0, sizeof(blkcfg));
|
||||
stq_raw(&blkcfg.capacity, capacity);
|
||||
stl_raw(&blkcfg.seg_max, 128 - 2);
|
||||
stw_raw(&blkcfg.cylinders, s->conf->cyls);
|
||||
stl_raw(&blkcfg.blk_size, blk_size);
|
||||
stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
|
||||
stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
|
||||
stq_p(&blkcfg.capacity, capacity);
|
||||
stl_p(&blkcfg.seg_max, 128 - 2);
|
||||
stw_p(&blkcfg.cylinders, s->conf->cyls);
|
||||
stl_p(&blkcfg.blk_size, blk_size);
|
||||
stw_p(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
|
||||
stw_p(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
|
||||
blkcfg.heads = s->conf->heads;
|
||||
/*
|
||||
* We must ensure that the block device capacity is a multiple of
|
||||
@@ -523,7 +530,10 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
|
||||
struct virtio_blk_config blkcfg;
|
||||
|
||||
memcpy(&blkcfg, config, sizeof(blkcfg));
|
||||
|
||||
aio_context_acquire(bdrv_get_aio_context(s->bs));
|
||||
bdrv_set_enable_write_cache(s->bs, blkcfg.wce != 0);
|
||||
aio_context_release(bdrv_get_aio_context(s->bs));
|
||||
}
|
||||
|
||||
static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
|
||||
@@ -582,7 +592,10 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
||||
* s->bs would erroneously be placed in writethrough mode.
|
||||
*/
|
||||
if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) {
|
||||
bdrv_set_enable_write_cache(s->bs, !!(features & (1 << VIRTIO_BLK_F_WCE)));
|
||||
aio_context_acquire(bdrv_get_aio_context(s->bs));
|
||||
bdrv_set_enable_write_cache(s->bs,
|
||||
!!(features & (1 << VIRTIO_BLK_F_WCE)));
|
||||
aio_context_release(bdrv_get_aio_context(s->bs));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,7 @@
|
||||
typedef struct PCISerialState {
|
||||
PCIDevice dev;
|
||||
SerialState state;
|
||||
uint8_t prog_if;
|
||||
} PCISerialState;
|
||||
|
||||
typedef struct PCIMultiSerialState {
|
||||
@@ -44,6 +45,7 @@ typedef struct PCIMultiSerialState {
|
||||
SerialState state[PCI_SERIAL_MAX_PORTS];
|
||||
uint32_t level[PCI_SERIAL_MAX_PORTS];
|
||||
qemu_irq *irqs;
|
||||
uint8_t prog_if;
|
||||
} PCIMultiSerialState;
|
||||
|
||||
static int serial_pci_init(PCIDevice *dev)
|
||||
@@ -60,6 +62,7 @@ static int serial_pci_init(PCIDevice *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
|
||||
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
|
||||
s->irq = pci_allocate_irq(&pci->dev);
|
||||
|
||||
@@ -101,6 +104,7 @@ static int multi_serial_pci_init(PCIDevice *dev)
|
||||
assert(pci->ports > 0);
|
||||
assert(pci->ports <= PCI_SERIAL_MAX_PORTS);
|
||||
|
||||
pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
|
||||
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
|
||||
memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * pci->ports);
|
||||
pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
|
||||
@@ -177,12 +181,14 @@ static const VMStateDescription vmstate_pci_multi_serial = {
|
||||
|
||||
static Property serial_pci_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev", PCISerialState, state.chr),
|
||||
DEFINE_PROP_UINT8("prog_if", PCISerialState, prog_if, 0x02),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static Property multi_2x_serial_pci_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr),
|
||||
DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
|
||||
DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -191,6 +197,7 @@ static Property multi_4x_serial_pci_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
|
||||
DEFINE_PROP_CHR("chardev3", PCIMultiSerialState, state[2].chr),
|
||||
DEFINE_PROP_CHR("chardev4", PCIMultiSerialState, state[3].chr),
|
||||
DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@@ -87,6 +87,11 @@ static void uart_update_status(XilinxUARTLite *s)
|
||||
s->regs[R_STATUS] = r;
|
||||
}
|
||||
|
||||
static void xilinx_uartlite_reset(DeviceState *dev)
|
||||
{
|
||||
uart_update_status(XILINX_UARTLITE(dev));
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
uart_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
@@ -196,34 +201,39 @@ static void uart_event(void *opaque, int event)
|
||||
|
||||
}
|
||||
|
||||
static int xilinx_uartlite_init(SysBusDevice *dev)
|
||||
static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
XilinxUARTLite *s = XILINX_UARTLITE(dev);
|
||||
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
|
||||
uart_update_status(s);
|
||||
memory_region_init_io(&s->mmio, OBJECT(s), &uart_ops, s,
|
||||
"xlnx.xps-uartlite", R_MAX * 4);
|
||||
sysbus_init_mmio(dev, &s->mmio);
|
||||
|
||||
s->chr = qemu_char_get_next_serial();
|
||||
if (s->chr)
|
||||
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xilinx_uartlite_init(Object *obj)
|
||||
{
|
||||
XilinxUARTLite *s = XILINX_UARTLITE(obj);
|
||||
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
|
||||
|
||||
memory_region_init_io(&s->mmio, obj, &uart_ops, s,
|
||||
"xlnx.xps-uartlite", R_MAX * 4);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
|
||||
}
|
||||
|
||||
static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
sdc->init = xilinx_uartlite_init;
|
||||
dc->reset = xilinx_uartlite_reset;
|
||||
dc->realize = xilinx_uartlite_realize;
|
||||
}
|
||||
|
||||
static const TypeInfo xilinx_uartlite_info = {
|
||||
.name = TYPE_XILINX_UARTLITE,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(XilinxUARTLite),
|
||||
.instance_init = xilinx_uartlite_init,
|
||||
.class_init = xilinx_uartlite_class_init,
|
||||
};
|
||||
|
||||
|
@@ -11,6 +11,284 @@
|
||||
*/
|
||||
|
||||
#include "hw/boards.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
static char *machine_get_accel(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->accel);
|
||||
}
|
||||
|
||||
static void machine_set_accel(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->accel = g_strdup(value);
|
||||
}
|
||||
|
||||
static bool machine_get_kernel_irqchip(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return ms->kernel_irqchip;
|
||||
}
|
||||
|
||||
static void machine_set_kernel_irqchip(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->kernel_irqchip = value;
|
||||
}
|
||||
|
||||
static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
int64_t value = ms->kvm_shadow_mem;
|
||||
|
||||
visit_type_int(v, &value, name, errp);
|
||||
}
|
||||
|
||||
static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
Error *error = NULL;
|
||||
int64_t value;
|
||||
|
||||
visit_type_int(v, &value, name, &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
return;
|
||||
}
|
||||
|
||||
ms->kvm_shadow_mem = value;
|
||||
}
|
||||
|
||||
static char *machine_get_kernel(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->kernel_filename);
|
||||
}
|
||||
|
||||
static void machine_set_kernel(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->kernel_filename = g_strdup(value);
|
||||
}
|
||||
|
||||
static char *machine_get_initrd(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->initrd_filename);
|
||||
}
|
||||
|
||||
static void machine_set_initrd(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->initrd_filename = g_strdup(value);
|
||||
}
|
||||
|
||||
static char *machine_get_append(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->kernel_cmdline);
|
||||
}
|
||||
|
||||
static void machine_set_append(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->kernel_cmdline = g_strdup(value);
|
||||
}
|
||||
|
||||
static char *machine_get_dtb(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->dtb);
|
||||
}
|
||||
|
||||
static void machine_set_dtb(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->dtb = g_strdup(value);
|
||||
}
|
||||
|
||||
static char *machine_get_dumpdtb(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->dumpdtb);
|
||||
}
|
||||
|
||||
static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->dumpdtb = g_strdup(value);
|
||||
}
|
||||
|
||||
static void machine_get_phandle_start(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
int64_t value = ms->phandle_start;
|
||||
|
||||
visit_type_int(v, &value, name, errp);
|
||||
}
|
||||
|
||||
static void machine_set_phandle_start(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
Error *error = NULL;
|
||||
int64_t value;
|
||||
|
||||
visit_type_int(v, &value, name, &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
return;
|
||||
}
|
||||
|
||||
ms->phandle_start = value;
|
||||
}
|
||||
|
||||
static char *machine_get_dt_compatible(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->dt_compatible);
|
||||
}
|
||||
|
||||
static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->dt_compatible = g_strdup(value);
|
||||
}
|
||||
|
||||
static bool machine_get_dump_guest_core(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return ms->dump_guest_core;
|
||||
}
|
||||
|
||||
static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->dump_guest_core = value;
|
||||
}
|
||||
|
||||
static bool machine_get_mem_merge(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return ms->mem_merge;
|
||||
}
|
||||
|
||||
static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->mem_merge = value;
|
||||
}
|
||||
|
||||
static bool machine_get_usb(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return ms->usb;
|
||||
}
|
||||
|
||||
static void machine_set_usb(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->usb = value;
|
||||
}
|
||||
|
||||
static char *machine_get_firmware(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
return g_strdup(ms->firmware);
|
||||
}
|
||||
|
||||
static void machine_set_firmware(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
ms->firmware = g_strdup(value);
|
||||
}
|
||||
|
||||
static void machine_initfn(Object *obj)
|
||||
{
|
||||
object_property_add_str(obj, "accel",
|
||||
machine_get_accel, machine_set_accel, NULL);
|
||||
object_property_add_bool(obj, "kernel_irqchip",
|
||||
machine_get_kernel_irqchip,
|
||||
machine_set_kernel_irqchip,
|
||||
NULL);
|
||||
object_property_add(obj, "kvm_shadow_mem", "int",
|
||||
machine_get_kvm_shadow_mem,
|
||||
machine_set_kvm_shadow_mem,
|
||||
NULL, NULL, NULL);
|
||||
object_property_add_str(obj, "kernel",
|
||||
machine_get_kernel, machine_set_kernel, NULL);
|
||||
object_property_add_str(obj, "initrd",
|
||||
machine_get_initrd, machine_set_initrd, NULL);
|
||||
object_property_add_str(obj, "append",
|
||||
machine_get_append, machine_set_append, NULL);
|
||||
object_property_add_str(obj, "dtb",
|
||||
machine_get_dtb, machine_set_dtb, NULL);
|
||||
object_property_add_str(obj, "dumpdtb",
|
||||
machine_get_dumpdtb, machine_set_dumpdtb, NULL);
|
||||
object_property_add(obj, "phandle_start", "int",
|
||||
machine_get_phandle_start,
|
||||
machine_set_phandle_start,
|
||||
NULL, NULL, NULL);
|
||||
object_property_add_str(obj, "dt_compatible",
|
||||
machine_get_dt_compatible,
|
||||
machine_set_dt_compatible,
|
||||
NULL);
|
||||
object_property_add_bool(obj, "dump-guest-core",
|
||||
machine_get_dump_guest_core,
|
||||
machine_set_dump_guest_core,
|
||||
NULL);
|
||||
object_property_add_bool(obj, "mem-merge",
|
||||
machine_get_mem_merge, machine_set_mem_merge, NULL);
|
||||
object_property_add_bool(obj, "usb", machine_get_usb, machine_set_usb, NULL);
|
||||
object_property_add_str(obj, "firmware",
|
||||
machine_get_firmware, machine_set_firmware, NULL);
|
||||
}
|
||||
|
||||
static void machine_finalize(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->accel);
|
||||
g_free(ms->kernel_filename);
|
||||
g_free(ms->initrd_filename);
|
||||
g_free(ms->kernel_cmdline);
|
||||
g_free(ms->dtb);
|
||||
g_free(ms->dumpdtb);
|
||||
g_free(ms->dt_compatible);
|
||||
g_free(ms->firmware);
|
||||
}
|
||||
|
||||
static const TypeInfo machine_info = {
|
||||
.name = TYPE_MACHINE,
|
||||
@@ -18,6 +296,8 @@ static const TypeInfo machine_info = {
|
||||
.abstract = true,
|
||||
.class_size = sizeof(MachineClass),
|
||||
.instance_size = sizeof(MachineState),
|
||||
.instance_init = machine_initfn,
|
||||
.instance_finalize = machine_finalize,
|
||||
};
|
||||
|
||||
static void machine_register_types(void)
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
static void machine_none_init(QEMUMachineInitArgs *args)
|
||||
static void machine_none_init(MachineState *machine)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -439,11 +439,27 @@ PropertyInfo qdev_prop_iothread = {
|
||||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
GlobalProperty *g;
|
||||
ObjectClass *oc;
|
||||
|
||||
g = g_malloc0(sizeof(*g));
|
||||
g->driver = qemu_opt_get(opts, "driver");
|
||||
g->property = qemu_opt_get(opts, "property");
|
||||
g->value = qemu_opt_get(opts, "value");
|
||||
oc = object_class_by_name(g->driver);
|
||||
if (oc) {
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
if (dc->hotpluggable) {
|
||||
/* If hotpluggable then skip not_used checking. */
|
||||
g->not_used = false;
|
||||
} else {
|
||||
/* Maybe a typo. */
|
||||
g->not_used = true;
|
||||
}
|
||||
} else {
|
||||
/* Maybe a typo. */
|
||||
g->not_used = true;
|
||||
}
|
||||
qdev_prop_register_global(g);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -955,6 +955,23 @@ void qdev_prop_register_global_list(GlobalProperty *props)
|
||||
}
|
||||
}
|
||||
|
||||
int qdev_prop_check_global(void)
|
||||
{
|
||||
GlobalProperty *prop;
|
||||
int ret = 0;
|
||||
|
||||
QTAILQ_FOREACH(prop, &global_props, next) {
|
||||
if (!prop->not_used) {
|
||||
continue;
|
||||
}
|
||||
ret = 1;
|
||||
error_report("Warning: \"-global %s.%s=%s\" not used",
|
||||
prop->driver, prop->property, prop->value);
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -966,6 +983,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
|
||||
if (strcmp(typename, prop->driver) != 0) {
|
||||
continue;
|
||||
}
|
||||
prop->not_used = false;
|
||||
object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
|
@@ -312,30 +312,82 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
|
||||
return dev->parent_bus;
|
||||
}
|
||||
|
||||
static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
|
||||
const char *name)
|
||||
{
|
||||
NamedGPIOList *ngl;
|
||||
|
||||
QLIST_FOREACH(ngl, &dev->gpios, node) {
|
||||
/* NULL is a valid and matchable name, otherwise do a normal
|
||||
* strcmp match.
|
||||
*/
|
||||
if ((!ngl->name && !name) ||
|
||||
(name && ngl->name && strcmp(name, ngl->name) == 0)) {
|
||||
return ngl;
|
||||
}
|
||||
}
|
||||
|
||||
ngl = g_malloc0(sizeof(*ngl));
|
||||
ngl->name = g_strdup(name);
|
||||
QLIST_INSERT_HEAD(&dev->gpios, ngl, node);
|
||||
return ngl;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
|
||||
const char *name, int n)
|
||||
{
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
|
||||
dev, n);
|
||||
gpio_list->num_in += n;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
|
||||
{
|
||||
dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
|
||||
dev, n);
|
||||
dev->num_gpio_in += n;
|
||||
qdev_init_gpio_in_named(dev, handler, NULL, n);
|
||||
}
|
||||
|
||||
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
|
||||
const char *name, int n)
|
||||
{
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(gpio_list->num_out == 0);
|
||||
gpio_list->num_out = n;
|
||||
gpio_list->out = pins;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
|
||||
{
|
||||
assert(dev->num_gpio_out == 0);
|
||||
dev->num_gpio_out = n;
|
||||
dev->gpio_out = pins;
|
||||
qdev_init_gpio_out_named(dev, pins, NULL, n);
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n)
|
||||
{
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(n >= 0 && n < gpio_list->num_in);
|
||||
return gpio_list->in[n];
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
|
||||
{
|
||||
assert(n >= 0 && n < dev->num_gpio_in);
|
||||
return dev->gpio_in[n];
|
||||
return qdev_get_gpio_in_named(dev, NULL, n);
|
||||
}
|
||||
|
||||
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
|
||||
qemu_irq pin)
|
||||
{
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(n >= 0 && n < gpio_list->num_out);
|
||||
gpio_list->out[n] = pin;
|
||||
}
|
||||
|
||||
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
|
||||
{
|
||||
assert(n >= 0 && n < dev->num_gpio_out);
|
||||
dev->gpio_out[n] = pin;
|
||||
qdev_connect_gpio_out_named(dev, NULL, n, pin);
|
||||
}
|
||||
|
||||
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
||||
@@ -844,6 +896,7 @@ static void device_initfn(Object *obj)
|
||||
object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
|
||||
(Object **)&dev->parent_bus, NULL, 0,
|
||||
&error_abort);
|
||||
QLIST_INIT(&dev->gpios);
|
||||
}
|
||||
|
||||
static void device_post_init(Object *obj)
|
||||
@@ -854,10 +907,22 @@ static void device_post_init(Object *obj)
|
||||
/* Unlink device from bus and free the structure. */
|
||||
static void device_finalize(Object *obj)
|
||||
{
|
||||
NamedGPIOList *ngl, *next;
|
||||
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
if (dev->opts) {
|
||||
qemu_opts_del(dev->opts);
|
||||
}
|
||||
|
||||
QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
|
||||
QLIST_REMOVE(ngl, node);
|
||||
qemu_free_irqs(ngl->in);
|
||||
g_free(ngl->name);
|
||||
g_free(ngl);
|
||||
/* ngl->out irqs are owned by the other end and should not be freed
|
||||
* here
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static void device_class_base_init(ObjectClass *class, void *data)
|
||||
|
@@ -243,12 +243,12 @@ static const MemoryRegionOps gpio_ops = {
|
||||
static struct cris_load_info li;
|
||||
|
||||
static
|
||||
void axisdev88_init(QEMUMachineInitArgs *args)
|
||||
void axisdev88_init(MachineState *machine)
|
||||
{
|
||||
ram_addr_t ram_size = args->ram_size;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
const char *cpu_model = machine->cpu_model;
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
CRISCPU *cpu;
|
||||
CPUCRISState *env;
|
||||
DeviceState *dev;
|
||||
|
@@ -177,7 +177,7 @@ static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size)
|
||||
/* monitor ID 6, board type = 1 (color) */
|
||||
val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR;
|
||||
break;
|
||||
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
|
||||
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
|
||||
val = s->regs[addr - 0x10];
|
||||
break;
|
||||
default:
|
||||
@@ -247,7 +247,7 @@ static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
qemu_irq_lower(s->irq);
|
||||
}
|
||||
break;
|
||||
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
|
||||
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
|
||||
s->regs[addr - 0x10] = val;
|
||||
break;
|
||||
default:
|
||||
@@ -274,6 +274,20 @@ static const GraphicHwOps cg3_ops = {
|
||||
.gfx_update = cg3_update_display,
|
||||
};
|
||||
|
||||
static void cg3_initfn(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
CG3State *s = CG3(obj);
|
||||
|
||||
memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
|
||||
memory_region_set_readonly(&s->rom, true);
|
||||
sysbus_init_mmio(sbd, &s->rom);
|
||||
|
||||
memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
|
||||
CG3_REG_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->reg);
|
||||
}
|
||||
|
||||
static void cg3_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
@@ -282,11 +296,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
|
||||
char *fcode_filename;
|
||||
|
||||
/* FCode ROM */
|
||||
memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
|
||||
vmstate_register_ram_global(&s->rom);
|
||||
memory_region_set_readonly(&s->rom, true);
|
||||
sysbus_init_mmio(sbd, &s->rom);
|
||||
|
||||
fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE);
|
||||
if (fcode_filename) {
|
||||
ret = load_image_targphys(fcode_filename, s->prom_addr,
|
||||
@@ -296,10 +306,6 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
|
||||
CG3_REG_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->reg);
|
||||
|
||||
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size);
|
||||
vmstate_register_ram_global(&s->vram_mem);
|
||||
sysbus_init_mmio(sbd, &s->vram_mem);
|
||||
@@ -374,6 +380,7 @@ static const TypeInfo cg3_info = {
|
||||
.name = TYPE_CG3,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(CG3State),
|
||||
.instance_init = cg3_initfn,
|
||||
.class_init = cg3_class_init,
|
||||
};
|
||||
|
||||
|
@@ -173,6 +173,7 @@ static void jazz_led_update_display(void *opaque)
|
||||
case 16:
|
||||
color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
|
||||
color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
|
||||
break;
|
||||
case 24:
|
||||
color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
|
||||
color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
|
||||
|
@@ -50,7 +50,7 @@ static void glue(draw_line2_, DEPTH)(void *opaque,
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_raw((void *) s);
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
@@ -89,7 +89,7 @@ static void glue(draw_line4_, DEPTH)(void *opaque,
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_raw((void *) s);
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v & 0xf] >> 4) & 0xf0;
|
||||
g = pal[v & 0xf] & 0xf0;
|
||||
b = (pal[v & 0xf] << 4) & 0xf0;
|
||||
@@ -116,7 +116,7 @@ static void glue(draw_line8_, DEPTH)(void *opaque,
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_raw((void *) s);
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v] >> 4) & 0xf0;
|
||||
g = pal[v] & 0xf0;
|
||||
b = (pal[v] << 4) & 0xf0;
|
||||
@@ -136,7 +136,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_raw((void *) s);
|
||||
v = lduw_p((void *) s);
|
||||
r = (v >> 4) & 0xf0;
|
||||
g = v & 0xf0;
|
||||
b = (v << 4) & 0xf0;
|
||||
@@ -159,7 +159,7 @@ static void glue(draw_line16_, DEPTH)(void *opaque,
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_raw((void *) s);
|
||||
v = lduw_p((void *) s);
|
||||
r = (v >> 8) & 0xf8;
|
||||
g = (v >> 3) & 0xfc;
|
||||
b = (v << 3) & 0xf8;
|
||||
|
@@ -620,17 +620,6 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
|
||||
src += 2;
|
||||
break;
|
||||
case 1: /* 16 bpp plus transparency */
|
||||
alpha = *(uint16_t *) src & (1 << 24);
|
||||
if (s->control[0] & LCCR0_CMS)
|
||||
r = g = b = *(uint16_t *) src & 0xff;
|
||||
else {
|
||||
r = (*(uint16_t *) src & 0xf800) >> 8;
|
||||
g = (*(uint16_t *) src & 0x07e0) >> 3;
|
||||
b = (*(uint16_t *) src & 0x001f) << 3;
|
||||
}
|
||||
src += 2;
|
||||
break;
|
||||
case 2: /* 18 bpp plus transparency */
|
||||
alpha = *(uint32_t *) src & (1 << 24);
|
||||
if (s->control[0] & LCCR0_CMS)
|
||||
r = g = b = *(uint32_t *) src & 0xff;
|
||||
@@ -641,6 +630,17 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
|
||||
}
|
||||
src += 4;
|
||||
break;
|
||||
case 2: /* 18 bpp plus transparency */
|
||||
alpha = *(uint32_t *) src & (1 << 24);
|
||||
if (s->control[0] & LCCR0_CMS)
|
||||
r = g = b = *(uint32_t *) src & 0xff;
|
||||
else {
|
||||
r = (*(uint32_t *) src & 0xfc0000) >> 16;
|
||||
g = (*(uint32_t *) src & 0x00fc00) >> 8;
|
||||
b = (*(uint32_t *) src & 0x0000fc);
|
||||
}
|
||||
src += 4;
|
||||
break;
|
||||
case 3: /* 24 bpp plus transparency */
|
||||
alpha = *(uint32_t *) src & (1 << 24);
|
||||
if (s->control[0] & LCCR0_CMS)
|
||||
|
@@ -47,7 +47,7 @@ static void glue(draw_line8_, PIXEL_NAME)(
|
||||
{
|
||||
uint8_t v, r, g, b;
|
||||
do {
|
||||
v = ldub_raw(s);
|
||||
v = ldub_p(s);
|
||||
r = (pal[v] >> 16) & 0xff;
|
||||
g = (pal[v] >> 8) & 0xff;
|
||||
b = (pal[v] >> 0) & 0xff;
|
||||
@@ -64,7 +64,7 @@ static void glue(draw_line16_, PIXEL_NAME)(
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
rgb565 = lduw_raw(s);
|
||||
rgb565 = lduw_p(s);
|
||||
r = ((rgb565 >> 11) & 0x1f) << 3;
|
||||
g = ((rgb565 >> 5) & 0x3f) << 2;
|
||||
b = ((rgb565 >> 0) & 0x1f) << 3;
|
||||
@@ -80,7 +80,7 @@ static void glue(draw_line32_, PIXEL_NAME)(
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
ldub_raw(s);
|
||||
ldub_p(s);
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
r = s[1];
|
||||
g = s[2];
|
||||
|
@@ -530,8 +530,36 @@ static const GraphicHwOps tcx24_ops = {
|
||||
.gfx_update = tcx24_update_display,
|
||||
};
|
||||
|
||||
static int tcx_init1(SysBusDevice *dev)
|
||||
static void tcx_initfn(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
TCXState *s = TCX(obj);
|
||||
|
||||
memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
|
||||
memory_region_set_readonly(&s->rom, true);
|
||||
sysbus_init_mmio(sbd, &s->rom);
|
||||
|
||||
/* DAC */
|
||||
memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
|
||||
"tcx.dac", TCX_DAC_NREGS);
|
||||
sysbus_init_mmio(sbd, &s->dac);
|
||||
|
||||
/* TEC (dummy) */
|
||||
memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
|
||||
"tcx.tec", TCX_TEC_NREGS);
|
||||
sysbus_init_mmio(sbd, &s->tec);
|
||||
|
||||
/* THC: NetBSD writes here even with 8-bit display: dummy */
|
||||
memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
|
||||
TCX_THC_NREGS_24);
|
||||
sysbus_init_mmio(sbd, &s->thc24);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void tcx_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
TCXState *s = TCX(dev);
|
||||
ram_addr_t vram_offset = 0;
|
||||
int size, ret;
|
||||
@@ -544,18 +572,13 @@ static int tcx_init1(SysBusDevice *dev)
|
||||
vram_base = memory_region_get_ram_ptr(&s->vram_mem);
|
||||
|
||||
/* FCode ROM */
|
||||
memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
|
||||
vmstate_register_ram_global(&s->rom);
|
||||
memory_region_set_readonly(&s->rom, true);
|
||||
sysbus_init_mmio(dev, &s->rom);
|
||||
|
||||
fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, TCX_ROM_FILE);
|
||||
if (fcode_filename) {
|
||||
ret = load_image_targphys(fcode_filename, s->prom_addr,
|
||||
FCODE_MAX_ROM_SIZE);
|
||||
if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
|
||||
fprintf(stderr, "tcx: could not load prom '%s'\n", TCX_ROM_FILE);
|
||||
return -1;
|
||||
error_report("tcx: could not load prom '%s'", TCX_ROM_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,24 +587,10 @@ static int tcx_init1(SysBusDevice *dev)
|
||||
size = s->vram_size;
|
||||
memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit",
|
||||
&s->vram_mem, vram_offset, size);
|
||||
sysbus_init_mmio(dev, &s->vram_8bit);
|
||||
sysbus_init_mmio(sbd, &s->vram_8bit);
|
||||
vram_offset += size;
|
||||
vram_base += size;
|
||||
|
||||
/* DAC */
|
||||
memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
|
||||
"tcx.dac", TCX_DAC_NREGS);
|
||||
sysbus_init_mmio(dev, &s->dac);
|
||||
|
||||
/* TEC (dummy) */
|
||||
memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
|
||||
"tcx.tec", TCX_TEC_NREGS);
|
||||
sysbus_init_mmio(dev, &s->tec);
|
||||
/* THC: NetBSD writes here even with 8-bit display: dummy */
|
||||
memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
|
||||
TCX_THC_NREGS_24);
|
||||
sysbus_init_mmio(dev, &s->thc24);
|
||||
|
||||
if (s->depth == 24) {
|
||||
/* 24-bit plane */
|
||||
size = s->vram_size * 4;
|
||||
@@ -589,7 +598,7 @@ static int tcx_init1(SysBusDevice *dev)
|
||||
s->vram24_offset = vram_offset;
|
||||
memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit",
|
||||
&s->vram_mem, vram_offset, size);
|
||||
sysbus_init_mmio(dev, &s->vram_24bit);
|
||||
sysbus_init_mmio(sbd, &s->vram_24bit);
|
||||
vram_offset += size;
|
||||
vram_base += size;
|
||||
|
||||
@@ -599,20 +608,19 @@ static int tcx_init1(SysBusDevice *dev)
|
||||
s->cplane_offset = vram_offset;
|
||||
memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane",
|
||||
&s->vram_mem, vram_offset, size);
|
||||
sysbus_init_mmio(dev, &s->vram_cplane);
|
||||
sysbus_init_mmio(sbd, &s->vram_cplane);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
|
||||
} else {
|
||||
/* THC 8 bit (dummy) */
|
||||
memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
|
||||
TCX_THC_NREGS_8);
|
||||
sysbus_init_mmio(dev, &s->thc8);
|
||||
sysbus_init_mmio(sbd, &s->thc8);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
|
||||
}
|
||||
|
||||
qemu_console_resize(s->con, s->width, s->height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Property tcx_properties[] = {
|
||||
@@ -627,9 +635,8 @@ static Property tcx_properties[] = {
|
||||
static void tcx_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = tcx_init1;
|
||||
dc->realize = tcx_realizefn;
|
||||
dc->reset = tcx_reset;
|
||||
dc->vmsd = &vmstate_tcx;
|
||||
dc->props = tcx_properties;
|
||||
@@ -639,6 +646,7 @@ static const TypeInfo tcx_info = {
|
||||
.name = TYPE_TCX,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(TCXState),
|
||||
.instance_init = tcx_initfn,
|
||||
.class_init = tcx_class_init,
|
||||
};
|
||||
|
||||
|
@@ -361,7 +361,7 @@ static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
|
||||
|
||||
w = width;
|
||||
do {
|
||||
v = lduw_raw((void *)s);
|
||||
v = lduw_p((void *)s);
|
||||
r = (v >> 7) & 0xf8;
|
||||
g = (v >> 2) & 0xf8;
|
||||
b = (v << 3) & 0xf8;
|
||||
@@ -386,7 +386,7 @@ static void glue(vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
|
||||
|
||||
w = width;
|
||||
do {
|
||||
v = lduw_raw((void *)s);
|
||||
v = lduw_p((void *)s);
|
||||
r = (v >> 8) & 0xf8;
|
||||
g = (v >> 3) & 0xfc;
|
||||
b = (v << 3) & 0xf8;
|
||||
|
@@ -863,7 +863,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
|
||||
break;
|
||||
|
||||
case SVGA_REG_CURSOR_Y:
|
||||
ret = s->cursor.x;
|
||||
ret = s->cursor.y;
|
||||
break;
|
||||
|
||||
case SVGA_REG_CURSOR_ON:
|
||||
|
@@ -157,11 +157,6 @@ static inline int stream_running(struct Stream *s)
|
||||
return s->regs[R_DMACR] & DMACR_RUNSTOP;
|
||||
}
|
||||
|
||||
static inline int stream_halted(struct Stream *s)
|
||||
{
|
||||
return s->regs[R_DMASR] & DMASR_HALTED;
|
||||
}
|
||||
|
||||
static inline int stream_idle(struct Stream *s)
|
||||
{
|
||||
return !!(s->regs[R_DMASR] & DMASR_IDLE);
|
||||
|
@@ -14,8 +14,10 @@
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/kvm/clock.h"
|
||||
|
||||
@@ -34,6 +36,48 @@ typedef struct KVMClockState {
|
||||
bool clock_valid;
|
||||
} KVMClockState;
|
||||
|
||||
struct pvclock_vcpu_time_info {
|
||||
uint32_t version;
|
||||
uint32_t pad0;
|
||||
uint64_t tsc_timestamp;
|
||||
uint64_t system_time;
|
||||
uint32_t tsc_to_system_mul;
|
||||
int8_t tsc_shift;
|
||||
uint8_t flags;
|
||||
uint8_t pad[2];
|
||||
} __attribute__((__packed__)); /* 32 bytes */
|
||||
|
||||
static uint64_t kvmclock_current_nsec(KVMClockState *s)
|
||||
{
|
||||
CPUState *cpu = first_cpu;
|
||||
CPUX86State *env = cpu->env_ptr;
|
||||
hwaddr kvmclock_struct_pa = env->system_time_msr & ~1ULL;
|
||||
uint64_t migration_tsc = env->tsc;
|
||||
struct pvclock_vcpu_time_info time;
|
||||
uint64_t delta;
|
||||
uint64_t nsec_lo;
|
||||
uint64_t nsec_hi;
|
||||
uint64_t nsec;
|
||||
|
||||
if (!(env->system_time_msr & 1ULL)) {
|
||||
/* KVM clock not active */
|
||||
return 0;
|
||||
}
|
||||
|
||||
cpu_physical_memory_read(kvmclock_struct_pa, &time, sizeof(time));
|
||||
|
||||
assert(time.tsc_timestamp <= migration_tsc);
|
||||
delta = migration_tsc - time.tsc_timestamp;
|
||||
if (time.tsc_shift < 0) {
|
||||
delta >>= -time.tsc_shift;
|
||||
} else {
|
||||
delta <<= time.tsc_shift;
|
||||
}
|
||||
|
||||
mulu64(&nsec_lo, &nsec_hi, delta, time.tsc_to_system_mul);
|
||||
nsec = (nsec_lo >> 32) | (nsec_hi << 32);
|
||||
return nsec + time.system_time;
|
||||
}
|
||||
|
||||
static void kvmclock_vm_state_change(void *opaque, int running,
|
||||
RunState state)
|
||||
@@ -45,9 +89,15 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
||||
|
||||
if (running) {
|
||||
struct kvm_clock_data data;
|
||||
uint64_t time_at_migration = kvmclock_current_nsec(s);
|
||||
|
||||
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.flags = 0;
|
||||
ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
|
||||
@@ -75,6 +125,8 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
||||
if (s->clock_valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_synchronize_all_states();
|
||||
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
|
||||
|
@@ -922,9 +922,6 @@ static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
|
||||
0x280, 0x380 };
|
||||
static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
|
||||
|
||||
static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
|
||||
static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
|
||||
|
||||
void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
|
||||
{
|
||||
static int nb_ne2k = 0;
|
||||
|
@@ -69,7 +69,7 @@ static bool smbios_legacy_mode;
|
||||
static bool gigabyte_align = true;
|
||||
|
||||
/* PC hardware initialisation */
|
||||
static void pc_init1(QEMUMachineInitArgs *args,
|
||||
static void pc_init1(MachineState *machine,
|
||||
int pci_enabled,
|
||||
int kvmclock_enabled)
|
||||
{
|
||||
@@ -106,7 +106,7 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
||||
object_property_add_child(qdev_get_machine(), "icc-bridge",
|
||||
OBJECT(icc_bridge), NULL);
|
||||
|
||||
pc_cpus_init(args->cpu_model, icc_bridge);
|
||||
pc_cpus_init(machine->cpu_model, icc_bridge);
|
||||
|
||||
if (kvm_enabled() && kvmclock_enabled) {
|
||||
kvmclock_create();
|
||||
@@ -119,13 +119,13 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
||||
* For old machine types, use whatever split we used historically to avoid
|
||||
* breaking migration.
|
||||
*/
|
||||
if (args->ram_size >= 0xe0000000) {
|
||||
if (machine->ram_size >= 0xe0000000) {
|
||||
ram_addr_t lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000;
|
||||
above_4g_mem_size = args->ram_size - lowmem;
|
||||
above_4g_mem_size = machine->ram_size - lowmem;
|
||||
below_4g_mem_size = lowmem;
|
||||
} else {
|
||||
above_4g_mem_size = 0;
|
||||
below_4g_mem_size = args->ram_size;
|
||||
below_4g_mem_size = machine->ram_size;
|
||||
}
|
||||
|
||||
if (pci_enabled) {
|
||||
@@ -145,16 +145,17 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
||||
guest_info->isapc_ram_fw = !pci_enabled;
|
||||
|
||||
if (smbios_defaults) {
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
/* These values are guest ABI, do not change */
|
||||
smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
|
||||
args->machine->name, smbios_legacy_mode);
|
||||
mc->name, smbios_legacy_mode);
|
||||
}
|
||||
|
||||
/* allocate ram and load rom/bios */
|
||||
if (!xen_enabled()) {
|
||||
fw_cfg = pc_memory_init(system_memory,
|
||||
args->kernel_filename, args->kernel_cmdline,
|
||||
args->initrd_filename,
|
||||
machine->kernel_filename, machine->kernel_cmdline,
|
||||
machine->initrd_filename,
|
||||
below_4g_mem_size, above_4g_mem_size,
|
||||
rom_memory, &ram_memory, guest_info);
|
||||
}
|
||||
@@ -170,7 +171,7 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
||||
|
||||
if (pci_enabled) {
|
||||
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
|
||||
system_memory, system_io, args->ram_size,
|
||||
system_memory, system_io, machine->ram_size,
|
||||
below_4g_mem_size,
|
||||
above_4g_mem_size,
|
||||
pci_memory, ram_memory);
|
||||
@@ -235,7 +236,7 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
||||
}
|
||||
}
|
||||
|
||||
pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_order,
|
||||
pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order,
|
||||
floppy, idebus[0], idebus[1], rtc_state);
|
||||
|
||||
if (pci_enabled && usb_enabled(false)) {
|
||||
@@ -258,131 +259,131 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
||||
}
|
||||
}
|
||||
|
||||
static void pc_init_pci(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci(MachineState *machine)
|
||||
{
|
||||
pc_init1(args, 1, 1);
|
||||
pc_init1(machine, 1, 1);
|
||||
}
|
||||
|
||||
static void pc_compat_2_0(QEMUMachineInitArgs *args)
|
||||
static void pc_compat_2_0(MachineState *machine)
|
||||
{
|
||||
smbios_legacy_mode = true;
|
||||
}
|
||||
|
||||
static void pc_compat_1_7(QEMUMachineInitArgs *args)
|
||||
static void pc_compat_1_7(MachineState *machine)
|
||||
{
|
||||
pc_compat_2_0(args);
|
||||
pc_compat_2_0(machine);
|
||||
smbios_defaults = false;
|
||||
gigabyte_align = false;
|
||||
option_rom_has_mr = true;
|
||||
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
||||
}
|
||||
|
||||
static void pc_compat_1_6(QEMUMachineInitArgs *args)
|
||||
static void pc_compat_1_6(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_7(args);
|
||||
pc_compat_1_7(machine);
|
||||
has_pci_info = false;
|
||||
rom_file_has_mr = false;
|
||||
has_acpi_build = false;
|
||||
}
|
||||
|
||||
static void pc_compat_1_5(QEMUMachineInitArgs *args)
|
||||
static void pc_compat_1_5(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_6(args);
|
||||
pc_compat_1_6(machine);
|
||||
}
|
||||
|
||||
static void pc_compat_1_4(QEMUMachineInitArgs *args)
|
||||
static void pc_compat_1_4(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_5(args);
|
||||
pc_compat_1_5(machine);
|
||||
x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
|
||||
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
|
||||
}
|
||||
|
||||
static void pc_compat_1_3(QEMUMachineInitArgs *args)
|
||||
static void pc_compat_1_3(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_4(args);
|
||||
pc_compat_1_4(machine);
|
||||
enable_compat_apic_id_mode();
|
||||
}
|
||||
|
||||
/* PC compat function for pc-0.14 to pc-1.2 */
|
||||
static void pc_compat_1_2(QEMUMachineInitArgs *args)
|
||||
static void pc_compat_1_2(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_3(args);
|
||||
pc_compat_1_3(machine);
|
||||
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||
}
|
||||
|
||||
static void pc_init_pci_2_0(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_2_0(MachineState *machine)
|
||||
{
|
||||
pc_compat_2_0(args);
|
||||
pc_init_pci(args);
|
||||
pc_compat_2_0(machine);
|
||||
pc_init_pci(machine);
|
||||
}
|
||||
|
||||
static void pc_init_pci_1_7(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_1_7(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_7(args);
|
||||
pc_init_pci(args);
|
||||
pc_compat_1_7(machine);
|
||||
pc_init_pci(machine);
|
||||
}
|
||||
|
||||
static void pc_init_pci_1_6(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_1_6(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_6(args);
|
||||
pc_init_pci(args);
|
||||
pc_compat_1_6(machine);
|
||||
pc_init_pci(machine);
|
||||
}
|
||||
|
||||
static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_1_5(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_5(args);
|
||||
pc_init_pci(args);
|
||||
pc_compat_1_5(machine);
|
||||
pc_init_pci(machine);
|
||||
}
|
||||
|
||||
static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_1_4(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_4(args);
|
||||
pc_init_pci(args);
|
||||
pc_compat_1_4(machine);
|
||||
pc_init_pci(machine);
|
||||
}
|
||||
|
||||
static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_1_3(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_3(args);
|
||||
pc_init_pci(args);
|
||||
pc_compat_1_3(machine);
|
||||
pc_init_pci(machine);
|
||||
}
|
||||
|
||||
/* PC machine init function for pc-0.14 to pc-1.2 */
|
||||
static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_1_2(MachineState *machine)
|
||||
{
|
||||
pc_compat_1_2(args);
|
||||
pc_init_pci(args);
|
||||
pc_compat_1_2(machine);
|
||||
pc_init_pci(machine);
|
||||
}
|
||||
|
||||
/* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
|
||||
static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
|
||||
static void pc_init_pci_no_kvmclock(MachineState *machine)
|
||||
{
|
||||
has_pci_info = false;
|
||||
has_acpi_build = false;
|
||||
smbios_defaults = false;
|
||||
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||
enable_compat_apic_id_mode();
|
||||
pc_init1(args, 1, 0);
|
||||
pc_init1(machine, 1, 0);
|
||||
}
|
||||
|
||||
static void pc_init_isa(QEMUMachineInitArgs *args)
|
||||
static void pc_init_isa(MachineState *machine)
|
||||
{
|
||||
has_pci_info = false;
|
||||
has_acpi_build = false;
|
||||
smbios_defaults = false;
|
||||
if (!args->cpu_model) {
|
||||
args->cpu_model = "486";
|
||||
if (!machine->cpu_model) {
|
||||
machine->cpu_model = "486";
|
||||
}
|
||||
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||
enable_compat_apic_id_mode();
|
||||
pc_init1(args, 0, 1);
|
||||
pc_init1(machine, 0, 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
|
||||
static void pc_xen_hvm_init(MachineState *machine)
|
||||
{
|
||||
PCIBus *bus;
|
||||
|
||||
pc_init_pci(args);
|
||||
pc_init_pci(machine);
|
||||
|
||||
bus = pci_find_primary_bus();
|
||||
if (bus != NULL) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user