Compare commits
416 Commits
pull-roms-
...
pull-input
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2082bac151 | ||
|
|
90525fe279 | ||
|
|
3503206a90 | ||
|
|
2deb4acc7c | ||
|
|
5a165668e7 | ||
|
|
2e377f1730 | ||
|
|
be1a717624 | ||
|
|
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 | ||
|
|
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 | ||
|
|
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 | ||
|
|
3f9a6e852e | ||
|
|
fd07d07ba9 | ||
|
|
aea7947c74 | ||
|
|
b35e3ba01a | ||
|
|
521a580d23 | ||
|
|
afff2b15e8 | ||
|
|
d09b8fa161 | ||
|
|
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 | ||
|
|
178ac111bc | ||
|
|
6054d883d6 | ||
|
|
5118dc5975 | ||
|
|
45e66b7beb | ||
|
|
65903a8b08 | ||
|
|
fc13d93726 | ||
|
|
3478881130 | ||
|
|
d2e064a73e | ||
|
|
3894c78764 | ||
|
|
0aff637e92 | ||
|
|
5f758366c0 | ||
|
|
3f9286b721 | ||
|
|
3b69595068 | ||
|
|
5a7733b0b7 | ||
|
|
770a63792b | ||
|
|
b30f4dfbda | ||
|
|
8e4e86afa5 | ||
|
|
76eb98d51c | ||
|
|
d426d9fba8 | ||
|
|
7bca3892cb | ||
|
|
03cf077ac9 | ||
|
|
7b35d0c44c | ||
|
|
61c7bbd236 | ||
|
|
ca8c0fab95 | ||
|
|
f2564d88fe | ||
|
|
b1fe60cd35 | ||
|
|
a2554a334a | ||
|
|
c5fa6c86d0 | ||
|
|
5bc8f026dd | ||
|
|
465bee1da8 | ||
|
|
6a23082b4e | ||
|
|
82a402e99f | ||
|
|
43f35cb5e0 | ||
|
|
d66e5cee00 | ||
|
|
46485de0cb | ||
|
|
42eb58179b | ||
|
|
7159a45b2b | ||
|
|
ea54feff58 | ||
|
|
0a86cb7317 | ||
|
|
97a3ea5719 | ||
|
|
e3542c67af | ||
|
|
9aedd5a5d6 | ||
|
|
b5e51dd714 | ||
|
|
d530e34232 | ||
|
|
4ad303369c | ||
|
|
4993f7ea7e | ||
|
|
8a5eb36a1c | ||
|
|
9c52681277 | ||
|
|
26e2da7279 | ||
|
|
6906046169 | ||
|
|
395071a763 | ||
|
|
e88ae2264d | ||
|
|
91e7fcca47 | ||
|
|
c4ce4c4b1f | ||
|
|
24fd848950 | ||
|
|
59e7a13005 | ||
|
|
97256073b1 | ||
|
|
2ada510698 | ||
|
|
65e7545ea3 | ||
|
|
2a766d294a | ||
|
|
66e6536e0c | ||
|
|
ce53f2f98f | ||
|
|
528728fd93 | ||
|
|
02aa76c2ba | ||
|
|
2858ab09e6 | ||
|
|
11b389f21e | ||
|
|
b162b49adc | ||
|
|
40d19394b7 | ||
|
|
13e315dada | ||
|
|
6297d9a279 | ||
|
|
29136cd8a4 | ||
|
|
87a560c455 | ||
|
|
297a3646c2 | ||
|
|
cdaec3808e | ||
|
|
2ddb16a95f | ||
|
|
f9f3a5ecde | ||
|
|
be3c771796 | ||
|
|
192cca60ae | ||
|
|
4fa953f20d | ||
|
|
468866b816 | ||
|
|
e2cd0f4fb4 | ||
|
|
cbc95538ed | ||
|
|
f9bee751be | ||
|
|
6e2bb3ec70 | ||
|
|
1a381811b4 | ||
|
|
16a9189921 | ||
|
|
ba43bc25c9 | ||
|
|
895527eea5 | ||
|
|
a10c64e0df | ||
|
|
061cdd8182 | ||
|
|
50cb70d185 | ||
|
|
6b7aa99eb4 | ||
|
|
ef3cb5ca82 | ||
|
|
06e33c1c3c | ||
|
|
7d983531c6 | ||
|
|
7b7066b1db | ||
|
|
ad19b35808 | ||
|
|
f167dc37da | ||
|
|
547ec12141 | ||
|
|
fb5964152d | ||
|
|
f24efee41e | ||
|
|
b8dd88b85c | ||
|
|
a5a04f2830 | ||
|
|
a175689654 | ||
|
|
450445d543 | ||
|
|
719ffe1f5f | ||
|
|
d6ed7312d1 | ||
|
|
35d08458a9 | ||
|
|
6e3d652ab2 | ||
|
|
14bcfdc7f1 | ||
|
|
fb626663da | ||
|
|
89f26e6b7b | ||
|
|
1a7917210b | ||
|
|
c3a699be3c | ||
|
|
2a41c92854 | ||
|
|
7e7e5858f8 | ||
|
|
c94239fe56 | ||
|
|
654039b42a | ||
|
|
2f0d8631b7 | ||
|
|
2e11986727 | ||
|
|
889ac2a32f | ||
|
|
eacd606ca7 | ||
|
|
a9171c4fb5 | ||
|
|
c6fa443b3d | ||
|
|
7fd5f064d1 | ||
|
|
5c10495ab1 | ||
|
|
8f1e884b38 | ||
|
|
09319b3041 | ||
|
|
4700a316df | ||
|
|
4a92a558f4 | ||
|
|
7b4d915e11 | ||
|
|
43175fa96a | ||
|
|
05e7e819d7 | ||
|
|
e0723c4510 | ||
|
|
50a2c6e55f | ||
|
|
7848c8d19f | ||
|
|
fd460606fd | ||
|
|
010e639a8d | ||
|
|
304520291a | ||
|
|
639973a474 | ||
|
|
ee11f7a822 | ||
|
|
ada4135f84 | ||
|
|
8e03c100a7 | ||
|
|
dc1823ce26 | ||
|
|
9372514080 | ||
|
|
6a86dec619 | ||
|
|
3d2acaa308 | ||
|
|
5917af812e | ||
|
|
b03c38057b | ||
|
|
dbe5c58f2a | ||
|
|
d383c625e2 | ||
|
|
4522b69c6c | ||
|
|
23335f6273 | ||
|
|
34bb4d02e0 | ||
|
|
6ee143a0a4 | ||
|
|
4bbeb8b173 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@
|
|||||||
/config-host.*
|
/config-host.*
|
||||||
/config-target.*
|
/config-target.*
|
||||||
/config.status
|
/config.status
|
||||||
|
/config-temp
|
||||||
/trace/generated-tracers.h
|
/trace/generated-tracers.h
|
||||||
/trace/generated-tracers.c
|
/trace/generated-tracers.c
|
||||||
/trace/generated-tracers-dtrace.h
|
/trace/generated-tracers-dtrace.h
|
||||||
|
|||||||
10
MAINTAINERS
10
MAINTAINERS
@@ -243,8 +243,8 @@ S: Maintained
|
|||||||
F: hw/*/exynos*
|
F: hw/*/exynos*
|
||||||
|
|
||||||
Calxeda Highbank
|
Calxeda Highbank
|
||||||
M: Mark Langsdorf <mark.langsdorf@calxeda.com>
|
M: Rob Herring <robh@kernel.org>
|
||||||
S: Supported
|
S: Maintained
|
||||||
F: hw/arm/highbank.c
|
F: hw/arm/highbank.c
|
||||||
F: hw/net/xgmac.c
|
F: hw/net/xgmac.c
|
||||||
|
|
||||||
@@ -659,6 +659,12 @@ S: Supported
|
|||||||
F: hw/block/nvme*
|
F: hw/block/nvme*
|
||||||
F: tests/nvme-test.c
|
F: tests/nvme-test.c
|
||||||
|
|
||||||
|
megasas
|
||||||
|
M: Hannes Reinecke <hare@suse.de>
|
||||||
|
S: Supported
|
||||||
|
F: hw/scsi/megasas.c
|
||||||
|
F: hw/scsi/mfi.h
|
||||||
|
|
||||||
Xilinx EDK
|
Xilinx EDK
|
||||||
M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
|
M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
|
||||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
|
|||||||
129
arch_init.c
129
arch_init.c
@@ -560,45 +560,22 @@ static void migration_bitmap_sync(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ram_save_block: Writes a page of memory to the stream f
|
* ram_save_page: Send the given page to the stream
|
||||||
*
|
*
|
||||||
* Returns: The number of bytes written.
|
* Returns: Number of bytes written.
|
||||||
* 0 means no dirty pages
|
|
||||||
*/
|
*/
|
||||||
|
static int ram_save_page(QEMUFile *f, RAMBlock* block, ram_addr_t offset,
|
||||||
static int ram_save_block(QEMUFile *f, bool last_stage)
|
bool last_stage)
|
||||||
{
|
{
|
||||||
RAMBlock *block = last_seen_block;
|
int bytes_sent;
|
||||||
ram_addr_t offset = last_offset;
|
int cont;
|
||||||
bool complete_round = false;
|
|
||||||
int bytes_sent = 0;
|
|
||||||
MemoryRegion *mr;
|
|
||||||
ram_addr_t current_addr;
|
ram_addr_t current_addr;
|
||||||
|
MemoryRegion *mr = block->mr;
|
||||||
if (!block)
|
|
||||||
block = QTAILQ_FIRST(&ram_list.blocks);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
mr = block->mr;
|
|
||||||
offset = migration_bitmap_find_and_reset_dirty(mr, offset);
|
|
||||||
if (complete_round && block == last_seen_block &&
|
|
||||||
offset >= last_offset) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (offset >= block->length) {
|
|
||||||
offset = 0;
|
|
||||||
block = QTAILQ_NEXT(block, next);
|
|
||||||
if (!block) {
|
|
||||||
block = QTAILQ_FIRST(&ram_list.blocks);
|
|
||||||
complete_round = true;
|
|
||||||
ram_bulk_stage = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int ret;
|
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
|
int ret;
|
||||||
bool send_async = true;
|
bool send_async = true;
|
||||||
int cont = (block == last_sent_block) ?
|
|
||||||
RAM_SAVE_FLAG_CONTINUE : 0;
|
cont = (block == last_sent_block) ? RAM_SAVE_FLAG_CONTINUE : 0;
|
||||||
|
|
||||||
p = memory_region_get_ram_ptr(mr) + offset;
|
p = memory_region_get_ram_ptr(mr) + offset;
|
||||||
|
|
||||||
@@ -652,6 +629,46 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
XBZRLE_cache_unlock();
|
XBZRLE_cache_unlock();
|
||||||
|
|
||||||
|
return bytes_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ram_find_and_save_block: Finds a page to send and sends it to f
|
||||||
|
*
|
||||||
|
* Returns: The number of bytes written.
|
||||||
|
* 0 means no dirty pages
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
|
||||||
|
{
|
||||||
|
RAMBlock *block = last_seen_block;
|
||||||
|
ram_addr_t offset = last_offset;
|
||||||
|
bool complete_round = false;
|
||||||
|
int bytes_sent = 0;
|
||||||
|
MemoryRegion *mr;
|
||||||
|
|
||||||
|
if (!block)
|
||||||
|
block = QTAILQ_FIRST(&ram_list.blocks);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
mr = block->mr;
|
||||||
|
offset = migration_bitmap_find_and_reset_dirty(mr, offset);
|
||||||
|
if (complete_round && block == last_seen_block &&
|
||||||
|
offset >= last_offset) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (offset >= block->length) {
|
||||||
|
offset = 0;
|
||||||
|
block = QTAILQ_NEXT(block, next);
|
||||||
|
if (!block) {
|
||||||
|
block = QTAILQ_FIRST(&ram_list.blocks);
|
||||||
|
complete_round = true;
|
||||||
|
ram_bulk_stage = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes_sent = ram_save_page(f, block, offset, last_stage);
|
||||||
|
|
||||||
/* if page is unmodified, continue to the next */
|
/* if page is unmodified, continue to the next */
|
||||||
if (bytes_sent > 0) {
|
if (bytes_sent > 0) {
|
||||||
last_sent_block = block;
|
last_sent_block = block;
|
||||||
@@ -850,7 +867,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
|
|||||||
while ((ret = qemu_file_rate_limit(f)) == 0) {
|
while ((ret = qemu_file_rate_limit(f)) == 0) {
|
||||||
int bytes_sent;
|
int bytes_sent;
|
||||||
|
|
||||||
bytes_sent = ram_save_block(f, false);
|
bytes_sent = ram_find_and_save_block(f, false);
|
||||||
/* no more blocks to sent */
|
/* no more blocks to sent */
|
||||||
if (bytes_sent == 0) {
|
if (bytes_sent == 0) {
|
||||||
break;
|
break;
|
||||||
@@ -912,7 +929,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
|
|||||||
while (true) {
|
while (true) {
|
||||||
int bytes_sent;
|
int bytes_sent;
|
||||||
|
|
||||||
bytes_sent = ram_save_block(f, true);
|
bytes_sent = ram_find_and_save_block(f, true);
|
||||||
/* no more blocks to sent */
|
/* no more blocks to sent */
|
||||||
if (bytes_sent == 0) {
|
if (bytes_sent == 0) {
|
||||||
break;
|
break;
|
||||||
@@ -946,7 +963,6 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
|
|||||||
|
|
||||||
static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
|
static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
|
||||||
{
|
{
|
||||||
int ret, rc = 0;
|
|
||||||
unsigned int xh_len;
|
unsigned int xh_len;
|
||||||
int xh_flags;
|
int xh_flags;
|
||||||
|
|
||||||
@@ -959,30 +975,25 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
|
|||||||
xh_len = qemu_get_be16(f);
|
xh_len = qemu_get_be16(f);
|
||||||
|
|
||||||
if (xh_flags != ENCODING_FLAG_XBZRLE) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xh_len > TARGET_PAGE_SIZE) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
/* load data and decode */
|
/* load data and decode */
|
||||||
qemu_get_buffer(f, xbzrle_decoded_buf, xh_len);
|
qemu_get_buffer(f, xbzrle_decoded_buf, xh_len);
|
||||||
|
|
||||||
/* decode RLE */
|
/* decode RLE */
|
||||||
ret = xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host,
|
if (xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host,
|
||||||
TARGET_PAGE_SIZE);
|
TARGET_PAGE_SIZE) == -1) {
|
||||||
if (ret == -1) {
|
error_report("Failed to load XBZRLE page - decode error!");
|
||||||
fprintf(stderr, "Failed to load XBZRLE page - decode error!\n");
|
return -1;
|
||||||
rc = -1;
|
|
||||||
} else if (ret > TARGET_PAGE_SIZE) {
|
|
||||||
fprintf(stderr, "Failed to load XBZRLE page - size %d exceeds %d!\n",
|
|
||||||
ret, TARGET_PAGE_SIZE);
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *host_from_stream_offset(QEMUFile *f,
|
static inline void *host_from_stream_offset(QEMUFile *f,
|
||||||
@@ -995,7 +1006,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
|
|||||||
|
|
||||||
if (flags & RAM_SAVE_FLAG_CONTINUE) {
|
if (flags & RAM_SAVE_FLAG_CONTINUE) {
|
||||||
if (!block) {
|
if (!block) {
|
||||||
fprintf(stderr, "Ack, bad migration stream!\n");
|
error_report("Ack, bad migration stream!");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1011,7 +1022,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
|
|||||||
return memory_region_get_ram_ptr(block->mr) + offset;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1064,9 +1075,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
|
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
|
||||||
if (!strncmp(id, block->idstr, sizeof(id))) {
|
if (!strncmp(id, block->idstr, sizeof(id))) {
|
||||||
if (block->length != length) {
|
if (block->length != length) {
|
||||||
fprintf(stderr,
|
error_report("Length mismatch: %s: " RAM_ADDR_FMT
|
||||||
"Length mismatch: %s: " RAM_ADDR_FMT
|
" in != " RAM_ADDR_FMT, id, length,
|
||||||
" in != " RAM_ADDR_FMT "\n", id, length,
|
|
||||||
block->length);
|
block->length);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -1076,8 +1086,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!block) {
|
if (!block) {
|
||||||
fprintf(stderr, "Unknown ramblock \"%s\", cannot "
|
error_report("Unknown ramblock \"%s\", cannot "
|
||||||
"accept migration\n", id);
|
"accept migration", id);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -1232,11 +1242,10 @@ void select_soundhw(const char *optarg)
|
|||||||
|
|
||||||
if (!c->name) {
|
if (!c->name) {
|
||||||
if (l > 80) {
|
if (l > 80) {
|
||||||
fprintf(stderr,
|
error_report("Unknown sound card name (too big to show)");
|
||||||
"Unknown sound card name (too big to show)\n");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "Unknown sound card name `%.*s'\n",
|
error_report("Unknown sound card name `%.*s'",
|
||||||
(int) l, p);
|
(int) l, p);
|
||||||
}
|
}
|
||||||
bad_card = 1;
|
bad_card = 1;
|
||||||
@@ -1260,13 +1269,13 @@ void audio_init(void)
|
|||||||
if (c->enabled) {
|
if (c->enabled) {
|
||||||
if (c->isa) {
|
if (c->isa) {
|
||||||
if (!isa_bus) {
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
c->init.init_isa(isa_bus);
|
c->init.init_isa(isa_bus);
|
||||||
} else {
|
} else {
|
||||||
if (!pci_bus) {
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
c->init.init_pci(pci_bus);
|
c->init.init_pci(pci_bus);
|
||||||
|
|||||||
@@ -1812,7 +1812,6 @@ static const VMStateDescription vmstate_audio = {
|
|||||||
.name = "audio",
|
.name = "audio",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 ());
|
bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
|
||||||
samples = (bytes - rate->bytes_sent) >> info->shift;
|
samples = (bytes - rate->bytes_sent) >> info->shift;
|
||||||
if (samples < 0 || samples > 65536) {
|
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);
|
rate_start (rate);
|
||||||
samples = 0;
|
samples = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ static void wav_destroy (void *opaque)
|
|||||||
}
|
}
|
||||||
doclose:
|
doclose:
|
||||||
if (fclose (wav->f)) {
|
if (fclose (wav->f)) {
|
||||||
fprintf (stderr, "wav_destroy: fclose failed: %s",
|
error_report("wav_destroy: fclose failed: %s", strerror(errno));
|
||||||
strerror (errno));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ typedef struct BlkMigDevState {
|
|||||||
unsigned long *aio_bitmap;
|
unsigned long *aio_bitmap;
|
||||||
int64_t completed_sectors;
|
int64_t completed_sectors;
|
||||||
BdrvDirtyBitmap *dirty_bitmap;
|
BdrvDirtyBitmap *dirty_bitmap;
|
||||||
|
Error *blocker;
|
||||||
} BlkMigDevState;
|
} BlkMigDevState;
|
||||||
|
|
||||||
typedef struct BlkMigBlock {
|
typedef struct BlkMigBlock {
|
||||||
@@ -361,7 +362,8 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
|
|||||||
bmds->completed_sectors = 0;
|
bmds->completed_sectors = 0;
|
||||||
bmds->shared_base = block_mig_state.shared_base;
|
bmds->shared_base = block_mig_state.shared_base;
|
||||||
alloc_aio_bitmap(bmds);
|
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);
|
bdrv_ref(bs);
|
||||||
|
|
||||||
block_mig_state.total_sector_sum += sectors;
|
block_mig_state.total_sector_sum += sectors;
|
||||||
@@ -599,7 +601,8 @@ static void blk_mig_cleanup(void)
|
|||||||
blk_mig_lock();
|
blk_mig_lock();
|
||||||
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
|
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
|
||||||
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
|
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);
|
bdrv_unref(bmds->bs);
|
||||||
g_free(bmds->aio_bitmap);
|
g_free(bmds->aio_bitmap);
|
||||||
g_free(bmds);
|
g_free(bmds);
|
||||||
|
|||||||
213
block.c
213
block.c
@@ -335,6 +335,7 @@ void bdrv_register(BlockDriver *bdrv)
|
|||||||
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (bdrv_find(device_name)) {
|
if (bdrv_find(device_name)) {
|
||||||
error_setg(errp, "Device with id '%s' already exists",
|
error_setg(errp, "Device with id '%s' already exists",
|
||||||
@@ -353,6 +354,9 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
|||||||
if (device_name[0] != '\0') {
|
if (device_name[0] != '\0') {
|
||||||
QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
|
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);
|
bdrv_iostatus_disable(bs);
|
||||||
notifier_list_init(&bs->close_notifiers);
|
notifier_list_init(&bs->close_notifiers);
|
||||||
notifier_with_return_list_init(&bs->before_write_notifiers);
|
notifier_with_return_list_init(&bs->before_write_notifiers);
|
||||||
@@ -1090,6 +1094,37 @@ fail:
|
|||||||
return ret;
|
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
|
* Opens the backing file for a BlockDriverState if not yet open
|
||||||
*
|
*
|
||||||
@@ -1103,6 +1138,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
|||||||
char *backing_filename = g_malloc0(PATH_MAX);
|
char *backing_filename = g_malloc0(PATH_MAX);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
BlockDriver *back_drv = NULL;
|
BlockDriver *back_drv = NULL;
|
||||||
|
BlockDriverState *backing_hd;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (bs->backing_hd != NULL) {
|
if (bs->backing_hd != NULL) {
|
||||||
@@ -1125,30 +1161,26 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
|||||||
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
|
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backing_hd = bdrv_new("", errp);
|
||||||
|
|
||||||
if (bs->backing_format[0] != '\0') {
|
if (bs->backing_format[0] != '\0') {
|
||||||
back_drv = bdrv_find_format(bs->backing_format);
|
back_drv = bdrv_find_format(bs->backing_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(bs->backing_hd == NULL);
|
assert(bs->backing_hd == NULL);
|
||||||
ret = bdrv_open(&bs->backing_hd,
|
ret = bdrv_open(&backing_hd,
|
||||||
*backing_filename ? backing_filename : NULL, NULL, options,
|
*backing_filename ? backing_filename : NULL, NULL, options,
|
||||||
bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
|
bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bs->backing_hd = NULL;
|
bdrv_unref(backing_hd);
|
||||||
|
backing_hd = NULL;
|
||||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||||
error_setg(errp, "Could not open backing file: %s",
|
error_setg(errp, "Could not open backing file: %s",
|
||||||
error_get_pretty(local_err));
|
error_get_pretty(local_err));
|
||||||
error_free(local_err);
|
error_free(local_err);
|
||||||
goto free_exit;
|
goto free_exit;
|
||||||
}
|
}
|
||||||
|
bdrv_set_backing_hd(bs, backing_hd);
|
||||||
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);
|
|
||||||
|
|
||||||
free_exit:
|
free_exit:
|
||||||
g_free(backing_filename);
|
g_free(backing_filename);
|
||||||
@@ -1196,6 +1228,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
|||||||
bdref_key);
|
bdref_key);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
QDECREF(image_options);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1274,6 +1307,33 @@ out:
|
|||||||
g_free(tmp_filename);
|
g_free(tmp_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QDict *parse_json_filename(const char *filename, Error **errp)
|
||||||
|
{
|
||||||
|
QObject *options_obj;
|
||||||
|
QDict *options;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = strstart(filename, "json:", &filename);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
options_obj = qobject_from_json(filename);
|
||||||
|
if (!options_obj) {
|
||||||
|
error_setg(errp, "Could not parse the JSON options");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qobject_type(options_obj) != QTYPE_QDICT) {
|
||||||
|
qobject_decref(options_obj);
|
||||||
|
error_setg(errp, "Invalid JSON object given");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
options = qobject_to_qdict(options_obj);
|
||||||
|
qdict_flatten(options);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opens a disk image (raw, qcow2, vmdk, ...)
|
* Opens a disk image (raw, qcow2, vmdk, ...)
|
||||||
*
|
*
|
||||||
@@ -1337,6 +1397,20 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
options = qdict_new();
|
options = qdict_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filename && g_str_has_prefix(filename, "json:")) {
|
||||||
|
QDict *json_options = parse_json_filename(filename, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Options given in the filename have lower priority than options
|
||||||
|
* specified directly */
|
||||||
|
qdict_join(options, json_options, false);
|
||||||
|
QDECREF(json_options);
|
||||||
|
filename = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bs->options = options;
|
bs->options = options;
|
||||||
options = qdict_clone_shallow(options);
|
options = qdict_clone_shallow(options);
|
||||||
|
|
||||||
@@ -1743,8 +1817,9 @@ void bdrv_close(BlockDriverState *bs)
|
|||||||
|
|
||||||
if (bs->drv) {
|
if (bs->drv) {
|
||||||
if (bs->backing_hd) {
|
if (bs->backing_hd) {
|
||||||
bdrv_unref(bs->backing_hd);
|
BlockDriverState *backing_hd = bs->backing_hd;
|
||||||
bs->backing_hd = NULL;
|
bdrv_set_backing_hd(bs, NULL);
|
||||||
|
bdrv_unref(backing_hd);
|
||||||
}
|
}
|
||||||
bs->drv->bdrv_close(bs);
|
bs->drv->bdrv_close(bs);
|
||||||
g_free(bs->opaque);
|
g_free(bs->opaque);
|
||||||
@@ -1904,13 +1979,14 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
|
|||||||
bs_dest->refcnt = bs_src->refcnt;
|
bs_dest->refcnt = bs_src->refcnt;
|
||||||
|
|
||||||
/* job */
|
/* job */
|
||||||
bs_dest->in_use = bs_src->in_use;
|
|
||||||
bs_dest->job = bs_src->job;
|
bs_dest->job = bs_src->job;
|
||||||
|
|
||||||
/* keep the same entry in bdrv_states */
|
/* keep the same entry in bdrv_states */
|
||||||
pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
|
pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
|
||||||
bs_src->device_name);
|
bs_src->device_name);
|
||||||
bs_dest->device_list = bs_src->device_list;
|
bs_dest->device_list = bs_src->device_list;
|
||||||
|
memcpy(bs_dest->op_blockers, bs_src->op_blockers,
|
||||||
|
sizeof(bs_dest->op_blockers));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1945,7 +2021,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
|
|||||||
assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
|
assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
|
||||||
assert(bs_new->job == NULL);
|
assert(bs_new->job == NULL);
|
||||||
assert(bs_new->dev == NULL);
|
assert(bs_new->dev == NULL);
|
||||||
assert(bs_new->in_use == 0);
|
|
||||||
assert(bs_new->io_limits_enabled == false);
|
assert(bs_new->io_limits_enabled == false);
|
||||||
assert(!throttle_have_timer(&bs_new->throttle_state));
|
assert(!throttle_have_timer(&bs_new->throttle_state));
|
||||||
|
|
||||||
@@ -1964,7 +2039,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
|
|||||||
/* Check a few fields that should remain attached to the device */
|
/* Check a few fields that should remain attached to the device */
|
||||||
assert(bs_new->dev == NULL);
|
assert(bs_new->dev == NULL);
|
||||||
assert(bs_new->job == NULL);
|
assert(bs_new->job == NULL);
|
||||||
assert(bs_new->in_use == 0);
|
|
||||||
assert(bs_new->io_limits_enabled == false);
|
assert(bs_new->io_limits_enabled == false);
|
||||||
assert(!throttle_have_timer(&bs_new->throttle_state));
|
assert(!throttle_have_timer(&bs_new->throttle_state));
|
||||||
|
|
||||||
@@ -1997,19 +2071,14 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
|
|||||||
|
|
||||||
/* The contents of 'tmp' will become bs_top, as we are
|
/* The contents of 'tmp' will become bs_top, as we are
|
||||||
* swapping bs_new and bs_top contents. */
|
* swapping bs_new and bs_top contents. */
|
||||||
bs_top->backing_hd = bs_new;
|
bdrv_set_backing_hd(bs_top, 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 : "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bdrv_delete(BlockDriverState *bs)
|
static void bdrv_delete(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
assert(!bs->dev);
|
assert(!bs->dev);
|
||||||
assert(!bs->job);
|
assert(!bs->job);
|
||||||
assert(!bs->in_use);
|
assert(bdrv_op_blocker_is_empty(bs));
|
||||||
assert(!bs->refcnt);
|
assert(!bs->refcnt);
|
||||||
assert(QLIST_EMPTY(&bs->dirty_bitmaps));
|
assert(QLIST_EMPTY(&bs->dirty_bitmaps));
|
||||||
|
|
||||||
@@ -2191,7 +2260,8 @@ int bdrv_commit(BlockDriverState *bs)
|
|||||||
return -ENOTSUP;
|
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;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2595,13 +2665,11 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
new_top_bs->backing_hd = base_bs;
|
bdrv_set_backing_hd(new_top_bs, base_bs);
|
||||||
|
|
||||||
bdrv_refresh_limits(new_top_bs);
|
|
||||||
|
|
||||||
QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) {
|
QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) {
|
||||||
/* so that bdrv_close() does not recursively close the chain */
|
/* 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);
|
bdrv_unref(intermediate_state->bs);
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -3248,6 +3316,15 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
|
|||||||
|
|
||||||
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
|
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
|
||||||
|
|
||||||
|
if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF &&
|
||||||
|
!(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_write_zeroes &&
|
||||||
|
qemu_iovec_is_zero(qiov)) {
|
||||||
|
flags |= BDRV_REQ_ZERO_WRITE;
|
||||||
|
if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
|
||||||
|
flags |= BDRV_REQ_MAY_UNMAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* Do nothing, write notifier decided to fail this request */
|
/* Do nothing, write notifier decided to fail this request */
|
||||||
} else if (flags & BDRV_REQ_ZERO_WRITE) {
|
} else if (flags & BDRV_REQ_ZERO_WRITE) {
|
||||||
@@ -3444,8 +3521,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
|
|||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
if (bs->read_only)
|
if (bs->read_only)
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
if (bdrv_in_use(bs))
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
}
|
||||||
ret = drv->bdrv_truncate(bs, offset);
|
ret = drv->bdrv_truncate(bs, offset);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
||||||
@@ -3864,7 +3942,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
|
|||||||
|
|
||||||
if (!bs->drv->bdrv_co_get_block_status) {
|
if (!bs->drv->bdrv_co_get_block_status) {
|
||||||
*pnum = nb_sectors;
|
*pnum = nb_sectors;
|
||||||
ret = BDRV_BLOCK_DATA;
|
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
|
||||||
if (bs->drv->protocol_name) {
|
if (bs->drv->protocol_name) {
|
||||||
ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
|
ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
|
||||||
}
|
}
|
||||||
@@ -3883,6 +3961,10 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
|
|||||||
*pnum, pnum);
|
*pnum, pnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
|
||||||
|
ret |= BDRV_BLOCK_ALLOCATED;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO)) {
|
if (!(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO)) {
|
||||||
if (bdrv_unallocated_blocks_are_zero(bs)) {
|
if (bdrv_unallocated_blocks_are_zero(bs)) {
|
||||||
ret |= BDRV_BLOCK_ZERO;
|
ret |= BDRV_BLOCK_ZERO;
|
||||||
@@ -3959,9 +4041,7 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return
|
return (ret & BDRV_BLOCK_ALLOCATED);
|
||||||
(ret & BDRV_BLOCK_DATA) ||
|
|
||||||
((ret & BDRV_BLOCK_ZERO) && !bdrv_has_zero_init(bs));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -5273,15 +5353,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);
|
BdrvOpBlocker *blocker;
|
||||||
bs->in_use = in_use;
|
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)
|
void bdrv_iostatus_enable(BlockDriverState *bs)
|
||||||
|
|||||||
79
block/curl.c
79
block/curl.c
@@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
|
#include "qapi/qmp/qbool.h"
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
// #define DEBUG
|
// #define DEBUG
|
||||||
@@ -37,6 +38,21 @@
|
|||||||
#if LIBCURL_VERSION_NUM >= 0x071000
|
#if LIBCURL_VERSION_NUM >= 0x071000
|
||||||
/* The multi interface timer callback was introduced in 7.16.0 */
|
/* The multi interface timer callback was introduced in 7.16.0 */
|
||||||
#define NEED_CURL_TIMER_CALLBACK
|
#define NEED_CURL_TIMER_CALLBACK
|
||||||
|
#define HAVE_SOCKET_ACTION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_SOCKET_ACTION
|
||||||
|
/* If curl_multi_socket_action isn't available, define it statically here in
|
||||||
|
* terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is
|
||||||
|
* less efficient but still safe. */
|
||||||
|
static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
|
||||||
|
curl_socket_t sockfd,
|
||||||
|
int ev_bitmask,
|
||||||
|
int *running_handles)
|
||||||
|
{
|
||||||
|
return curl_multi_socket(multi_handle, sockfd, running_handles);
|
||||||
|
}
|
||||||
|
#define curl_multi_socket_action __curl_multi_socket_action
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
|
#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
|
||||||
@@ -46,12 +62,16 @@
|
|||||||
#define CURL_NUM_STATES 8
|
#define CURL_NUM_STATES 8
|
||||||
#define CURL_NUM_ACB 8
|
#define CURL_NUM_ACB 8
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
#define READ_AHEAD_SIZE (256 * 1024)
|
#define READ_AHEAD_DEFAULT (256 * 1024)
|
||||||
|
|
||||||
#define FIND_RET_NONE 0
|
#define FIND_RET_NONE 0
|
||||||
#define FIND_RET_OK 1
|
#define FIND_RET_OK 1
|
||||||
#define FIND_RET_WAIT 2
|
#define FIND_RET_WAIT 2
|
||||||
|
|
||||||
|
#define CURL_BLOCK_OPT_URL "url"
|
||||||
|
#define CURL_BLOCK_OPT_READAHEAD "readahead"
|
||||||
|
#define CURL_BLOCK_OPT_SSLVERIFY "sslverify"
|
||||||
|
|
||||||
struct BDRVCURLState;
|
struct BDRVCURLState;
|
||||||
|
|
||||||
typedef struct CURLAIOCB {
|
typedef struct CURLAIOCB {
|
||||||
@@ -88,6 +108,7 @@ typedef struct BDRVCURLState {
|
|||||||
CURLState states[CURL_NUM_STATES];
|
CURLState states[CURL_NUM_STATES];
|
||||||
char *url;
|
char *url;
|
||||||
size_t readahead_size;
|
size_t readahead_size;
|
||||||
|
bool sslverify;
|
||||||
bool accept_range;
|
bool accept_range;
|
||||||
} BDRVCURLState;
|
} BDRVCURLState;
|
||||||
|
|
||||||
@@ -354,6 +375,8 @@ static CURLState *curl_init_state(BDRVCURLState *s)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
|
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER,
|
||||||
|
(long) s->sslverify);
|
||||||
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
|
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
|
||||||
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
|
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
|
||||||
(void *)curl_read_cb);
|
(void *)curl_read_cb);
|
||||||
@@ -396,43 +419,7 @@ static void curl_clean_state(CURLState *s)
|
|||||||
static void curl_parse_filename(const char *filename, QDict *options,
|
static void curl_parse_filename(const char *filename, QDict *options,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
|
||||||
#define RA_OPTSTR ":readahead="
|
|
||||||
char *file;
|
|
||||||
char *ra;
|
|
||||||
const char *ra_val;
|
|
||||||
int parse_state = 0;
|
|
||||||
|
|
||||||
file = g_strdup(filename);
|
|
||||||
|
|
||||||
/* Parse a trailing ":readahead=#:" param, if present. */
|
|
||||||
ra = file + strlen(file) - 1;
|
|
||||||
while (ra >= file) {
|
|
||||||
if (parse_state == 0) {
|
|
||||||
if (*ra == ':') {
|
|
||||||
parse_state++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (parse_state == 1) {
|
|
||||||
if (*ra > '9' || *ra < '0') {
|
|
||||||
char *opt_start = ra - strlen(RA_OPTSTR) + 1;
|
|
||||||
if (opt_start > file &&
|
|
||||||
strncmp(opt_start, RA_OPTSTR, strlen(RA_OPTSTR)) == 0) {
|
|
||||||
ra_val = ra + 1;
|
|
||||||
ra -= strlen(RA_OPTSTR) - 1;
|
|
||||||
*ra = '\0';
|
|
||||||
qdict_put(options, "readahead", qstring_from_str(ra_val));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ra--;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdict_put(options, "url", qstring_from_str(file));
|
|
||||||
|
|
||||||
g_free(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QemuOptsList runtime_opts = {
|
static QemuOptsList runtime_opts = {
|
||||||
@@ -440,15 +427,20 @@ static QemuOptsList runtime_opts = {
|
|||||||
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
||||||
.desc = {
|
.desc = {
|
||||||
{
|
{
|
||||||
.name = "url",
|
.name = CURL_BLOCK_OPT_URL,
|
||||||
.type = QEMU_OPT_STRING,
|
.type = QEMU_OPT_STRING,
|
||||||
.help = "URL to open",
|
.help = "URL to open",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "readahead",
|
.name = CURL_BLOCK_OPT_READAHEAD,
|
||||||
.type = QEMU_OPT_SIZE,
|
.type = QEMU_OPT_SIZE,
|
||||||
.help = "Readahead size",
|
.help = "Readahead size",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = CURL_BLOCK_OPT_SSLVERIFY,
|
||||||
|
.type = QEMU_OPT_BOOL,
|
||||||
|
.help = "Verify SSL certificate"
|
||||||
|
},
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -477,14 +469,17 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
goto out_noclean;
|
goto out_noclean;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->readahead_size = qemu_opt_get_size(opts, "readahead", READ_AHEAD_SIZE);
|
s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
|
||||||
|
READ_AHEAD_DEFAULT);
|
||||||
if ((s->readahead_size & 0x1ff) != 0) {
|
if ((s->readahead_size & 0x1ff) != 0) {
|
||||||
error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
|
error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
|
||||||
s->readahead_size);
|
s->readahead_size);
|
||||||
goto out_noclean;
|
goto out_noclean;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = qemu_opt_get(opts, "url");
|
s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
|
||||||
|
|
||||||
|
file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL);
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
error_setg(errp, "curl block driver requires an 'url' option");
|
error_setg(errp, "curl block driver requires an 'url' option");
|
||||||
goto out_noclean;
|
goto out_noclean;
|
||||||
|
|||||||
317
block/iscsi.c
317
block/iscsi.c
@@ -30,6 +30,8 @@
|
|||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "qemu/bitops.h"
|
||||||
|
#include "qemu/bitmap.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "block/scsi.h"
|
#include "block/scsi.h"
|
||||||
@@ -59,6 +61,8 @@ typedef struct IscsiLun {
|
|||||||
struct scsi_inquiry_logical_block_provisioning lbp;
|
struct scsi_inquiry_logical_block_provisioning lbp;
|
||||||
struct scsi_inquiry_block_limits bl;
|
struct scsi_inquiry_block_limits bl;
|
||||||
unsigned char *zeroblock;
|
unsigned char *zeroblock;
|
||||||
|
unsigned long *allocationmap;
|
||||||
|
int cluster_sectors;
|
||||||
} IscsiLun;
|
} IscsiLun;
|
||||||
|
|
||||||
typedef struct IscsiTask {
|
typedef struct IscsiTask {
|
||||||
@@ -92,6 +96,15 @@ typedef struct IscsiAIOCB {
|
|||||||
#define MAX_NOP_FAILURES 3
|
#define MAX_NOP_FAILURES 3
|
||||||
#define ISCSI_CMD_RETRIES 5
|
#define ISCSI_CMD_RETRIES 5
|
||||||
|
|
||||||
|
/* this threshhold is a trade-off knob to choose between
|
||||||
|
* the potential additional overhead of an extra GET_LBA_STATUS request
|
||||||
|
* vs. unnecessarily reading a lot of zero sectors over the wire.
|
||||||
|
* If a read request is greater or equal than ISCSI_CHECKALLOC_THRES
|
||||||
|
* sectors we check the allocation status of the area covered by the
|
||||||
|
* request first if the allocationmap indicates that the area might be
|
||||||
|
* unallocated. */
|
||||||
|
#define ISCSI_CHECKALLOC_THRES 64
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iscsi_bh_cb(void *p)
|
iscsi_bh_cb(void *p)
|
||||||
{
|
{
|
||||||
@@ -273,6 +286,32 @@ static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iscsi_allocationmap_set(IscsiLun *iscsilun, int64_t sector_num,
|
||||||
|
int nb_sectors)
|
||||||
|
{
|
||||||
|
if (iscsilun->allocationmap == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bitmap_set(iscsilun->allocationmap,
|
||||||
|
sector_num / iscsilun->cluster_sectors,
|
||||||
|
DIV_ROUND_UP(nb_sectors, iscsilun->cluster_sectors));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iscsi_allocationmap_clear(IscsiLun *iscsilun, int64_t sector_num,
|
||||||
|
int nb_sectors)
|
||||||
|
{
|
||||||
|
int64_t cluster_num, nb_clusters;
|
||||||
|
if (iscsilun->allocationmap == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cluster_num = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors);
|
||||||
|
nb_clusters = (sector_num + nb_sectors) / iscsilun->cluster_sectors
|
||||||
|
- cluster_num;
|
||||||
|
if (nb_clusters > 0) {
|
||||||
|
bitmap_clear(iscsilun->allocationmap, cluster_num, nb_clusters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int coroutine_fn iscsi_co_writev(BlockDriverState *bs,
|
static int coroutine_fn iscsi_co_writev(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors,
|
int64_t sector_num, int nb_sectors,
|
||||||
QEMUIOVector *iov)
|
QEMUIOVector *iov)
|
||||||
@@ -336,9 +375,125 @@ retry:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
static bool iscsi_allocationmap_is_allocated(IscsiLun *iscsilun,
|
||||||
|
int64_t sector_num, int nb_sectors)
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
if (iscsilun->allocationmap == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
|
||||||
|
return !(find_next_bit(iscsilun->allocationmap, size,
|
||||||
|
sector_num / iscsilun->cluster_sectors) == size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
||||||
|
int64_t sector_num,
|
||||||
|
int nb_sectors, int *pnum)
|
||||||
|
{
|
||||||
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
|
struct scsi_get_lba_status *lbas = NULL;
|
||||||
|
struct scsi_lba_status_descriptor *lbasd = NULL;
|
||||||
|
struct IscsiTask iTask;
|
||||||
|
int64_t ret;
|
||||||
|
|
||||||
|
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||||
|
|
||||||
|
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default to all sectors allocated */
|
||||||
|
ret = BDRV_BLOCK_DATA;
|
||||||
|
ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
|
||||||
|
*pnum = nb_sectors;
|
||||||
|
|
||||||
|
/* LUN does not support logical block provisioning */
|
||||||
|
if (iscsilun->lbpme == 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
|
||||||
|
sector_qemu2lun(sector_num, iscsilun),
|
||||||
|
8 + 16, iscsi_co_generic_cb,
|
||||||
|
&iTask) == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!iTask.complete) {
|
||||||
|
iscsi_set_events(iscsilun);
|
||||||
|
qemu_coroutine_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iTask.do_retry) {
|
||||||
|
if (iTask.task != NULL) {
|
||||||
|
scsi_free_scsi_task(iTask.task);
|
||||||
|
iTask.task = NULL;
|
||||||
|
}
|
||||||
|
iTask.complete = 0;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||||
|
/* in case the get_lba_status_callout fails (i.e.
|
||||||
|
* because the device is busy or the cmd is not
|
||||||
|
* supported) we pretend all blocks are allocated
|
||||||
|
* for backwards compatibility */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbas = scsi_datain_unmarshall(iTask.task);
|
||||||
|
if (lbas == NULL) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbasd = &lbas->descriptors[0];
|
||||||
|
|
||||||
|
if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
|
||||||
|
|
||||||
|
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
|
||||||
|
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
|
||||||
|
ret &= ~BDRV_BLOCK_DATA;
|
||||||
|
if (iscsilun->lbprz) {
|
||||||
|
ret |= BDRV_BLOCK_ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret & BDRV_BLOCK_ZERO) {
|
||||||
|
iscsi_allocationmap_clear(iscsilun, sector_num, *pnum);
|
||||||
|
} else {
|
||||||
|
iscsi_allocationmap_set(iscsilun, sector_num, *pnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pnum > nb_sectors) {
|
||||||
|
*pnum = nb_sectors;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (iTask.task != NULL) {
|
||||||
|
scsi_free_scsi_task(iTask.task);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LIBISCSI_FEATURE_IOVECTOR */
|
||||||
|
|
||||||
|
|
||||||
static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors,
|
int64_t sector_num, int nb_sectors,
|
||||||
QEMUIOVector *iov)
|
QEMUIOVector *iov)
|
||||||
@@ -355,6 +510,22 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
if (iscsilun->lbprz && nb_sectors >= ISCSI_CHECKALLOC_THRES &&
|
||||||
|
!iscsi_allocationmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
|
||||||
|
int64_t ret;
|
||||||
|
int pnum;
|
||||||
|
ret = iscsi_co_get_block_status(bs, sector_num, INT_MAX, &pnum);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors) {
|
||||||
|
qemu_iovec_memset(iov, 0, 0x00, iov->size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
lba = sector_qemu2lun(sector_num, iscsilun);
|
||||||
num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
|
num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
|
||||||
|
|
||||||
@@ -643,101 +814,6 @@ iscsi_getlength(BlockDriverState *bs)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
|
||||||
|
|
||||||
static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
|
||||||
int64_t sector_num,
|
|
||||||
int nb_sectors, int *pnum)
|
|
||||||
{
|
|
||||||
IscsiLun *iscsilun = bs->opaque;
|
|
||||||
struct scsi_get_lba_status *lbas = NULL;
|
|
||||||
struct scsi_lba_status_descriptor *lbasd = NULL;
|
|
||||||
struct IscsiTask iTask;
|
|
||||||
int64_t ret;
|
|
||||||
|
|
||||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
|
||||||
|
|
||||||
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* default to all sectors allocated */
|
|
||||||
ret = BDRV_BLOCK_DATA;
|
|
||||||
ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
|
|
||||||
*pnum = nb_sectors;
|
|
||||||
|
|
||||||
/* LUN does not support logical block provisioning */
|
|
||||||
if (iscsilun->lbpme == 0) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
retry:
|
|
||||||
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
|
|
||||||
sector_qemu2lun(sector_num, iscsilun),
|
|
||||||
8 + 16, iscsi_co_generic_cb,
|
|
||||||
&iTask) == NULL) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!iTask.complete) {
|
|
||||||
iscsi_set_events(iscsilun);
|
|
||||||
qemu_coroutine_yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iTask.do_retry) {
|
|
||||||
if (iTask.task != NULL) {
|
|
||||||
scsi_free_scsi_task(iTask.task);
|
|
||||||
iTask.task = NULL;
|
|
||||||
}
|
|
||||||
iTask.complete = 0;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
|
||||||
/* in case the get_lba_status_callout fails (i.e.
|
|
||||||
* because the device is busy or the cmd is not
|
|
||||||
* supported) we pretend all blocks are allocated
|
|
||||||
* for backwards compatibility */
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbas = scsi_datain_unmarshall(iTask.task);
|
|
||||||
if (lbas == NULL) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbasd = &lbas->descriptors[0];
|
|
||||||
|
|
||||||
if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
|
|
||||||
if (*pnum > nb_sectors) {
|
|
||||||
*pnum = nb_sectors;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
|
|
||||||
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
|
|
||||||
ret &= ~BDRV_BLOCK_DATA;
|
|
||||||
if (iscsilun->lbprz) {
|
|
||||||
ret |= BDRV_BLOCK_ZERO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (iTask.task != NULL) {
|
|
||||||
scsi_free_scsi_task(iTask.task);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LIBISCSI_FEATURE_IOVECTOR */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
|
coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
|
||||||
int nb_sectors)
|
int nb_sectors)
|
||||||
@@ -791,6 +867,8 @@ retry:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,13 +887,14 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
|
if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
|
||||||
/* WRITE SAME without UNMAP is not supported by the target */
|
/* WRITE SAME with UNMAP is not supported by the target,
|
||||||
return -ENOTSUP;
|
* fall back and try WRITE SAME without UNMAP */
|
||||||
|
flags &= ~BDRV_REQ_MAY_UNMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
|
if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
|
||||||
/* WRITE SAME with UNMAP is not supported by the target */
|
/* WRITE SAME without UNMAP is not supported by the target */
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,6 +943,12 @@ retry:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & BDRV_REQ_MAY_UNMAP) {
|
||||||
|
iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors);
|
||||||
|
} else {
|
||||||
|
iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,6 +1380,22 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* reasonable size */
|
||||||
|
if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&
|
||||||
|
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
|
||||||
|
iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *
|
||||||
|
iscsilun->block_size) >> BDRV_SECTOR_BITS;
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
if (iscsilun->lbprz && !(bs->open_flags & BDRV_O_NOCACHE)) {
|
||||||
|
iscsilun->allocationmap =
|
||||||
|
bitmap_new(DIV_ROUND_UP(bs->total_sectors,
|
||||||
|
iscsilun->cluster_sectors));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
if (initiator_name != NULL) {
|
if (initiator_name != NULL) {
|
||||||
@@ -1328,6 +1429,7 @@ static void iscsi_close(BlockDriverState *bs)
|
|||||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
|
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
|
||||||
iscsi_destroy_context(iscsi);
|
iscsi_destroy_context(iscsi);
|
||||||
g_free(iscsilun->zeroblock);
|
g_free(iscsilun->zeroblock);
|
||||||
|
g_free(iscsilun->allocationmap);
|
||||||
memset(iscsilun, 0, sizeof(IscsiLun));
|
memset(iscsilun, 0, sizeof(IscsiLun));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1388,6 +1490,13 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iscsilun->allocationmap != NULL) {
|
||||||
|
g_free(iscsilun->allocationmap);
|
||||||
|
iscsilun->allocationmap =
|
||||||
|
bitmap_new(DIV_ROUND_UP(bs->total_sectors,
|
||||||
|
iscsilun->cluster_sectors));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1450,13 +1559,7 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
|
bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
|
||||||
bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
|
bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
|
||||||
/* Guess the internal cluster (page) size of the iscsi target by the means
|
bdi->cluster_size = iscsilun->cluster_sectors * BDRV_SECTOR_SIZE;
|
||||||
* of opt_unmap_gran. Transfer the unmap granularity only if it has a
|
|
||||||
* reasonable size for bdi->cluster_size */
|
|
||||||
if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 64 * 1024 &&
|
|
||||||
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
|
|
||||||
bdi->cluster_size = iscsilun->bl.opt_unmap_gran * iscsilun->block_size;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -498,7 +498,7 @@ immediate_exit:
|
|||||||
/* drop the bs loop chain formed by the swap: break the loop then
|
/* drop the bs loop chain formed by the swap: break the loop then
|
||||||
* trigger the unref from the top one */
|
* trigger the unref from the top one */
|
||||||
BlockDriverState *p = s->base->backing_hd;
|
BlockDriverState *p = s->base->backing_hd;
|
||||||
s->base->backing_hd = NULL;
|
bdrv_set_backing_hd(s->base, NULL);
|
||||||
bdrv_unref(p);
|
bdrv_unref(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
info->backing_file_depth = bdrv_get_backing_file_depth(bs);
|
info->backing_file_depth = bdrv_get_backing_file_depth(bs);
|
||||||
|
info->detect_zeroes = bs->detect_zeroes;
|
||||||
|
|
||||||
if (bs->io_limits_enabled) {
|
if (bs->io_limits_enabled) {
|
||||||
ThrottleConfig cfg;
|
ThrottleConfig cfg;
|
||||||
@@ -474,6 +475,7 @@ static void dump_qobject(fprintf_function func_fprintf, void *f,
|
|||||||
case QTYPE_QERROR: {
|
case QTYPE_QERROR: {
|
||||||
QString *value = qerror_human((QError *)obj);
|
QString *value = qerror_human((QError *)obj);
|
||||||
func_fprintf(f, "%s", qstring_get_str(value));
|
func_fprintf(f, "%s", qstring_get_str(value));
|
||||||
|
QDECREF(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QTYPE_NONE:
|
case QTYPE_NONE:
|
||||||
|
|||||||
44
block/qcow.c
44
block/qcow.c
@@ -48,9 +48,10 @@ typedef struct QCowHeader {
|
|||||||
uint64_t size; /* in bytes */
|
uint64_t size; /* in bytes */
|
||||||
uint8_t cluster_bits;
|
uint8_t cluster_bits;
|
||||||
uint8_t l2_bits;
|
uint8_t l2_bits;
|
||||||
|
uint16_t padding;
|
||||||
uint32_t crypt_method;
|
uint32_t crypt_method;
|
||||||
uint64_t l1_table_offset;
|
uint64_t l1_table_offset;
|
||||||
} QCowHeader;
|
} QEMU_PACKED QCowHeader;
|
||||||
|
|
||||||
#define L2_CACHE_SIZE 16
|
#define L2_CACHE_SIZE 16
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ typedef struct BDRVQcowState {
|
|||||||
int cluster_sectors;
|
int cluster_sectors;
|
||||||
int l2_bits;
|
int l2_bits;
|
||||||
int l2_size;
|
int l2_size;
|
||||||
int l1_size;
|
unsigned int l1_size;
|
||||||
uint64_t cluster_offset_mask;
|
uint64_t cluster_offset_mask;
|
||||||
uint64_t l1_table_offset;
|
uint64_t l1_table_offset;
|
||||||
uint64_t *l1_table;
|
uint64_t *l1_table;
|
||||||
@@ -96,7 +97,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
int len, i, shift, ret;
|
unsigned int len, i, shift;
|
||||||
|
int ret;
|
||||||
QCowHeader header;
|
QCowHeader header;
|
||||||
|
|
||||||
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
|
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
|
||||||
@@ -127,11 +129,25 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.size <= 1 || header.cluster_bits < 9) {
|
if (header.size <= 1) {
|
||||||
error_setg(errp, "invalid value in qcow header");
|
error_setg(errp, "Image size is too small (must be at least 2 bytes)");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (header.cluster_bits < 9 || header.cluster_bits > 16) {
|
||||||
|
error_setg(errp, "Cluster size must be between 512 and 64k");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* l2_bits specifies number of entries; storing a uint64_t in each entry,
|
||||||
|
* so bytes = num_entries << 3. */
|
||||||
|
if (header.l2_bits < 9 - 3 || header.l2_bits > 16 - 3) {
|
||||||
|
error_setg(errp, "L2 table size must be between 512 and 64k");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (header.crypt_method > QCOW_CRYPT_AES) {
|
if (header.crypt_method > QCOW_CRYPT_AES) {
|
||||||
error_setg(errp, "invalid encryption method in qcow header");
|
error_setg(errp, "invalid encryption method in qcow header");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@@ -151,7 +167,19 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
/* read the level 1 table */
|
/* read the level 1 table */
|
||||||
shift = s->cluster_bits + s->l2_bits;
|
shift = s->cluster_bits + s->l2_bits;
|
||||||
s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
|
if (header.size > UINT64_MAX - (1LL << shift)) {
|
||||||
|
error_setg(errp, "Image too large");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
} else {
|
||||||
|
uint64_t l1_size = (header.size + (1LL << shift) - 1) >> shift;
|
||||||
|
if (l1_size > INT_MAX / sizeof(uint64_t)) {
|
||||||
|
error_setg(errp, "Image too large");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
s->l1_size = l1_size;
|
||||||
|
}
|
||||||
|
|
||||||
s->l1_table_offset = header.l1_table_offset;
|
s->l1_table_offset = header.l1_table_offset;
|
||||||
s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
|
s->l1_table = g_malloc(s->l1_size * sizeof(uint64_t));
|
||||||
@@ -175,7 +203,9 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
if (header.backing_file_offset != 0) {
|
if (header.backing_file_offset != 0) {
|
||||||
len = header.backing_file_size;
|
len = header.backing_file_size;
|
||||||
if (len > 1023) {
|
if (len > 1023) {
|
||||||
len = 1023;
|
error_setg(errp, "Backing file name too long");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
ret = bdrv_pread(bs->file, header.backing_file_offset,
|
ret = bdrv_pread(bs->file, header.backing_file_offset,
|
||||||
bs->backing_file, len);
|
bs->backing_file, len);
|
||||||
|
|||||||
@@ -379,7 +379,8 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
|
|||||||
BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
|
BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
|
||||||
|
|
||||||
if (!bs->drv) {
|
if (!bs->drv) {
|
||||||
return -ENOMEDIUM;
|
ret = -ENOMEDIUM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call .bdrv_co_readv() directly instead of using the public block-layer
|
/* 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);
|
options = qdict_clone_shallow(bs->options);
|
||||||
|
|
||||||
ret = qcow2_open(bs, options, flags, &local_err);
|
ret = qcow2_open(bs, options, flags, &local_err);
|
||||||
|
QDECREF(options);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_setg(errp, "Could not reopen qcow2 layer: %s",
|
error_setg(errp, "Could not reopen qcow2 layer: %s",
|
||||||
error_get_pretty(local_err));
|
error_get_pretty(local_err));
|
||||||
@@ -1318,8 +1319,6 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDECREF(options);
|
|
||||||
|
|
||||||
if (crypt_method) {
|
if (crypt_method) {
|
||||||
s->crypt_method = crypt_method;
|
s->crypt_method = crypt_method;
|
||||||
memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
|
memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
|
||||||
|
|||||||
@@ -1192,7 +1192,7 @@ again:
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
#endif
|
#endif
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
size = LONG_LONG_MAX;
|
size = LLONG_MAX;
|
||||||
#else
|
#else
|
||||||
size = lseek(fd, 0LL, SEEK_END);
|
size = lseek(fd, 0LL, SEEK_END);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
71
block/rbd.c
71
block/rbd.c
@@ -105,7 +105,7 @@ typedef struct BDRVRBDState {
|
|||||||
static int qemu_rbd_next_tok(char *dst, int dst_len,
|
static int qemu_rbd_next_tok(char *dst, int dst_len,
|
||||||
char *src, char delim,
|
char *src, char delim,
|
||||||
const char *name,
|
const char *name,
|
||||||
char **p)
|
char **p, Error **errp)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
char *end;
|
char *end;
|
||||||
@@ -128,10 +128,10 @@ static int qemu_rbd_next_tok(char *dst, int dst_len,
|
|||||||
}
|
}
|
||||||
l = strlen(src);
|
l = strlen(src);
|
||||||
if (l >= dst_len) {
|
if (l >= dst_len) {
|
||||||
error_report("%s too long", name);
|
error_setg(errp, "%s too long", name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if (l == 0) {
|
} else if (l == 0) {
|
||||||
error_report("%s too short", name);
|
error_setg(errp, "%s too short", name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,13 +157,15 @@ static int qemu_rbd_parsename(const char *filename,
|
|||||||
char *pool, int pool_len,
|
char *pool, int pool_len,
|
||||||
char *snap, int snap_len,
|
char *snap, int snap_len,
|
||||||
char *name, int name_len,
|
char *name, int name_len,
|
||||||
char *conf, int conf_len)
|
char *conf, int conf_len,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
const char *start;
|
const char *start;
|
||||||
char *p, *buf;
|
char *p, *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!strstart(filename, "rbd:", &start)) {
|
if (!strstart(filename, "rbd:", &start)) {
|
||||||
|
error_setg(errp, "File name must start with 'rbd:'");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +174,8 @@ static int qemu_rbd_parsename(const char *filename,
|
|||||||
*snap = '\0';
|
*snap = '\0';
|
||||||
*conf = '\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) {
|
if (ret < 0 || !p) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -180,21 +183,25 @@ static int qemu_rbd_parsename(const char *filename,
|
|||||||
qemu_rbd_unescape(pool);
|
qemu_rbd_unescape(pool);
|
||||||
|
|
||||||
if (strchr(p, '@')) {
|
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) {
|
if (ret < 0) {
|
||||||
goto done;
|
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);
|
qemu_rbd_unescape(snap);
|
||||||
} else {
|
} 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);
|
qemu_rbd_unescape(name);
|
||||||
if (ret < 0 || !p) {
|
if (ret < 0 || !p) {
|
||||||
goto done;
|
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:
|
done:
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
@@ -229,7 +236,7 @@ static char *qemu_rbd_parse_clientname(const char *conf, char *clientname)
|
|||||||
return NULL;
|
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 *p, *buf;
|
||||||
char name[RBD_MAX_CONF_NAME_SIZE];
|
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) {
|
while (p) {
|
||||||
ret = qemu_rbd_next_tok(name, sizeof(name), p,
|
ret = qemu_rbd_next_tok(name, sizeof(name), p,
|
||||||
'=', "conf option name", &p);
|
'=', "conf option name", &p, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
qemu_rbd_unescape(name);
|
qemu_rbd_unescape(name);
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
error_report("conf option %s has no value", name);
|
error_setg(errp, "conf option %s has no value", name);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qemu_rbd_next_tok(value, sizeof(value), p,
|
ret = qemu_rbd_next_tok(value, sizeof(value), p,
|
||||||
':', "conf option value", &p);
|
':', "conf option value", &p, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -263,7 +270,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
|
|||||||
if (strcmp(name, "conf") == 0) {
|
if (strcmp(name, "conf") == 0) {
|
||||||
ret = rados_conf_read_file(cluster, value);
|
ret = rados_conf_read_file(cluster, value);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("error reading conf file %s", value);
|
error_setg(errp, "error reading conf file %s", value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (strcmp(name, "id") == 0) {
|
} else if (strcmp(name, "id") == 0) {
|
||||||
@@ -271,7 +278,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
|
|||||||
} else {
|
} else {
|
||||||
ret = rados_conf_set(cluster, name, value);
|
ret = rados_conf_set(cluster, name, value);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("invalid conf option %s", name);
|
error_setg(errp, "invalid conf option %s", name);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
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,
|
static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
int64_t bytes = 0;
|
int64_t bytes = 0;
|
||||||
int64_t objsize;
|
int64_t objsize;
|
||||||
int obj_order = 0;
|
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),
|
if (qemu_rbd_parsename(filename, pool, sizeof(pool),
|
||||||
snap_buf, sizeof(snap_buf),
|
snap_buf, sizeof(snap_buf),
|
||||||
name, sizeof(name),
|
name, sizeof(name),
|
||||||
conf, sizeof(conf)) < 0) {
|
conf, sizeof(conf), &local_err) < 0) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,11 +322,11 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
if (options->value.n) {
|
if (options->value.n) {
|
||||||
objsize = options->value.n;
|
objsize = options->value.n;
|
||||||
if ((objsize - 1) & objsize) { /* not a power of 2? */
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (objsize < 4096) {
|
if (objsize < 4096) {
|
||||||
error_report("obj size too small");
|
error_setg(errp, "obj size too small");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
obj_order = ffs(objsize) - 1;
|
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);
|
clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
|
||||||
if (rados_create(&cluster, clientname) < 0) {
|
if (rados_create(&cluster, clientname) < 0) {
|
||||||
error_report("error initializing");
|
error_setg(errp, "error initializing");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,20 +347,20 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (conf[0] != '\0' &&
|
if (conf[0] != '\0' &&
|
||||||
qemu_rbd_set_conf(cluster, conf) < 0) {
|
qemu_rbd_set_conf(cluster, conf, &local_err) < 0) {
|
||||||
error_report("error setting config options");
|
|
||||||
rados_shutdown(cluster);
|
rados_shutdown(cluster);
|
||||||
|
error_propagate(errp, local_err);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rados_connect(cluster) < 0) {
|
if (rados_connect(cluster) < 0) {
|
||||||
error_report("error connecting");
|
error_setg(errp, "error connecting");
|
||||||
rados_shutdown(cluster);
|
rados_shutdown(cluster);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) {
|
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);
|
rados_shutdown(cluster);
|
||||||
return -EIO;
|
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);
|
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
qerror_report_err(local_err);
|
error_propagate(errp, local_err);
|
||||||
error_free(local_err);
|
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
return -EINVAL;
|
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),
|
if (qemu_rbd_parsename(filename, pool, sizeof(pool),
|
||||||
snap_buf, sizeof(snap_buf),
|
snap_buf, sizeof(snap_buf),
|
||||||
s->name, sizeof(s->name),
|
s->name, sizeof(s->name),
|
||||||
conf, sizeof(conf)) < 0) {
|
conf, sizeof(conf), errp) < 0) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto failed_opts;
|
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);
|
clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
|
||||||
r = rados_create(&s->cluster, clientname);
|
r = rados_create(&s->cluster, clientname);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_report("error initializing");
|
error_setg(&local_err, "error initializing");
|
||||||
goto failed_opts;
|
goto failed_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,28 +496,27 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (conf[0] != '\0') {
|
if (conf[0] != '\0') {
|
||||||
r = qemu_rbd_set_conf(s->cluster, conf);
|
r = qemu_rbd_set_conf(s->cluster, conf, errp);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_report("error setting config options");
|
|
||||||
goto failed_shutdown;
|
goto failed_shutdown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rados_connect(s->cluster);
|
r = rados_connect(s->cluster);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_report("error connecting");
|
error_setg(&local_err, "error connecting");
|
||||||
goto failed_shutdown;
|
goto failed_shutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rados_ioctx_create(s->cluster, pool, &s->io_ctx);
|
r = rados_ioctx_create(s->cluster, pool, &s->io_ctx);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_report("error opening pool %s", pool);
|
error_setg(&local_err, "error opening pool %s", pool);
|
||||||
goto failed_shutdown;
|
goto failed_shutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
|
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
|
||||||
if (r < 0) {
|
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;
|
goto failed_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
149
block/sheepdog.c
149
block/sheepdog.c
@@ -526,17 +526,16 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
|
|||||||
return acb;
|
return acb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int connect_to_sdog(BDRVSheepdogState *s)
|
static int connect_to_sdog(BDRVSheepdogState *s, Error **errp)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
Error *err = NULL;
|
|
||||||
|
|
||||||
if (s->is_unix) {
|
if (s->is_unix) {
|
||||||
fd = unix_connect(s->host_spec, &err);
|
fd = unix_connect(s->host_spec, errp);
|
||||||
} else {
|
} 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);
|
int ret = socket_set_nodelay(fd);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("%s", strerror(errno));
|
error_report("%s", strerror(errno));
|
||||||
@@ -544,10 +543,7 @@ static int connect_to_sdog(BDRVSheepdogState *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err != NULL) {
|
if (fd >= 0) {
|
||||||
qerror_report_err(err);
|
|
||||||
error_free(err);
|
|
||||||
} else {
|
|
||||||
qemu_set_nonblock(fd);
|
qemu_set_nonblock(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,7 +668,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
|||||||
enum AIOCBState aiocb_type);
|
enum AIOCBState aiocb_type);
|
||||||
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req);
|
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 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 void co_write_request(void *opaque);
|
||||||
|
|
||||||
static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid)
|
static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid)
|
||||||
@@ -709,6 +705,7 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid)
|
|||||||
|
|
||||||
static coroutine_fn void reconnect_to_sdog(void *opaque)
|
static coroutine_fn void reconnect_to_sdog(void *opaque)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
BDRVSheepdogState *s = opaque;
|
BDRVSheepdogState *s = opaque;
|
||||||
AIOReq *aio_req, *next;
|
AIOReq *aio_req, *next;
|
||||||
|
|
||||||
@@ -723,9 +720,11 @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
|
|||||||
|
|
||||||
/* Try to reconnect the sheepdog server every one second. */
|
/* Try to reconnect the sheepdog server every one second. */
|
||||||
while (s->fd < 0) {
|
while (s->fd < 0) {
|
||||||
s->fd = get_sheep_fd(s);
|
s->fd = get_sheep_fd(s, &local_err);
|
||||||
if (s->fd < 0) {
|
if (s->fd < 0) {
|
||||||
DPRINTF("Wait for connection to be established\n");
|
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,
|
co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME,
|
||||||
1000000000ULL);
|
1000000000ULL);
|
||||||
}
|
}
|
||||||
@@ -914,11 +913,11 @@ static void co_write_request(void *opaque)
|
|||||||
* We cannot use this descriptor for other operations because
|
* We cannot use this descriptor for other operations because
|
||||||
* the block driver may be on waiting response from the server.
|
* the block driver may be on waiting response from the server.
|
||||||
*/
|
*/
|
||||||
static int get_sheep_fd(BDRVSheepdogState *s)
|
static int get_sheep_fd(BDRVSheepdogState *s, Error **errp)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, errp);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -1061,7 +1060,7 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
|
|||||||
|
|
||||||
static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
||||||
uint32_t snapid, const char *tag, uint32_t *vid,
|
uint32_t snapid, const char *tag, uint32_t *vid,
|
||||||
bool lock)
|
bool lock, Error **errp)
|
||||||
{
|
{
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
SheepdogVdiReq hdr;
|
SheepdogVdiReq hdr;
|
||||||
@@ -1069,7 +1068,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
|||||||
unsigned int wlen, rlen = 0;
|
unsigned int wlen, rlen = 0;
|
||||||
char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN];
|
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) {
|
if (fd < 0) {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -1095,11 +1094,12 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
|||||||
|
|
||||||
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
error_setg_errno(errp, -ret, "cannot get vdi info");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsp->result != SD_RES_SUCCESS) {
|
if (rsp->result != SD_RES_SUCCESS) {
|
||||||
error_report("cannot get vdi info, %s, %s %" PRIu32 " %s",
|
error_setg(errp, "cannot get vdi info, %s, %s %" PRIu32 " %s",
|
||||||
sd_strerror(rsp->result), filename, snapid, tag);
|
sd_strerror(rsp->result), filename, snapid, tag);
|
||||||
if (rsp->result == SD_RES_NO_VDI) {
|
if (rsp->result == SD_RES_NO_VDI) {
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
@@ -1263,19 +1263,24 @@ static int write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
|
|||||||
/* update inode with the latest state */
|
/* update inode with the latest state */
|
||||||
static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
|
static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
SheepdogInode *inode;
|
SheepdogInode *inode;
|
||||||
int ret = 0, fd;
|
int ret = 0, fd;
|
||||||
uint32_t vid = 0;
|
uint32_t vid = 0;
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = g_malloc(sizeof(s->inode));
|
inode = g_malloc(sizeof(s->inode));
|
||||||
|
|
||||||
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) {
|
if (ret) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1386,8 +1391,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
qerror_report_err(local_err);
|
error_propagate(errp, local_err);
|
||||||
error_free(local_err);
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1408,15 +1412,16 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
ret = parse_vdiname(s, filename, vdi, &snapid, tag);
|
ret = parse_vdiname(s, filename, vdi, &snapid, tag);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "Can't parse filename");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
s->fd = get_sheep_fd(s);
|
s->fd = get_sheep_fd(s, errp);
|
||||||
if (s->fd < 0) {
|
if (s->fd < 0) {
|
||||||
ret = s->fd;
|
ret = s->fd;
|
||||||
goto out;
|
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) {
|
if (ret) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1436,7 +1441,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
s->is_snapshot = true;
|
s->is_snapshot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, errp);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
ret = fd;
|
ret = fd;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1449,6 +1454,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
error_setg(errp, "Can't read snapshot inode");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1472,7 +1478,8 @@ out:
|
|||||||
return ret;
|
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;
|
SheepdogVdiReq hdr;
|
||||||
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
||||||
@@ -1480,7 +1487,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
|
|||||||
unsigned int wlen, rlen = 0;
|
unsigned int wlen, rlen = 0;
|
||||||
char buf[SD_MAX_VDI_LEN];
|
char buf[SD_MAX_VDI_LEN];
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, errp);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -1510,11 +1517,12 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
|
|||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
error_setg_errno(errp, -ret, "create failed");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsp->result != SD_RES_SUCCESS) {
|
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;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1525,21 +1533,18 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sd_prealloc(const char *filename)
|
static int sd_prealloc(const char *filename, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
uint32_t idx, max_idx;
|
uint32_t idx, max_idx;
|
||||||
int64_t vdi_size;
|
int64_t vdi_size;
|
||||||
void *buf = g_malloc0(SD_DATA_OBJ_SIZE);
|
void *buf = g_malloc0(SD_DATA_OBJ_SIZE);
|
||||||
Error *local_err = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
|
ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
|
||||||
NULL, &local_err);
|
NULL, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qerror_report_err(local_err);
|
goto out_with_err_set;
|
||||||
error_free(local_err);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vdi_size = bdrv_getlength(bs);
|
vdi_size = bdrv_getlength(bs);
|
||||||
@@ -1563,7 +1568,12 @@ static int sd_prealloc(const char *filename)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Can't pre-allocate");
|
||||||
|
}
|
||||||
|
out_with_err_set:
|
||||||
if (bs) {
|
if (bs) {
|
||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
}
|
}
|
||||||
@@ -1636,7 +1646,6 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
char tag[SD_MAX_VDI_TAG_LEN];
|
char tag[SD_MAX_VDI_TAG_LEN];
|
||||||
uint32_t snapid;
|
uint32_t snapid;
|
||||||
bool prealloc = false;
|
bool prealloc = false;
|
||||||
Error *local_err = NULL;
|
|
||||||
|
|
||||||
s = g_malloc0(sizeof(BDRVSheepdogState));
|
s = g_malloc0(sizeof(BDRVSheepdogState));
|
||||||
|
|
||||||
@@ -1647,6 +1656,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
ret = parse_vdiname(s, filename, s->name, &snapid, tag);
|
ret = parse_vdiname(s, filename, s->name, &snapid, tag);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "Can't parse filename");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1661,7 +1671,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
} else if (!strcmp(options->value.s, "full")) {
|
} else if (!strcmp(options->value.s, "full")) {
|
||||||
prealloc = true;
|
prealloc = true;
|
||||||
} else {
|
} else {
|
||||||
error_report("Invalid preallocation mode: '%s'",
|
error_setg(errp, "Invalid preallocation mode: '%s'",
|
||||||
options->value.s);
|
options->value.s);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1670,6 +1680,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
if (options->value.s) {
|
if (options->value.s) {
|
||||||
ret = parse_redundancy(s, options->value.s);
|
ret = parse_redundancy(s, options->value.s);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "Invalid redundancy mode: '%s'",
|
||||||
|
options->value.s);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1678,7 +1690,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s->inode.vdi_size > SD_MAX_VDI_SIZE) {
|
if (s->inode.vdi_size > SD_MAX_VDI_SIZE) {
|
||||||
error_report("too big image size");
|
error_setg(errp, "too big image size");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1691,24 +1703,22 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
/* Currently, only Sheepdog backing image is supported. */
|
/* Currently, only Sheepdog backing image is supported. */
|
||||||
drv = bdrv_find_protocol(backing_file, true);
|
drv = bdrv_find_protocol(backing_file, true);
|
||||||
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
|
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;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = NULL;
|
bs = NULL;
|
||||||
ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_PROTOCOL, NULL,
|
ret = bdrv_open(&bs, backing_file, NULL, NULL, BDRV_O_PROTOCOL, NULL,
|
||||||
&local_err);
|
errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qerror_report_err(local_err);
|
|
||||||
error_free(local_err);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
base = bs->opaque;
|
base = bs->opaque;
|
||||||
|
|
||||||
if (!is_snapshot(&base->inode)) {
|
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);
|
bdrv_unref(bs);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1717,12 +1727,14 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = do_sd_create(s, &vid, 0);
|
ret = do_sd_create(s, &vid, 0, errp);
|
||||||
if (!prealloc || ret) {
|
if (ret) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sd_prealloc(filename);
|
if (prealloc) {
|
||||||
|
ret = sd_prealloc(filename, errp);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
g_free(s);
|
g_free(s);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1730,6 +1742,7 @@ out:
|
|||||||
|
|
||||||
static void sd_close(BlockDriverState *bs)
|
static void sd_close(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
BDRVSheepdogState *s = bs->opaque;
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
SheepdogVdiReq hdr;
|
SheepdogVdiReq hdr;
|
||||||
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
||||||
@@ -1738,8 +1751,10 @@ static void sd_close(BlockDriverState *bs)
|
|||||||
|
|
||||||
DPRINTF("%s\n", s->name);
|
DPRINTF("%s\n", s->name);
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1774,6 +1789,7 @@ static int64_t sd_getlength(BlockDriverState *bs)
|
|||||||
|
|
||||||
static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
BDRVSheepdogState *s = bs->opaque;
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
unsigned int datalen;
|
unsigned int datalen;
|
||||||
@@ -1786,8 +1802,10 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1846,6 +1864,7 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
|
|||||||
/* Delete current working VDI on the snapshot chain */
|
/* Delete current working VDI on the snapshot chain */
|
||||||
static bool sd_delete(BDRVSheepdogState *s)
|
static bool sd_delete(BDRVSheepdogState *s)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0;
|
unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0;
|
||||||
SheepdogVdiReq hdr = {
|
SheepdogVdiReq hdr = {
|
||||||
.opcode = SD_OP_DEL_VDI,
|
.opcode = SD_OP_DEL_VDI,
|
||||||
@@ -1856,8 +1875,10 @@ static bool sd_delete(BDRVSheepdogState *s)
|
|||||||
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1885,6 +1906,7 @@ static bool sd_delete(BDRVSheepdogState *s)
|
|||||||
*/
|
*/
|
||||||
static int sd_create_branch(BDRVSheepdogState *s)
|
static int sd_create_branch(BDRVSheepdogState *s)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
uint32_t vid;
|
uint32_t vid;
|
||||||
char *buf;
|
char *buf;
|
||||||
@@ -1900,15 +1922,19 @@ static int sd_create_branch(BDRVSheepdogState *s)
|
|||||||
* false bail out.
|
* false bail out.
|
||||||
*/
|
*/
|
||||||
deleted = sd_delete(s);
|
deleted = sd_delete(s);
|
||||||
ret = do_sd_create(s, &vid, !deleted);
|
ret = do_sd_create(s, &vid, !deleted, &local_err);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF("%" PRIx32 " is created.\n", vid);
|
DPRINTF("%" PRIx32 " is created.\n", vid);
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
ret = fd;
|
ret = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -2122,6 +2148,7 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
|
|||||||
|
|
||||||
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
BDRVSheepdogState *s = bs->opaque;
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
uint32_t new_vid;
|
uint32_t new_vid;
|
||||||
@@ -2149,10 +2176,13 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
|||||||
strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
|
strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
|
||||||
/* we don't need to update entire object */
|
/* we don't need to update entire object */
|
||||||
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
|
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
|
||||||
|
inode = g_malloc(datalen);
|
||||||
|
|
||||||
/* refresh inode. */
|
/* refresh inode. */
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
ret = fd;
|
ret = fd;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@@ -2164,15 +2194,15 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = do_sd_create(s, &new_vid, 1);
|
ret = do_sd_create(s, &new_vid, 1, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
error_report("failed to create inode for snapshot. %s",
|
error_report("failed to create inode for snapshot. %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = (SheepdogInode *)g_malloc(datalen);
|
|
||||||
|
|
||||||
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
|
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
|
||||||
s->inode.nr_copies, datalen, 0, s->cache_flags);
|
s->inode.nr_copies, datalen, 0, s->cache_flags);
|
||||||
|
|
||||||
@@ -2186,6 +2216,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
|||||||
s->inode.name, s->inode.snap_id, s->inode.vdi_id);
|
s->inode.name, s->inode.snap_id, s->inode.vdi_id);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
g_free(inode);
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -2249,6 +2280,7 @@ static int sd_snapshot_delete(BlockDriverState *bs,
|
|||||||
|
|
||||||
static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
BDRVSheepdogState *s = bs->opaque;
|
BDRVSheepdogState *s = bs->opaque;
|
||||||
SheepdogReq req;
|
SheepdogReq req;
|
||||||
int fd, nr = 1024, ret, max = BITS_TO_LONGS(SD_NR_VDIS) * sizeof(long);
|
int fd, nr = 1024, ret, max = BITS_TO_LONGS(SD_NR_VDIS) * sizeof(long);
|
||||||
@@ -2263,8 +2295,10 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
|||||||
|
|
||||||
vdi_inuse = g_malloc(max);
|
vdi_inuse = g_malloc(max);
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
ret = fd;
|
ret = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -2290,8 +2324,10 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
|||||||
hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT);
|
hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT);
|
||||||
start_nr = hval & (SD_NR_VDIS - 1);
|
start_nr = hval & (SD_NR_VDIS - 1);
|
||||||
|
|
||||||
fd = connect_to_sdog(s);
|
fd = connect_to_sdog(s, &local_err);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
ret = fd;
|
ret = fd;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -2341,6 +2377,7 @@ out:
|
|||||||
static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||||
int64_t pos, int size, int load)
|
int64_t pos, int size, int load)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
bool create;
|
bool create;
|
||||||
int fd, ret = 0, remaining = size;
|
int fd, ret = 0, remaining = size;
|
||||||
unsigned int data_len;
|
unsigned int data_len;
|
||||||
@@ -2349,8 +2386,10 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
|||||||
uint32_t vdi_index;
|
uint32_t vdi_index;
|
||||||
uint32_t vdi_id = load ? s->inode.parent_vdi_id : s->inode.vdi_id;
|
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) {
|
if (fd < 0) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));;
|
||||||
|
error_free(local_err);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
147
block/ssh.c
147
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
|
static void GCC_FMT_ATTR(3, 4)
|
||||||
* information from libssh2 as possible.
|
session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...)
|
||||||
*/
|
|
||||||
static void GCC_FMT_ATTR(2, 3)
|
|
||||||
session_error_report(BDRVSSHState *s, const char *fs, ...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
char *msg;
|
||||||
|
|
||||||
va_start(args, fs);
|
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;
|
char *ssh_err;
|
||||||
int ssh_err_code;
|
int ssh_err_code;
|
||||||
|
|
||||||
libssh2_session_last_error((s)->session, &ssh_err, NULL, 0);
|
|
||||||
/* This is not an errno. See <libssh2.h>. */
|
/* 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);
|
||||||
error_printf(": %s (libssh2 error code: %d)", ssh_err, ssh_err_code);
|
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);
|
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)
|
static void GCC_FMT_ATTR(2, 3)
|
||||||
@@ -145,9 +174,9 @@ sftp_error_report(BDRVSSHState *s, const char *fs, ...)
|
|||||||
int ssh_err_code;
|
int ssh_err_code;
|
||||||
unsigned long sftp_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>. */
|
/* 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>. */
|
/* See <libssh2_sftp.h>. */
|
||||||
sftp_err_code = libssh2_sftp_last_error((s)->sftp);
|
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,
|
static int check_host_key_knownhosts(BDRVSSHState *s,
|
||||||
const char *host, int port)
|
const char *host, int port, Error **errp)
|
||||||
{
|
{
|
||||||
const char *home;
|
const char *home;
|
||||||
char *knh_file = NULL;
|
char *knh_file = NULL;
|
||||||
@@ -257,14 +286,15 @@ static int check_host_key_knownhosts(BDRVSSHState *s,
|
|||||||
hostkey = libssh2_session_hostkey(s->session, &len, &type);
|
hostkey = libssh2_session_hostkey(s->session, &len, &type);
|
||||||
if (!hostkey) {
|
if (!hostkey) {
|
||||||
ret = -EINVAL;
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
knh = libssh2_knownhost_init(s->session);
|
knh = libssh2_knownhost_init(s->session);
|
||||||
if (!knh) {
|
if (!knh) {
|
||||||
ret = -EINVAL;
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,21 +319,23 @@ static int check_host_key_knownhosts(BDRVSSHState *s,
|
|||||||
break;
|
break;
|
||||||
case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
|
case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
session_error_report(s, "host key does not match the one in known_hosts (found key %s)",
|
session_error_setg(errp, s,
|
||||||
found->key);
|
"host key does not match the one in known_hosts"
|
||||||
|
" (found key %s)", found->key);
|
||||||
goto out;
|
goto out;
|
||||||
case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
|
case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
|
||||||
ret = -EINVAL;
|
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;
|
goto out;
|
||||||
case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
|
case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
|
||||||
ret = -EINVAL;
|
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;
|
goto out;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
session_error_report(s, "unknown error matching the host key with known_hosts (%d)",
|
session_error_setg(errp, s, "unknown error matching the host key"
|
||||||
r);
|
" with known_hosts (%d)", r);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,19 +390,19 @@ static int compare_fingerprint(const unsigned char *fingerprint, size_t len,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
check_host_key_hash(BDRVSSHState *s, const char *hash,
|
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;
|
const char *fingerprint;
|
||||||
|
|
||||||
fingerprint = libssh2_hostkey_hash(s->session, hash_type);
|
fingerprint = libssh2_hostkey_hash(s->session, hash_type);
|
||||||
if (!fingerprint) {
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len,
|
if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len,
|
||||||
hash) != 0) {
|
hash) != 0) {
|
||||||
error_report("remote host key does not match host_key_check '%s'",
|
error_setg(errp, "remote host key does not match host_key_check '%s'",
|
||||||
hash);
|
hash);
|
||||||
return -EPERM;
|
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,
|
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 */
|
/* host_key_check=no */
|
||||||
if (strcmp(host_key_check, "no") == 0) {
|
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:... */
|
/* host_key_check=md5:xx:yy:zz:... */
|
||||||
if (strncmp(host_key_check, "md5:", 4) == 0) {
|
if (strncmp(host_key_check, "md5:", 4) == 0) {
|
||||||
return check_host_key_hash(s, &host_key_check[4],
|
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:... */
|
/* host_key_check=sha1:xx:yy:zz:... */
|
||||||
if (strncmp(host_key_check, "sha1:", 5) == 0) {
|
if (strncmp(host_key_check, "sha1:", 5) == 0) {
|
||||||
return check_host_key_hash(s, &host_key_check[5],
|
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 */
|
/* host_key_check=yes */
|
||||||
if (strcmp(host_key_check, "yes") == 0) {
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int authenticate(BDRVSSHState *s, const char *user)
|
static int authenticate(BDRVSSHState *s, const char *user, Error **errp)
|
||||||
{
|
{
|
||||||
int r, ret;
|
int r, ret;
|
||||||
const char *userauthlist;
|
const char *userauthlist;
|
||||||
@@ -418,7 +450,8 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
|||||||
userauthlist = libssh2_userauth_list(s->session, user, strlen(user));
|
userauthlist = libssh2_userauth_list(s->session, user, strlen(user));
|
||||||
if (strstr(userauthlist, "publickey") == NULL) {
|
if (strstr(userauthlist, "publickey") == NULL) {
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
error_report("remote server does not support \"publickey\" authentication");
|
error_setg(errp,
|
||||||
|
"remote server does not support \"publickey\" authentication");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,17 +459,18 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
|||||||
agent = libssh2_agent_init(s->session);
|
agent = libssh2_agent_init(s->session);
|
||||||
if (!agent) {
|
if (!agent) {
|
||||||
ret = -EINVAL;
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
if (libssh2_agent_connect(agent)) {
|
if (libssh2_agent_connect(agent)) {
|
||||||
ret = -ECONNREFUSED;
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
if (libssh2_agent_list_identities(agent)) {
|
if (libssh2_agent_list_identities(agent)) {
|
||||||
ret = -EINVAL;
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,7 +481,8 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
|||||||
}
|
}
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
ret = -EINVAL;
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
r = libssh2_agent_userauth(agent, user, identity);
|
r = libssh2_agent_userauth(agent, user, identity);
|
||||||
@@ -461,7 +496,7 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
error_report("failed to authenticate using publickey authentication "
|
error_setg(errp, "failed to authenticate using publickey authentication "
|
||||||
"and the identities held by your ssh-agent");
|
"and the identities held by your ssh-agent");
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -476,10 +511,9 @@ static int authenticate(BDRVSSHState *s, const char *user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
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;
|
int r, ret;
|
||||||
Error *err = NULL;
|
|
||||||
const char *host, *user, *path, *host_key_check;
|
const char *host, *user, *path, *host_key_check;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
@@ -498,6 +532,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
|||||||
} else {
|
} else {
|
||||||
user = g_get_user_name();
|
user = g_get_user_name();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
error_setg_errno(errp, errno, "Can't get user name");
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -514,11 +549,9 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
|||||||
s->hostport = g_strdup_printf("%s:%d", host, port);
|
s->hostport = g_strdup_printf("%s:%d", host, port);
|
||||||
|
|
||||||
/* Open the socket and connect. */
|
/* Open the socket and connect. */
|
||||||
s->sock = inet_connect(s->hostport, &err);
|
s->sock = inet_connect(s->hostport, errp);
|
||||||
if (err != NULL) {
|
if (s->sock < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
qerror_report_err(err);
|
|
||||||
error_free(err);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +559,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
|||||||
s->session = libssh2_session_init();
|
s->session = libssh2_session_init();
|
||||||
if (!s->session) {
|
if (!s->session) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
session_error_report(s, "failed to initialize libssh2 session");
|
session_error_setg(errp, s, "failed to initialize libssh2 session");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,18 +570,18 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
|||||||
r = libssh2_session_handshake(s->session, s->sock);
|
r = libssh2_session_handshake(s->session, s->sock);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
session_error_report(s, "failed to establish SSH session");
|
session_error_setg(errp, s, "failed to establish SSH session");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the remote host's key against known_hosts. */
|
/* 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) {
|
if (ret < 0) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Authenticate. */
|
/* Authenticate. */
|
||||||
ret = authenticate(s, user);
|
ret = authenticate(s, user, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -556,7 +589,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
|||||||
/* Start SFTP. */
|
/* Start SFTP. */
|
||||||
s->sftp = libssh2_sftp_init(s->session);
|
s->sftp = libssh2_sftp_init(s->session);
|
||||||
if (!s->sftp) {
|
if (!s->sftp) {
|
||||||
session_error_report(s, "failed to initialize sftp handle");
|
session_error_setg(errp, s, "failed to initialize sftp handle");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -566,14 +599,14 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
|||||||
path, ssh_flags, creat_mode);
|
path, ssh_flags, creat_mode);
|
||||||
s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode);
|
s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode);
|
||||||
if (!s->sftp_handle) {
|
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;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);
|
r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sftp_error_report(s, "failed to read file attributes");
|
sftp_error_setg(errp, s, "failed to read file attributes");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,7 +656,7 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Start up SSH. */
|
/* 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) {
|
if (ret < 0) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -655,7 +688,6 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
int r, ret;
|
int r, ret;
|
||||||
Error *local_err = NULL;
|
|
||||||
int64_t total_size = 0;
|
int64_t total_size = 0;
|
||||||
QDict *uri_options = NULL;
|
QDict *uri_options = NULL;
|
||||||
BDRVSSHState s;
|
BDRVSSHState s;
|
||||||
@@ -674,17 +706,16 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
DPRINTF("total_size=%" PRIi64, total_size);
|
DPRINTF("total_size=%" PRIi64, total_size);
|
||||||
|
|
||||||
uri_options = qdict_new();
|
uri_options = qdict_new();
|
||||||
r = parse_uri(filename, uri_options, &local_err);
|
r = parse_uri(filename, uri_options, errp);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
qerror_report_err(local_err);
|
|
||||||
error_free(local_err);
|
|
||||||
ret = r;
|
ret = r;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = connect_to_ssh(&s, uri_options,
|
r = connect_to_ssh(&s, uri_options,
|
||||||
LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|
|
LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|
|
||||||
LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0644);
|
LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
|
||||||
|
0644, errp);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
ret = r;
|
ret = r;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -694,7 +725,7 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
libssh2_sftp_seek64(s.sftp_handle, total_size-1);
|
libssh2_sftp_seek64(s.sftp_handle, total_size-1);
|
||||||
r2 = libssh2_sftp_write(s.sftp_handle, c, 1);
|
r2 = libssh2_sftp_write(s.sftp_handle, c, 1);
|
||||||
if (r2 < 0) {
|
if (r2 < 0) {
|
||||||
sftp_error_report(&s, "truncate failed");
|
sftp_error_setg(errp, &s, "truncate failed");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
|
|||||||
/* Must assign before bdrv_delete() to prevent traversing dangling pointer
|
/* Must assign before bdrv_delete() to prevent traversing dangling pointer
|
||||||
* while we delete backing image instances.
|
* while we delete backing image instances.
|
||||||
*/
|
*/
|
||||||
top->backing_hd = base;
|
bdrv_set_backing_hd(top, base);
|
||||||
|
|
||||||
while (intermediate) {
|
while (intermediate) {
|
||||||
BlockDriverState *unused;
|
BlockDriverState *unused;
|
||||||
@@ -72,7 +72,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
|
|||||||
|
|
||||||
unused = intermediate;
|
unused = intermediate;
|
||||||
intermediate = intermediate->backing_hd;
|
intermediate = intermediate->backing_hd;
|
||||||
unused->backing_hd = NULL;
|
bdrv_set_backing_hd(unused, NULL);
|
||||||
bdrv_unref(unused);
|
bdrv_unref(unused);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -472,10 +472,17 @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
|
|||||||
s->curr_header = 0;
|
s->curr_header = 0;
|
||||||
} else if (h2_seq > h1_seq) {
|
} else if (h2_seq > h1_seq) {
|
||||||
s->curr_header = 1;
|
s->curr_header = 1;
|
||||||
|
} else {
|
||||||
|
/* The Microsoft Disk2VHD tool will create 2 identical
|
||||||
|
* headers, with identical sequence numbers. If the headers are
|
||||||
|
* identical, don't consider the file corrupt */
|
||||||
|
if (!memcmp(header1, header2, sizeof(VHDXHeader))) {
|
||||||
|
s->curr_header = 0;
|
||||||
} else {
|
} else {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vhdx_region_register(s, s->headers[s->curr_header]->log_offset,
|
vhdx_region_register(s, s->headers[s->curr_header]->log_offset,
|
||||||
s->headers[s->curr_header]->log_length);
|
s->headers[s->curr_header]->log_length);
|
||||||
|
|||||||
@@ -1534,7 +1534,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
|
|||||||
int ret, i;
|
int ret, i;
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
VMDK4Header header;
|
VMDK4Header header;
|
||||||
Error *local_err;
|
Error *local_err = NULL;
|
||||||
uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count;
|
uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count;
|
||||||
uint32_t *gd_buf = NULL;
|
uint32_t *gd_buf = NULL;
|
||||||
int gd_buf_size;
|
int gd_buf_size;
|
||||||
@@ -1700,7 +1700,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
BlockDriverState *new_bs = NULL;
|
BlockDriverState *new_bs = NULL;
|
||||||
Error *local_err;
|
Error *local_err = NULL;
|
||||||
char *desc = NULL;
|
char *desc = NULL;
|
||||||
int64_t total_size = 0, filesize;
|
int64_t total_size = 0, filesize;
|
||||||
const char *adapter_type = NULL;
|
const char *adapter_type = NULL;
|
||||||
@@ -1881,7 +1881,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
} else {
|
} else {
|
||||||
ret = bdrv_create_file(filename, options, &local_err);
|
ret = bdrv_create_file(filename, options, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not create image file");
|
error_propagate(errp, local_err);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1889,7 +1889,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
ret = bdrv_open(&new_bs, filename, NULL, NULL,
|
ret = bdrv_open(&new_bs, filename, NULL, NULL,
|
||||||
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
|
BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not write description");
|
error_propagate(errp, local_err);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
ret = bdrv_pwrite(new_bs, desc_offset, desc, desc_len);
|
ret = bdrv_pwrite(new_bs, desc_offset, desc, desc_len);
|
||||||
|
|||||||
@@ -787,6 +787,8 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
|||||||
s->current_mapping->path=buffer;
|
s->current_mapping->path=buffer;
|
||||||
s->current_mapping->read_only =
|
s->current_mapping->read_only =
|
||||||
(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
|
(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
|
||||||
|
} else {
|
||||||
|
g_free(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
@@ -831,7 +833,8 @@ static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int init_directories(BDRVVVFATState* s,
|
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;
|
bootsector_t* bootsector;
|
||||||
mapping_t* mapping;
|
mapping_t* mapping;
|
||||||
@@ -892,7 +895,7 @@ static int init_directories(BDRVVVFATState* s,
|
|||||||
if (mapping->mode & MODE_DIRECTORY) {
|
if (mapping->mode & MODE_DIRECTORY) {
|
||||||
mapping->begin = cluster;
|
mapping->begin = cluster;
|
||||||
if(read_directory(s, i)) {
|
if(read_directory(s, i)) {
|
||||||
fprintf(stderr, "Could not read directory %s\n",
|
error_setg(errp, "Could not read directory %s",
|
||||||
mapping->path);
|
mapping->path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -919,9 +922,10 @@ static int init_directories(BDRVVVFATState* s,
|
|||||||
cluster = mapping->end;
|
cluster = mapping->end;
|
||||||
|
|
||||||
if(cluster > s->cluster_count) {
|
if(cluster > s->cluster_count) {
|
||||||
fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
|
error_setg(errp,
|
||||||
|
"Directory does not fit in FAT%d (capacity %.2f MB)",
|
||||||
s->fat_type, s->sector_count / 2000.0);
|
s->fat_type, s->sector_count / 2000.0);
|
||||||
return -EINVAL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fix fat for entry */
|
/* fix fat for entry */
|
||||||
@@ -979,7 +983,7 @@ static int init_directories(BDRVVVFATState* s,
|
|||||||
static BDRVVVFATState *vvv = NULL;
|
static BDRVVVFATState *vvv = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int enable_write_target(BDRVVVFATState *s);
|
static int enable_write_target(BDRVVVFATState *s, Error **errp);
|
||||||
static int is_consistent(BDRVVVFATState *s);
|
static int is_consistent(BDRVVVFATState *s);
|
||||||
|
|
||||||
static void vvfat_rebind(BlockDriverState *bs)
|
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);
|
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
|
||||||
|
|
||||||
if (qemu_opt_get_bool(opts, "rw", false)) {
|
if (qemu_opt_get_bool(opts, "rw", false)) {
|
||||||
ret = enable_write_target(s);
|
ret = enable_write_target(s, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -1169,7 +1173,7 @@ DLOG(if (stderr == NULL) {
|
|||||||
|
|
||||||
bs->total_sectors = cyls * heads * secs;
|
bs->total_sectors = cyls * heads * secs;
|
||||||
|
|
||||||
if (init_directories(s, dirname, heads, secs)) {
|
if (init_directories(s, dirname, heads, secs, errp)) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -1864,7 +1868,7 @@ static int check_directory_consistency(BDRVVVFATState *s,
|
|||||||
|
|
||||||
if (s->used_clusters[cluster_num] & USED_ANY) {
|
if (s->used_clusters[cluster_num] & USED_ANY) {
|
||||||
fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
|
fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
|
||||||
return 0;
|
goto fail;
|
||||||
}
|
}
|
||||||
s->used_clusters[cluster_num] = USED_DIRECTORY;
|
s->used_clusters[cluster_num] = USED_DIRECTORY;
|
||||||
|
|
||||||
@@ -2904,11 +2908,10 @@ static BlockDriver vvfat_write_target = {
|
|||||||
.bdrv_close = write_target_close,
|
.bdrv_close = write_target_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int enable_write_target(BDRVVVFATState *s)
|
static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriver *bdrv_qcow;
|
BlockDriver *bdrv_qcow;
|
||||||
QEMUOptionParameter *options;
|
QEMUOptionParameter *options;
|
||||||
Error *local_err = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
int size = sector2cluster(s, s->sector_count);
|
int size = sector2cluster(s, s->sector_count);
|
||||||
s->used_clusters = calloc(size, 1);
|
s->used_clusters = calloc(size, 1);
|
||||||
@@ -2918,6 +2921,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
|||||||
s->qcow_filename = g_malloc(1024);
|
s->qcow_filename = g_malloc(1024);
|
||||||
ret = get_tmp_filename(s->qcow_filename, 1024);
|
ret = get_tmp_filename(s->qcow_filename, 1024);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "can't create temporary file");
|
||||||
goto err;
|
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_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
|
||||||
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
|
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) {
|
if (ret < 0) {
|
||||||
qerror_report_err(local_err);
|
|
||||||
error_free(local_err);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->qcow = NULL;
|
s->qcow = NULL;
|
||||||
ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL,
|
ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL,
|
||||||
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow,
|
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH,
|
||||||
&local_err);
|
bdrv_qcow, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qerror_report_err(local_err);
|
|
||||||
error_free(local_err);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2947,7 +2948,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
|||||||
unlink(s->qcow_filename);
|
unlink(s->qcow_filename);
|
||||||
#endif
|
#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->drv = &vvfat_write_target;
|
||||||
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
|
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
|
||||||
*(void**)s->bs->backing_hd->opaque = s;
|
*(void**)s->bs->backing_hd->opaque = s;
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ static void nbd_accept(void *opaque)
|
|||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
|
||||||
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
||||||
if (fd >= 0) {
|
if (fd >= 0 && !nbd_client_new(NULL, fd, nbd_client_put)) {
|
||||||
nbd_client_new(NULL, fd, nbd_client_put);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
84
blockdev.c
84
blockdev.c
@@ -34,7 +34,6 @@
|
|||||||
#include "hw/block/block.h"
|
#include "hw/block/block.h"
|
||||||
#include "block/blockjob.h"
|
#include "block/blockjob.h"
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qapi/qmp/types.h"
|
#include "qapi/qmp/types.h"
|
||||||
@@ -288,6 +287,25 @@ static int parse_block_error_action(const char *buf, bool is_read, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int parse_enum_option(const char *lookup[], const char *buf,
|
||||||
|
int max, int def, Error **errp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < max; i++) {
|
||||||
|
if (!strcmp(buf, lookup[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_setg(errp, "invalid parameter value: %s", buf);
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
|
static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
|
||||||
{
|
{
|
||||||
if (throttle_conflicting(cfg)) {
|
if (throttle_conflicting(cfg)) {
|
||||||
@@ -324,6 +342,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
const char *id;
|
const char *id;
|
||||||
bool has_driver_specific_opts;
|
bool has_driver_specific_opts;
|
||||||
|
BlockdevDetectZeroesOptions detect_zeroes;
|
||||||
BlockDriver *drv = NULL;
|
BlockDriver *drv = NULL;
|
||||||
|
|
||||||
/* Check common options by copying from bs_opts to opts, all other options
|
/* Check common options by copying from bs_opts to opts, all other options
|
||||||
@@ -332,7 +351,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
|
opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
|
||||||
if (error) {
|
if (error) {
|
||||||
error_propagate(errp, error);
|
error_propagate(errp, error);
|
||||||
return NULL;
|
goto err_no_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_opts_absorb_qdict(opts, bs_opts, &error);
|
qemu_opts_absorb_qdict(opts, bs_opts, &error);
|
||||||
@@ -452,6 +471,24 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_zeroes =
|
||||||
|
parse_enum_option(BlockdevDetectZeroesOptions_lookup,
|
||||||
|
qemu_opt_get(opts, "detect-zeroes"),
|
||||||
|
BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX,
|
||||||
|
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||||
|
&error);
|
||||||
|
if (error) {
|
||||||
|
error_propagate(errp, error);
|
||||||
|
goto early_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
|
||||||
|
!(bdrv_flags & BDRV_O_UNMAP)) {
|
||||||
|
error_setg(errp, "setting detect-zeroes to unmap is not allowed "
|
||||||
|
"without setting discard operation to unmap");
|
||||||
|
goto early_err;
|
||||||
|
}
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
dinfo = g_malloc0(sizeof(*dinfo));
|
dinfo = g_malloc0(sizeof(*dinfo));
|
||||||
dinfo->id = g_strdup(qemu_opts_id(opts));
|
dinfo->id = g_strdup(qemu_opts_id(opts));
|
||||||
@@ -462,6 +499,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
}
|
}
|
||||||
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
|
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
|
||||||
dinfo->bdrv->read_only = ro;
|
dinfo->bdrv->read_only = ro;
|
||||||
|
dinfo->bdrv->detect_zeroes = detect_zeroes;
|
||||||
dinfo->refcount = 1;
|
dinfo->refcount = 1;
|
||||||
if (serial != NULL) {
|
if (serial != NULL) {
|
||||||
dinfo->serial = g_strdup(serial);
|
dinfo->serial = g_strdup(serial);
|
||||||
@@ -526,8 +564,9 @@ bdrv_new_err:
|
|||||||
g_free(dinfo->id);
|
g_free(dinfo->id);
|
||||||
g_free(dinfo);
|
g_free(dinfo);
|
||||||
early_err:
|
early_err:
|
||||||
QDECREF(bs_opts);
|
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
|
err_no_opts:
|
||||||
|
QDECREF(bs_opts);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -691,7 +730,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||||||
&error_abort);
|
&error_abort);
|
||||||
qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
|
qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
qerror_report_err(local_err);
|
error_report("%s", error_get_pretty(local_err));
|
||||||
error_free(local_err);
|
error_free(local_err);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -901,9 +940,10 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||||||
|
|
||||||
/* Actual block device init: Functionality shared with blockdev-add */
|
/* Actual block device init: Functionality shared with blockdev-add */
|
||||||
dinfo = blockdev_init(filename, bs_opts, &local_err);
|
dinfo = blockdev_init(filename, bs_opts, &local_err);
|
||||||
|
bs_opts = NULL;
|
||||||
if (dinfo == NULL) {
|
if (dinfo == NULL) {
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
qerror_report_err(local_err);
|
error_report("%s", error_get_pretty(local_err));
|
||||||
error_free(local_err);
|
error_free(local_err);
|
||||||
}
|
}
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -938,6 +978,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||||||
|
|
||||||
fail:
|
fail:
|
||||||
qemu_opts_del(legacy_opts);
|
qemu_opts_del(legacy_opts);
|
||||||
|
QDECREF(bs_opts);
|
||||||
return dinfo;
|
return dinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,8 +1336,8 @@ static void external_snapshot_prepare(BlkTransactionState *common,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_in_use(state->old_bs)) {
|
if (bdrv_op_is_blocked(state->old_bs,
|
||||||
error_set(errp, QERR_DEVICE_IN_USE, device);
|
BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1518,8 +1559,7 @@ exit:
|
|||||||
|
|
||||||
static void eject_device(BlockDriverState *bs, int force, Error **errp)
|
static void eject_device(BlockDriverState *bs, int force, Error **errp)
|
||||||
{
|
{
|
||||||
if (bdrv_in_use(bs)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
|
||||||
error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!bdrv_dev_has_removable_media(bs)) {
|
if (!bdrv_dev_has_removable_media(bs)) {
|
||||||
@@ -1721,14 +1761,16 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
|||||||
{
|
{
|
||||||
const char *id = qdict_get_str(qdict, "id");
|
const char *id = qdict_get_str(qdict, "id");
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
bs = bdrv_find(id);
|
bs = bdrv_find(id);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
qerror_report(QERR_DEVICE_NOT_FOUND, id);
|
error_report("Device '%s' not found", id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (bdrv_in_use(bs)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
|
||||||
qerror_report(QERR_DEVICE_IN_USE, id);
|
error_report("%s", error_get_pretty(local_err));
|
||||||
|
error_free(local_err);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1849,6 +1891,10 @@ void qmp_block_stream(const char *device, bool has_base,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_STREAM, errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (base) {
|
if (base) {
|
||||||
base_bs = bdrv_find_backing_image(bs, base);
|
base_bs = bdrv_find_backing_image(bs, base);
|
||||||
if (base_bs == NULL) {
|
if (base_bs == NULL) {
|
||||||
@@ -1893,6 +1939,10 @@ void qmp_block_commit(const char *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT, errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* default top_bs is the active layer */
|
/* default top_bs is the active layer */
|
||||||
top_bs = bs;
|
top_bs = bs;
|
||||||
|
|
||||||
@@ -1984,8 +2034,7 @@ void qmp_drive_backup(const char *device, const char *target,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_in_use(bs)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
||||||
error_set(errp, QERR_DEVICE_IN_USE, device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2118,8 +2167,7 @@ void qmp_drive_mirror(const char *device, const char *target,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_in_use(bs)) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR, errp)) {
|
||||||
error_set(errp, QERR_DEVICE_IN_USE, device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2455,6 +2503,10 @@ QemuOptsList qemu_common_drive_opts = {
|
|||||||
.name = "copy-on-read",
|
.name = "copy-on-read",
|
||||||
.type = QEMU_OPT_BOOL,
|
.type = QEMU_OPT_BOOL,
|
||||||
.help = "copy read data from backing file into image file",
|
.help = "copy read data from backing file into image file",
|
||||||
|
},{
|
||||||
|
.name = "detect-zeroes",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "try to optimize zero writes (off, on, unmap)",
|
||||||
},
|
},
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
},
|
},
|
||||||
|
|||||||
14
blockjob.c
14
blockjob.c
@@ -41,14 +41,16 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
|
|||||||
{
|
{
|
||||||
BlockJob *job;
|
BlockJob *job;
|
||||||
|
|
||||||
if (bs->job || bdrv_in_use(bs)) {
|
if (bs->job) {
|
||||||
error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
bdrv_ref(bs);
|
bdrv_ref(bs);
|
||||||
bdrv_set_in_use(bs, 1);
|
|
||||||
|
|
||||||
job = g_malloc0(driver->instance_size);
|
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->driver = driver;
|
||||||
job->bs = bs;
|
job->bs = bs;
|
||||||
job->cb = cb;
|
job->cb = cb;
|
||||||
@@ -63,8 +65,9 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
|
|||||||
block_job_set_speed(job, speed, &local_err);
|
block_job_set_speed(job, speed, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
bs->job = NULL;
|
bs->job = NULL;
|
||||||
|
bdrv_op_unblock_all(bs, job->blocker);
|
||||||
|
error_free(job->blocker);
|
||||||
g_free(job);
|
g_free(job);
|
||||||
bdrv_set_in_use(bs, 0);
|
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -79,8 +82,9 @@ void block_job_completed(BlockJob *job, int ret)
|
|||||||
assert(bs->job == job);
|
assert(bs->job == job);
|
||||||
job->cb(job->opaque, ret);
|
job->cb(job->opaque, ret);
|
||||||
bs->job = NULL;
|
bs->job = NULL;
|
||||||
|
bdrv_op_unblock_all(bs, job->blocker);
|
||||||
|
error_free(job->blocker);
|
||||||
g_free(job);
|
g_free(job);
|
||||||
bdrv_set_in_use(bs, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
|
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
|
||||||
|
|||||||
@@ -1003,8 +1003,6 @@ int main(int argc, char **argv)
|
|||||||
cpu->opaque = ts;
|
cpu->opaque = ts;
|
||||||
|
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
cpu_x86_set_cpl(env, 3);
|
|
||||||
|
|
||||||
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
|
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
|
||||||
env->hflags |= HF_PE_MASK;
|
env->hflags |= HF_PE_MASK;
|
||||||
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
|
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
|
||||||
|
|||||||
68
configure
vendored
68
configure
vendored
@@ -2,26 +2,28 @@
|
|||||||
#
|
#
|
||||||
# qemu configure script (c) 2003 Fabrice Bellard
|
# qemu configure script (c) 2003 Fabrice Bellard
|
||||||
#
|
#
|
||||||
# set temporary file name
|
|
||||||
if test ! -z "$TMPDIR" ; then
|
# Temporary directory used for files created while
|
||||||
TMPDIR1="${TMPDIR}"
|
# configure runs. Since it is in the build directory
|
||||||
elif test ! -z "$TEMPDIR" ; then
|
# we can safely blow away any previous version of it
|
||||||
TMPDIR1="${TEMPDIR}"
|
# (and we need not jump through hoops to try to delete
|
||||||
else
|
# it when configure exits.)
|
||||||
TMPDIR1="/tmp"
|
TMPDIR1="config-temp"
|
||||||
|
rm -rf "${TMPDIR1}"
|
||||||
|
mkdir -p "${TMPDIR1}"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "ERROR: failed to create temporary directory"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
|
TMPB="qemu-conf"
|
||||||
TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}"
|
TMPC="${TMPDIR1}/${TMPB}.c"
|
||||||
TMPO="${TMPDIR1}/${TMPB}.o"
|
TMPO="${TMPDIR1}/${TMPB}.o"
|
||||||
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
|
TMPCXX="${TMPDIR1}/${TMPB}.cxx"
|
||||||
TMPL="${TMPDIR1}/${TMPB}.lo"
|
TMPL="${TMPDIR1}/${TMPB}.lo"
|
||||||
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
||||||
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
|
TMPE="${TMPDIR1}/${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
|
rm -f config.log
|
||||||
|
|
||||||
# Print a helpful header at the top of config.log
|
# Print a helpful header at the top of config.log
|
||||||
@@ -317,7 +319,7 @@ glusterfs_discard="no"
|
|||||||
glusterfs_zerofill="no"
|
glusterfs_zerofill="no"
|
||||||
virtio_blk_data_plane=""
|
virtio_blk_data_plane=""
|
||||||
gtk=""
|
gtk=""
|
||||||
gtkabi="2.0"
|
gtkabi=""
|
||||||
vte=""
|
vte=""
|
||||||
tpm="no"
|
tpm="no"
|
||||||
libssh2=""
|
libssh2=""
|
||||||
@@ -1137,11 +1139,11 @@ case "$cpu" in
|
|||||||
CPU_CFLAGS="-m64 -mcpu=ultrasparc"
|
CPU_CFLAGS="-m64 -mcpu=ultrasparc"
|
||||||
;;
|
;;
|
||||||
s390)
|
s390)
|
||||||
CPU_CFLAGS="-m31 -march=z990"
|
CPU_CFLAGS="-m31"
|
||||||
LDFLAGS="-m31 $LDFLAGS"
|
LDFLAGS="-m31 $LDFLAGS"
|
||||||
;;
|
;;
|
||||||
s390x)
|
s390x)
|
||||||
CPU_CFLAGS="-m64 -march=z990"
|
CPU_CFLAGS="-m64"
|
||||||
LDFLAGS="-m64 $LDFLAGS"
|
LDFLAGS="-m64 $LDFLAGS"
|
||||||
;;
|
;;
|
||||||
i386)
|
i386)
|
||||||
@@ -1970,6 +1972,18 @@ fi
|
|||||||
##########################################
|
##########################################
|
||||||
# GTK probe
|
# 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
|
if test "$gtk" != "no"; then
|
||||||
gtkpackage="gtk+-$gtkabi"
|
gtkpackage="gtk+-$gtkabi"
|
||||||
if test "$gtkabi" = "3.0" ; then
|
if test "$gtkabi" = "3.0" ; then
|
||||||
@@ -1983,7 +1997,7 @@ if test "$gtk" != "no"; then
|
|||||||
libs_softmmu="$gtk_libs $libs_softmmu"
|
libs_softmmu="$gtk_libs $libs_softmmu"
|
||||||
gtk="yes"
|
gtk="yes"
|
||||||
elif test "$gtk" = "yes"; then
|
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
|
else
|
||||||
gtk="no"
|
gtk="no"
|
||||||
fi
|
fi
|
||||||
@@ -2006,7 +2020,11 @@ if test "$vte" != "no"; then
|
|||||||
libs_softmmu="$vte_libs $libs_softmmu"
|
libs_softmmu="$vte_libs $libs_softmmu"
|
||||||
vte="yes"
|
vte="yes"
|
||||||
elif test "$vte" = "yes"; then
|
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
|
else
|
||||||
vte="no"
|
vte="no"
|
||||||
fi
|
fi
|
||||||
@@ -4029,11 +4047,14 @@ fi
|
|||||||
if test "$pie" = "no" ; then
|
if test "$pie" = "no" ; then
|
||||||
textseg_addr=
|
textseg_addr=
|
||||||
case "$cpu" in
|
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
|
textseg_addr=0x60000000
|
||||||
;;
|
;;
|
||||||
mips)
|
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
|
esac
|
||||||
if [ -n "$textseg_addr" ]; then
|
if [ -n "$textseg_addr" ]; then
|
||||||
@@ -4768,12 +4789,6 @@ if test "$gcov" = "yes" ; then
|
|||||||
echo "GCOV=$gcov_tool" >> $config_host_mak
|
echo "GCOV=$gcov_tool" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
iotests_common_env="tests/qemu-iotests/common.env"
|
|
||||||
|
|
||||||
echo "# Automatically generated by configure - do not modify" > $iotests_common_env
|
|
||||||
echo >> $iotests_common_env
|
|
||||||
echo "PYTHON='$python'" >> $iotests_common_env
|
|
||||||
|
|
||||||
# use included Linux headers
|
# use included Linux headers
|
||||||
if test "$linux" = "yes" ; then
|
if test "$linux" = "yes" ; then
|
||||||
mkdir -p linux-headers
|
mkdir -p linux-headers
|
||||||
@@ -5225,3 +5240,4 @@ printf " '%s'" "$0" "$@" >>config.status
|
|||||||
echo >>config.status
|
echo >>config.status
|
||||||
chmod +x config.status
|
chmod +x config.status
|
||||||
|
|
||||||
|
rm -r "$TMPDIR1"
|
||||||
|
|||||||
23
cpu-exec.c
23
cpu-exec.c
@@ -335,6 +335,18 @@ int cpu_exec(CPUArchState *env)
|
|||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(TARGET_I386)
|
||||||
|
if (interrupt_request & CPU_INTERRUPT_INIT) {
|
||||||
|
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
|
||||||
|
do_cpu_init(x86_cpu);
|
||||||
|
cpu->exception_index = EXCP_HALTED;
|
||||||
|
cpu_loop_exit(cpu);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (interrupt_request & CPU_INTERRUPT_RESET) {
|
||||||
|
cpu_reset(cpu);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
if (interrupt_request & CPU_INTERRUPT_POLL) {
|
if (interrupt_request & CPU_INTERRUPT_POLL) {
|
||||||
@@ -342,13 +354,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
apic_poll_irq(x86_cpu->apic_state);
|
apic_poll_irq(x86_cpu->apic_state);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (interrupt_request & CPU_INTERRUPT_INIT) {
|
if (interrupt_request & CPU_INTERRUPT_SIPI) {
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
|
|
||||||
0);
|
|
||||||
do_cpu_init(x86_cpu);
|
|
||||||
cpu->exception_index = EXCP_HALTED;
|
|
||||||
cpu_loop_exit(cpu);
|
|
||||||
} else if (interrupt_request & CPU_INTERRUPT_SIPI) {
|
|
||||||
do_cpu_sipi(x86_cpu);
|
do_cpu_sipi(x86_cpu);
|
||||||
} else if (env->hflags2 & HF2_GIF_MASK) {
|
} else if (env->hflags2 & HF2_GIF_MASK) {
|
||||||
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
|
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
|
||||||
@@ -405,9 +411,6 @@ int cpu_exec(CPUArchState *env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_PPC)
|
#elif defined(TARGET_PPC)
|
||||||
if ((interrupt_request & CPU_INTERRUPT_RESET)) {
|
|
||||||
cpu_reset(cpu);
|
|
||||||
}
|
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||||
ppc_hw_interrupt(env);
|
ppc_hw_interrupt(env);
|
||||||
if (env->pending_interrupts == 0) {
|
if (env->pending_interrupts == 0) {
|
||||||
|
|||||||
1
cpus.c
1
cpus.c
@@ -430,7 +430,6 @@ static const VMStateDescription vmstate_timers = {
|
|||||||
.name = "timer",
|
.name = "timer",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_INT64(cpu_ticks_offset, TimersState),
|
VMSTATE_INT64(cpu_ticks_offset, TimersState),
|
||||||
VMSTATE_INT64(dummy, TimersState),
|
VMSTATE_INT64(dummy, TimersState),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
CONFIG_VIRTIO=y
|
CONFIG_VIRTIO=y
|
||||||
CONFIG_SCLPCONSOLE=y
|
CONFIG_SCLPCONSOLE=y
|
||||||
CONFIG_S390_FLIC=$(CONFIG_KVM)
|
CONFIG_S390_FLIC=y
|
||||||
|
CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -116,6 +116,8 @@ V_(ImmCmpBranch, 23, 5, SignedBits) \
|
|||||||
V_(ImmLLiteral, 23, 5, SignedBits) \
|
V_(ImmLLiteral, 23, 5, SignedBits) \
|
||||||
V_(ImmException, 20, 5, Bits) \
|
V_(ImmException, 20, 5, Bits) \
|
||||||
V_(ImmHint, 11, 5, Bits) \
|
V_(ImmHint, 11, 5, Bits) \
|
||||||
|
V_(ImmBarrierDomain, 11, 10, Bits) \
|
||||||
|
V_(ImmBarrierType, 9, 8, Bits) \
|
||||||
\
|
\
|
||||||
/* System (MRS, MSR) */ \
|
/* System (MRS, MSR) */ \
|
||||||
V_(ImmSystemRegister, 19, 5, Bits) \
|
V_(ImmSystemRegister, 19, 5, Bits) \
|
||||||
@@ -181,7 +183,7 @@ enum Condition {
|
|||||||
inline Condition InvertCondition(Condition cond) {
|
inline Condition InvertCondition(Condition cond) {
|
||||||
// Conditions al and nv behave identically, as "always true". They can't be
|
// Conditions al and nv behave identically, as "always true". They can't be
|
||||||
// inverted, because there is no "always false" condition.
|
// inverted, because there is no "always false" condition.
|
||||||
ASSERT((cond != al) && (cond != nv));
|
VIXL_ASSERT((cond != al) && (cond != nv));
|
||||||
return static_cast<Condition>(cond ^ 1);
|
return static_cast<Condition>(cond ^ 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,6 +248,20 @@ enum SystemHint {
|
|||||||
SEVL = 5
|
SEVL = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BarrierDomain {
|
||||||
|
OuterShareable = 0,
|
||||||
|
NonShareable = 1,
|
||||||
|
InnerShareable = 2,
|
||||||
|
FullSystem = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BarrierType {
|
||||||
|
BarrierOther = 0,
|
||||||
|
BarrierReads = 1,
|
||||||
|
BarrierWrites = 2,
|
||||||
|
BarrierAll = 3
|
||||||
|
};
|
||||||
|
|
||||||
// System/special register names.
|
// System/special register names.
|
||||||
// This information is not encoded as one field but as the concatenation of
|
// This information is not encoded as one field but as the concatenation of
|
||||||
// multiple fields (Op0<0>, Op1, Crn, Crm, Op2).
|
// multiple fields (Op0<0>, Op1, Crn, Crm, Op2).
|
||||||
@@ -274,7 +290,7 @@ enum SystemRegister {
|
|||||||
//
|
//
|
||||||
// The enumerations can be used like this:
|
// The enumerations can be used like this:
|
||||||
//
|
//
|
||||||
// ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed);
|
// VIXL_ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed);
|
||||||
// switch(instr->Mask(PCRelAddressingMask)) {
|
// switch(instr->Mask(PCRelAddressingMask)) {
|
||||||
// case ADR: Format("adr 'Xd, 'AddrPCRelByte"); break;
|
// case ADR: Format("adr 'Xd, 'AddrPCRelByte"); break;
|
||||||
// case ADRP: Format("adrp 'Xd, 'AddrPCRelPage"); break;
|
// case ADRP: Format("adrp 'Xd, 'AddrPCRelPage"); break;
|
||||||
@@ -560,6 +576,15 @@ enum ExceptionOp {
|
|||||||
DCPS3 = ExceptionFixed | 0x00A00003
|
DCPS3 = ExceptionFixed | 0x00A00003
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MemBarrierOp {
|
||||||
|
MemBarrierFixed = 0xD503309F,
|
||||||
|
MemBarrierFMask = 0xFFFFF09F,
|
||||||
|
MemBarrierMask = 0xFFFFF0FF,
|
||||||
|
DSB = MemBarrierFixed | 0x00000000,
|
||||||
|
DMB = MemBarrierFixed | 0x00000020,
|
||||||
|
ISB = MemBarrierFixed | 0x00000040
|
||||||
|
};
|
||||||
|
|
||||||
// Any load or store.
|
// Any load or store.
|
||||||
enum LoadStoreAnyOp {
|
enum LoadStoreAnyOp {
|
||||||
LoadStoreAnyFMask = 0x0a000000,
|
LoadStoreAnyFMask = 0x0a000000,
|
||||||
@@ -927,17 +952,22 @@ enum FPDataProcessing1SourceOp {
|
|||||||
FRINTN = FRINTN_s,
|
FRINTN = FRINTN_s,
|
||||||
FRINTP_s = FPDataProcessing1SourceFixed | 0x00048000,
|
FRINTP_s = FPDataProcessing1SourceFixed | 0x00048000,
|
||||||
FRINTP_d = FPDataProcessing1SourceFixed | FP64 | 0x00048000,
|
FRINTP_d = FPDataProcessing1SourceFixed | FP64 | 0x00048000,
|
||||||
|
FRINTP = FRINTP_s,
|
||||||
FRINTM_s = FPDataProcessing1SourceFixed | 0x00050000,
|
FRINTM_s = FPDataProcessing1SourceFixed | 0x00050000,
|
||||||
FRINTM_d = FPDataProcessing1SourceFixed | FP64 | 0x00050000,
|
FRINTM_d = FPDataProcessing1SourceFixed | FP64 | 0x00050000,
|
||||||
|
FRINTM = FRINTM_s,
|
||||||
FRINTZ_s = FPDataProcessing1SourceFixed | 0x00058000,
|
FRINTZ_s = FPDataProcessing1SourceFixed | 0x00058000,
|
||||||
FRINTZ_d = FPDataProcessing1SourceFixed | FP64 | 0x00058000,
|
FRINTZ_d = FPDataProcessing1SourceFixed | FP64 | 0x00058000,
|
||||||
FRINTZ = FRINTZ_s,
|
FRINTZ = FRINTZ_s,
|
||||||
FRINTA_s = FPDataProcessing1SourceFixed | 0x00060000,
|
FRINTA_s = FPDataProcessing1SourceFixed | 0x00060000,
|
||||||
FRINTA_d = FPDataProcessing1SourceFixed | FP64 | 0x00060000,
|
FRINTA_d = FPDataProcessing1SourceFixed | FP64 | 0x00060000,
|
||||||
|
FRINTA = FRINTA_s,
|
||||||
FRINTX_s = FPDataProcessing1SourceFixed | 0x00070000,
|
FRINTX_s = FPDataProcessing1SourceFixed | 0x00070000,
|
||||||
FRINTX_d = FPDataProcessing1SourceFixed | FP64 | 0x00070000,
|
FRINTX_d = FPDataProcessing1SourceFixed | FP64 | 0x00070000,
|
||||||
|
FRINTX = FRINTX_s,
|
||||||
FRINTI_s = FPDataProcessing1SourceFixed | 0x00078000,
|
FRINTI_s = FPDataProcessing1SourceFixed | 0x00078000,
|
||||||
FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000
|
FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000,
|
||||||
|
FRINTI = FRINTI_s
|
||||||
};
|
};
|
||||||
|
|
||||||
// Floating point data processing 2 source.
|
// Floating point data processing 2 source.
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
|
|||||||
}
|
}
|
||||||
// We reached the end of the list. The last element must be
|
// We reached the end of the list. The last element must be
|
||||||
// registered_visitor.
|
// registered_visitor.
|
||||||
ASSERT(*it == registered_visitor);
|
VIXL_ASSERT(*it == registered_visitor);
|
||||||
visitors_.insert(it, new_visitor);
|
visitors_.insert(it, new_visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
|
|||||||
}
|
}
|
||||||
// We reached the end of the list. The last element must be
|
// We reached the end of the list. The last element must be
|
||||||
// registered_visitor.
|
// registered_visitor.
|
||||||
ASSERT(*it == registered_visitor);
|
VIXL_ASSERT(*it == registered_visitor);
|
||||||
visitors_.push_back(new_visitor);
|
visitors_.push_back(new_visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,16 +161,16 @@ void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodePCRelAddressing(Instruction* instr) {
|
void Decoder::DecodePCRelAddressing(Instruction* instr) {
|
||||||
ASSERT(instr->Bits(27, 24) == 0x0);
|
VIXL_ASSERT(instr->Bits(27, 24) == 0x0);
|
||||||
// We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
|
// We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
|
||||||
// decode.
|
// decode.
|
||||||
ASSERT(instr->Bit(28) == 0x1);
|
VIXL_ASSERT(instr->Bit(28) == 0x1);
|
||||||
VisitPCRelAddressing(instr);
|
VisitPCRelAddressing(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeBranchSystemException(Instruction* instr) {
|
void Decoder::DecodeBranchSystemException(Instruction* instr) {
|
||||||
ASSERT((instr->Bits(27, 24) == 0x4) ||
|
VIXL_ASSERT((instr->Bits(27, 24) == 0x4) ||
|
||||||
(instr->Bits(27, 24) == 0x5) ||
|
(instr->Bits(27, 24) == 0x5) ||
|
||||||
(instr->Bits(27, 24) == 0x6) ||
|
(instr->Bits(27, 24) == 0x6) ||
|
||||||
(instr->Bits(27, 24) == 0x7) );
|
(instr->Bits(27, 24) == 0x7) );
|
||||||
@@ -271,7 +271,7 @@ void Decoder::DecodeBranchSystemException(Instruction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeLoadStore(Instruction* instr) {
|
void Decoder::DecodeLoadStore(Instruction* instr) {
|
||||||
ASSERT((instr->Bits(27, 24) == 0x8) ||
|
VIXL_ASSERT((instr->Bits(27, 24) == 0x8) ||
|
||||||
(instr->Bits(27, 24) == 0x9) ||
|
(instr->Bits(27, 24) == 0x9) ||
|
||||||
(instr->Bits(27, 24) == 0xC) ||
|
(instr->Bits(27, 24) == 0xC) ||
|
||||||
(instr->Bits(27, 24) == 0xD) );
|
(instr->Bits(27, 24) == 0xD) );
|
||||||
@@ -390,7 +390,7 @@ void Decoder::DecodeLoadStore(Instruction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeLogical(Instruction* instr) {
|
void Decoder::DecodeLogical(Instruction* instr) {
|
||||||
ASSERT(instr->Bits(27, 24) == 0x2);
|
VIXL_ASSERT(instr->Bits(27, 24) == 0x2);
|
||||||
|
|
||||||
if (instr->Mask(0x80400000) == 0x00400000) {
|
if (instr->Mask(0x80400000) == 0x00400000) {
|
||||||
VisitUnallocated(instr);
|
VisitUnallocated(instr);
|
||||||
@@ -409,7 +409,7 @@ void Decoder::DecodeLogical(Instruction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeBitfieldExtract(Instruction* instr) {
|
void Decoder::DecodeBitfieldExtract(Instruction* instr) {
|
||||||
ASSERT(instr->Bits(27, 24) == 0x3);
|
VIXL_ASSERT(instr->Bits(27, 24) == 0x3);
|
||||||
|
|
||||||
if ((instr->Mask(0x80400000) == 0x80000000) ||
|
if ((instr->Mask(0x80400000) == 0x80000000) ||
|
||||||
(instr->Mask(0x80400000) == 0x00400000) ||
|
(instr->Mask(0x80400000) == 0x00400000) ||
|
||||||
@@ -434,7 +434,7 @@ void Decoder::DecodeBitfieldExtract(Instruction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeAddSubImmediate(Instruction* instr) {
|
void Decoder::DecodeAddSubImmediate(Instruction* instr) {
|
||||||
ASSERT(instr->Bits(27, 24) == 0x1);
|
VIXL_ASSERT(instr->Bits(27, 24) == 0x1);
|
||||||
if (instr->Bit(23) == 1) {
|
if (instr->Bit(23) == 1) {
|
||||||
VisitUnallocated(instr);
|
VisitUnallocated(instr);
|
||||||
} else {
|
} else {
|
||||||
@@ -444,7 +444,7 @@ void Decoder::DecodeAddSubImmediate(Instruction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeDataProcessing(Instruction* instr) {
|
void Decoder::DecodeDataProcessing(Instruction* instr) {
|
||||||
ASSERT((instr->Bits(27, 24) == 0xA) ||
|
VIXL_ASSERT((instr->Bits(27, 24) == 0xA) ||
|
||||||
(instr->Bits(27, 24) == 0xB));
|
(instr->Bits(27, 24) == 0xB));
|
||||||
|
|
||||||
if (instr->Bit(24) == 0) {
|
if (instr->Bit(24) == 0) {
|
||||||
@@ -559,7 +559,7 @@ void Decoder::DecodeDataProcessing(Instruction* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeFP(Instruction* instr) {
|
void Decoder::DecodeFP(Instruction* instr) {
|
||||||
ASSERT((instr->Bits(27, 24) == 0xE) ||
|
VIXL_ASSERT((instr->Bits(27, 24) == 0xE) ||
|
||||||
(instr->Bits(27, 24) == 0xF));
|
(instr->Bits(27, 24) == 0xF));
|
||||||
|
|
||||||
if (instr->Bit(28) == 0) {
|
if (instr->Bit(28) == 0) {
|
||||||
@@ -665,14 +665,14 @@ void Decoder::DecodeFP(Instruction* instr) {
|
|||||||
VisitFPConditionalSelect(instr);
|
VisitFPConditionalSelect(instr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Bit 30 == 1 has been handled earlier.
|
// Bit 30 == 1 has been handled earlier.
|
||||||
ASSERT(instr->Bit(30) == 0);
|
VIXL_ASSERT(instr->Bit(30) == 0);
|
||||||
if (instr->Mask(0xA0800000) != 0) {
|
if (instr->Mask(0xA0800000) != 0) {
|
||||||
VisitUnallocated(instr);
|
VisitUnallocated(instr);
|
||||||
} else {
|
} else {
|
||||||
@@ -687,21 +687,21 @@ void Decoder::DecodeFP(Instruction* instr) {
|
|||||||
|
|
||||||
void Decoder::DecodeAdvSIMDLoadStore(Instruction* instr) {
|
void Decoder::DecodeAdvSIMDLoadStore(Instruction* instr) {
|
||||||
// TODO: Implement Advanced SIMD load/store instruction decode.
|
// TODO: Implement Advanced SIMD load/store instruction decode.
|
||||||
ASSERT(instr->Bits(29, 25) == 0x6);
|
VIXL_ASSERT(instr->Bits(29, 25) == 0x6);
|
||||||
VisitUnimplemented(instr);
|
VisitUnimplemented(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Decoder::DecodeAdvSIMDDataProcessing(Instruction* instr) {
|
void Decoder::DecodeAdvSIMDDataProcessing(Instruction* instr) {
|
||||||
// TODO: Implement Advanced SIMD data processing instruction decode.
|
// TODO: Implement Advanced SIMD data processing instruction decode.
|
||||||
ASSERT(instr->Bits(27, 25) == 0x7);
|
VIXL_ASSERT(instr->Bits(27, 25) == 0x7);
|
||||||
VisitUnimplemented(instr);
|
VisitUnimplemented(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define DEFINE_VISITOR_CALLERS(A) \
|
#define DEFINE_VISITOR_CALLERS(A) \
|
||||||
void Decoder::Visit##A(Instruction *instr) { \
|
void Decoder::Visit##A(Instruction *instr) { \
|
||||||
ASSERT(instr->Mask(A##FMask) == A##Fixed); \
|
VIXL_ASSERT(instr->Mask(A##FMask) == A##Fixed); \
|
||||||
std::list<DecoderVisitor*>::iterator it; \
|
std::list<DecoderVisitor*>::iterator it; \
|
||||||
for (it = visitors_.begin(); it != visitors_.end(); it++) { \
|
for (it = visitors_.begin(); it != visitors_.end(); it++) { \
|
||||||
(*it)->Visit##A(instr); \
|
(*it)->Visit##A(instr); \
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ void Disassembler::VisitAddSubImmediate(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ void Disassembler::VisitAddSubShifted(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ void Disassembler::VisitAddSubExtended(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ void Disassembler::VisitAddSubWithCarry(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -258,30 +258,30 @@ void Disassembler::VisitLogicalImmediate(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
|
bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
|
||||||
ASSERT((reg_size == kXRegSize) ||
|
VIXL_ASSERT((reg_size == kXRegSize) ||
|
||||||
((reg_size == kWRegSize) && (value <= 0xffffffff)));
|
((reg_size == kWRegSize) && (value <= 0xffffffff)));
|
||||||
|
|
||||||
// Test for movz: 16 bits set at positions 0, 16, 32 or 48.
|
// Test for movz: 16 bits set at positions 0, 16, 32 or 48.
|
||||||
if (((value & 0xffffffffffff0000ULL) == 0ULL) ||
|
if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
|
||||||
((value & 0xffffffff0000ffffULL) == 0ULL) ||
|
((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
|
||||||
((value & 0xffff0000ffffffffULL) == 0ULL) ||
|
((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
|
||||||
((value & 0x0000ffffffffffffULL) == 0ULL)) {
|
((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
|
// Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
|
||||||
if ((reg_size == kXRegSize) &&
|
if ((reg_size == kXRegSize) &&
|
||||||
(((value & 0xffffffffffff0000ULL) == 0xffffffffffff0000ULL) ||
|
(((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
|
||||||
((value & 0xffffffff0000ffffULL) == 0xffffffff0000ffffULL) ||
|
((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
|
||||||
((value & 0xffff0000ffffffffULL) == 0xffff0000ffffffffULL) ||
|
((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
|
||||||
((value & 0x0000ffffffffffffULL) == 0x0000ffffffffffffULL))) {
|
((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((reg_size == kWRegSize) &&
|
if ((reg_size == kWRegSize) &&
|
||||||
@@ -337,7 +337,7 @@ void Disassembler::VisitLogicalShifted(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
@@ -353,7 +353,7 @@ void Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
|
|||||||
case CCMN_x: mnemonic = "ccmn"; break;
|
case CCMN_x: mnemonic = "ccmn"; break;
|
||||||
case CCMP_w:
|
case CCMP_w:
|
||||||
case CCMP_x: mnemonic = "ccmp"; break;
|
case CCMP_x: mnemonic = "ccmp"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
|
|||||||
case CCMN_x_imm: mnemonic = "ccmn"; break;
|
case CCMN_x_imm: mnemonic = "ccmn"; break;
|
||||||
case CCMP_w_imm:
|
case CCMP_w_imm:
|
||||||
case CCMP_x_imm: mnemonic = "ccmp"; break;
|
case CCMP_x_imm: mnemonic = "ccmp"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -421,7 +421,7 @@ void Disassembler::VisitConditionalSelect(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -520,7 +520,7 @@ void Disassembler::VisitExtract(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -538,7 +538,7 @@ void Disassembler::VisitPCRelAddressing(Instruction* instr) {
|
|||||||
void Disassembler::VisitConditionalBranch(Instruction* instr) {
|
void Disassembler::VisitConditionalBranch(Instruction* instr) {
|
||||||
switch (instr->Mask(ConditionalBranchMask)) {
|
switch (instr->Mask(ConditionalBranchMask)) {
|
||||||
case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
|
case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +570,7 @@ void Disassembler::VisitUnconditionalBranch(Instruction* instr) {
|
|||||||
switch (instr->Mask(UnconditionalBranchMask)) {
|
switch (instr->Mask(UnconditionalBranchMask)) {
|
||||||
case B: mnemonic = "b"; break;
|
case B: mnemonic = "b"; break;
|
||||||
case BL: mnemonic = "bl"; break;
|
case BL: mnemonic = "bl"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -591,7 +591,7 @@ void Disassembler::VisitDataProcessing1Source(Instruction* instr) {
|
|||||||
FORMAT(CLS, "cls");
|
FORMAT(CLS, "cls");
|
||||||
#undef FORMAT
|
#undef FORMAT
|
||||||
case REV32_x: mnemonic = "rev32"; break;
|
case REV32_x: mnemonic = "rev32"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -690,7 +690,7 @@ void Disassembler::VisitDataProcessing3Source(Instruction* instr) {
|
|||||||
form = form_xxx;
|
form = form_xxx;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -705,7 +705,7 @@ void Disassembler::VisitCompareBranch(Instruction* instr) {
|
|||||||
case CBZ_x: mnemonic = "cbz"; break;
|
case CBZ_x: mnemonic = "cbz"; break;
|
||||||
case CBNZ_w:
|
case CBNZ_w:
|
||||||
case CBNZ_x: mnemonic = "cbnz"; break;
|
case CBNZ_x: mnemonic = "cbnz"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -722,7 +722,7 @@ void Disassembler::VisitTestBranch(Instruction* instr) {
|
|||||||
switch (instr->Mask(TestBranchMask)) {
|
switch (instr->Mask(TestBranchMask)) {
|
||||||
case TBZ: mnemonic = "tbz"; break;
|
case TBZ: mnemonic = "tbz"; break;
|
||||||
case TBNZ: mnemonic = "tbnz"; break;
|
case TBNZ: mnemonic = "tbnz"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -742,7 +742,7 @@ void Disassembler::VisitMoveWideImmediate(Instruction* instr) {
|
|||||||
case MOVZ_x: mnemonic = "movz"; break;
|
case MOVZ_x: mnemonic = "movz"; break;
|
||||||
case MOVK_w:
|
case MOVK_w:
|
||||||
case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
|
case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -981,7 +981,7 @@ void Disassembler::VisitFPConditionalSelect(Instruction* instr) {
|
|||||||
switch (instr->Mask(FPConditionalSelectMask)) {
|
switch (instr->Mask(FPConditionalSelectMask)) {
|
||||||
case FCSEL_s:
|
case FCSEL_s:
|
||||||
case FCSEL_d: mnemonic = "fcsel"; break;
|
case FCSEL_d: mnemonic = "fcsel"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -1033,7 +1033,7 @@ void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
|
|||||||
FORMAT(FMINNM, "fminnm");
|
FORMAT(FMINNM, "fminnm");
|
||||||
FORMAT(FNMUL, "fnmul");
|
FORMAT(FNMUL, "fnmul");
|
||||||
#undef FORMAT
|
#undef FORMAT
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -1052,7 +1052,7 @@ void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
|
|||||||
FORMAT(FNMADD, "fnmadd");
|
FORMAT(FNMADD, "fnmadd");
|
||||||
FORMAT(FNMSUB, "fnmsub");
|
FORMAT(FNMSUB, "fnmsub");
|
||||||
#undef FORMAT
|
#undef FORMAT
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1065,7 @@ void Disassembler::VisitFPImmediate(Instruction* instr) {
|
|||||||
switch (instr->Mask(FPImmediateMask)) {
|
switch (instr->Mask(FPImmediateMask)) {
|
||||||
case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
|
case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
|
||||||
case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
|
case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -1082,6 +1082,14 @@ void Disassembler::VisitFPIntegerConvert(Instruction* instr) {
|
|||||||
case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
|
case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
|
||||||
case FMOV_sw:
|
case FMOV_sw:
|
||||||
case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
|
case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
|
||||||
|
case FCVTAS_ws:
|
||||||
|
case FCVTAS_xs:
|
||||||
|
case FCVTAS_wd:
|
||||||
|
case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break;
|
||||||
|
case FCVTAU_ws:
|
||||||
|
case FCVTAU_xs:
|
||||||
|
case FCVTAU_wd:
|
||||||
|
case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break;
|
||||||
case FCVTMS_ws:
|
case FCVTMS_ws:
|
||||||
case FCVTMS_xs:
|
case FCVTMS_xs:
|
||||||
case FCVTMS_wd:
|
case FCVTMS_wd:
|
||||||
@@ -1141,7 +1149,7 @@ void Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
|
|||||||
case UCVTF_sx_fixed:
|
case UCVTF_sx_fixed:
|
||||||
case UCVTF_dw_fixed:
|
case UCVTF_dw_fixed:
|
||||||
case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
|
case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
}
|
}
|
||||||
@@ -1176,7 +1184,7 @@ void Disassembler::VisitSystem(Instruction* instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
|
} else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
|
||||||
ASSERT(instr->Mask(SystemHintMask) == HINT);
|
VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
|
||||||
switch (instr->ImmHint()) {
|
switch (instr->ImmHint()) {
|
||||||
case NOP: {
|
case NOP: {
|
||||||
mnemonic = "nop";
|
mnemonic = "nop";
|
||||||
@@ -1184,6 +1192,24 @@ void Disassembler::VisitSystem(Instruction* instr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
|
||||||
|
switch (instr->Mask(MemBarrierMask)) {
|
||||||
|
case DMB: {
|
||||||
|
mnemonic = "dmb";
|
||||||
|
form = "'M";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSB: {
|
||||||
|
mnemonic = "dsb";
|
||||||
|
form = "'M";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ISB: {
|
||||||
|
mnemonic = "isb";
|
||||||
|
form = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Format(instr, mnemonic, form);
|
Format(instr, mnemonic, form);
|
||||||
@@ -1226,7 +1252,7 @@ void Disassembler::ProcessOutput(Instruction* /*instr*/) {
|
|||||||
|
|
||||||
void Disassembler::Format(Instruction* instr, const char* mnemonic,
|
void Disassembler::Format(Instruction* instr, const char* mnemonic,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(mnemonic != NULL);
|
VIXL_ASSERT(mnemonic != NULL);
|
||||||
ResetOutput();
|
ResetOutput();
|
||||||
Substitute(instr, mnemonic);
|
Substitute(instr, mnemonic);
|
||||||
if (format != NULL) {
|
if (format != NULL) {
|
||||||
@@ -1268,8 +1294,9 @@ int Disassembler::SubstituteField(Instruction* instr, const char* format) {
|
|||||||
case 'A': return SubstitutePCRelAddressField(instr, format);
|
case 'A': return SubstitutePCRelAddressField(instr, format);
|
||||||
case 'B': return SubstituteBranchTargetField(instr, format);
|
case 'B': return SubstituteBranchTargetField(instr, format);
|
||||||
case 'O': return SubstituteLSRegOffsetField(instr, format);
|
case 'O': return SubstituteLSRegOffsetField(instr, format);
|
||||||
|
case 'M': return SubstituteBarrierField(instr, format);
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
VIXL_UNREACHABLE();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1294,7 +1321,7 @@ int Disassembler::SubstituteRegisterField(Instruction* instr,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase field length for registers tagged as stack.
|
// Increase field length for registers tagged as stack.
|
||||||
@@ -1331,7 +1358,7 @@ int Disassembler::SubstituteRegisterField(Instruction* instr,
|
|||||||
|
|
||||||
int Disassembler::SubstituteImmediateField(Instruction* instr,
|
int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(format[0] == 'I');
|
VIXL_ASSERT(format[0] == 'I');
|
||||||
|
|
||||||
switch (format[1]) {
|
switch (format[1]) {
|
||||||
case 'M': { // IMoveImm or IMoveLSL.
|
case 'M': { // IMoveImm or IMoveLSL.
|
||||||
@@ -1339,10 +1366,10 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||||||
uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide());
|
uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide());
|
||||||
AppendToOutput("#0x%" PRIx64, imm);
|
AppendToOutput("#0x%" PRIx64, imm);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(format[5] == 'L');
|
VIXL_ASSERT(format[5] == 'L');
|
||||||
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
|
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
|
||||||
if (instr->ShiftMoveWide() > 0) {
|
if (instr->ShiftMoveWide() > 0) {
|
||||||
AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide());
|
AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 8;
|
return 8;
|
||||||
@@ -1384,14 +1411,14 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
case 'A': { // IAddSub.
|
case 'A': { // IAddSub.
|
||||||
ASSERT(instr->ShiftAddSub() <= 1);
|
VIXL_ASSERT(instr->ShiftAddSub() <= 1);
|
||||||
int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
|
int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
|
||||||
AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
|
AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
case 'F': { // IFPSingle, IFPDouble or IFPFBits.
|
case 'F': { // IFPSingle, IFPDouble or IFPFBits.
|
||||||
if (format[3] == 'F') { // IFPFbits.
|
if (format[3] == 'F') { // IFPFbits.
|
||||||
AppendToOutput("#%" PRId64, 64 - instr->FPScale());
|
AppendToOutput("#%d", 64 - instr->FPScale());
|
||||||
return 8;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
|
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
|
||||||
@@ -1412,27 +1439,27 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
case 'P': { // IP - Conditional compare.
|
case 'P': { // IP - Conditional compare.
|
||||||
AppendToOutput("#%" PRId64, instr->ImmCondCmp());
|
AppendToOutput("#%d", instr->ImmCondCmp());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
case 'B': { // Bitfields.
|
case 'B': { // Bitfields.
|
||||||
return SubstituteBitfieldImmediateField(instr, format);
|
return SubstituteBitfieldImmediateField(instr, format);
|
||||||
}
|
}
|
||||||
case 'E': { // IExtract.
|
case 'E': { // IExtract.
|
||||||
AppendToOutput("#%" PRId64, instr->ImmS());
|
AppendToOutput("#%d", instr->ImmS());
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
case 'S': { // IS - Test and branch bit.
|
case 'S': { // IS - Test and branch bit.
|
||||||
AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) |
|
AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
|
||||||
instr->ImmTestBranchBit40());
|
instr->ImmTestBranchBit40());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
case 'D': { // IDebug - HLT and BRK instructions.
|
case 'D': { // IDebug - HLT and BRK instructions.
|
||||||
AppendToOutput("#0x%" PRIx64, instr->ImmException());
|
AppendToOutput("#0x%x", instr->ImmException());
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
UNIMPLEMENTED();
|
VIXL_UNIMPLEMENTED();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1441,7 +1468,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||||||
|
|
||||||
int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT((format[0] == 'I') && (format[1] == 'B'));
|
VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
|
||||||
unsigned r = instr->ImmR();
|
unsigned r = instr->ImmR();
|
||||||
unsigned s = instr->ImmS();
|
unsigned s = instr->ImmS();
|
||||||
|
|
||||||
@@ -1455,19 +1482,19 @@ int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
|||||||
AppendToOutput("#%d", s + 1);
|
AppendToOutput("#%d", s + 1);
|
||||||
return 5;
|
return 5;
|
||||||
} else {
|
} else {
|
||||||
ASSERT(format[3] == '-');
|
VIXL_ASSERT(format[3] == '-');
|
||||||
AppendToOutput("#%d", s - r + 1);
|
AppendToOutput("#%d", s - r + 1);
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'Z': { // IBZ-r.
|
case 'Z': { // IBZ-r.
|
||||||
ASSERT((format[3] == '-') && (format[4] == 'r'));
|
VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
|
||||||
unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize;
|
unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize;
|
||||||
AppendToOutput("#%d", reg_size - r);
|
AppendToOutput("#%d", reg_size - r);
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
VIXL_UNREACHABLE();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1476,7 +1503,7 @@ int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
|||||||
|
|
||||||
int Disassembler::SubstituteLiteralField(Instruction* instr,
|
int Disassembler::SubstituteLiteralField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(strncmp(format, "LValue", 6) == 0);
|
VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
|
||||||
USE(format);
|
USE(format);
|
||||||
|
|
||||||
switch (instr->Mask(LoadLiteralMask)) {
|
switch (instr->Mask(LoadLiteralMask)) {
|
||||||
@@ -1484,7 +1511,7 @@ int Disassembler::SubstituteLiteralField(Instruction* instr,
|
|||||||
case LDR_x_lit:
|
case LDR_x_lit:
|
||||||
case LDR_s_lit:
|
case LDR_s_lit:
|
||||||
case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break;
|
case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break;
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 6;
|
return 6;
|
||||||
@@ -1492,12 +1519,12 @@ int Disassembler::SubstituteLiteralField(Instruction* instr,
|
|||||||
|
|
||||||
|
|
||||||
int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
||||||
ASSERT(format[0] == 'H');
|
VIXL_ASSERT(format[0] == 'H');
|
||||||
ASSERT(instr->ShiftDP() <= 0x3);
|
VIXL_ASSERT(instr->ShiftDP() <= 0x3);
|
||||||
|
|
||||||
switch (format[1]) {
|
switch (format[1]) {
|
||||||
case 'D': { // HDP.
|
case 'D': { // HDP.
|
||||||
ASSERT(instr->ShiftDP() != ROR);
|
VIXL_ASSERT(instr->ShiftDP() != ROR);
|
||||||
} // Fall through.
|
} // Fall through.
|
||||||
case 'L': { // HLo.
|
case 'L': { // HLo.
|
||||||
if (instr->ImmDPShift() != 0) {
|
if (instr->ImmDPShift() != 0) {
|
||||||
@@ -1508,7 +1535,7 @@ int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED();
|
VIXL_UNIMPLEMENTED();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1516,7 +1543,7 @@ int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
|||||||
|
|
||||||
int Disassembler::SubstituteConditionField(Instruction* instr,
|
int Disassembler::SubstituteConditionField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(format[0] == 'C');
|
VIXL_ASSERT(format[0] == 'C');
|
||||||
const char* condition_code[] = { "eq", "ne", "hs", "lo",
|
const char* condition_code[] = { "eq", "ne", "hs", "lo",
|
||||||
"mi", "pl", "vs", "vc",
|
"mi", "pl", "vs", "vc",
|
||||||
"hi", "ls", "ge", "lt",
|
"hi", "ls", "ge", "lt",
|
||||||
@@ -1538,27 +1565,27 @@ int Disassembler::SubstituteConditionField(Instruction* instr,
|
|||||||
int Disassembler::SubstitutePCRelAddressField(Instruction* instr,
|
int Disassembler::SubstitutePCRelAddressField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
USE(format);
|
USE(format);
|
||||||
ASSERT(strncmp(format, "AddrPCRel", 9) == 0);
|
VIXL_ASSERT(strncmp(format, "AddrPCRel", 9) == 0);
|
||||||
|
|
||||||
int offset = instr->ImmPCRel();
|
int offset = instr->ImmPCRel();
|
||||||
|
|
||||||
// Only ADR (AddrPCRelByte) is supported.
|
// Only ADR (AddrPCRelByte) is supported.
|
||||||
ASSERT(strcmp(format, "AddrPCRelByte") == 0);
|
VIXL_ASSERT(strcmp(format, "AddrPCRelByte") == 0);
|
||||||
|
|
||||||
char sign = '+';
|
char sign = '+';
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
offset = -offset;
|
offset = -offset;
|
||||||
sign = '-';
|
sign = '-';
|
||||||
}
|
}
|
||||||
// TODO: Extend this to support printing the target address.
|
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
|
||||||
AppendToOutput("#%c0x%x", sign, offset);
|
AppendToOutput("#%c0x%x (addr %p)", sign, offset, instr + offset);
|
||||||
return 13;
|
return 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(strncmp(format, "BImm", 4) == 0);
|
VIXL_ASSERT(strncmp(format, "BImm", 4) == 0);
|
||||||
|
|
||||||
int64_t offset = 0;
|
int64_t offset = 0;
|
||||||
switch (format[5]) {
|
switch (format[5]) {
|
||||||
@@ -1570,7 +1597,7 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
|||||||
case 'm': offset = instr->ImmCmpBranch(); break;
|
case 'm': offset = instr->ImmCmpBranch(); break;
|
||||||
// BImmTest - test and branch immediate.
|
// BImmTest - test and branch immediate.
|
||||||
case 'e': offset = instr->ImmTestBranch(); break;
|
case 'e': offset = instr->ImmTestBranch(); break;
|
||||||
default: UNIMPLEMENTED();
|
default: VIXL_UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
offset <<= kInstructionSizeLog2;
|
offset <<= kInstructionSizeLog2;
|
||||||
char sign = '+';
|
char sign = '+';
|
||||||
@@ -1578,15 +1605,16 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
|||||||
offset = -offset;
|
offset = -offset;
|
||||||
sign = '-';
|
sign = '-';
|
||||||
}
|
}
|
||||||
AppendToOutput("#%c0x%" PRIx64, sign, offset);
|
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
|
||||||
|
AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, offset, instr + offset);
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Disassembler::SubstituteExtendField(Instruction* instr,
|
int Disassembler::SubstituteExtendField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(strncmp(format, "Ext", 3) == 0);
|
VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
|
||||||
ASSERT(instr->ExtendMode() <= 7);
|
VIXL_ASSERT(instr->ExtendMode() <= 7);
|
||||||
USE(format);
|
USE(format);
|
||||||
|
|
||||||
const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
|
const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
|
||||||
@@ -1598,12 +1626,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
|
|||||||
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
|
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
|
||||||
(instr->ExtendMode() == UXTX))) {
|
(instr->ExtendMode() == UXTX))) {
|
||||||
if (instr->ImmExtendShift() > 0) {
|
if (instr->ImmExtendShift() > 0) {
|
||||||
AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift());
|
AppendToOutput(", lsl #%d", instr->ImmExtendShift());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
|
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
|
||||||
if (instr->ImmExtendShift() > 0) {
|
if (instr->ImmExtendShift() > 0) {
|
||||||
AppendToOutput(" #%" PRId64, instr->ImmExtendShift());
|
AppendToOutput(" #%d", instr->ImmExtendShift());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 3;
|
return 3;
|
||||||
@@ -1612,7 +1640,7 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
|
|||||||
|
|
||||||
int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(strncmp(format, "Offsetreg", 9) == 0);
|
VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
|
||||||
const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
|
const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
|
||||||
"undefined", "undefined", "sxtw", "sxtx" };
|
"undefined", "undefined", "sxtw", "sxtx" };
|
||||||
USE(format);
|
USE(format);
|
||||||
@@ -1632,7 +1660,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
|||||||
if (!((ext == UXTX) && (shift == 0))) {
|
if (!((ext == UXTX) && (shift == 0))) {
|
||||||
AppendToOutput(", %s", extend_mode[ext]);
|
AppendToOutput(", %s", extend_mode[ext]);
|
||||||
if (shift != 0) {
|
if (shift != 0) {
|
||||||
AppendToOutput(" #%" PRId64, instr->SizeLS());
|
AppendToOutput(" #%d", instr->SizeLS());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 9;
|
return 9;
|
||||||
@@ -1641,7 +1669,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
|||||||
|
|
||||||
int Disassembler::SubstitutePrefetchField(Instruction* instr,
|
int Disassembler::SubstitutePrefetchField(Instruction* instr,
|
||||||
const char* format) {
|
const char* format) {
|
||||||
ASSERT(format[0] == 'P');
|
VIXL_ASSERT(format[0] == 'P');
|
||||||
USE(format);
|
USE(format);
|
||||||
|
|
||||||
int prefetch_mode = instr->PrefetchMode();
|
int prefetch_mode = instr->PrefetchMode();
|
||||||
@@ -1654,6 +1682,23 @@ int Disassembler::SubstitutePrefetchField(Instruction* instr,
|
|||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Disassembler::SubstituteBarrierField(Instruction* instr,
|
||||||
|
const char* format) {
|
||||||
|
VIXL_ASSERT(format[0] == 'M');
|
||||||
|
USE(format);
|
||||||
|
|
||||||
|
static const char* options[4][4] = {
|
||||||
|
{ "sy (0b0000)", "oshld", "oshst", "osh" },
|
||||||
|
{ "sy (0b0100)", "nshld", "nshst", "nsh" },
|
||||||
|
{ "sy (0b1000)", "ishld", "ishst", "ish" },
|
||||||
|
{ "sy (0b1100)", "ld", "st", "sy" }
|
||||||
|
};
|
||||||
|
int domain = instr->ImmBarrierDomain();
|
||||||
|
int type = instr->ImmBarrierType();
|
||||||
|
|
||||||
|
AppendToOutput("%s", options[domain][type]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void Disassembler::ResetOutput() {
|
void Disassembler::ResetOutput() {
|
||||||
buffer_pos_ = 0;
|
buffer_pos_ = 0;
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ class Disassembler: public DecoderVisitor {
|
|||||||
int SubstituteBranchTargetField(Instruction* instr, const char* format);
|
int SubstituteBranchTargetField(Instruction* instr, const char* format);
|
||||||
int SubstituteLSRegOffsetField(Instruction* instr, const char* format);
|
int SubstituteLSRegOffsetField(Instruction* instr, const char* format);
|
||||||
int SubstitutePrefetchField(Instruction* instr, const char* format);
|
int SubstitutePrefetchField(Instruction* instr, const char* format);
|
||||||
|
int SubstituteBarrierField(Instruction* instr, const char* format);
|
||||||
|
|
||||||
inline bool RdIsZROrSP(Instruction* instr) const {
|
inline bool RdIsZROrSP(Instruction* instr) const {
|
||||||
return (instr->Rd() == kZeroRegCode);
|
return (instr->Rd() == kZeroRegCode);
|
||||||
|
|||||||
@@ -33,20 +33,20 @@ namespace vixl {
|
|||||||
static uint64_t RotateRight(uint64_t value,
|
static uint64_t RotateRight(uint64_t value,
|
||||||
unsigned int rotate,
|
unsigned int rotate,
|
||||||
unsigned int width) {
|
unsigned int width) {
|
||||||
ASSERT(width <= 64);
|
VIXL_ASSERT(width <= 64);
|
||||||
rotate &= 63;
|
rotate &= 63;
|
||||||
return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) |
|
return ((value & ((UINT64_C(1) << rotate) - 1)) <<
|
||||||
(value >> rotate);
|
(width - rotate)) | (value >> rotate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
|
static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
|
||||||
uint64_t value,
|
uint64_t value,
|
||||||
unsigned width) {
|
unsigned width) {
|
||||||
ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
|
VIXL_ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
|
||||||
(width == 32));
|
(width == 32));
|
||||||
ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
|
VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
|
||||||
uint64_t result = value & ((1UL << width) - 1UL);
|
uint64_t result = value & ((UINT64_C(1) << width) - 1);
|
||||||
for (unsigned i = width; i < reg_size; i *= 2) {
|
for (unsigned i = width; i < reg_size; i *= 2) {
|
||||||
result |= (result << i);
|
result |= (result << i);
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ uint64_t Instruction::ImmLogical() {
|
|||||||
if (imm_s == 0x3F) {
|
if (imm_s == 0x3F) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint64_t bits = (1UL << (imm_s + 1)) - 1;
|
uint64_t bits = (UINT64_C(1) << (imm_s + 1)) - 1;
|
||||||
return RotateRight(bits, imm_r, 64);
|
return RotateRight(bits, imm_r, 64);
|
||||||
} else {
|
} else {
|
||||||
if ((imm_s >> 1) == 0x1F) {
|
if ((imm_s >> 1) == 0x1F) {
|
||||||
@@ -96,14 +96,14 @@ uint64_t Instruction::ImmLogical() {
|
|||||||
if ((imm_s & mask) == mask) {
|
if ((imm_s & mask) == mask) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1;
|
uint64_t bits = (UINT64_C(1) << ((imm_s & mask) + 1)) - 1;
|
||||||
return RepeatBitsAcrossReg(reg_size,
|
return RepeatBitsAcrossReg(reg_size,
|
||||||
RotateRight(bits, imm_r & mask, width),
|
RotateRight(bits, imm_r & mask, width),
|
||||||
width);
|
width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
VIXL_UNREACHABLE();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ Instruction* Instruction::ImmPCOffsetTarget() {
|
|||||||
offset = ImmPCRel();
|
offset = ImmPCRel();
|
||||||
} else {
|
} else {
|
||||||
// All PC-relative branches.
|
// All PC-relative branches.
|
||||||
ASSERT(BranchType() != UnknownBranchType);
|
VIXL_ASSERT(BranchType() != UnknownBranchType);
|
||||||
// Relative branch offsets are instruction-size-aligned.
|
// Relative branch offsets are instruction-size-aligned.
|
||||||
offset = ImmBranch() << kInstructionSizeLog2;
|
offset = ImmBranch() << kInstructionSizeLog2;
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ inline int Instruction::ImmBranch() const {
|
|||||||
case UncondBranchType: return ImmUncondBranch();
|
case UncondBranchType: return ImmUncondBranch();
|
||||||
case CompareBranchType: return ImmCmpBranch();
|
case CompareBranchType: return ImmCmpBranch();
|
||||||
case TestBranchType: return ImmTestBranch();
|
case TestBranchType: return ImmTestBranch();
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ void Instruction::SetImmPCOffsetTarget(Instruction* target) {
|
|||||||
|
|
||||||
void Instruction::SetPCRelImmTarget(Instruction* target) {
|
void Instruction::SetPCRelImmTarget(Instruction* target) {
|
||||||
// ADRP is not supported, so 'this' must point to an ADR instruction.
|
// ADRP is not supported, so 'this' must point to an ADR instruction.
|
||||||
ASSERT(Mask(PCRelAddressingMask) == ADR);
|
VIXL_ASSERT(Mask(PCRelAddressingMask) == ADR);
|
||||||
|
|
||||||
Instr imm = Assembler::ImmPCRelAddress(target - this);
|
Instr imm = Assembler::ImmPCRelAddress(target - this);
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ void Instruction::SetPCRelImmTarget(Instruction* target) {
|
|||||||
|
|
||||||
|
|
||||||
void Instruction::SetBranchImmTarget(Instruction* target) {
|
void Instruction::SetBranchImmTarget(Instruction* target) {
|
||||||
ASSERT(((target - this) & 3) == 0);
|
VIXL_ASSERT(((target - this) & 3) == 0);
|
||||||
Instr branch_imm = 0;
|
Instr branch_imm = 0;
|
||||||
uint32_t imm_mask = 0;
|
uint32_t imm_mask = 0;
|
||||||
int offset = (target - this) >> kInstructionSizeLog2;
|
int offset = (target - this) >> kInstructionSizeLog2;
|
||||||
@@ -220,14 +220,14 @@ void Instruction::SetBranchImmTarget(Instruction* target) {
|
|||||||
imm_mask = ImmTestBranch_mask;
|
imm_mask = ImmTestBranch_mask;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: UNREACHABLE();
|
default: VIXL_UNREACHABLE();
|
||||||
}
|
}
|
||||||
SetInstructionBits(Mask(~imm_mask) | branch_imm);
|
SetInstructionBits(Mask(~imm_mask) | branch_imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Instruction::SetImmLLiteral(Instruction* source) {
|
void Instruction::SetImmLLiteral(Instruction* source) {
|
||||||
ASSERT(((source - this) & 3) == 0);
|
VIXL_ASSERT(((source - this) & 3) == 0);
|
||||||
int offset = (source - this) >> kLiteralEntrySizeLog2;
|
int offset = (source - this) >> kLiteralEntrySizeLog2;
|
||||||
Instr imm = Assembler::ImmLLiteral(offset);
|
Instr imm = Assembler::ImmLLiteral(offset);
|
||||||
Instr mask = ImmLLiteral_mask;
|
Instr mask = ImmLLiteral_mask;
|
||||||
|
|||||||
@@ -44,30 +44,36 @@ const unsigned kMaxLoadLiteralRange = 1 * MBytes;
|
|||||||
const unsigned kWRegSize = 32;
|
const unsigned kWRegSize = 32;
|
||||||
const unsigned kWRegSizeLog2 = 5;
|
const unsigned kWRegSizeLog2 = 5;
|
||||||
const unsigned kWRegSizeInBytes = kWRegSize / 8;
|
const unsigned kWRegSizeInBytes = kWRegSize / 8;
|
||||||
|
const unsigned kWRegSizeInBytesLog2 = kWRegSizeLog2 - 3;
|
||||||
const unsigned kXRegSize = 64;
|
const unsigned kXRegSize = 64;
|
||||||
const unsigned kXRegSizeLog2 = 6;
|
const unsigned kXRegSizeLog2 = 6;
|
||||||
const unsigned kXRegSizeInBytes = kXRegSize / 8;
|
const unsigned kXRegSizeInBytes = kXRegSize / 8;
|
||||||
|
const unsigned kXRegSizeInBytesLog2 = kXRegSizeLog2 - 3;
|
||||||
const unsigned kSRegSize = 32;
|
const unsigned kSRegSize = 32;
|
||||||
const unsigned kSRegSizeLog2 = 5;
|
const unsigned kSRegSizeLog2 = 5;
|
||||||
const unsigned kSRegSizeInBytes = kSRegSize / 8;
|
const unsigned kSRegSizeInBytes = kSRegSize / 8;
|
||||||
|
const unsigned kSRegSizeInBytesLog2 = kSRegSizeLog2 - 3;
|
||||||
const unsigned kDRegSize = 64;
|
const unsigned kDRegSize = 64;
|
||||||
const unsigned kDRegSizeLog2 = 6;
|
const unsigned kDRegSizeLog2 = 6;
|
||||||
const unsigned kDRegSizeInBytes = kDRegSize / 8;
|
const unsigned kDRegSizeInBytes = kDRegSize / 8;
|
||||||
const int64_t kWRegMask = 0x00000000ffffffffLL;
|
const unsigned kDRegSizeInBytesLog2 = kDRegSizeLog2 - 3;
|
||||||
const int64_t kXRegMask = 0xffffffffffffffffLL;
|
const uint64_t kWRegMask = UINT64_C(0xffffffff);
|
||||||
const int64_t kSRegMask = 0x00000000ffffffffLL;
|
const uint64_t kXRegMask = UINT64_C(0xffffffffffffffff);
|
||||||
const int64_t kDRegMask = 0xffffffffffffffffLL;
|
const uint64_t kSRegMask = UINT64_C(0xffffffff);
|
||||||
const int64_t kXSignMask = 0x1LL << 63;
|
const uint64_t kDRegMask = UINT64_C(0xffffffffffffffff);
|
||||||
const int64_t kWSignMask = 0x1LL << 31;
|
const uint64_t kSSignMask = UINT64_C(0x80000000);
|
||||||
const int64_t kByteMask = 0xffL;
|
const uint64_t kDSignMask = UINT64_C(0x8000000000000000);
|
||||||
const int64_t kHalfWordMask = 0xffffL;
|
const uint64_t kWSignMask = UINT64_C(0x80000000);
|
||||||
const int64_t kWordMask = 0xffffffffLL;
|
const uint64_t kXSignMask = UINT64_C(0x8000000000000000);
|
||||||
const uint64_t kXMaxUInt = 0xffffffffffffffffULL;
|
const uint64_t kByteMask = UINT64_C(0xff);
|
||||||
const uint64_t kWMaxUInt = 0xffffffffULL;
|
const uint64_t kHalfWordMask = UINT64_C(0xffff);
|
||||||
const int64_t kXMaxInt = 0x7fffffffffffffffLL;
|
const uint64_t kWordMask = UINT64_C(0xffffffff);
|
||||||
const int64_t kXMinInt = 0x8000000000000000LL;
|
const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff);
|
||||||
const int32_t kWMaxInt = 0x7fffffff;
|
const uint64_t kWMaxUInt = UINT64_C(0xffffffff);
|
||||||
const int32_t kWMinInt = 0x80000000;
|
const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff);
|
||||||
|
const int64_t kXMinInt = INT64_C(0x8000000000000000);
|
||||||
|
const int32_t kWMaxInt = INT32_C(0x7fffffff);
|
||||||
|
const int32_t kWMinInt = INT32_C(0x80000000);
|
||||||
const unsigned kLinkRegCode = 30;
|
const unsigned kLinkRegCode = 30;
|
||||||
const unsigned kZeroRegCode = 31;
|
const unsigned kZeroRegCode = 31;
|
||||||
const unsigned kSPRegInternalCode = 63;
|
const unsigned kSPRegInternalCode = 63;
|
||||||
@@ -81,18 +87,28 @@ const unsigned kFloatExponentBits = 8;
|
|||||||
|
|
||||||
const float kFP32PositiveInfinity = rawbits_to_float(0x7f800000);
|
const float kFP32PositiveInfinity = rawbits_to_float(0x7f800000);
|
||||||
const float kFP32NegativeInfinity = rawbits_to_float(0xff800000);
|
const float kFP32NegativeInfinity = rawbits_to_float(0xff800000);
|
||||||
const double kFP64PositiveInfinity = rawbits_to_double(0x7ff0000000000000ULL);
|
const double kFP64PositiveInfinity =
|
||||||
const double kFP64NegativeInfinity = rawbits_to_double(0xfff0000000000000ULL);
|
rawbits_to_double(UINT64_C(0x7ff0000000000000));
|
||||||
|
const double kFP64NegativeInfinity =
|
||||||
|
rawbits_to_double(UINT64_C(0xfff0000000000000));
|
||||||
|
|
||||||
// This value is a signalling NaN as both a double and as a float (taking the
|
// This value is a signalling NaN as both a double and as a float (taking the
|
||||||
// least-significant word).
|
// least-significant word).
|
||||||
static const double kFP64SignallingNaN = rawbits_to_double(0x7ff000007f800001ULL);
|
static const double kFP64SignallingNaN =
|
||||||
|
rawbits_to_double(UINT64_C(0x7ff000007f800001));
|
||||||
static const float kFP32SignallingNaN = rawbits_to_float(0x7f800001);
|
static const float kFP32SignallingNaN = rawbits_to_float(0x7f800001);
|
||||||
|
|
||||||
// A similar value, but as a quiet NaN.
|
// A similar value, but as a quiet NaN.
|
||||||
static const double kFP64QuietNaN = rawbits_to_double(0x7ff800007fc00001ULL);
|
static const double kFP64QuietNaN =
|
||||||
|
rawbits_to_double(UINT64_C(0x7ff800007fc00001));
|
||||||
static const float kFP32QuietNaN = rawbits_to_float(0x7fc00001);
|
static const float kFP32QuietNaN = rawbits_to_float(0x7fc00001);
|
||||||
|
|
||||||
|
// The default NaN values (for FPCR.DN=1).
|
||||||
|
static const double kFP64DefaultNaN =
|
||||||
|
rawbits_to_double(UINT64_C(0x7ff8000000000000));
|
||||||
|
static const float kFP32DefaultNaN = rawbits_to_float(0x7fc00000);
|
||||||
|
|
||||||
|
|
||||||
enum LSDataSize {
|
enum LSDataSize {
|
||||||
LSByte = 0,
|
LSByte = 0,
|
||||||
LSHalfword = 1,
|
LSHalfword = 1,
|
||||||
@@ -325,7 +341,7 @@ class Instruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline Instruction* InstructionAtOffset(int64_t offset) {
|
inline Instruction* InstructionAtOffset(int64_t offset) {
|
||||||
ASSERT(IsWordAligned(this + offset));
|
VIXL_ASSERT(IsWordAligned(this + offset));
|
||||||
return this + offset;
|
return this + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,20 @@
|
|||||||
#ifndef VIXL_GLOBALS_H
|
#ifndef VIXL_GLOBALS_H
|
||||||
#define VIXL_GLOBALS_H
|
#define VIXL_GLOBALS_H
|
||||||
|
|
||||||
// Get the standard printf format macros for C99 stdint types.
|
// Get standard C99 macros for integer types.
|
||||||
|
#ifndef __STDC_CONSTANT_MACROS
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __STDC_LIMIT_MACROS
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __STDC_FORMAT_MACROS
|
||||||
#define __STDC_FORMAT_MACROS
|
#define __STDC_FORMAT_MACROS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -45,21 +57,29 @@ typedef uint8_t byte;
|
|||||||
const int KBytes = 1024;
|
const int KBytes = 1024;
|
||||||
const int MBytes = 1024 * KBytes;
|
const int MBytes = 1024 * KBytes;
|
||||||
|
|
||||||
#define ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort()
|
#define VIXL_ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort()
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define ASSERT(condition) assert(condition)
|
#define VIXL_ASSERT(condition) assert(condition)
|
||||||
#define CHECK(condition) ASSERT(condition)
|
#define VIXL_CHECK(condition) VIXL_ASSERT(condition)
|
||||||
#define UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); ABORT()
|
#define VIXL_UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); VIXL_ABORT()
|
||||||
#define UNREACHABLE() printf("UNREACHABLE\t"); ABORT()
|
#define VIXL_UNREACHABLE() printf("UNREACHABLE\t"); VIXL_ABORT()
|
||||||
#else
|
#else
|
||||||
#define ASSERT(condition) ((void) 0)
|
#define VIXL_ASSERT(condition) ((void) 0)
|
||||||
#define CHECK(condition) assert(condition)
|
#define VIXL_CHECK(condition) assert(condition)
|
||||||
#define UNIMPLEMENTED() ((void) 0)
|
#define VIXL_UNIMPLEMENTED() ((void) 0)
|
||||||
#define UNREACHABLE() ((void) 0)
|
#define VIXL_UNREACHABLE() ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
|
// This is not as powerful as template based assertions, but it is simple.
|
||||||
|
// It assumes that the descriptions are unique. If this starts being a problem,
|
||||||
|
// we can switch to a different implemention.
|
||||||
|
#define VIXL_CONCAT(a, b) a##b
|
||||||
|
#define VIXL_STATIC_ASSERT_LINE(line, condition) \
|
||||||
|
typedef char VIXL_CONCAT(STATIC_ASSERT_LINE_, line)[(condition) ? 1 : -1] \
|
||||||
|
__attribute__((unused))
|
||||||
|
#define VIXL_STATIC_ASSERT(condition) VIXL_STATIC_ASSERT_LINE(__LINE__, condition) //NOLINT
|
||||||
|
|
||||||
template <typename T> inline void USE(T) {}
|
template <typename T> inline void USE(T) {}
|
||||||
|
|
||||||
#define ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); ABORT()
|
#define VIXL_ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); VIXL_ABORT()
|
||||||
|
|
||||||
#endif // VIXL_GLOBALS_H
|
#endif // VIXL_GLOBALS_H
|
||||||
|
|||||||
@@ -34,9 +34,7 @@ namespace vixl {
|
|||||||
// Currently we assume running the simulator implies running on x86 hardware.
|
// Currently we assume running the simulator implies running on x86 hardware.
|
||||||
inline void HostBreakpoint() { asm("int3"); }
|
inline void HostBreakpoint() { asm("int3"); }
|
||||||
#else
|
#else
|
||||||
inline void HostBreakpoint() {
|
inline void HostBreakpoint() { asm("brk"); }
|
||||||
// TODO: Implement HostBreakpoint on a64.
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
} // namespace vixl
|
} // namespace vixl
|
||||||
|
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ double rawbits_to_double(uint64_t bits) {
|
|||||||
|
|
||||||
|
|
||||||
int CountLeadingZeros(uint64_t value, int width) {
|
int CountLeadingZeros(uint64_t value, int width) {
|
||||||
ASSERT((width == 32) || (width == 64));
|
VIXL_ASSERT((width == 32) || (width == 64));
|
||||||
int count = 0;
|
int count = 0;
|
||||||
uint64_t bit_test = 1UL << (width - 1);
|
uint64_t bit_test = UINT64_C(1) << (width - 1);
|
||||||
while ((count < width) && ((bit_test & value) == 0)) {
|
while ((count < width) && ((bit_test & value) == 0)) {
|
||||||
count++;
|
count++;
|
||||||
bit_test >>= 1;
|
bit_test >>= 1;
|
||||||
@@ -70,7 +70,7 @@ int CountLeadingZeros(uint64_t value, int width) {
|
|||||||
|
|
||||||
|
|
||||||
int CountLeadingSignBits(int64_t value, int width) {
|
int CountLeadingSignBits(int64_t value, int width) {
|
||||||
ASSERT((width == 32) || (width == 64));
|
VIXL_ASSERT((width == 32) || (width == 64));
|
||||||
if (value >= 0) {
|
if (value >= 0) {
|
||||||
return CountLeadingZeros(value, width) - 1;
|
return CountLeadingZeros(value, width) - 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -80,7 +80,7 @@ int CountLeadingSignBits(int64_t value, int width) {
|
|||||||
|
|
||||||
|
|
||||||
int CountTrailingZeros(uint64_t value, int width) {
|
int CountTrailingZeros(uint64_t value, int width) {
|
||||||
ASSERT((width == 32) || (width == 64));
|
VIXL_ASSERT((width == 32) || (width == 64));
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while ((count < width) && (((value >> count) & 1) == 0)) {
|
while ((count < width) && (((value >> count) & 1) == 0)) {
|
||||||
count++;
|
count++;
|
||||||
@@ -92,10 +92,10 @@ int CountTrailingZeros(uint64_t value, int width) {
|
|||||||
int CountSetBits(uint64_t value, int width) {
|
int CountSetBits(uint64_t value, int width) {
|
||||||
// TODO: Other widths could be added here, as the implementation already
|
// TODO: Other widths could be added here, as the implementation already
|
||||||
// supports them.
|
// supports them.
|
||||||
ASSERT((width == 32) || (width == 64));
|
VIXL_ASSERT((width == 32) || (width == 64));
|
||||||
|
|
||||||
// Mask out unused bits to ensure that they are not counted.
|
// Mask out unused bits to ensure that they are not counted.
|
||||||
value &= (0xffffffffffffffffULL >> (64-width));
|
value &= (UINT64_C(0xffffffffffffffff) >> (64-width));
|
||||||
|
|
||||||
// Add up the set bits.
|
// Add up the set bits.
|
||||||
// The algorithm works by adding pairs of bit fields together iteratively,
|
// The algorithm works by adding pairs of bit fields together iteratively,
|
||||||
@@ -108,18 +108,19 @@ int CountSetBits(uint64_t value, int width) {
|
|||||||
// value = h+g+f+e d+c+b+a
|
// value = h+g+f+e d+c+b+a
|
||||||
// \ |
|
// \ |
|
||||||
// value = h+g+f+e+d+c+b+a
|
// value = h+g+f+e+d+c+b+a
|
||||||
value = ((value >> 1) & 0x5555555555555555ULL) +
|
const uint64_t kMasks[] = {
|
||||||
(value & 0x5555555555555555ULL);
|
UINT64_C(0x5555555555555555),
|
||||||
value = ((value >> 2) & 0x3333333333333333ULL) +
|
UINT64_C(0x3333333333333333),
|
||||||
(value & 0x3333333333333333ULL);
|
UINT64_C(0x0f0f0f0f0f0f0f0f),
|
||||||
value = ((value >> 4) & 0x0f0f0f0f0f0f0f0fULL) +
|
UINT64_C(0x00ff00ff00ff00ff),
|
||||||
(value & 0x0f0f0f0f0f0f0f0fULL);
|
UINT64_C(0x0000ffff0000ffff),
|
||||||
value = ((value >> 8) & 0x00ff00ff00ff00ffULL) +
|
UINT64_C(0x00000000ffffffff),
|
||||||
(value & 0x00ff00ff00ff00ffULL);
|
};
|
||||||
value = ((value >> 16) & 0x0000ffff0000ffffULL) +
|
|
||||||
(value & 0x0000ffff0000ffffULL);
|
for (unsigned i = 0; i < (sizeof(kMasks) / sizeof(kMasks[0])); i++) {
|
||||||
value = ((value >> 32) & 0x00000000ffffffffULL) +
|
int shift = 1 << i;
|
||||||
(value & 0x00000000ffffffffULL);
|
value = ((value >> shift) & kMasks[i]) + (value & kMasks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#ifndef VIXL_UTILS_H
|
#ifndef VIXL_UTILS_H
|
||||||
#define VIXL_UTILS_H
|
#define VIXL_UTILS_H
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
@@ -35,19 +35,19 @@ namespace vixl {
|
|||||||
|
|
||||||
// Check number width.
|
// Check number width.
|
||||||
inline bool is_intn(unsigned n, int64_t x) {
|
inline bool is_intn(unsigned n, int64_t x) {
|
||||||
ASSERT((0 < n) && (n < 64));
|
VIXL_ASSERT((0 < n) && (n < 64));
|
||||||
int64_t limit = 1ULL << (n - 1);
|
int64_t limit = INT64_C(1) << (n - 1);
|
||||||
return (-limit <= x) && (x < limit);
|
return (-limit <= x) && (x < limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_uintn(unsigned n, int64_t x) {
|
inline bool is_uintn(unsigned n, int64_t x) {
|
||||||
ASSERT((0 < n) && (n < 64));
|
VIXL_ASSERT((0 < n) && (n < 64));
|
||||||
return !(x >> n);
|
return !(x >> n);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned truncate_to_intn(unsigned n, int64_t x) {
|
inline unsigned truncate_to_intn(unsigned n, int64_t x) {
|
||||||
ASSERT((0 < n) && (n < 64));
|
VIXL_ASSERT((0 < n) && (n < 64));
|
||||||
return (x & ((1ULL << n) - 1));
|
return (x & ((INT64_C(1) << n) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INT_1_TO_63_LIST(V) \
|
#define INT_1_TO_63_LIST(V) \
|
||||||
@@ -90,13 +90,67 @@ inline int64_t signed_bitextract_64(int msb, int lsb, int64_t x) {
|
|||||||
return (x << (63 - msb)) >> (lsb + 63 - msb);
|
return (x << (63 - msb)) >> (lsb + 63 - msb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// floating point representation
|
// Floating point representation.
|
||||||
uint32_t float_to_rawbits(float value);
|
uint32_t float_to_rawbits(float value);
|
||||||
uint64_t double_to_rawbits(double value);
|
uint64_t double_to_rawbits(double value);
|
||||||
float rawbits_to_float(uint32_t bits);
|
float rawbits_to_float(uint32_t bits);
|
||||||
double rawbits_to_double(uint64_t bits);
|
double rawbits_to_double(uint64_t bits);
|
||||||
|
|
||||||
// Bits counting.
|
|
||||||
|
// NaN tests.
|
||||||
|
inline bool IsSignallingNaN(double num) {
|
||||||
|
const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000);
|
||||||
|
uint64_t raw = double_to_rawbits(num);
|
||||||
|
if (isnan(num) && ((raw & kFP64QuietNaNMask) == 0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool IsSignallingNaN(float num) {
|
||||||
|
const uint32_t kFP32QuietNaNMask = 0x00400000;
|
||||||
|
uint32_t raw = float_to_rawbits(num);
|
||||||
|
if (isnan(num) && ((raw & kFP32QuietNaNMask) == 0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool IsQuietNaN(T num) {
|
||||||
|
return isnan(num) && !IsSignallingNaN(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Convert the NaN in 'num' to a quiet NaN.
|
||||||
|
inline double ToQuietNaN(double num) {
|
||||||
|
const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000);
|
||||||
|
VIXL_ASSERT(isnan(num));
|
||||||
|
return rawbits_to_double(double_to_rawbits(num) | kFP64QuietNaNMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline float ToQuietNaN(float num) {
|
||||||
|
const uint32_t kFP32QuietNaNMask = 0x00400000;
|
||||||
|
VIXL_ASSERT(isnan(num));
|
||||||
|
return rawbits_to_float(float_to_rawbits(num) | kFP32QuietNaNMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fused multiply-add.
|
||||||
|
inline double FusedMultiplyAdd(double op1, double op2, double a) {
|
||||||
|
return fma(op1, op2, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline float FusedMultiplyAdd(float op1, float op2, float a) {
|
||||||
|
return fmaf(op1, op2, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Bit counting.
|
||||||
int CountLeadingZeros(uint64_t value, int width);
|
int CountLeadingZeros(uint64_t value, int width);
|
||||||
int CountLeadingSignBits(int64_t value, int width);
|
int CountLeadingSignBits(int64_t value, int width);
|
||||||
int CountTrailingZeros(uint64_t value, int width);
|
int CountTrailingZeros(uint64_t value, int width);
|
||||||
@@ -106,20 +160,30 @@ int CountSetBits(uint64_t value, int width);
|
|||||||
// TODO: rename/refactor to make it specific to instructions.
|
// TODO: rename/refactor to make it specific to instructions.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool IsWordAligned(T pointer) {
|
bool IsWordAligned(T pointer) {
|
||||||
ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof)
|
VIXL_ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof)
|
||||||
return (reinterpret_cast<intptr_t>(pointer) & 3) == 0;
|
return (reinterpret_cast<intptr_t>(pointer) & 3) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increment a pointer until it has the specified alignment.
|
// Increment a pointer until it has the specified alignment.
|
||||||
template<class T>
|
template<class T>
|
||||||
T AlignUp(T pointer, size_t alignment) {
|
T AlignUp(T pointer, size_t alignment) {
|
||||||
ASSERT(sizeof(pointer) == sizeof(uintptr_t));
|
VIXL_STATIC_ASSERT(sizeof(pointer) == sizeof(uintptr_t));
|
||||||
uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer);
|
uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer);
|
||||||
size_t align_step = (alignment - pointer_raw) % alignment;
|
size_t align_step = (alignment - pointer_raw) % alignment;
|
||||||
ASSERT((pointer_raw + align_step) % alignment == 0);
|
VIXL_ASSERT((pointer_raw + align_step) % alignment == 0);
|
||||||
return reinterpret_cast<T>(pointer_raw + align_step);
|
return reinterpret_cast<T>(pointer_raw + align_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decrement a pointer until it has the specified alignment.
|
||||||
|
template<class T>
|
||||||
|
T AlignDown(T pointer, size_t alignment) {
|
||||||
|
VIXL_STATIC_ASSERT(sizeof(pointer) == sizeof(uintptr_t));
|
||||||
|
uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer);
|
||||||
|
size_t align_step = pointer_raw % alignment;
|
||||||
|
VIXL_ASSERT((pointer_raw - align_step) % alignment == 0);
|
||||||
|
return reinterpret_cast<T>(pointer_raw - align_step);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace vixl
|
} // namespace vixl
|
||||||
|
|
||||||
|
|||||||
@@ -143,12 +143,12 @@ static void dma_bdrv_cb(void *opaque, int ret)
|
|||||||
|
|
||||||
dbs->acb = NULL;
|
dbs->acb = NULL;
|
||||||
dbs->sector_num += dbs->iov.size / 512;
|
dbs->sector_num += dbs->iov.size / 512;
|
||||||
dma_bdrv_unmap(dbs);
|
|
||||||
|
|
||||||
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
|
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
|
||||||
dma_complete(dbs, ret);
|
dma_complete(dbs, ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
dma_bdrv_unmap(dbs);
|
||||||
|
|
||||||
while (dbs->sg_cur_index < dbs->sg->nsg) {
|
while (dbs->sg_cur_index < dbs->sg->nsg) {
|
||||||
cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
|
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>
|
||||||
@@ -48,7 +48,7 @@ The QAPI schema definitions can be modularized using the 'include' directive:
|
|||||||
{ 'include': 'path/to/file.json'}
|
{ 'include': 'path/to/file.json'}
|
||||||
|
|
||||||
The directive is evaluated recursively, and include paths are relative to the
|
The directive is evaluated recursively, and include paths are relative to the
|
||||||
file using the directive.
|
file using the directive. Multiple includes of the same file are safe.
|
||||||
|
|
||||||
|
|
||||||
=== Complex types ===
|
=== Complex types ===
|
||||||
@@ -230,14 +230,13 @@ node structure that can be used to chain together a list of such types in
|
|||||||
case we want to accept/return a list of this type with a command), and a
|
case we want to accept/return a list of this type with a command), and a
|
||||||
command which takes that type as a parameter and returns the same type:
|
command which takes that type as a parameter and returns the same type:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat example-schema.json
|
$ cat example-schema.json
|
||||||
{ 'type': 'UserDefOne',
|
{ 'type': 'UserDefOne',
|
||||||
'data': { 'integer': 'int', 'string': 'str' } }
|
'data': { 'integer': 'int', 'string': 'str' } }
|
||||||
|
|
||||||
{ 'command': 'my-command',
|
{ 'command': 'my-command',
|
||||||
'data': {'arg1': 'UserDefOne'},
|
'data': {'arg1': 'UserDefOne'},
|
||||||
'returns': 'UserDefOne' }
|
'returns': 'UserDefOne' }
|
||||||
mdroth@illuin:~/w/qemu2.git$
|
|
||||||
|
|
||||||
=== scripts/qapi-types.py ===
|
=== scripts/qapi-types.py ===
|
||||||
|
|
||||||
@@ -255,14 +254,25 @@ created code.
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
|
$ python scripts/qapi-types.py --output-dir="qapi-generated" \
|
||||||
--output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json
|
--prefix="example-" --input-file=example-schema.json
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
|
$ cat qapi-generated/example-qapi-types.c
|
||||||
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#include "qapi/qapi-dealloc-visitor.h"
|
void qapi_free_UserDefOneList(UserDefOneList * obj)
|
||||||
#include "example-qapi-types.h"
|
{
|
||||||
#include "example-qapi-visit.h"
|
QapiDeallocVisitor *md;
|
||||||
|
Visitor *v;
|
||||||
|
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
md = qapi_dealloc_visitor_new();
|
||||||
|
v = qapi_dealloc_get_visitor(md);
|
||||||
|
visit_type_UserDefOneList(v, &obj, NULL, NULL);
|
||||||
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
|
}
|
||||||
|
|
||||||
void qapi_free_UserDefOne(UserDefOne * obj)
|
void qapi_free_UserDefOne(UserDefOne * obj)
|
||||||
{
|
{
|
||||||
@@ -279,32 +289,38 @@ Example:
|
|||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
|
$ cat qapi-generated/example-qapi-types.h
|
||||||
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
|
|
||||||
#define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
|
|
||||||
|
|
||||||
#include "qapi/qapi-types-core.h"
|
#ifndef EXAMPLE_QAPI_TYPES_H
|
||||||
|
#define EXAMPLE_QAPI_TYPES_H
|
||||||
|
|
||||||
|
[Builtin types omitted...]
|
||||||
|
|
||||||
typedef struct UserDefOne UserDefOne;
|
typedef struct UserDefOne UserDefOne;
|
||||||
|
|
||||||
typedef struct UserDefOneList
|
typedef struct UserDefOneList
|
||||||
{
|
{
|
||||||
|
union {
|
||||||
UserDefOne *value;
|
UserDefOne *value;
|
||||||
|
uint64_t padding;
|
||||||
|
};
|
||||||
struct UserDefOneList *next;
|
struct UserDefOneList *next;
|
||||||
} UserDefOneList;
|
} UserDefOneList;
|
||||||
|
|
||||||
|
[Functions on builtin types omitted...]
|
||||||
|
|
||||||
struct UserDefOne
|
struct UserDefOne
|
||||||
{
|
{
|
||||||
int64_t integer;
|
int64_t integer;
|
||||||
char * string;
|
char * string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void qapi_free_UserDefOneList(UserDefOneList * obj);
|
||||||
void qapi_free_UserDefOne(UserDefOne * obj);
|
void qapi_free_UserDefOne(UserDefOne * obj);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
=== scripts/qapi-visit.py ===
|
=== scripts/qapi-visit.py ===
|
||||||
|
|
||||||
Used to generate the visitor functions used to walk through and convert
|
Used to generate the visitor functions used to walk through and convert
|
||||||
@@ -325,51 +341,78 @@ $(prefix)qapi-visit.h: declarations for previously mentioned visitor
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
|
$ python scripts/qapi-visit.py --output-dir="qapi-generated"
|
||||||
--output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json
|
--prefix="example-" --input-file=example-schema.json
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
|
$ cat qapi-generated/example-qapi-visit.c
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#include "example-qapi-visit.h"
|
static void visit_type_UserDefOne_fields(Visitor *m, UserDefOne ** obj, Error **errp)
|
||||||
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
visit_type_int(m, &(*obj)->integer, "integer", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
visit_type_str(m, &(*obj)->string, "string", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
}
|
||||||
|
|
||||||
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
|
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
|
Error *err = NULL;
|
||||||
visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
|
|
||||||
visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
|
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), &err);
|
||||||
visit_end_struct(m, errp);
|
if (!err) {
|
||||||
|
if (*obj) {
|
||||||
|
visit_type_UserDefOne_fields(m, obj, errp);
|
||||||
|
}
|
||||||
|
visit_end_struct(m, &err);
|
||||||
|
}
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
|
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
GenericList *i, **prev = (GenericList **)obj;
|
Error *err = NULL;
|
||||||
|
GenericList *i, **prev;
|
||||||
|
|
||||||
visit_start_list(m, name, errp);
|
visit_start_list(m, name, &err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
|
for (prev = (GenericList **)obj;
|
||||||
|
!err && (i = visit_next_list(m, prev, &err)) != NULL;
|
||||||
|
prev = &i) {
|
||||||
UserDefOneList *native_i = (UserDefOneList *)i;
|
UserDefOneList *native_i = (UserDefOneList *)i;
|
||||||
visit_type_UserDefOne(m, &native_i->value, NULL, errp);
|
visit_type_UserDefOne(m, &native_i->value, NULL, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
visit_end_list(m, errp);
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
visit_end_list(m, &err);
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
|
$ python scripts/qapi-commands.py --output-dir="qapi-generated" \
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
--prefix="example-" --input-file=example-schema.json
|
||||||
|
$ cat qapi-generated/example-qapi-visit.h
|
||||||
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
|
#ifndef EXAMPLE_QAPI_VISIT_H
|
||||||
#define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
|
#define EXAMPLE_QAPI_VISIT_H
|
||||||
|
|
||||||
#include "qapi/qapi-visit-core.h"
|
[Visitors for builtin types omitted...]
|
||||||
#include "example-qapi-types.h"
|
|
||||||
|
|
||||||
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
|
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
|
||||||
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
|
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
mdroth@illuin:~/w/qemu2.git$
|
|
||||||
|
|
||||||
(The actual structure of the visit_type_* functions is a bit more complex
|
|
||||||
in order to propagate errors correctly and avoid leaking memory).
|
|
||||||
|
|
||||||
=== scripts/qapi-commands.py ===
|
=== scripts/qapi-commands.py ===
|
||||||
|
|
||||||
@@ -390,77 +433,80 @@ $(prefix)qmp-commands.h: Function prototypes for the QMP commands
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
|
$ cat qapi-generated/example-qmp-marshal.c
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#include "qemu-objects.h"
|
|
||||||
#include "qapi/qmp-core.h"
|
|
||||||
#include "qapi/qapi-visit-core.h"
|
|
||||||
#include "qapi/qmp-output-visitor.h"
|
|
||||||
#include "qapi/qmp-input-visitor.h"
|
|
||||||
#include "qapi/qapi-dealloc-visitor.h"
|
|
||||||
#include "example-qapi-types.h"
|
|
||||||
#include "example-qapi-visit.h"
|
|
||||||
|
|
||||||
#include "example-qmp-commands.h"
|
|
||||||
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
|
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
|
||||||
{
|
{
|
||||||
QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
|
Error *local_err = NULL;
|
||||||
QmpOutputVisitor *mo = qmp_output_visitor_new();
|
QmpOutputVisitor *mo = qmp_output_visitor_new();
|
||||||
|
QapiDeallocVisitor *md;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
|
||||||
v = qmp_output_get_visitor(mo);
|
v = qmp_output_get_visitor(mo);
|
||||||
visit_type_UserDefOne(v, &ret_in, "unused", errp);
|
visit_type_UserDefOne(v, &ret_in, "unused", &local_err);
|
||||||
v = qapi_dealloc_get_visitor(md);
|
if (local_err) {
|
||||||
visit_type_UserDefOne(v, &ret_in, "unused", errp);
|
goto out;
|
||||||
qapi_dealloc_visitor_cleanup(md);
|
}
|
||||||
|
|
||||||
|
|
||||||
*ret_out = qmp_output_get_qobject(mo);
|
*ret_out = qmp_output_get_qobject(mo);
|
||||||
|
|
||||||
|
out:
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
qmp_output_visitor_cleanup(mo);
|
||||||
|
md = qapi_dealloc_visitor_new();
|
||||||
|
v = qapi_dealloc_get_visitor(md);
|
||||||
|
visit_type_UserDefOne(v, &ret_in, "unused", NULL);
|
||||||
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
|
static void qmp_marshal_input_my_command(QDict *args, QObject **ret, Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
UserDefOne * retval = NULL;
|
UserDefOne * retval = NULL;
|
||||||
QmpInputVisitor *mi;
|
QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
|
||||||
QapiDeallocVisitor *md;
|
QapiDeallocVisitor *md;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
UserDefOne * arg1 = NULL;
|
UserDefOne * arg1 = NULL;
|
||||||
|
|
||||||
mi = qmp_input_visitor_new(QOBJECT(args));
|
|
||||||
v = qmp_input_get_visitor(mi);
|
v = qmp_input_get_visitor(mi);
|
||||||
visit_type_UserDefOne(v, &arg1, "arg1", errp);
|
visit_type_UserDefOne(v, &arg1, "arg1", &local_err);
|
||||||
|
if (local_err) {
|
||||||
if (error_is_set(errp)) {
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
retval = qmp_my_command(arg1, errp);
|
|
||||||
qmp_marshal_output_my_command(retval, ret, errp);
|
retval = qmp_my_command(arg1, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
qmp_marshal_output_my_command(retval, ret, &local_err);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
qmp_input_visitor_cleanup(mi);
|
||||||
md = qapi_dealloc_visitor_new();
|
md = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(md);
|
v = qapi_dealloc_get_visitor(md);
|
||||||
visit_type_UserDefOne(v, &arg1, "arg1", errp);
|
visit_type_UserDefOne(v, &arg1, "arg1", NULL);
|
||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qmp_init_marshal(void)
|
static void qmp_init_marshal(void)
|
||||||
{
|
{
|
||||||
qmp_register_command("my-command", qmp_marshal_input_my_command);
|
qmp_register_command("my-command", qmp_marshal_input_my_command, QCO_NO_OPTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
qapi_init(qmp_init_marshal);
|
qapi_init(qmp_init_marshal);
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
|
$ cat qapi-generated/example-qmp-commands.h
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
|
#ifndef EXAMPLE_QMP_COMMANDS_H
|
||||||
#define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
|
#define EXAMPLE_QMP_COMMANDS_H
|
||||||
|
|
||||||
#include "example-qapi-types.h"
|
#include "example-qapi-types.h"
|
||||||
#include "error.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
|
UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
mdroth@illuin:~/w/qemu2.git$
|
|
||||||
|
|||||||
@@ -107,8 +107,9 @@ in the description of a field.
|
|||||||
|
|
||||||
96 - 99: refcount_order
|
96 - 99: refcount_order
|
||||||
Describes the width of a reference count block entry (width
|
Describes the width of a reference count block entry (width
|
||||||
in bits = 1 << refcount_order). For version 2 images, the
|
in bits: refcount_bits = 1 << refcount_order). For version 2
|
||||||
order is always assumed to be 4 (i.e. the width is 16 bits).
|
images, the order is always assumed to be 4
|
||||||
|
(i.e. refcount_bits = 16).
|
||||||
|
|
||||||
100 - 103: header_length
|
100 - 103: header_length
|
||||||
Length of the header structure in bytes. For version 2
|
Length of the header structure in bytes. For version 2
|
||||||
|
|||||||
1
exec.c
1
exec.c
@@ -429,7 +429,6 @@ const VMStateDescription vmstate_cpu_common = {
|
|||||||
.name = "cpu_common",
|
.name = "cpu_common",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.post_load = cpu_common_post_load,
|
.post_load = cpu_common_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(halted, CPUState),
|
VMSTATE_UINT32(halted, CPUState),
|
||||||
|
|||||||
@@ -556,6 +556,7 @@ ETEXI
|
|||||||
.params = "keys [hold_ms]",
|
.params = "keys [hold_ms]",
|
||||||
.help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
|
.help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
|
||||||
.mhandler.cmd = hmp_send_key,
|
.mhandler.cmd = hmp_send_key,
|
||||||
|
.command_completion = sendkey_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1233,9 +1234,10 @@ ETEXI
|
|||||||
{
|
{
|
||||||
.name = "netdev_add",
|
.name = "netdev_add",
|
||||||
.args_type = "netdev:O",
|
.args_type = "netdev:O",
|
||||||
.params = "[user|tap|socket|hubport|netmap],id=str[,prop=value][,...]",
|
.params = "[user|tap|socket|vde|bridge|hubport|netmap],id=str[,prop=value][,...]",
|
||||||
.help = "add host network device",
|
.help = "add host network device",
|
||||||
.mhandler.cmd = hmp_netdev_add,
|
.mhandler.cmd = hmp_netdev_add,
|
||||||
|
.command_completion = netdev_add_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1250,6 +1252,7 @@ ETEXI
|
|||||||
.params = "id",
|
.params = "id",
|
||||||
.help = "remove host network device",
|
.help = "remove host network device",
|
||||||
.mhandler.cmd = hmp_netdev_del,
|
.mhandler.cmd = hmp_netdev_del,
|
||||||
|
.command_completion = netdev_del_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1339,6 +1342,7 @@ ETEXI
|
|||||||
.params = "name on|off",
|
.params = "name on|off",
|
||||||
.help = "change the link status of a network adapter",
|
.help = "change the link status of a network adapter",
|
||||||
.mhandler.cmd = hmp_set_link,
|
.mhandler.cmd = hmp_set_link,
|
||||||
|
.command_completion = set_link_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1622,6 +1626,7 @@ ETEXI
|
|||||||
.params = "args",
|
.params = "args",
|
||||||
.help = "add chardev",
|
.help = "add chardev",
|
||||||
.mhandler.cmd = hmp_chardev_add,
|
.mhandler.cmd = hmp_chardev_add,
|
||||||
|
.command_completion = chardev_add_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1638,6 +1643,7 @@ ETEXI
|
|||||||
.params = "id",
|
.params = "id",
|
||||||
.help = "remove chardev",
|
.help = "remove chardev",
|
||||||
.mhandler.cmd = hmp_chardev_remove,
|
.mhandler.cmd = hmp_chardev_remove,
|
||||||
|
.command_completion = chardev_remove_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
|
|||||||
21
hmp.c
21
hmp.c
@@ -341,6 +341,11 @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
|
|||||||
info->value->inserted->backing_file_depth);
|
info->value->inserted->backing_file_depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->value->inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) {
|
||||||
|
monitor_printf(mon, " Detect zeroes: %s\n",
|
||||||
|
BlockdevDetectZeroesOptions_lookup[info->value->inserted->detect_zeroes]);
|
||||||
|
}
|
||||||
|
|
||||||
if (info->value->inserted->bps
|
if (info->value->inserted->bps
|
||||||
|| info->value->inserted->bps_rd
|
|| info->value->inserted->bps_rd
|
||||||
|| info->value->inserted->bps_wr
|
|| info->value->inserted->bps_wr
|
||||||
@@ -1388,6 +1393,7 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)
|
|||||||
void hmp_object_add(Monitor *mon, const QDict *qdict)
|
void hmp_object_add(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
Error *err_end = NULL;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
char *type = NULL;
|
char *type = NULL;
|
||||||
char *id = NULL;
|
char *id = NULL;
|
||||||
@@ -1411,24 +1417,23 @@ void hmp_object_add(Monitor *mon, const QDict *qdict)
|
|||||||
qdict_del(pdict, "qom-type");
|
qdict_del(pdict, "qom-type");
|
||||||
visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
|
visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out_clean;
|
goto out_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
qdict_del(pdict, "id");
|
qdict_del(pdict, "id");
|
||||||
visit_type_str(opts_get_visitor(ov), &id, "id", &err);
|
visit_type_str(opts_get_visitor(ov), &id, "id", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out_clean;
|
goto out_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
object_add(type, id, pdict, opts_get_visitor(ov), &err);
|
object_add(type, id, pdict, opts_get_visitor(ov), &err);
|
||||||
if (err) {
|
|
||||||
goto out_clean;
|
out_end:
|
||||||
}
|
visit_end_struct(opts_get_visitor(ov), &err_end);
|
||||||
visit_end_struct(opts_get_visitor(ov), &err);
|
if (!err && err_end) {
|
||||||
if (err) {
|
|
||||||
qmp_object_del(id, NULL);
|
qmp_object_del(id, NULL);
|
||||||
}
|
}
|
||||||
|
error_propagate(&err, err_end);
|
||||||
out_clean:
|
out_clean:
|
||||||
opts_visitor_cleanup(ov);
|
opts_visitor_cleanup(ov);
|
||||||
|
|
||||||
|
|||||||
6
hmp.h
6
hmp.h
@@ -97,5 +97,11 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
|||||||
void object_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
void object_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
void device_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
void device_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
void device_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
void device_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void sendkey_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void set_link_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
|
|||||||
return (slot + 1) * 4 + 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;
|
ram_addr_t ram_size = machine->ram_size;
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
AlphaCPU *cpus[4];
|
AlphaCPU *cpus[4];
|
||||||
PCIBus *pci_bus;
|
PCIBus *pci_bus;
|
||||||
ISABus *isa_bus;
|
ISABus *isa_bus;
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ static struct arm_boot_info collie_binfo = {
|
|||||||
.ram_size = 0x20000000,
|
.ram_size = 0x20000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void collie_init(QEMUMachineInitArgs *args)
|
static void collie_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
StrongARMState *s;
|
StrongARMState *s;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ typedef struct CubieBoardState {
|
|||||||
MemoryRegion sdram;
|
MemoryRegion sdram;
|
||||||
} CubieBoardState;
|
} CubieBoardState;
|
||||||
|
|
||||||
static void cubieboard_init(QEMUMachineInitArgs *args)
|
static void cubieboard_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
CubieBoardState *s = g_new(CubieBoardState, 1);
|
CubieBoardState *s = g_new(CubieBoardState, 1);
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
@@ -63,14 +63,15 @@ static void cubieboard_init(QEMUMachineInitArgs *args)
|
|||||||
exit(1);
|
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);
|
vmstate_register_ram_global(&s->sdram);
|
||||||
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
|
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
|
||||||
&s->sdram);
|
&s->sdram);
|
||||||
|
|
||||||
cubieboard_binfo.ram_size = args->ram_size;
|
cubieboard_binfo.ram_size = machine->ram_size;
|
||||||
cubieboard_binfo.kernel_filename = args->kernel_filename;
|
cubieboard_binfo.kernel_filename = machine->kernel_filename;
|
||||||
cubieboard_binfo.kernel_cmdline = args->kernel_cmdline;
|
cubieboard_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
arm_load_kernel(&s->a10->cpu, &cubieboard_binfo);
|
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",
|
.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);
|
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)
|
Exynos4BoardType board_type)
|
||||||
{
|
{
|
||||||
if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
|
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.board_id = exynos4_board_id[board_type];
|
||||||
exynos4_board_binfo.smp_bootreg_addr =
|
exynos4_board_binfo.smp_bootreg_addr =
|
||||||
exynos4_board_smp_bootreg_addr[board_type];
|
exynos4_board_smp_bootreg_addr[board_type];
|
||||||
exynos4_board_binfo.kernel_filename = args->kernel_filename;
|
exynos4_board_binfo.kernel_filename = machine->kernel_filename;
|
||||||
exynos4_board_binfo.initrd_filename = args->initrd_filename;
|
exynos4_board_binfo.initrd_filename = machine->initrd_filename;
|
||||||
exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
|
exynos4_board_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
exynos4_board_binfo.gic_cpu_if_addr =
|
exynos4_board_binfo.gic_cpu_if_addr =
|
||||||
EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
|
EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
|
||||||
|
|
||||||
@@ -120,24 +120,24 @@ static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
|
|||||||
" initrd_filename: %s\n",
|
" initrd_filename: %s\n",
|
||||||
exynos4_board_ram_size[board_type] / 1048576,
|
exynos4_board_ram_size[board_type] / 1048576,
|
||||||
exynos4_board_ram_size[board_type],
|
exynos4_board_ram_size[board_type],
|
||||||
args->kernel_filename,
|
machine->kernel_filename,
|
||||||
args->kernel_cmdline,
|
machine->kernel_cmdline,
|
||||||
args->initrd_filename);
|
machine->initrd_filename);
|
||||||
|
|
||||||
return exynos4210_init(get_system_memory(),
|
return exynos4210_init(get_system_memory(),
|
||||||
exynos4_board_ram_size[board_type]);
|
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);
|
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);
|
EXYNOS4_BOARD_SMDKC210);
|
||||||
|
|
||||||
lan9215_init(SMDK_LAN9118_BASE_ADDR,
|
lan9215_init(SMDK_LAN9118_BASE_ADDR,
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
static const int sector_len = 128 * 1024;
|
static const int sector_len = 128 * 1024;
|
||||||
|
|
||||||
static void connex_init(QEMUMachineInitArgs *args)
|
static void connex_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
PXA2xxState *cpu;
|
PXA2xxState *cpu;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
@@ -83,9 +83,9 @@ static void connex_init(QEMUMachineInitArgs *args)
|
|||||||
qdev_get_gpio_in(cpu->gpio, 36));
|
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;
|
PXA2xxState *cpu;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
int be;
|
int be;
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ static VMStateDescription vmstate_highbank_regs = {
|
|||||||
.name = "highbank-regs",
|
.name = "highbank-regs",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
|
VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
|
||||||
VMSTATE_END_OF_LIST(),
|
VMSTATE_END_OF_LIST(),
|
||||||
@@ -200,13 +199,13 @@ enum cxmachines {
|
|||||||
* 32-bit host, set the reg value of memory to 0xf7ff00000 in the
|
* 32-bit host, set the reg value of memory to 0xf7ff00000 in the
|
||||||
* device tree and pass -m 2047 to QEMU.
|
* 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;
|
ram_addr_t ram_size = machine->ram_size;
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
DeviceState *dev = NULL;
|
DeviceState *dev = NULL;
|
||||||
SysBusDevice *busdev;
|
SysBusDevice *busdev;
|
||||||
qemu_irq pic[128];
|
qemu_irq pic[128];
|
||||||
@@ -218,7 +217,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
|||||||
char *sysboot_filename;
|
char *sysboot_filename;
|
||||||
|
|
||||||
if (!cpu_model) {
|
if (!cpu_model) {
|
||||||
switch (machine) {
|
switch (machine_id) {
|
||||||
case CALXEDA_HIGHBANK:
|
case CALXEDA_HIGHBANK:
|
||||||
cpu_model = "cortex-a9";
|
cpu_model = "cortex-a9";
|
||||||
break;
|
break;
|
||||||
@@ -275,7 +274,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (machine) {
|
switch (machine_id) {
|
||||||
case CALXEDA_HIGHBANK:
|
case CALXEDA_HIGHBANK:
|
||||||
dev = qdev_create(NULL, "l2x0");
|
dev = qdev_create(NULL, "l2x0");
|
||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
@@ -360,14 +359,14 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
|||||||
arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo);
|
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 = {
|
static QEMUMachine highbank_machine = {
|
||||||
|
|||||||
@@ -461,13 +461,13 @@ static struct arm_boot_info integrator_binfo = {
|
|||||||
.board_id = 0x113,
|
.board_id = 0x113,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void integratorcp_init(QEMUMachineInitArgs *args)
|
static void integratorcp_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
ram_addr_t ram_size = args->ram_size;
|
ram_addr_t ram_size = machine->ram_size;
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
ARMCPU *cpu;
|
ARMCPU *cpu;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
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,
|
.board_id = 1722,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void kzm_init(QEMUMachineInitArgs *args)
|
static void kzm_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
ram_addr_t ram_size = args->ram_size;
|
ram_addr_t ram_size = machine->ram_size;
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
ARMCPU *cpu;
|
ARMCPU *cpu;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
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,
|
static void mainstone_common_init(MemoryRegion *address_space_mem,
|
||||||
QEMUMachineInitArgs *args,
|
MachineState *machine,
|
||||||
enum mainstone_model_e model, int arm_id)
|
enum mainstone_model_e model, int arm_id)
|
||||||
{
|
{
|
||||||
uint32_t sector_len = 256 * 1024;
|
uint32_t sector_len = 256 * 1024;
|
||||||
@@ -116,7 +116,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
|
|||||||
int i;
|
int i;
|
||||||
int be;
|
int be;
|
||||||
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
|
|
||||||
if (!cpu_model)
|
if (!cpu_model)
|
||||||
cpu_model = "pxa270-c5";
|
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,
|
smc91c111_init(&nd_table[0], MST_ETH_PHYS,
|
||||||
qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
|
qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
|
||||||
|
|
||||||
mainstone_binfo.kernel_filename = args->kernel_filename;
|
mainstone_binfo.kernel_filename = machine->kernel_filename;
|
||||||
mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
|
mainstone_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
mainstone_binfo.initrd_filename = args->initrd_filename;
|
mainstone_binfo.initrd_filename = machine->initrd_filename;
|
||||||
mainstone_binfo.board_id = arm_id;
|
mainstone_binfo.board_id = arm_id;
|
||||||
arm_load_kernel(mpu->cpu, &mainstone_binfo);
|
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 = {
|
static QEMUMachine mainstone2_machine = {
|
||||||
|
|||||||
@@ -405,7 +405,6 @@ static const VMStateDescription mv88w8618_eth_vmsd = {
|
|||||||
.name = "mv88w8618_eth",
|
.name = "mv88w8618_eth",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(smir, mv88w8618_eth_state),
|
VMSTATE_UINT32(smir, mv88w8618_eth_state),
|
||||||
VMSTATE_UINT32(icr, mv88w8618_eth_state),
|
VMSTATE_UINT32(icr, mv88w8618_eth_state),
|
||||||
@@ -642,7 +641,6 @@ static const VMStateDescription musicpal_lcd_vmsd = {
|
|||||||
.name = "musicpal_lcd",
|
.name = "musicpal_lcd",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(brightness, musicpal_lcd_state),
|
VMSTATE_UINT32(brightness, musicpal_lcd_state),
|
||||||
VMSTATE_UINT32(mode, musicpal_lcd_state),
|
VMSTATE_UINT32(mode, musicpal_lcd_state),
|
||||||
@@ -769,7 +767,6 @@ static const VMStateDescription mv88w8618_pic_vmsd = {
|
|||||||
.name = "mv88w8618_pic",
|
.name = "mv88w8618_pic",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(level, mv88w8618_pic_state),
|
VMSTATE_UINT32(level, mv88w8618_pic_state),
|
||||||
VMSTATE_UINT32(enabled, mv88w8618_pic_state),
|
VMSTATE_UINT32(enabled, mv88w8618_pic_state),
|
||||||
@@ -940,7 +937,6 @@ static const VMStateDescription mv88w8618_timer_vmsd = {
|
|||||||
.name = "timer",
|
.name = "timer",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
|
VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
|
||||||
VMSTATE_UINT32(limit, mv88w8618_timer_state),
|
VMSTATE_UINT32(limit, mv88w8618_timer_state),
|
||||||
@@ -952,7 +948,6 @@ static const VMStateDescription mv88w8618_pit_vmsd = {
|
|||||||
.name = "mv88w8618_pit",
|
.name = "mv88w8618_pit",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
|
VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
|
||||||
mv88w8618_timer_vmsd, mv88w8618_timer_state),
|
mv88w8618_timer_vmsd, mv88w8618_timer_state),
|
||||||
@@ -1041,7 +1036,6 @@ static const VMStateDescription mv88w8618_flashcfg_vmsd = {
|
|||||||
.name = "mv88w8618_flashcfg",
|
.name = "mv88w8618_flashcfg",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
|
VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
@@ -1381,7 +1375,6 @@ static const VMStateDescription musicpal_gpio_vmsd = {
|
|||||||
.name = "musicpal_gpio",
|
.name = "musicpal_gpio",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
|
VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
|
||||||
VMSTATE_UINT32(out_state, musicpal_gpio_state),
|
VMSTATE_UINT32(out_state, musicpal_gpio_state),
|
||||||
@@ -1548,7 +1541,6 @@ static const VMStateDescription musicpal_key_vmsd = {
|
|||||||
.name = "musicpal_key",
|
.name = "musicpal_key",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(kbd_extended, musicpal_key_state),
|
VMSTATE_UINT32(kbd_extended, musicpal_key_state),
|
||||||
VMSTATE_UINT32(pressed_keys, musicpal_key_state),
|
VMSTATE_UINT32(pressed_keys, musicpal_key_state),
|
||||||
@@ -1577,12 +1569,12 @@ static struct arm_boot_info musicpal_binfo = {
|
|||||||
.board_id = 0x20e,
|
.board_id = 0x20e,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void musicpal_init(QEMUMachineInitArgs *args)
|
static void musicpal_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
ARMCPU *cpu;
|
ARMCPU *cpu;
|
||||||
qemu_irq pic[32];
|
qemu_irq pic[32];
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
|
|||||||
@@ -1278,14 +1278,14 @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p)
|
|||||||
return n8x0_atag_setup(p, 810);
|
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)
|
struct arm_boot_info *binfo, int model)
|
||||||
{
|
{
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
|
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
|
||||||
int sdram_size = binfo->ram_size;
|
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
|
/* Setup peripherals
|
||||||
*
|
*
|
||||||
@@ -1329,18 +1329,18 @@ static void n8x0_init(QEMUMachineInitArgs *args,
|
|||||||
n8x0_usb_setup(s);
|
n8x0_usb_setup(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
/* Or at the linux loader. */
|
/* Or at the linux loader. */
|
||||||
binfo->kernel_filename = args->kernel_filename;
|
binfo->kernel_filename = machine->kernel_filename;
|
||||||
binfo->kernel_cmdline = args->kernel_cmdline;
|
binfo->kernel_cmdline = machine->kernel_cmdline;
|
||||||
binfo->initrd_filename = args->initrd_filename;
|
binfo->initrd_filename = machine->initrd_filename;
|
||||||
arm_load_kernel(s->mpu->cpu, binfo);
|
arm_load_kernel(s->mpu->cpu, binfo);
|
||||||
|
|
||||||
qemu_register_reset(n8x0_boot_init, s);
|
qemu_register_reset(n8x0_boot_init, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option_rom[0].name &&
|
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];
|
uint8_t nolo_tags[0x10000];
|
||||||
/* No, wait, better start at the ROM. */
|
/* No, wait, better start at the ROM. */
|
||||||
s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
|
s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
|
||||||
@@ -1382,14 +1382,14 @@ static struct arm_boot_info n810_binfo = {
|
|||||||
.atag_board = n810_atag_setup,
|
.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 = {
|
static QEMUMachine n800_machine = {
|
||||||
|
|||||||
@@ -2709,8 +2709,8 @@ static void omap_rtc_write(void *opaque, hwaddr addr,
|
|||||||
s->ti += ti[1];
|
s->ti += ti[1];
|
||||||
} else {
|
} else {
|
||||||
/* A less accurate version */
|
/* A less accurate version */
|
||||||
s->ti -= (s->current_tm.tm_year % 100) * 31536000;
|
s->ti -= (time_t)(s->current_tm.tm_year % 100) * 31536000;
|
||||||
s->ti += from_bcd(value) * 31536000;
|
s->ti += (time_t)from_bcd(value) * 31536000;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ static struct arm_boot_info sx1_binfo = {
|
|||||||
.board_id = 0x265,
|
.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;
|
struct omap_mpu_state_s *mpu;
|
||||||
MemoryRegion *address_space = get_system_memory();
|
MemoryRegion *address_space = get_system_memory();
|
||||||
@@ -118,7 +118,8 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version)
|
|||||||
flash_size = flash2_size;
|
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) */
|
/* External Flash (EMIFS) */
|
||||||
memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size);
|
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]);
|
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");
|
fprintf(stderr, "Kernel or Flash image must be specified\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the kernel. */
|
/* Load the kernel. */
|
||||||
sx1_binfo.kernel_filename = args->kernel_filename;
|
sx1_binfo.kernel_filename = machine->kernel_filename;
|
||||||
sx1_binfo.kernel_cmdline = args->kernel_cmdline;
|
sx1_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
sx1_binfo.initrd_filename = args->initrd_filename;
|
sx1_binfo.initrd_filename = machine->initrd_filename;
|
||||||
arm_load_kernel(mpu->cpu, &sx1_binfo);
|
arm_load_kernel(mpu->cpu, &sx1_binfo);
|
||||||
|
|
||||||
/* TODO: fix next line */
|
/* TODO: fix next line */
|
||||||
//~ qemu_console_resize(ds, 640, 480);
|
//~ 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 = {
|
static QEMUMachine sx1_machine_v2 = {
|
||||||
|
|||||||
@@ -191,12 +191,12 @@ static struct arm_boot_info palmte_binfo = {
|
|||||||
.board_id = 0x331,
|
.board_id = 0x331,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void palmte_init(QEMUMachineInitArgs *args)
|
static void palmte_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
struct omap_mpu_state_s *mpu;
|
struct omap_mpu_state_s *mpu;
|
||||||
int flash_size = 0x00800000;
|
int flash_size = 0x00800000;
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ static const VMStateDescription vmstate_pxa2xx_pm = {
|
|||||||
.name = "pxa2xx_pm",
|
.name = "pxa2xx_pm",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40),
|
VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
@@ -215,7 +214,6 @@ static const VMStateDescription vmstate_pxa2xx_cm = {
|
|||||||
.name = "pxa2xx_cm",
|
.name = "pxa2xx_cm",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4),
|
VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4),
|
||||||
VMSTATE_UINT32(clkcfg, PXA2xxState),
|
VMSTATE_UINT32(clkcfg, PXA2xxState),
|
||||||
@@ -440,7 +438,6 @@ static const VMStateDescription vmstate_pxa2xx_mm = {
|
|||||||
.name = "pxa2xx_mm",
|
.name = "pxa2xx_mm",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a),
|
VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
@@ -1172,7 +1169,6 @@ static const VMStateDescription vmstate_pxa2xx_rtc_regs = {
|
|||||||
.name = "pxa2xx_rtc",
|
.name = "pxa2xx_rtc",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.pre_save = pxa2xx_rtc_pre_save,
|
.pre_save = pxa2xx_rtc_pre_save,
|
||||||
.post_load = pxa2xx_rtc_post_load,
|
.post_load = pxa2xx_rtc_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
@@ -1436,7 +1432,6 @@ static const VMStateDescription vmstate_pxa2xx_i2c_slave = {
|
|||||||
.name = "pxa2xx_i2c_slave",
|
.name = "pxa2xx_i2c_slave",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_I2C_SLAVE(parent_obj, PXA2xxI2CSlaveState),
|
VMSTATE_I2C_SLAVE(parent_obj, PXA2xxI2CSlaveState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
@@ -1447,7 +1442,6 @@ static const VMStateDescription vmstate_pxa2xx_i2c = {
|
|||||||
.name = "pxa2xx_i2c",
|
.name = "pxa2xx_i2c",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT16(control, PXA2xxI2CState),
|
VMSTATE_UINT16(control, PXA2xxI2CState),
|
||||||
VMSTATE_UINT16(status, PXA2xxI2CState),
|
VMSTATE_UINT16(status, PXA2xxI2CState),
|
||||||
@@ -1705,7 +1699,6 @@ static const VMStateDescription vmstate_pxa2xx_i2s = {
|
|||||||
.name = "pxa2xx_i2s",
|
.name = "pxa2xx_i2s",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2),
|
VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2),
|
||||||
VMSTATE_UINT32(status, PXA2xxI2SState),
|
VMSTATE_UINT32(status, PXA2xxI2SState),
|
||||||
|
|||||||
@@ -313,7 +313,6 @@ static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
|
|||||||
.name = "pxa2xx-gpio",
|
.name = "pxa2xx-gpio",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_INT32(lines, PXA2xxGPIOInfo),
|
VMSTATE_INT32(lines, PXA2xxGPIOInfo),
|
||||||
VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
||||||
|
|||||||
@@ -296,7 +296,6 @@ static VMStateDescription vmstate_pxa2xx_pic_regs = {
|
|||||||
.name = "pxa2xx_pic",
|
.name = "pxa2xx_pic",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.post_load = pxa2xx_pic_post_load,
|
.post_load = pxa2xx_pic_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(int_enabled, PXA2xxPICState, 2),
|
VMSTATE_UINT32_ARRAY(int_enabled, PXA2xxPICState, 2),
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ static const int realview_board_id[] = {
|
|||||||
0x76d
|
0x76d
|
||||||
};
|
};
|
||||||
|
|
||||||
static void realview_init(QEMUMachineInitArgs *args,
|
static void realview_init(MachineState *machine,
|
||||||
enum realview_board_type board_type)
|
enum realview_board_type board_type)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = NULL;
|
ARMCPU *cpu = NULL;
|
||||||
@@ -71,7 +71,7 @@ static void realview_init(QEMUMachineInitArgs *args,
|
|||||||
uint32_t proc_id = 0;
|
uint32_t proc_id = 0;
|
||||||
uint32_t sys_id;
|
uint32_t sys_id;
|
||||||
ram_addr_t low_ram_size;
|
ram_addr_t low_ram_size;
|
||||||
ram_addr_t ram_size = args->ram_size;
|
ram_addr_t ram_size = machine->ram_size;
|
||||||
hwaddr periphbase = 0;
|
hwaddr periphbase = 0;
|
||||||
|
|
||||||
switch (board_type) {
|
switch (board_type) {
|
||||||
@@ -91,7 +91,7 @@ static void realview_init(QEMUMachineInitArgs *args,
|
|||||||
break;
|
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) {
|
if (!cpu_oc) {
|
||||||
fprintf(stderr, "Unable to find CPU definition\n");
|
fprintf(stderr, "Unable to find CPU definition\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -342,45 +342,45 @@ static void realview_init(QEMUMachineInitArgs *args,
|
|||||||
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
|
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
|
||||||
|
|
||||||
realview_binfo.ram_size = ram_size;
|
realview_binfo.ram_size = ram_size;
|
||||||
realview_binfo.kernel_filename = args->kernel_filename;
|
realview_binfo.kernel_filename = machine->kernel_filename;
|
||||||
realview_binfo.kernel_cmdline = args->kernel_cmdline;
|
realview_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
realview_binfo.initrd_filename = args->initrd_filename;
|
realview_binfo.initrd_filename = machine->initrd_filename;
|
||||||
realview_binfo.nb_cpus = smp_cpus;
|
realview_binfo.nb_cpus = smp_cpus;
|
||||||
realview_binfo.board_id = realview_board_id[board_type];
|
realview_binfo.board_id = realview_board_id[board_type];
|
||||||
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
|
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
|
||||||
arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo);
|
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) {
|
if (!machine->cpu_model) {
|
||||||
args->cpu_model = "arm926";
|
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) {
|
if (!machine->cpu_model) {
|
||||||
args->cpu_model = "arm11mpcore";
|
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) {
|
if (!machine->cpu_model) {
|
||||||
args->cpu_model = "cortex-a8";
|
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) {
|
if (!machine->cpu_model) {
|
||||||
args->cpu_model = "cortex-a9";
|
machine->cpu_model = "cortex-a9";
|
||||||
}
|
}
|
||||||
realview_init(args, BOARD_PBX_A9);
|
realview_init(machine, BOARD_PBX_A9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QEMUMachine realview_eb_machine = {
|
static QEMUMachine realview_eb_machine = {
|
||||||
|
|||||||
@@ -887,14 +887,14 @@ static struct arm_boot_info spitz_binfo = {
|
|||||||
.ram_size = 0x04000000,
|
.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)
|
enum spitz_model_e model, int arm_id)
|
||||||
{
|
{
|
||||||
PXA2xxState *mpu;
|
PXA2xxState *mpu;
|
||||||
DeviceState *scp0, *scp1 = NULL;
|
DeviceState *scp0, *scp1 = NULL;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
|
|
||||||
if (!cpu_model)
|
if (!cpu_model)
|
||||||
cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
|
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. */
|
/* A 4.0 GB microdrive is permanently sitting in CF slot 0. */
|
||||||
spitz_microdrive_attach(mpu, 0);
|
spitz_microdrive_attach(mpu, 0);
|
||||||
|
|
||||||
spitz_binfo.kernel_filename = args->kernel_filename;
|
spitz_binfo.kernel_filename = machine->kernel_filename;
|
||||||
spitz_binfo.kernel_cmdline = args->kernel_cmdline;
|
spitz_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
spitz_binfo.initrd_filename = args->initrd_filename;
|
spitz_binfo.initrd_filename = machine->initrd_filename;
|
||||||
spitz_binfo.board_id = arm_id;
|
spitz_binfo.board_id = arm_id;
|
||||||
arm_load_kernel(mpu->cpu, &spitz_binfo);
|
arm_load_kernel(mpu->cpu, &spitz_binfo);
|
||||||
sl_bootparam_write(SL_PXA_PARAM_BASE);
|
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 = {
|
static QEMUMachine akitapda_machine = {
|
||||||
@@ -1006,7 +1006,6 @@ static VMStateDescription vmstate_sl_nand_info = {
|
|||||||
.name = "sl-nand",
|
.name = "sl-nand",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(ctl, SLNANDState),
|
VMSTATE_UINT8(ctl, SLNANDState),
|
||||||
VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
|
VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
|
||||||
@@ -1041,7 +1040,6 @@ static VMStateDescription vmstate_spitz_kbd = {
|
|||||||
.name = "spitz-keyboard",
|
.name = "spitz-keyboard",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.post_load = spitz_keyboard_post_load,
|
.post_load = spitz_keyboard_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT16(sense_state, SpitzKeyboardState),
|
VMSTATE_UINT16(sense_state, SpitzKeyboardState),
|
||||||
@@ -1076,7 +1074,6 @@ static const VMStateDescription vmstate_corgi_ssp_regs = {
|
|||||||
.name = "corgi-ssp",
|
.name = "corgi-ssp",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 2,
|
||||||
.minimum_version_id_old = 2,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState),
|
VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState),
|
||||||
VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
|
VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
|
||||||
@@ -1105,7 +1102,6 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = {
|
|||||||
.name = "spitz-lcdtg",
|
.name = "spitz-lcdtg",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG),
|
VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG),
|
||||||
VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
|
VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
|
||||||
|
|||||||
@@ -185,12 +185,19 @@ static uint64_t gptm_read(void *opaque, hwaddr offset,
|
|||||||
case 0x44: /* TBPMR */
|
case 0x44: /* TBPMR */
|
||||||
return s->match_prescale[1];
|
return s->match_prescale[1];
|
||||||
case 0x48: /* TAR */
|
case 0x48: /* TAR */
|
||||||
if (s->control == 1)
|
if (s->config == 1) {
|
||||||
return s->rtc;
|
return s->rtc;
|
||||||
|
}
|
||||||
|
qemu_log_mask(LOG_UNIMP,
|
||||||
|
"GPTM: read of TAR but timer read not supported");
|
||||||
|
return 0;
|
||||||
case 0x4c: /* TBR */
|
case 0x4c: /* TBR */
|
||||||
hw_error("TODO: Timer value read\n");
|
qemu_log_mask(LOG_UNIMP,
|
||||||
|
"GPTM: read of TBR but timer read not supported");
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
hw_error("gptm_read: Bad offset 0x%x\n", (int)offset);
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"GPTM: read at bad offset 0x%x\n", (int)offset);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,7 +293,6 @@ static const VMStateDescription vmstate_stellaris_gptm = {
|
|||||||
.name = "stellaris_gptm",
|
.name = "stellaris_gptm",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(config, gptm_state),
|
VMSTATE_UINT32(config, gptm_state),
|
||||||
VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
|
VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
|
||||||
@@ -643,7 +649,6 @@ static const VMStateDescription vmstate_stellaris_sys = {
|
|||||||
.name = "stellaris_sys",
|
.name = "stellaris_sys",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.post_load = stellaris_sys_post_load,
|
.post_load = stellaris_sys_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(pborctl, ssys_state),
|
VMSTATE_UINT32(pborctl, ssys_state),
|
||||||
@@ -851,7 +856,6 @@ static const VMStateDescription vmstate_stellaris_i2c = {
|
|||||||
.name = "stellaris_i2c",
|
.name = "stellaris_i2c",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(msa, stellaris_i2c_state),
|
VMSTATE_UINT32(msa, stellaris_i2c_state),
|
||||||
VMSTATE_UINT32(mcs, stellaris_i2c_state),
|
VMSTATE_UINT32(mcs, stellaris_i2c_state),
|
||||||
@@ -1121,7 +1125,6 @@ static const VMStateDescription vmstate_stellaris_adc = {
|
|||||||
.name = "stellaris_adc",
|
.name = "stellaris_adc",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(actss, stellaris_adc_state),
|
VMSTATE_UINT32(actss, stellaris_adc_state),
|
||||||
VMSTATE_UINT32(ris, stellaris_adc_state),
|
VMSTATE_UINT32(ris, stellaris_adc_state),
|
||||||
@@ -1287,9 +1290,10 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||||||
|
|
||||||
sddev = ssi_create_slave(bus, "ssi-sd");
|
sddev = ssi_create_slave(bus, "ssi-sd");
|
||||||
ssddev = ssi_create_slave(bus, "ssd0323");
|
ssddev = ssi_create_slave(bus, "ssd0323");
|
||||||
gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0),
|
gpio_out[GPIO_D][0] = qemu_irq_split(
|
||||||
qdev_get_gpio_in(ssddev, 0));
|
qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
|
||||||
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1);
|
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. */
|
/* Make sure the select pin is high. */
|
||||||
qemu_irq_raise(gpio_out[GPIO_D][0]);
|
qemu_irq_raise(gpio_out[GPIO_D][0]);
|
||||||
@@ -1330,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. */
|
/* 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 *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
|
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 *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
|
stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,7 +199,6 @@ static VMStateDescription vmstate_strongarm_pic_regs = {
|
|||||||
.name = "strongarm_pic",
|
.name = "strongarm_pic",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.post_load = strongarm_pic_post_load,
|
.post_load = strongarm_pic_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(pending, StrongARMPICState),
|
VMSTATE_UINT32(pending, StrongARMPICState),
|
||||||
@@ -424,7 +423,6 @@ static const VMStateDescription vmstate_strongarm_rtc_regs = {
|
|||||||
.name = "strongarm-rtc",
|
.name = "strongarm-rtc",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.pre_save = strongarm_rtc_pre_save,
|
.pre_save = strongarm_rtc_pre_save,
|
||||||
.post_load = strongarm_rtc_post_load,
|
.post_load = strongarm_rtc_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
@@ -670,7 +668,6 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = {
|
|||||||
.name = "strongarm-gpio",
|
.name = "strongarm-gpio",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(ilevel, StrongARMGPIOInfo),
|
VMSTATE_UINT32(ilevel, StrongARMGPIOInfo),
|
||||||
VMSTATE_UINT32(olevel, StrongARMGPIOInfo),
|
VMSTATE_UINT32(olevel, StrongARMGPIOInfo),
|
||||||
@@ -842,7 +839,6 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = {
|
|||||||
.name = "strongarm-ppc",
|
.name = "strongarm-ppc",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(ilevel, StrongARMPPCInfo),
|
VMSTATE_UINT32(ilevel, StrongARMPPCInfo),
|
||||||
VMSTATE_UINT32(olevel, StrongARMPPCInfo),
|
VMSTATE_UINT32(olevel, StrongARMPPCInfo),
|
||||||
@@ -1293,7 +1289,6 @@ static const VMStateDescription vmstate_strongarm_uart_regs = {
|
|||||||
.name = "strongarm-uart",
|
.name = "strongarm-uart",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.post_load = strongarm_uart_post_load,
|
.post_load = strongarm_uart_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(utcr0, StrongARMUARTState),
|
VMSTATE_UINT8(utcr0, StrongARMUARTState),
|
||||||
@@ -1553,7 +1548,6 @@ static const VMStateDescription vmstate_strongarm_ssp_regs = {
|
|||||||
.name = "strongarm-ssp",
|
.name = "strongarm-ssp",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.post_load = strongarm_ssp_post_load,
|
.post_load = strongarm_ssp_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT16_ARRAY(sscr, StrongARMSSPState, 2),
|
VMSTATE_UINT16_ARRAY(sscr, StrongARMSSPState, 2),
|
||||||
|
|||||||
@@ -211,12 +211,12 @@ static struct arm_boot_info tosa_binfo = {
|
|||||||
.ram_size = 0x04000000,
|
.ram_size = 0x04000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void tosa_init(QEMUMachineInitArgs *args)
|
static void tosa_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
MemoryRegion *rom = g_new(MemoryRegion, 1);
|
||||||
PXA2xxState *mpu;
|
PXA2xxState *mpu;
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ static int vpb_sic_init(SysBusDevice *sbd)
|
|||||||
|
|
||||||
static struct arm_boot_info versatile_binfo;
|
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;
|
ARMCPU *cpu;
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
@@ -190,15 +190,15 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
|
|||||||
int done_smc = 0;
|
int done_smc = 0;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
|
|
||||||
if (!args->cpu_model) {
|
if (!machine->cpu_model) {
|
||||||
args->cpu_model = "arm926";
|
machine->cpu_model = "arm926";
|
||||||
}
|
}
|
||||||
cpu = cpu_arm_init(args->cpu_model);
|
cpu = cpu_arm_init(machine->cpu_model);
|
||||||
if (!cpu) {
|
if (!cpu) {
|
||||||
fprintf(stderr, "Unable to find CPU definition\n");
|
fprintf(stderr, "Unable to find CPU definition\n");
|
||||||
exit(1);
|
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);
|
vmstate_register_ram_global(ram);
|
||||||
/* ??? RAM should repeat to fill physical memory space. */
|
/* ??? RAM should repeat to fill physical memory space. */
|
||||||
/* SDRAM at address zero. */
|
/* 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");
|
fprintf(stderr, "qemu: Error registering flash memory.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
versatile_binfo.ram_size = args->ram_size;
|
versatile_binfo.ram_size = machine->ram_size;
|
||||||
versatile_binfo.kernel_filename = args->kernel_filename;
|
versatile_binfo.kernel_filename = machine->kernel_filename;
|
||||||
versatile_binfo.kernel_cmdline = args->kernel_cmdline;
|
versatile_binfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
versatile_binfo.initrd_filename = args->initrd_filename;
|
versatile_binfo.initrd_filename = machine->initrd_filename;
|
||||||
versatile_binfo.board_id = board_id;
|
versatile_binfo.board_id = board_id;
|
||||||
arm_load_kernel(cpu, &versatile_binfo);
|
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 = {
|
static QEMUMachine versatilepb_machine = {
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
||||||
QEMUMachineInitArgs *args)
|
MachineState *machine)
|
||||||
{
|
{
|
||||||
DeviceState *dev, *sysctl, *pl041;
|
DeviceState *dev, *sysctl, *pl041;
|
||||||
qemu_irq pic[64];
|
qemu_irq pic[64];
|
||||||
@@ -525,7 +525,8 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
|||||||
const hwaddr *map = daughterboard->motherboard_map;
|
const hwaddr *map = daughterboard->motherboard_map;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic);
|
daughterboard->init(daughterboard, machine->ram_size, machine->cpu_model,
|
||||||
|
pic);
|
||||||
|
|
||||||
/* Motherboard peripherals: the wiring is the same but the
|
/* Motherboard peripherals: the wiring is the same but the
|
||||||
* addresses vary between the legacy and A-Series memory maps.
|
* addresses vary between the legacy and A-Series memory maps.
|
||||||
@@ -639,10 +640,10 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
|||||||
pic[40 + i]);
|
pic[40 + i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
daughterboard->bootinfo.ram_size = args->ram_size;
|
daughterboard->bootinfo.ram_size = machine->ram_size;
|
||||||
daughterboard->bootinfo.kernel_filename = args->kernel_filename;
|
daughterboard->bootinfo.kernel_filename = machine->kernel_filename;
|
||||||
daughterboard->bootinfo.kernel_cmdline = args->kernel_cmdline;
|
daughterboard->bootinfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
daughterboard->bootinfo.initrd_filename = args->initrd_filename;
|
daughterboard->bootinfo.initrd_filename = machine->initrd_filename;
|
||||||
daughterboard->bootinfo.nb_cpus = smp_cpus;
|
daughterboard->bootinfo.nb_cpus = smp_cpus;
|
||||||
daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID;
|
daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID;
|
||||||
daughterboard->bootinfo.loader_start = daughterboard->loader_start;
|
daughterboard->bootinfo.loader_start = daughterboard->loader_start;
|
||||||
@@ -653,14 +654,14 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
|
|||||||
arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo);
|
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 = {
|
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;
|
return board->fdt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void machvirt_init(QEMUMachineInitArgs *args)
|
static void machvirt_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
qemu_irq pic[NUM_IRQS];
|
qemu_irq pic[NUM_IRQS];
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
int n;
|
int n;
|
||||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
VirtBoardInfo *vbi;
|
VirtBoardInfo *vbi;
|
||||||
|
|
||||||
if (!cpu_model) {
|
if (!cpu_model) {
|
||||||
@@ -415,7 +415,7 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
|||||||
exit(1);
|
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");
|
error_report("mach-virt: cannot model more than 30GB RAM");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -447,7 +447,7 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
|||||||
}
|
}
|
||||||
fdt_add_cpu_nodes(vbi);
|
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);
|
vmstate_register_ram_global(ram);
|
||||||
memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, 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);
|
create_virtio_devices(vbi, pic);
|
||||||
|
|
||||||
vbi->bootinfo.ram_size = args->ram_size;
|
vbi->bootinfo.ram_size = machine->ram_size;
|
||||||
vbi->bootinfo.kernel_filename = args->kernel_filename;
|
vbi->bootinfo.kernel_filename = machine->kernel_filename;
|
||||||
vbi->bootinfo.kernel_cmdline = args->kernel_cmdline;
|
vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline;
|
||||||
vbi->bootinfo.initrd_filename = args->initrd_filename;
|
vbi->bootinfo.initrd_filename = machine->initrd_filename;
|
||||||
vbi->bootinfo.nb_cpus = smp_cpus;
|
vbi->bootinfo.nb_cpus = smp_cpus;
|
||||||
vbi->bootinfo.board_id = -1;
|
vbi->bootinfo.board_id = -1;
|
||||||
vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
|
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) {
|
for (j = 0; j < num_ss; ++j) {
|
||||||
flash_dev = ssi_create_slave(spi, "n25q128");
|
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);
|
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;
|
ram_addr_t ram_size = machine->ram_size;
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
ObjectClass *cpu_oc;
|
ObjectClass *cpu_oc;
|
||||||
ARMCPU *cpu;
|
ARMCPU *cpu;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
|
|||||||
12
hw/arm/z2.c
12
hw/arm/z2.c
@@ -164,7 +164,6 @@ static VMStateDescription vmstate_zipit_lcd_state = {
|
|||||||
.name = "zipit-lcd",
|
.name = "zipit-lcd",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 2,
|
||||||
.minimum_version_id_old = 2,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_SSI_SLAVE(ssidev, ZipitLCD),
|
VMSTATE_SSI_SLAVE(ssidev, ZipitLCD),
|
||||||
VMSTATE_INT32(selected, ZipitLCD),
|
VMSTATE_INT32(selected, ZipitLCD),
|
||||||
@@ -275,7 +274,6 @@ static VMStateDescription vmstate_aer915_state = {
|
|||||||
.name = "aer915",
|
.name = "aer915",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_INT32(len, AER915State),
|
VMSTATE_INT32(len, AER915State),
|
||||||
VMSTATE_BUFFER(buf, AER915State),
|
VMSTATE_BUFFER(buf, AER915State),
|
||||||
@@ -302,12 +300,12 @@ static const TypeInfo aer915_info = {
|
|||||||
.class_init = aer915_class_init,
|
.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 *cpu_model = machine->cpu_model;
|
||||||
const char *kernel_filename = args->kernel_filename;
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_cmdline = args->kernel_cmdline;
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *initrd_filename = args->initrd_filename;
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
uint32_t sector_len = 0x10000;
|
uint32_t sector_len = 0x10000;
|
||||||
PXA2xxState *mpu;
|
PXA2xxState *mpu;
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
|
|||||||
|
|
||||||
/* update global status */
|
/* update global status */
|
||||||
if (sts & d->int_ctl) {
|
if (sts & d->int_ctl) {
|
||||||
sts |= (1 << 31);
|
sts |= (1U << 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
d->int_sts = sts;
|
d->int_sts = sts;
|
||||||
@@ -257,7 +257,7 @@ static void intel_hda_update_irq(IntelHDAState *d)
|
|||||||
int level;
|
int level;
|
||||||
|
|
||||||
intel_hda_update_int_sts(d);
|
intel_hda_update_int_sts(d);
|
||||||
if (d->int_sts & (1 << 31) && d->int_ctl & (1 << 31)) {
|
if (d->int_sts & (1U << 31) && d->int_ctl & (1U << 31)) {
|
||||||
level = 1;
|
level = 1;
|
||||||
} else {
|
} else {
|
||||||
level = 0;
|
level = 0;
|
||||||
@@ -574,7 +574,7 @@ static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint3
|
|||||||
if (st->ctl & 0x01) {
|
if (st->ctl & 0x01) {
|
||||||
/* reset */
|
/* reset */
|
||||||
dprint(d, 1, "st #%d: reset\n", reg->stream);
|
dprint(d, 1, "st #%d: reset\n", reg->stream);
|
||||||
st->ctl = 0;
|
st->ctl = SD_STS_FIFO_READY << 24;
|
||||||
}
|
}
|
||||||
if ((st->ctl & 0x02) != (old & 0x02)) {
|
if ((st->ctl & 0x02) != (old & 0x02)) {
|
||||||
uint32_t stnr = (st->ctl >> 20) & 0x0f;
|
uint32_t stnr = (st->ctl >> 20) & 0x0f;
|
||||||
@@ -829,6 +829,7 @@ static const struct IntelHDAReg regtab[] = {
|
|||||||
.wclear = 0x1c000000, \
|
.wclear = 0x1c000000, \
|
||||||
.offset = offsetof(IntelHDAState, st[_i].ctl), \
|
.offset = offsetof(IntelHDAState, st[_i].ctl), \
|
||||||
.whandler = intel_hda_set_st_ctl, \
|
.whandler = intel_hda_set_st_ctl, \
|
||||||
|
.reset = SD_STS_FIFO_READY << 24 \
|
||||||
}, \
|
}, \
|
||||||
[ ST_REG(_i, ICH6_REG_SD_LPIB) ] = { \
|
[ ST_REG(_i, ICH6_REG_SD_LPIB) ] = { \
|
||||||
.stream = _i, \
|
.stream = _i, \
|
||||||
|
|||||||
@@ -324,8 +324,7 @@ const VMStateDescription vmstate_lm4549_state = {
|
|||||||
.name = "lm4549_state",
|
.name = "lm4549_state",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
.post_load = lm4549_post_load,
|
||||||
.post_load = &lm4549_post_load,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(voice_is_active, lm4549_state),
|
VMSTATE_UINT32(voice_is_active, lm4549_state),
|
||||||
VMSTATE_UINT16_ARRAY(regfile, lm4549_state, 128),
|
VMSTATE_UINT16_ARRAY(regfile, lm4549_state, 128),
|
||||||
|
|||||||
@@ -259,7 +259,6 @@ static const VMStateDescription mv88w8618_audio_vmsd = {
|
|||||||
.name = "mv88w8618_audio",
|
.name = "mv88w8618_audio",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(playback_mode, mv88w8618_audio_state),
|
VMSTATE_UINT32(playback_mode, mv88w8618_audio_state),
|
||||||
VMSTATE_UINT32(status, mv88w8618_audio_state),
|
VMSTATE_UINT32(status, mv88w8618_audio_state),
|
||||||
|
|||||||
@@ -316,7 +316,6 @@ static const VMStateDescription vmstate_milkymist_ac97 = {
|
|||||||
.name = "milkymist-ac97",
|
.name = "milkymist-ac97",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.post_load = ac97_post_load,
|
.post_load = ac97_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX),
|
VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX),
|
||||||
|
|||||||
@@ -561,7 +561,6 @@ static const VMStateDescription vmstate_pl041_regfile = {
|
|||||||
.name = "pl041_regfile",
|
.name = "pl041_regfile",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
#define REGISTER(name, offset) VMSTATE_UINT32(name, pl041_regfile),
|
#define REGISTER(name, offset) VMSTATE_UINT32(name, pl041_regfile),
|
||||||
#include "pl041.hx"
|
#include "pl041.hx"
|
||||||
@@ -574,7 +573,6 @@ static const VMStateDescription vmstate_pl041_fifo = {
|
|||||||
.name = "pl041_fifo",
|
.name = "pl041_fifo",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(level, pl041_fifo),
|
VMSTATE_UINT32(level, pl041_fifo),
|
||||||
VMSTATE_UINT32_ARRAY(data, pl041_fifo, MAX_FIFO_DEPTH),
|
VMSTATE_UINT32_ARRAY(data, pl041_fifo, MAX_FIFO_DEPTH),
|
||||||
@@ -586,7 +584,6 @@ static const VMStateDescription vmstate_pl041_channel = {
|
|||||||
.name = "pl041_channel",
|
.name = "pl041_channel",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_STRUCT(tx_fifo, pl041_channel, 0,
|
VMSTATE_STRUCT(tx_fifo, pl041_channel, 0,
|
||||||
vmstate_pl041_fifo, pl041_fifo),
|
vmstate_pl041_fifo, pl041_fifo),
|
||||||
|
|||||||
@@ -583,7 +583,6 @@ static const VMStateDescription vmstate_wm8750 = {
|
|||||||
.name = CODEC,
|
.name = CODEC,
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.pre_save = wm8750_pre_save,
|
.pre_save = wm8750_pre_save,
|
||||||
.post_load = wm8750_post_load,
|
.post_load = wm8750_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ struct VirtIOBlockDataPlane {
|
|||||||
queue */
|
queue */
|
||||||
|
|
||||||
unsigned int num_reqs;
|
unsigned int num_reqs;
|
||||||
|
|
||||||
|
/* Operation blocker on BDS */
|
||||||
|
Error *blocker;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Raise an interrupt to signal guest, if necessary */
|
/* Raise an interrupt to signal guest, if necessary */
|
||||||
@@ -350,6 +353,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
|||||||
{
|
{
|
||||||
VirtIOBlockDataPlane *s;
|
VirtIOBlockDataPlane *s;
|
||||||
int fd;
|
int fd;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
*dataplane = NULL;
|
*dataplane = NULL;
|
||||||
|
|
||||||
@@ -372,9 +376,10 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
|||||||
/* If dataplane is (re-)enabled while the guest is running there could be
|
/* If dataplane is (re-)enabled while the guest is running there could be
|
||||||
* block jobs that can conflict.
|
* block jobs that can conflict.
|
||||||
*/
|
*/
|
||||||
if (bdrv_in_use(blk->conf.bs)) {
|
if (bdrv_op_is_blocked(blk->conf.bs, BLOCK_OP_TYPE_DATAPLANE, &local_err)) {
|
||||||
error_setg(errp,
|
error_report("cannot start dataplane thread: %s",
|
||||||
"cannot start dataplane thread while device is in use");
|
error_get_pretty(local_err));
|
||||||
|
error_free(local_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,8 +411,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
|||||||
}
|
}
|
||||||
s->ctx = iothread_get_aio_context(s->iothread);
|
s->ctx = iothread_get_aio_context(s->iothread);
|
||||||
|
|
||||||
/* Prevent block operations that conflict with data plane thread */
|
error_setg(&s->blocker, "block device is in use by data plane");
|
||||||
bdrv_set_in_use(blk->conf.bs, 1);
|
bdrv_op_block_all(blk->conf.bs, s->blocker);
|
||||||
|
|
||||||
*dataplane = s;
|
*dataplane = s;
|
||||||
}
|
}
|
||||||
@@ -420,7 +425,8 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtio_blk_data_plane_stop(s);
|
virtio_blk_data_plane_stop(s);
|
||||||
bdrv_set_in_use(s->blk->conf.bs, 0);
|
bdrv_op_unblock_all(s->blk->conf.bs, s->blocker);
|
||||||
|
error_free(s->blocker);
|
||||||
object_unref(OBJECT(s->iothread));
|
object_unref(OBJECT(s->iothread));
|
||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ VMStateDescription vmstate_ecc_state = {
|
|||||||
.name = "ecc-state",
|
.name = "ecc-state",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(cp, ECCState),
|
VMSTATE_UINT8(cp, ECCState),
|
||||||
VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
|
VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
|
||||||
|
|||||||
@@ -653,7 +653,6 @@ static const VMStateDescription vmstate_m25p80 = {
|
|||||||
.name = "xilinx_spi",
|
.name = "xilinx_spi",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.pre_save = m25p80_pre_save,
|
.pre_save = m25p80_pre_save,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(state, Flash),
|
VMSTATE_UINT8(state, Flash),
|
||||||
|
|||||||
@@ -346,7 +346,6 @@ static const VMStateDescription vmstate_nand = {
|
|||||||
.name = "nand",
|
.name = "nand",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.pre_save = nand_pre_save,
|
.pre_save = nand_pre_save,
|
||||||
.post_load = nand_post_load,
|
.post_load = nand_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
|
|||||||
@@ -169,7 +169,6 @@ static const VMStateDescription vmstate_onenand = {
|
|||||||
.name = "onenand",
|
.name = "onenand",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.pre_save = onenand_pre_save,
|
.pre_save = onenand_pre_save,
|
||||||
.post_load = onenand_post_load,
|
.post_load = onenand_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
|
|||||||
@@ -504,7 +504,6 @@ static const VMStateDescription vmstate_cadence_uart = {
|
|||||||
.name = "cadence_uart",
|
.name = "cadence_uart",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 2,
|
||||||
.minimum_version_id_old = 2,
|
|
||||||
.post_load = cadence_uart_post_load,
|
.post_load = cadence_uart_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
|
VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ static const VMStateDescription vmstate_digic_uart = {
|
|||||||
.name = "digic-uart",
|
.name = "digic-uart",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(reg_rx, DigicUartState),
|
VMSTATE_UINT32(reg_rx, DigicUartState),
|
||||||
VMSTATE_UINT32(reg_st, DigicUartState),
|
VMSTATE_UINT32(reg_st, DigicUartState),
|
||||||
|
|||||||
227
hw/char/escc.c
227
hw/char/escc.c
@@ -27,6 +27,7 @@
|
|||||||
#include "hw/char/escc.h"
|
#include "hw/char/escc.h"
|
||||||
#include "sysemu/char.h"
|
#include "sysemu/char.h"
|
||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
|
#include "ui/input.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -94,6 +95,7 @@ typedef struct ChannelState {
|
|||||||
ChnID chn; // this channel, A (base+4) or B (base+0)
|
ChnID chn; // this channel, A (base+4) or B (base+0)
|
||||||
ChnType type;
|
ChnType type;
|
||||||
uint8_t rx, tx;
|
uint8_t rx, tx;
|
||||||
|
QemuInputHandlerState *hs;
|
||||||
} ChannelState;
|
} ChannelState;
|
||||||
|
|
||||||
#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
|
#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
|
||||||
@@ -714,70 +716,180 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
|
|||||||
return &d->mmio;
|
return &d->mmio;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t keycodes[128] = {
|
static const uint8_t qcode_to_keycode[Q_KEY_CODE_MAX] = {
|
||||||
127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
|
[Q_KEY_CODE_SHIFT] = 99,
|
||||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
|
[Q_KEY_CODE_SHIFT_R] = 110,
|
||||||
79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
|
[Q_KEY_CODE_ALT] = 19,
|
||||||
104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
|
[Q_KEY_CODE_ALT_R] = 13,
|
||||||
14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
|
[Q_KEY_CODE_ALTGR] = 13,
|
||||||
113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
|
[Q_KEY_CODE_CTRL] = 76,
|
||||||
90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
|
[Q_KEY_CODE_CTRL_R] = 76,
|
||||||
0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
|
[Q_KEY_CODE_ESC] = 29,
|
||||||
|
[Q_KEY_CODE_1] = 30,
|
||||||
|
[Q_KEY_CODE_2] = 31,
|
||||||
|
[Q_KEY_CODE_3] = 32,
|
||||||
|
[Q_KEY_CODE_4] = 33,
|
||||||
|
[Q_KEY_CODE_5] = 34,
|
||||||
|
[Q_KEY_CODE_6] = 35,
|
||||||
|
[Q_KEY_CODE_7] = 36,
|
||||||
|
[Q_KEY_CODE_8] = 37,
|
||||||
|
[Q_KEY_CODE_9] = 38,
|
||||||
|
[Q_KEY_CODE_0] = 39,
|
||||||
|
[Q_KEY_CODE_MINUS] = 40,
|
||||||
|
[Q_KEY_CODE_EQUAL] = 41,
|
||||||
|
[Q_KEY_CODE_BACKSPACE] = 43,
|
||||||
|
[Q_KEY_CODE_TAB] = 53,
|
||||||
|
[Q_KEY_CODE_Q] = 54,
|
||||||
|
[Q_KEY_CODE_W] = 55,
|
||||||
|
[Q_KEY_CODE_E] = 56,
|
||||||
|
[Q_KEY_CODE_R] = 57,
|
||||||
|
[Q_KEY_CODE_T] = 58,
|
||||||
|
[Q_KEY_CODE_Y] = 59,
|
||||||
|
[Q_KEY_CODE_U] = 60,
|
||||||
|
[Q_KEY_CODE_I] = 61,
|
||||||
|
[Q_KEY_CODE_O] = 62,
|
||||||
|
[Q_KEY_CODE_P] = 63,
|
||||||
|
[Q_KEY_CODE_BRACKET_LEFT] = 64,
|
||||||
|
[Q_KEY_CODE_BRACKET_RIGHT] = 65,
|
||||||
|
[Q_KEY_CODE_RET] = 89,
|
||||||
|
[Q_KEY_CODE_A] = 77,
|
||||||
|
[Q_KEY_CODE_S] = 78,
|
||||||
|
[Q_KEY_CODE_D] = 79,
|
||||||
|
[Q_KEY_CODE_F] = 80,
|
||||||
|
[Q_KEY_CODE_G] = 81,
|
||||||
|
[Q_KEY_CODE_H] = 82,
|
||||||
|
[Q_KEY_CODE_J] = 83,
|
||||||
|
[Q_KEY_CODE_K] = 84,
|
||||||
|
[Q_KEY_CODE_L] = 85,
|
||||||
|
[Q_KEY_CODE_SEMICOLON] = 86,
|
||||||
|
[Q_KEY_CODE_APOSTROPHE] = 87,
|
||||||
|
[Q_KEY_CODE_GRAVE_ACCENT] = 42,
|
||||||
|
[Q_KEY_CODE_BACKSLASH] = 88,
|
||||||
|
[Q_KEY_CODE_Z] = 100,
|
||||||
|
[Q_KEY_CODE_X] = 101,
|
||||||
|
[Q_KEY_CODE_C] = 102,
|
||||||
|
[Q_KEY_CODE_V] = 103,
|
||||||
|
[Q_KEY_CODE_B] = 104,
|
||||||
|
[Q_KEY_CODE_N] = 105,
|
||||||
|
[Q_KEY_CODE_M] = 106,
|
||||||
|
[Q_KEY_CODE_COMMA] = 107,
|
||||||
|
[Q_KEY_CODE_DOT] = 108,
|
||||||
|
[Q_KEY_CODE_SLASH] = 109,
|
||||||
|
[Q_KEY_CODE_ASTERISK] = 47,
|
||||||
|
[Q_KEY_CODE_SPC] = 121,
|
||||||
|
[Q_KEY_CODE_CAPS_LOCK] = 119,
|
||||||
|
[Q_KEY_CODE_F1] = 5,
|
||||||
|
[Q_KEY_CODE_F2] = 6,
|
||||||
|
[Q_KEY_CODE_F3] = 8,
|
||||||
|
[Q_KEY_CODE_F4] = 10,
|
||||||
|
[Q_KEY_CODE_F5] = 12,
|
||||||
|
[Q_KEY_CODE_F6] = 14,
|
||||||
|
[Q_KEY_CODE_F7] = 16,
|
||||||
|
[Q_KEY_CODE_F8] = 17,
|
||||||
|
[Q_KEY_CODE_F9] = 18,
|
||||||
|
[Q_KEY_CODE_F10] = 7,
|
||||||
|
[Q_KEY_CODE_NUM_LOCK] = 98,
|
||||||
|
[Q_KEY_CODE_SCROLL_LOCK] = 23,
|
||||||
|
[Q_KEY_CODE_KP_DIVIDE] = 46,
|
||||||
|
[Q_KEY_CODE_KP_MULTIPLY] = 47,
|
||||||
|
[Q_KEY_CODE_KP_SUBTRACT] = 71,
|
||||||
|
[Q_KEY_CODE_KP_ADD] = 125,
|
||||||
|
[Q_KEY_CODE_KP_ENTER] = 90,
|
||||||
|
[Q_KEY_CODE_KP_DECIMAL] = 50,
|
||||||
|
[Q_KEY_CODE_KP_0] = 94,
|
||||||
|
[Q_KEY_CODE_KP_1] = 112,
|
||||||
|
[Q_KEY_CODE_KP_2] = 113,
|
||||||
|
[Q_KEY_CODE_KP_3] = 114,
|
||||||
|
[Q_KEY_CODE_KP_4] = 91,
|
||||||
|
[Q_KEY_CODE_KP_5] = 92,
|
||||||
|
[Q_KEY_CODE_KP_6] = 93,
|
||||||
|
[Q_KEY_CODE_KP_7] = 68,
|
||||||
|
[Q_KEY_CODE_KP_8] = 69,
|
||||||
|
[Q_KEY_CODE_KP_9] = 70,
|
||||||
|
[Q_KEY_CODE_LESS] = 124,
|
||||||
|
[Q_KEY_CODE_F11] = 9,
|
||||||
|
[Q_KEY_CODE_F12] = 11,
|
||||||
|
[Q_KEY_CODE_HOME] = 52,
|
||||||
|
[Q_KEY_CODE_PGUP] = 96,
|
||||||
|
[Q_KEY_CODE_PGDN] = 123,
|
||||||
|
[Q_KEY_CODE_END] = 74,
|
||||||
|
[Q_KEY_CODE_LEFT] = 24,
|
||||||
|
[Q_KEY_CODE_UP] = 20,
|
||||||
|
[Q_KEY_CODE_DOWN] = 27,
|
||||||
|
[Q_KEY_CODE_RIGHT] = 28,
|
||||||
|
[Q_KEY_CODE_INSERT] = 44,
|
||||||
|
[Q_KEY_CODE_DELETE] = 66,
|
||||||
|
[Q_KEY_CODE_STOP] = 1,
|
||||||
|
[Q_KEY_CODE_AGAIN] = 3,
|
||||||
|
[Q_KEY_CODE_PROPS] = 25,
|
||||||
|
[Q_KEY_CODE_UNDO] = 26,
|
||||||
|
[Q_KEY_CODE_FRONT] = 49,
|
||||||
|
[Q_KEY_CODE_COPY] = 51,
|
||||||
|
[Q_KEY_CODE_OPEN] = 72,
|
||||||
|
[Q_KEY_CODE_PASTE] = 73,
|
||||||
|
[Q_KEY_CODE_FIND] = 95,
|
||||||
|
[Q_KEY_CODE_CUT] = 97,
|
||||||
|
[Q_KEY_CODE_LF] = 111,
|
||||||
|
[Q_KEY_CODE_HELP] = 118,
|
||||||
|
[Q_KEY_CODE_META_L] = 120,
|
||||||
|
[Q_KEY_CODE_META_R] = 122,
|
||||||
|
[Q_KEY_CODE_COMPOSE] = 67,
|
||||||
|
[Q_KEY_CODE_PRINT] = 22,
|
||||||
|
[Q_KEY_CODE_SYSRQ] = 21,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t e0_keycodes[128] = {
|
static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
InputEvent *evt)
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
|
|
||||||
113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void sunkbd_event(void *opaque, int ch)
|
|
||||||
{
|
{
|
||||||
ChannelState *s = opaque;
|
ChannelState *s = (ChannelState *)dev;
|
||||||
int release = ch & 0x80;
|
int qcode, keycode;
|
||||||
|
|
||||||
trace_escc_sunkbd_event_in(ch);
|
assert(evt->kind == INPUT_EVENT_KIND_KEY);
|
||||||
switch (ch) {
|
qcode = qemu_input_key_value_to_qcode(evt->key->key);
|
||||||
case 58: // Caps lock press
|
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
|
||||||
|
evt->key->down);
|
||||||
|
|
||||||
|
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
|
||||||
|
if (evt->key->down) {
|
||||||
s->caps_lock_mode ^= 1;
|
s->caps_lock_mode ^= 1;
|
||||||
if (s->caps_lock_mode == 2)
|
if (s->caps_lock_mode == 2) {
|
||||||
return; // Drop second press
|
return; /* Drop second press */
|
||||||
break;
|
|
||||||
case 69: // Num lock press
|
|
||||||
s->num_lock_mode ^= 1;
|
|
||||||
if (s->num_lock_mode == 2)
|
|
||||||
return; // Drop second press
|
|
||||||
break;
|
|
||||||
case 186: // Caps lock release
|
|
||||||
s->caps_lock_mode ^= 2;
|
|
||||||
if (s->caps_lock_mode == 3)
|
|
||||||
return; // Drop first release
|
|
||||||
break;
|
|
||||||
case 197: // Num lock release
|
|
||||||
s->num_lock_mode ^= 2;
|
|
||||||
if (s->num_lock_mode == 3)
|
|
||||||
return; // Drop first release
|
|
||||||
break;
|
|
||||||
case 0xe0:
|
|
||||||
s->e0_mode = 1;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (s->e0_mode) {
|
|
||||||
s->e0_mode = 0;
|
|
||||||
ch = e0_keycodes[ch & 0x7f];
|
|
||||||
} else {
|
} else {
|
||||||
ch = keycodes[ch & 0x7f];
|
s->caps_lock_mode ^= 2;
|
||||||
|
if (s->caps_lock_mode == 3) {
|
||||||
|
return; /* Drop first release */
|
||||||
}
|
}
|
||||||
trace_escc_sunkbd_event_out(ch);
|
|
||||||
put_queue(s, ch | release);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qcode == Q_KEY_CODE_NUM_LOCK) {
|
||||||
|
if (evt->key->down) {
|
||||||
|
s->num_lock_mode ^= 1;
|
||||||
|
if (s->num_lock_mode == 2) {
|
||||||
|
return; /* Drop second press */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s->num_lock_mode ^= 2;
|
||||||
|
if (s->num_lock_mode == 3) {
|
||||||
|
return; /* Drop first release */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keycode = qcode_to_keycode[qcode];
|
||||||
|
if (!evt->key->down) {
|
||||||
|
keycode |= 0x80;
|
||||||
|
}
|
||||||
|
trace_escc_sunkbd_event_out(keycode);
|
||||||
|
put_queue(s, keycode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QemuInputHandler sunkbd_handler = {
|
||||||
|
.name = "sun keyboard",
|
||||||
|
.mask = INPUT_EVENT_MASK_KEY,
|
||||||
|
.event = sunkbd_handle_event,
|
||||||
|
};
|
||||||
|
|
||||||
static void handle_kbd_command(ChannelState *s, int val)
|
static void handle_kbd_command(ChannelState *s, int val)
|
||||||
{
|
{
|
||||||
@@ -800,7 +912,7 @@ static void handle_kbd_command(ChannelState *s, int val)
|
|||||||
case 0xf:
|
case 0xf:
|
||||||
clear_queue(s);
|
clear_queue(s);
|
||||||
put_queue(s, 0xfe);
|
put_queue(s, 0xfe);
|
||||||
put_queue(s, 0); // XXX, layout?
|
put_queue(s, 0x21); /* en-us layout */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -898,7 +1010,8 @@ static int escc_init1(SysBusDevice *dev)
|
|||||||
"QEMU Sun Mouse");
|
"QEMU Sun Mouse");
|
||||||
}
|
}
|
||||||
if (s->chn[1].type == kbd) {
|
if (s->chn[1].type == kbd) {
|
||||||
qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
|
s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
|
||||||
|
&sunkbd_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -560,7 +560,6 @@ static const VMStateDescription vmstate_exynos4210_uart_fifo = {
|
|||||||
.name = "exynos4210.uart.fifo",
|
.name = "exynos4210.uart.fifo",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(sp, Exynos4210UartFIFO),
|
VMSTATE_UINT32(sp, Exynos4210UartFIFO),
|
||||||
VMSTATE_UINT32(rp, Exynos4210UartFIFO),
|
VMSTATE_UINT32(rp, Exynos4210UartFIFO),
|
||||||
@@ -573,7 +572,6 @@ static const VMStateDescription vmstate_exynos4210_uart = {
|
|||||||
.name = "exynos4210.uart",
|
.name = "exynos4210.uart",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_STRUCT(rx, Exynos4210UartState, 1,
|
VMSTATE_STRUCT(rx, Exynos4210UartState, 1,
|
||||||
vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO),
|
vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO),
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ static const VMStateDescription vmstate_imx_serial = {
|
|||||||
.name = "imx-serial",
|
.name = "imx-serial",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_INT32(readbuff, IMXSerialState),
|
VMSTATE_INT32(readbuff, IMXSerialState),
|
||||||
VMSTATE_UINT32(usr1, IMXSerialState),
|
VMSTATE_UINT32(usr1, IMXSerialState),
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ static const VMStateDescription vmstate_scc2698_channel = {
|
|||||||
.name = "scc2698_channel",
|
.name = "scc2698_channel",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_BOOL(rx_enabled, SCC2698Channel),
|
VMSTATE_BOOL(rx_enabled, SCC2698Channel),
|
||||||
VMSTATE_UINT8_ARRAY(mr, SCC2698Channel, 2),
|
VMSTATE_UINT8_ARRAY(mr, SCC2698Channel, 2),
|
||||||
@@ -141,7 +140,6 @@ static const VMStateDescription vmstate_scc2698_block = {
|
|||||||
.name = "scc2698_block",
|
.name = "scc2698_block",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(imr, SCC2698Block),
|
VMSTATE_UINT8(imr, SCC2698Block),
|
||||||
VMSTATE_UINT8(isr, SCC2698Block),
|
VMSTATE_UINT8(isr, SCC2698Block),
|
||||||
@@ -153,7 +151,6 @@ static const VMStateDescription vmstate_ipoctal = {
|
|||||||
.name = "ipoctal232",
|
.name = "ipoctal232",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_IPACK_DEVICE(parent_obj, IPOctalState),
|
VMSTATE_IPACK_DEVICE(parent_obj, IPOctalState),
|
||||||
VMSTATE_STRUCT_ARRAY(ch, IPOctalState, N_CHANNELS, 1,
|
VMSTATE_STRUCT_ARRAY(ch, IPOctalState, N_CHANNELS, 1,
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ static const VMStateDescription vmstate_lm32_juart = {
|
|||||||
.name = "lm32-juart",
|
.name = "lm32-juart",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(jtx, LM32JuartState),
|
VMSTATE_UINT32(jtx, LM32JuartState),
|
||||||
VMSTATE_UINT32(jrx, LM32JuartState),
|
VMSTATE_UINT32(jrx, LM32JuartState),
|
||||||
|
|||||||
@@ -270,7 +270,6 @@ static const VMStateDescription vmstate_lm32_uart = {
|
|||||||
.name = "lm32-uart",
|
.name = "lm32-uart",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX),
|
VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
|
|||||||
@@ -221,7 +221,6 @@ static const VMStateDescription vmstate_milkymist_uart = {
|
|||||||
.name = "milkymist-uart",
|
.name = "milkymist-uart",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(regs, MilkymistUartState, R_MAX),
|
VMSTATE_UINT32_ARRAY(regs, MilkymistUartState, R_MAX),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
|
|||||||
@@ -251,7 +251,6 @@ static const VMStateDescription vmstate_pl011 = {
|
|||||||
.name = "pl011",
|
.name = "pl011",
|
||||||
.version_id = 2,
|
.version_id = 2,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 2,
|
||||||
.minimum_version_id_old = 2,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32(readbuff, PL011State),
|
VMSTATE_UINT32(readbuff, PL011State),
|
||||||
VMSTATE_UINT32(flags, PL011State),
|
VMSTATE_UINT32(flags, PL011State),
|
||||||
|
|||||||
@@ -291,7 +291,6 @@ static const VMStateDescription vmstate_sclplmconsole = {
|
|||||||
.name = "sclplmconsole",
|
.name = "sclplmconsole",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.minimum_version_id = 0,
|
.minimum_version_id = 0,
|
||||||
.minimum_version_id_old = 0,
|
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_BOOL(event.event_pending, SCLPConsoleLM),
|
VMSTATE_BOOL(event.event_pending, SCLPConsoleLM),
|
||||||
VMSTATE_UINT32(write_errors, SCLPConsoleLM),
|
VMSTATE_UINT32(write_errors, SCLPConsoleLM),
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user