Compare commits
345 Commits
pull-sdl-1
...
pull-smbio
Author | SHA1 | Date | |
---|---|---|---|
|
c97294ec1b | ||
|
2e6e8d7a25 | ||
|
cb36acb672 | ||
|
e41fca3da7 | ||
|
e6667f719c | ||
|
7bf8ef196e | ||
|
3458b2b075 | ||
|
fdaad4715a | ||
|
e50bf23438 | ||
|
c090c10dc4 | ||
|
87f6ede9bb | ||
|
f42c5c8ec8 | ||
|
3078e848fa | ||
|
6420474384 | ||
|
37f0806ed9 | ||
|
6ab9f49934 | ||
|
1b505f93bc | ||
|
fed3ffb9f1 | ||
|
252ec40576 | ||
|
e3da9921eb | ||
|
3b77157964 | ||
|
051b9980b9 | ||
|
52b08670e2 | ||
|
61e5b75c17 | ||
|
b7079df410 | ||
|
1f2cead324 | ||
|
838ef60249 | ||
|
b69cdef876 | ||
|
e466183718 | ||
|
38bbc0a580 | ||
|
9e550b3260 | ||
|
f6246509be | ||
|
0549ea8b6d | ||
|
e1b42f456f | ||
|
b93f995081 | ||
|
a49139af77 | ||
|
521b2b5df0 | ||
|
91f827dcff | ||
|
48add816cf | ||
|
e080f0fdff | ||
|
40f1ee27aa | ||
|
35d0d40a03 | ||
|
f1f25a2e2e | ||
|
7e3d98dd31 | ||
|
8bfea15dda | ||
|
5669b44de5 | ||
|
317fc44ef2 | ||
|
0b50cc8853 | ||
|
cffb12051a | ||
|
c883db0df9 | ||
|
cc8a7e560c | ||
|
c557527455 | ||
|
b006f8162e | ||
|
c3cc95bd15 | ||
|
373df5b135 | ||
|
e855e4fb7b | ||
|
3f2fde2a00 | ||
|
8b15d9f1d2 | ||
|
341a034742 | ||
|
d437074140 | ||
|
db1da1f2b5 | ||
|
3d914488ae | ||
|
105923e08c | ||
|
9068f20dfb | ||
|
a3f4d63d63 | ||
|
f92d61f336 | ||
|
4843877e5d | ||
|
5f6979cba9 | ||
|
ebd0c614d7 | ||
|
035b239826 | ||
|
35e2da1556 | ||
|
b357f902bf | ||
|
98b90bab3f | ||
|
425532d71d | ||
|
f4c166619e | ||
|
8b66eefe0d | ||
|
34b1a49cb1 | ||
|
a24fba935a | ||
|
9f44adc573 | ||
|
4bb7a41ed6 | ||
|
71b926992e | ||
|
f0e9736012 | ||
|
7db1689c35 | ||
|
e2da502c00 | ||
|
93156cef1c | ||
|
13de54eedd | ||
|
a41b2c995b | ||
|
d09a18d44d | ||
|
4a39cbb034 | ||
|
a889bc2bb2 | ||
|
0850fd583f | ||
|
63e3e24db2 | ||
|
e2bbfc8ee2 | ||
|
b87b8a8b32 | ||
|
7a30842186 | ||
|
b920cad669 | ||
|
00a9cacaea | ||
|
b0f9300ca3 | ||
|
9057698d93 | ||
|
d461863d3c | ||
|
7fb8b5d9c4 | ||
|
24c12b7923 | ||
|
6924bc1eef | ||
|
a629f2fdba | ||
|
5d77c8f9b6 | ||
|
a27b04577e | ||
|
296b14491a | ||
|
2d2ad6d090 | ||
|
6e1d3c1c85 | ||
|
e96e5ae880 | ||
|
eb6282f230 | ||
|
e3f9bb011a | ||
|
8439761852 | ||
|
172fc4dd33 | ||
|
f70edf9948 | ||
|
92de901290 | ||
|
4399c438a4 | ||
|
0fb6395c0c | ||
|
a28315ebaf | ||
|
460787605e | ||
|
9974ad40bf | ||
|
d1db760d7b | ||
|
1ba4b6a553 | ||
|
0b9f0e2fd7 | ||
|
1b7a0f758b | ||
|
c20499d985 | ||
|
c3481247e5 | ||
|
9083da1d4c | ||
|
638fb14169 | ||
|
2da1b3abbc | ||
|
bfa40f77af | ||
|
f7bdc41acc | ||
|
073a341151 | ||
|
0b15abfcbc | ||
|
f231b88db1 | ||
|
d73f0beadb | ||
|
4ad417baa4 | ||
|
4a66d3bf9a | ||
|
d876f60d14 | ||
|
027a79c373 | ||
|
02d1608980 | ||
|
411f491e0a | ||
|
f663faac3e | ||
|
b925965294 | ||
|
16cf0b2b34 | ||
|
13a12f869b | ||
|
7931b05987 | ||
|
44b0c0bbb5 | ||
|
860643bc5a | ||
|
9ffd26859d | ||
|
8c0124490b | ||
|
0e96643c98 | ||
|
ad600a4d49 | ||
|
ba3627ec38 | ||
|
4b8abfb78e | ||
|
370e681629 | ||
|
840a178c94 | ||
|
9b17031ac4 | ||
|
ac1307abfe | ||
|
409951f552 | ||
|
90d9d30152 | ||
|
f2d953ec31 | ||
|
9ffe333276 | ||
|
98522f63f4 | ||
|
5ff679b47d | ||
|
636ea3708c | ||
|
acd7fdc6d8 | ||
|
b8afb520e4 | ||
|
4ab9dab5b9 | ||
|
9ce10c0bdc | ||
|
da15ee5134 | ||
|
1dd3a44753 | ||
|
54db38a479 | ||
|
02eb19d0ec | ||
|
662deb908f | ||
|
f46fc4e6a9 | ||
|
df9ebea53e | ||
|
671c835b7d | ||
|
4b304cfae1 | ||
|
1194dcba22 | ||
|
170bf9315b | ||
|
f6c6afc1d4 | ||
|
d998e555d2 | ||
|
1976cccec8 | ||
|
50c5c4d125 | ||
|
20022fa15f | ||
|
ad5171dbd4 | ||
|
b36dc67b95 | ||
|
9d85d55732 | ||
|
2300aed15d | ||
|
e40cdb0e6e | ||
|
968fc24d84 | ||
|
423d00c857 | ||
|
ee25595f01 | ||
|
86e117724a | ||
|
d61ce900b9 | ||
|
1634df567d | ||
|
b321afbefd | ||
|
0374f5089a | ||
|
3bf16cb31a | ||
|
4bdd547aaa | ||
|
af9fe31070 | ||
|
1f91f39219 | ||
|
b672cf66c3 | ||
|
4c186ee2cf | ||
|
dcf91778ca | ||
|
2d03b49c3f | ||
|
e44a90c596 | ||
|
33bbd75a7c | ||
|
5538937368 | ||
|
6954a1cd97 | ||
|
15e3611e1c | ||
|
db302f8f93 | ||
|
6619bc5c55 | ||
|
103db49a10 | ||
|
286226a479 | ||
|
a63f9f85e3 | ||
|
323a8771cf | ||
|
2237094d96 | ||
|
1c70aa6264 | ||
|
f727d0e621 | ||
|
b5cde1da0a | ||
|
177311157c | ||
|
7633378d5f | ||
|
c29f9a0a29 | ||
|
f318cec6ad | ||
|
377a44ec8f | ||
|
3933443e38 | ||
|
19525524a7 | ||
|
f32cdad55d | ||
|
9449fdf61f | ||
|
00a29f3ddc | ||
|
85acfa9c38 | ||
|
1090b9c6cc | ||
|
2eef0bf821 | ||
|
014406b510 | ||
|
0ff644a786 | ||
|
cb1fa941c1 | ||
|
a50c0f5133 | ||
|
52e60cdd34 | ||
|
2f2a00aec9 | ||
|
a65f1de982 | ||
|
f502cfc207 | ||
|
a0618a1990 | ||
|
6cd8a2649a | ||
|
7e09797c29 | ||
|
aca3f40b37 | ||
|
9225d739e7 | ||
|
2c8dd31863 | ||
|
2c7ffc414d | ||
|
90e496386f | ||
|
8c6afa6ab1 | ||
|
00892383c9 | ||
|
d4a2dc675b | ||
|
8bcbf37caa | ||
|
abf1172fc6 | ||
|
c2b820fe58 | ||
|
ccd380876b | ||
|
c6138aabfb | ||
|
5149e557d7 | ||
|
06ef8604e9 | ||
|
39acc64741 | ||
|
e566be049a | ||
|
8f811b9a4a | ||
|
a9e05a1ceb | ||
|
0e154fe92c | ||
|
ef3765cb95 | ||
|
e8d8fef48f | ||
|
6580935246 | ||
|
76bff4f82f | ||
|
e20b8c04a3 | ||
|
8b0190bbde | ||
|
f477ed3c11 | ||
|
cd2754addc | ||
|
3d045dbca5 | ||
|
baee04abba | ||
|
b144be9e06 | ||
|
5e5863ecf1 | ||
|
9a734d64f9 | ||
|
9a8fa1bdad | ||
|
83ebb7cd01 | ||
|
42774a56ec | ||
|
958683482c | ||
|
cd2d46fd21 | ||
|
595b8fdd54 | ||
|
a4af30447b | ||
|
46010969f3 | ||
|
c67b67e511 | ||
|
1eaa1da7e4 | ||
|
8f56ced8aa | ||
|
89fe090bb3 | ||
|
6b88b37c0e | ||
|
075b8ddb9b | ||
|
de4d3555fa | ||
|
3bd67b7dab | ||
|
db4a16458c | ||
|
194cfb43d5 | ||
|
64f45e4991 | ||
|
5238c88657 | ||
|
67debe3ae5 | ||
|
a9e8aeb375 | ||
|
b825025f08 | ||
|
a056c9faa4 | ||
|
3d4299f425 | ||
|
dc73dfd4bc | ||
|
edd8824cd4 | ||
|
e81864a109 | ||
|
de61d14fa7 | ||
|
667b1cdd4e | ||
|
9e4177ad6d | ||
|
dc0c8aaf2c | ||
|
ae7ab46aa8 | ||
|
6f4724672c | ||
|
38d195aa05 | ||
|
95f72aa90a | ||
|
d82b78e48b | ||
|
3d9e69a238 | ||
|
cae1f6f3e6 | ||
|
81d8a5ee19 | ||
|
c6e310d938 | ||
|
d8918df577 | ||
|
4ec4f0bd56 | ||
|
dfeb5fe770 | ||
|
929f8b5550 | ||
|
8bf56493f1 | ||
|
661f7fa4b0 | ||
|
851627352c | ||
|
50212d6346 | ||
|
c2b9af1d6c | ||
|
940973ae0b | ||
|
8611224a7b | ||
|
482f38b948 | ||
|
590e5dd98f | ||
|
f12d048a52 | ||
|
3c99afc779 | ||
|
9878d173f5 | ||
|
8c6c047899 | ||
|
92b3eeadd9 | ||
|
edc2438512 | ||
|
21e2db7260 | ||
|
80fc7b1755 | ||
|
5450466394 | ||
|
cd82b6fb4d | ||
|
715c3f60ef | ||
|
28ec11bc88 |
18
.gitignore
vendored
18
.gitignore
vendored
@@ -18,8 +18,8 @@
|
|||||||
/*-darwin-user
|
/*-darwin-user
|
||||||
/*-linux-user
|
/*-linux-user
|
||||||
/*-bsd-user
|
/*-bsd-user
|
||||||
libdis*
|
/libdis*
|
||||||
libuser
|
/libuser
|
||||||
/linux-headers/asm
|
/linux-headers/asm
|
||||||
/qga/qapi-generated
|
/qga/qapi-generated
|
||||||
/qapi-generated
|
/qapi-generated
|
||||||
@@ -49,19 +49,9 @@ libuser
|
|||||||
/qemu-monitor.texi
|
/qemu-monitor.texi
|
||||||
/qmp-commands.txt
|
/qmp-commands.txt
|
||||||
/vscclient
|
/vscclient
|
||||||
/test-bitops
|
|
||||||
/test-coroutine
|
|
||||||
/test-int128
|
|
||||||
/test-opts-visitor
|
|
||||||
/test-qmp-input-visitor
|
|
||||||
/test-qmp-output-visitor
|
|
||||||
/test-string-input-visitor
|
|
||||||
/test-string-output-visitor
|
|
||||||
/test-visitor-serialization
|
|
||||||
/fsdev/virtfs-proxy-helper
|
/fsdev/virtfs-proxy-helper
|
||||||
/fsdev/virtfs-proxy-helper.1
|
/fsdev/virtfs-proxy-helper.1
|
||||||
/fsdev/virtfs-proxy-helper.pod
|
/fsdev/virtfs-proxy-helper.pod
|
||||||
/.gdbinit
|
|
||||||
*.a
|
*.a
|
||||||
*.aux
|
*.aux
|
||||||
*.cp
|
*.cp
|
||||||
@@ -90,12 +80,8 @@ libuser
|
|||||||
*.pc
|
*.pc
|
||||||
.libs
|
.libs
|
||||||
.sdk
|
.sdk
|
||||||
*.swp
|
|
||||||
*.orig
|
|
||||||
.pc
|
|
||||||
*.gcda
|
*.gcda
|
||||||
*.gcno
|
*.gcno
|
||||||
patches
|
|
||||||
/pc-bios/bios-pq/status
|
/pc-bios/bios-pq/status
|
||||||
/pc-bios/vgabios-pq/status
|
/pc-bios/vgabios-pq/status
|
||||||
/pc-bios/optionrom/linuxboot.asm
|
/pc-bios/optionrom/linuxboot.asm
|
||||||
|
@@ -674,6 +674,8 @@ S: Supported
|
|||||||
F: block*
|
F: block*
|
||||||
F: block/
|
F: block/
|
||||||
F: hw/block/
|
F: hw/block/
|
||||||
|
F: qemu-img*
|
||||||
|
F: qemu-io*
|
||||||
T: git git://repo.or.cz/qemu/kevin.git block
|
T: git git://repo.or.cz/qemu/kevin.git block
|
||||||
T: git git://github.com/stefanha/qemu.git block
|
T: git git://github.com/stefanha/qemu.git block
|
||||||
|
|
||||||
|
@@ -310,13 +310,28 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
|
|||||||
|
|
||||||
/* Called with iothread lock taken. */
|
/* Called with iothread lock taken. */
|
||||||
|
|
||||||
static void set_dirty_tracking(void)
|
static int set_dirty_tracking(void)
|
||||||
{
|
{
|
||||||
BlkMigDevState *bmds;
|
BlkMigDevState *bmds;
|
||||||
|
int ret;
|
||||||
|
|
||||||
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
||||||
bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE);
|
bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,
|
||||||
|
NULL);
|
||||||
|
if (!bmds->dirty_bitmap) {
|
||||||
|
ret = -errno;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
||||||
|
if (bmds->dirty_bitmap) {
|
||||||
|
bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unset_dirty_tracking(void)
|
static void unset_dirty_tracking(void)
|
||||||
@@ -611,10 +626,17 @@ static int block_save_setup(QEMUFile *f, void *opaque)
|
|||||||
block_mig_state.submitted, block_mig_state.transferred);
|
block_mig_state.submitted, block_mig_state.transferred);
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
init_blk_migration(f);
|
|
||||||
|
|
||||||
/* start track dirty blocks */
|
/* start track dirty blocks */
|
||||||
set_dirty_tracking();
|
ret = set_dirty_tracking();
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_blk_migration(f);
|
||||||
|
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
ret = flush_blks(f);
|
ret = flush_blks(f);
|
||||||
|
208
block.c
208
block.c
@@ -332,10 +332,21 @@ void bdrv_register(BlockDriver *bdrv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create a new block device (by default it is empty) */
|
/* create a new block device (by default it is empty) */
|
||||||
BlockDriverState *bdrv_new(const char *device_name)
|
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
|
||||||
|
if (bdrv_find(device_name)) {
|
||||||
|
error_setg(errp, "Device with id '%s' already exists",
|
||||||
|
device_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (bdrv_find_node(device_name)) {
|
||||||
|
error_setg(errp, "Device with node-name '%s' already exists",
|
||||||
|
device_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bs = g_malloc0(sizeof(BlockDriverState));
|
bs = g_malloc0(sizeof(BlockDriverState));
|
||||||
QLIST_INIT(&bs->dirty_bitmaps);
|
QLIST_INIT(&bs->dirty_bitmaps);
|
||||||
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
|
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
|
||||||
@@ -763,6 +774,45 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
|||||||
bs->copy_on_read--;
|
bs->copy_on_read--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the flags that bs->file should get, based on the given flags for
|
||||||
|
* the parent BDS
|
||||||
|
*/
|
||||||
|
static int bdrv_inherited_flags(int flags)
|
||||||
|
{
|
||||||
|
/* Enable protocol handling, disable format probing for bs->file */
|
||||||
|
flags |= BDRV_O_PROTOCOL;
|
||||||
|
|
||||||
|
/* Our block drivers take care to send flushes and respect unmap policy,
|
||||||
|
* so we can enable both unconditionally on lower layers. */
|
||||||
|
flags |= BDRV_O_CACHE_WB | BDRV_O_UNMAP;
|
||||||
|
|
||||||
|
/* The backing file of a temporary snapshot is read-only */
|
||||||
|
if (flags & BDRV_O_SNAPSHOT) {
|
||||||
|
flags &= ~BDRV_O_RDWR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear flags that only apply to the top layer */
|
||||||
|
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the flags that bs->backing_hd should get, based on the given flags
|
||||||
|
* for the parent BDS
|
||||||
|
*/
|
||||||
|
static int bdrv_backing_flags(int flags)
|
||||||
|
{
|
||||||
|
/* backing files always opened read-only */
|
||||||
|
flags &= ~(BDRV_O_RDWR | BDRV_O_COPY_ON_READ);
|
||||||
|
|
||||||
|
/* snapshot=on is handled on the top layer */
|
||||||
|
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||||
{
|
{
|
||||||
int open_flags = flags | BDRV_O_CACHE_WB;
|
int open_flags = flags | BDRV_O_CACHE_WB;
|
||||||
@@ -781,45 +831,43 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
|||||||
/*
|
/*
|
||||||
* Snapshots should be writable.
|
* Snapshots should be writable.
|
||||||
*/
|
*/
|
||||||
if (bs->is_temporary) {
|
if (flags & BDRV_O_TEMPORARY) {
|
||||||
open_flags |= BDRV_O_RDWR;
|
open_flags |= BDRV_O_RDWR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return open_flags;
|
return open_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdrv_assign_node_name(BlockDriverState *bs,
|
static void bdrv_assign_node_name(BlockDriverState *bs,
|
||||||
const char *node_name,
|
const char *node_name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (!node_name) {
|
if (!node_name) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* empty string node name is invalid */
|
/* empty string node name is invalid */
|
||||||
if (node_name[0] == '\0') {
|
if (node_name[0] == '\0') {
|
||||||
error_setg(errp, "Empty node name");
|
error_setg(errp, "Empty node name");
|
||||||
return -EINVAL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* takes care of avoiding namespaces collisions */
|
/* takes care of avoiding namespaces collisions */
|
||||||
if (bdrv_find(node_name)) {
|
if (bdrv_find(node_name)) {
|
||||||
error_setg(errp, "node-name=%s is conflicting with a device id",
|
error_setg(errp, "node-name=%s is conflicting with a device id",
|
||||||
node_name);
|
node_name);
|
||||||
return -EINVAL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* takes care of avoiding duplicates node names */
|
/* takes care of avoiding duplicates node names */
|
||||||
if (bdrv_find_node(node_name)) {
|
if (bdrv_find_node(node_name)) {
|
||||||
error_setg(errp, "Duplicate node name");
|
error_setg(errp, "Duplicate node name");
|
||||||
return -EINVAL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy node name into the bs and insert it into the graph list */
|
/* copy node name into the bs and insert it into the graph list */
|
||||||
pstrcpy(bs->node_name, sizeof(bs->node_name), node_name);
|
pstrcpy(bs->node_name, sizeof(bs->node_name), node_name);
|
||||||
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs, node_list);
|
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs, node_list);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -854,9 +902,10 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
|
trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
|
||||||
|
|
||||||
node_name = qdict_get_try_str(options, "node-name");
|
node_name = qdict_get_try_str(options, "node-name");
|
||||||
ret = bdrv_assign_node_name(bs, node_name, errp);
|
bdrv_assign_node_name(bs, node_name, &local_err);
|
||||||
if (ret < 0) {
|
if (local_err) {
|
||||||
return ret;
|
error_propagate(errp, local_err);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
qdict_del(options, "node-name");
|
qdict_del(options, "node-name");
|
||||||
|
|
||||||
@@ -941,13 +990,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
bdrv_refresh_limits(bs);
|
bdrv_refresh_limits(bs);
|
||||||
assert(bdrv_opt_mem_align(bs) != 0);
|
assert(bdrv_opt_mem_align(bs) != 0);
|
||||||
assert((bs->request_alignment != 0) || bs->sg);
|
assert((bs->request_alignment != 0) || bs->sg);
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
if (bs->is_temporary) {
|
|
||||||
assert(bs->filename[0] != '\0');
|
|
||||||
unlink(bs->filename);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
free_and_fail:
|
free_and_fail:
|
||||||
@@ -1058,14 +1100,14 @@ fail:
|
|||||||
*/
|
*/
|
||||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||||
{
|
{
|
||||||
char backing_filename[PATH_MAX];
|
char *backing_filename = g_malloc0(PATH_MAX);
|
||||||
int back_flags, ret;
|
int ret = 0;
|
||||||
BlockDriver *back_drv = NULL;
|
BlockDriver *back_drv = NULL;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (bs->backing_hd != NULL) {
|
if (bs->backing_hd != NULL) {
|
||||||
QDECREF(options);
|
QDECREF(options);
|
||||||
return 0;
|
goto free_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NULL means an empty set of options */
|
/* NULL means an empty set of options */
|
||||||
@@ -1078,31 +1120,26 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
|||||||
backing_filename[0] = '\0';
|
backing_filename[0] = '\0';
|
||||||
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
|
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
|
||||||
QDECREF(options);
|
QDECREF(options);
|
||||||
return 0;
|
goto free_exit;
|
||||||
} else {
|
} else {
|
||||||
bdrv_get_full_backing_filename(bs, backing_filename,
|
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
|
||||||
sizeof(backing_filename));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* backing files always opened read-only */
|
|
||||||
back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT |
|
|
||||||
BDRV_O_COPY_ON_READ);
|
|
||||||
|
|
||||||
assert(bs->backing_hd == NULL);
|
assert(bs->backing_hd == NULL);
|
||||||
ret = bdrv_open(&bs->backing_hd,
|
ret = bdrv_open(&bs->backing_hd,
|
||||||
*backing_filename ? backing_filename : NULL, NULL, options,
|
*backing_filename ? backing_filename : NULL, NULL, options,
|
||||||
back_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;
|
bs->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);
|
||||||
return ret;
|
goto free_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bs->backing_hd->file) {
|
if (bs->backing_hd->file) {
|
||||||
@@ -1113,7 +1150,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
|||||||
/* Recalculate the BlockLimits with the backing file */
|
/* Recalculate the BlockLimits with the backing file */
|
||||||
bdrv_refresh_limits(bs);
|
bdrv_refresh_limits(bs);
|
||||||
|
|
||||||
return 0;
|
free_exit:
|
||||||
|
g_free(backing_filename);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1170,8 +1209,7 @@ done:
|
|||||||
void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
|
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
|
||||||
char tmp_filename[PATH_MAX + 1];
|
char *tmp_filename = g_malloc0(PATH_MAX + 1);
|
||||||
|
|
||||||
int64_t total_size;
|
int64_t total_size;
|
||||||
BlockDriver *bdrv_qcow2;
|
BlockDriver *bdrv_qcow2;
|
||||||
QEMUOptionParameter *create_options;
|
QEMUOptionParameter *create_options;
|
||||||
@@ -1187,15 +1225,15 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
|||||||
total_size = bdrv_getlength(bs);
|
total_size = bdrv_getlength(bs);
|
||||||
if (total_size < 0) {
|
if (total_size < 0) {
|
||||||
error_setg_errno(errp, -total_size, "Could not get image size");
|
error_setg_errno(errp, -total_size, "Could not get image size");
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
total_size &= BDRV_SECTOR_MASK;
|
total_size &= BDRV_SECTOR_MASK;
|
||||||
|
|
||||||
/* Create the temporary image */
|
/* Create the temporary image */
|
||||||
ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
|
ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not get temporary filename");
|
error_setg_errno(errp, -ret, "Could not get temporary filename");
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_qcow2 = bdrv_find_format("qcow2");
|
bdrv_qcow2 = bdrv_find_format("qcow2");
|
||||||
@@ -1211,7 +1249,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
|||||||
"'%s': %s", tmp_filename,
|
"'%s': %s", tmp_filename,
|
||||||
error_get_pretty(local_err));
|
error_get_pretty(local_err));
|
||||||
error_free(local_err);
|
error_free(local_err);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare a new options QDict for the temporary file */
|
/* Prepare a new options QDict for the temporary file */
|
||||||
@@ -1221,17 +1259,20 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
|||||||
qdict_put(snapshot_options, "file.filename",
|
qdict_put(snapshot_options, "file.filename",
|
||||||
qstring_from_str(tmp_filename));
|
qstring_from_str(tmp_filename));
|
||||||
|
|
||||||
bs_snapshot = bdrv_new("");
|
bs_snapshot = bdrv_new("", &error_abort);
|
||||||
bs_snapshot->is_temporary = 1;
|
|
||||||
|
|
||||||
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
|
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
|
||||||
bs->open_flags & ~BDRV_O_SNAPSHOT, bdrv_qcow2, &local_err);
|
(bs->open_flags & ~BDRV_O_SNAPSHOT) | BDRV_O_TEMPORARY,
|
||||||
|
bdrv_qcow2, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_append(bs_snapshot, bs);
|
bdrv_append(bs_snapshot, bs);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_free(tmp_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1288,7 +1329,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
if (*pbs) {
|
if (*pbs) {
|
||||||
bs = *pbs;
|
bs = *pbs;
|
||||||
} else {
|
} else {
|
||||||
bs = bdrv_new("");
|
bs = bdrv_new("", &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NULL means an empty set of options */
|
/* NULL means an empty set of options */
|
||||||
@@ -1320,10 +1361,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
|
|
||||||
assert(file == NULL);
|
assert(file == NULL);
|
||||||
ret = bdrv_open_image(&file, filename, options, "file",
|
ret = bdrv_open_image(&file, filename, options, "file",
|
||||||
bdrv_open_flags(bs, flags | BDRV_O_UNMAP) |
|
bdrv_inherited_flags(flags),
|
||||||
BDRV_O_PROTOCOL, true, &local_err);
|
true, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto unlink_and_fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the right image format driver */
|
/* Find the right image format driver */
|
||||||
@@ -1334,7 +1375,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
if (!drv) {
|
if (!drv) {
|
||||||
error_setg(errp, "Invalid driver: '%s'", drvname);
|
error_setg(errp, "Invalid driver: '%s'", drvname);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlink_and_fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1344,18 +1385,18 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Must specify either driver or file");
|
error_setg(errp, "Must specify either driver or file");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlink_and_fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
goto unlink_and_fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the image */
|
/* Open the image */
|
||||||
ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
|
ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto unlink_and_fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file && (bs->file != file)) {
|
if (file && (bs->file != file)) {
|
||||||
@@ -1417,14 +1458,10 @@ done:
|
|||||||
*pbs = bs;
|
*pbs = bs;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unlink_and_fail:
|
fail:
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
bdrv_unref(file);
|
bdrv_unref(file);
|
||||||
}
|
}
|
||||||
if (bs->is_temporary) {
|
|
||||||
unlink(filename);
|
|
||||||
}
|
|
||||||
fail:
|
|
||||||
QDECREF(bs->options);
|
QDECREF(bs->options);
|
||||||
QDECREF(options);
|
QDECREF(options);
|
||||||
bs->options = NULL;
|
bs->options = NULL;
|
||||||
@@ -1488,8 +1525,11 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
|||||||
QSIMPLEQ_INIT(bs_queue);
|
QSIMPLEQ_INIT(bs_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bdrv_open() masks this flag out */
|
||||||
|
flags &= ~BDRV_O_PROTOCOL;
|
||||||
|
|
||||||
if (bs->file) {
|
if (bs->file) {
|
||||||
bdrv_reopen_queue(bs_queue, bs->file, flags);
|
bdrv_reopen_queue(bs_queue, bs->file, bdrv_inherited_flags(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
bs_entry = g_new0(BlockReopenQueueEntry, 1);
|
bs_entry = g_new0(BlockReopenQueueEntry, 1);
|
||||||
@@ -1704,11 +1744,6 @@ void bdrv_close(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
bs->drv->bdrv_close(bs);
|
bs->drv->bdrv_close(bs);
|
||||||
g_free(bs->opaque);
|
g_free(bs->opaque);
|
||||||
#ifdef _WIN32
|
|
||||||
if (bs->is_temporary) {
|
|
||||||
unlink(bs->filename);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bs->opaque = NULL;
|
bs->opaque = NULL;
|
||||||
bs->drv = NULL;
|
bs->drv = NULL;
|
||||||
bs->copy_on_read = 0;
|
bs->copy_on_read = 0;
|
||||||
@@ -1832,7 +1867,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
|
|||||||
BlockDriverState *bs_src)
|
BlockDriverState *bs_src)
|
||||||
{
|
{
|
||||||
/* move some fields that need to stay attached to the device */
|
/* move some fields that need to stay attached to the device */
|
||||||
bs_dest->open_flags = bs_src->open_flags;
|
|
||||||
|
|
||||||
/* dev info */
|
/* dev info */
|
||||||
bs_dest->dev_ops = bs_src->dev_ops;
|
bs_dest->dev_ops = bs_src->dev_ops;
|
||||||
@@ -2581,6 +2615,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
|||||||
{
|
{
|
||||||
int64_t len;
|
int64_t len;
|
||||||
|
|
||||||
|
if (size > INT_MAX) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (!bdrv_is_inserted(bs))
|
if (!bdrv_is_inserted(bs))
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
|
|
||||||
@@ -2601,7 +2639,7 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
|||||||
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
||||||
int nb_sectors)
|
int nb_sectors)
|
||||||
{
|
{
|
||||||
if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2686,6 +2724,10 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
|||||||
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||||
return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
|
return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
|
||||||
&qiov, is_write, flags);
|
&qiov, is_write, flags);
|
||||||
@@ -2741,10 +2783,16 @@ int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
|||||||
*/
|
*/
|
||||||
int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
int64_t target_size = bdrv_getlength(bs) / BDRV_SECTOR_SIZE;
|
int64_t target_size;
|
||||||
int64_t ret, nb_sectors, sector_num = 0;
|
int64_t ret, nb_sectors, sector_num = 0;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
target_size = bdrv_getlength(bs);
|
||||||
|
if (target_size < 0) {
|
||||||
|
return target_size;
|
||||||
|
}
|
||||||
|
target_size /= BDRV_SECTOR_SIZE;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
nb_sectors = target_size - sector_num;
|
nb_sectors = target_size - sector_num;
|
||||||
if (nb_sectors <= 0) {
|
if (nb_sectors <= 0) {
|
||||||
@@ -3574,10 +3622,25 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
|||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
BlockDriver *drv;
|
BlockDriver *drv;
|
||||||
|
int count = 0;
|
||||||
|
const char **formats = NULL;
|
||||||
|
|
||||||
QLIST_FOREACH(drv, &bdrv_drivers, list) {
|
QLIST_FOREACH(drv, &bdrv_drivers, list) {
|
||||||
it(opaque, drv->format_name);
|
if (drv->format_name) {
|
||||||
|
bool found = false;
|
||||||
|
int i = count;
|
||||||
|
while (formats && i && !found) {
|
||||||
|
found = !strcmp(formats[--i], drv->format_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
formats = g_realloc(formats, (count + 1) * sizeof(char *));
|
||||||
|
formats[count++] = drv->format_name;
|
||||||
|
it(opaque, drv->format_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
g_free(formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is to find block backend bs */
|
/* This function is to find block backend bs */
|
||||||
@@ -5096,7 +5159,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
|
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int64_t bitmap_size;
|
int64_t bitmap_size;
|
||||||
BdrvDirtyBitmap *bitmap;
|
BdrvDirtyBitmap *bitmap;
|
||||||
@@ -5105,7 +5169,13 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
|
|||||||
|
|
||||||
granularity >>= BDRV_SECTOR_BITS;
|
granularity >>= BDRV_SECTOR_BITS;
|
||||||
assert(granularity);
|
assert(granularity);
|
||||||
bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
|
bitmap_size = bdrv_getlength(bs);
|
||||||
|
if (bitmap_size < 0) {
|
||||||
|
error_setg_errno(errp, -bitmap_size, "could not get length of device");
|
||||||
|
errno = -bitmap_size;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bitmap_size >>= BDRV_SECTOR_BITS;
|
||||||
bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
|
bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
|
||||||
bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
|
bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
|
||||||
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
||||||
|
@@ -148,16 +148,26 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
|
s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
|
||||||
|
|
||||||
s->extent_size = le32_to_cpu(bochs.extent);
|
s->extent_size = le32_to_cpu(bochs.extent);
|
||||||
if (s->extent_size == 0) {
|
if (s->extent_size < BDRV_SECTOR_SIZE) {
|
||||||
error_setg(errp, "Extent size may not be zero");
|
/* bximage actually never creates extents smaller than 4k */
|
||||||
return -EINVAL;
|
error_setg(errp, "Extent size must be at least 512");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
} else if (!is_power_of_2(s->extent_size)) {
|
||||||
|
error_setg(errp, "Extent size %" PRIu32 " is not a power of two",
|
||||||
|
s->extent_size);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
} else if (s->extent_size > 0x800000) {
|
} else if (s->extent_size > 0x800000) {
|
||||||
error_setg(errp, "Extent size %" PRIu32 " is too large",
|
error_setg(errp, "Extent size %" PRIu32 " is too large",
|
||||||
s->extent_size);
|
s->extent_size);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->catalog_size < bs->total_sectors / s->extent_size) {
|
if (s->catalog_size < DIV_ROUND_UP(bs->total_sectors,
|
||||||
|
s->extent_size / BDRV_SECTOR_SIZE))
|
||||||
|
{
|
||||||
error_setg(errp, "Catalog size is too small for this disk size");
|
error_setg(errp, "Catalog size is too small for this disk size");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -177,13 +187,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
|||||||
uint64_t offset = sector_num * 512;
|
uint64_t offset = sector_num * 512;
|
||||||
uint64_t extent_index, extent_offset, bitmap_offset;
|
uint64_t extent_index, extent_offset, bitmap_offset;
|
||||||
char bitmap_entry;
|
char bitmap_entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
// seek to sector
|
// seek to sector
|
||||||
extent_index = offset / s->extent_size;
|
extent_index = offset / s->extent_size;
|
||||||
extent_offset = (offset % s->extent_size) / 512;
|
extent_offset = (offset % s->extent_size) / 512;
|
||||||
|
|
||||||
if (s->catalog_bitmap[extent_index] == 0xffffffff) {
|
if (s->catalog_bitmap[extent_index] == 0xffffffff) {
|
||||||
return -1; /* not allocated */
|
return 0; /* not allocated */
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap_offset = s->data_offset +
|
bitmap_offset = s->data_offset +
|
||||||
@@ -191,13 +202,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
|||||||
(s->extent_blocks + s->bitmap_blocks));
|
(s->extent_blocks + s->bitmap_blocks));
|
||||||
|
|
||||||
/* read in bitmap for current extent */
|
/* read in bitmap for current extent */
|
||||||
if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
|
ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
|
||||||
&bitmap_entry, 1) != 1) {
|
&bitmap_entry, 1);
|
||||||
return -1;
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
|
if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
|
||||||
return -1; /* not allocated */
|
return 0; /* not allocated */
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
|
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
|
||||||
@@ -210,13 +222,16 @@ static int bochs_read(BlockDriverState *bs, int64_t sector_num,
|
|||||||
|
|
||||||
while (nb_sectors > 0) {
|
while (nb_sectors > 0) {
|
||||||
int64_t block_offset = seek_to_sector(bs, sector_num);
|
int64_t block_offset = seek_to_sector(bs, sector_num);
|
||||||
if (block_offset >= 0) {
|
if (block_offset < 0) {
|
||||||
|
return block_offset;
|
||||||
|
} else if (block_offset > 0) {
|
||||||
ret = bdrv_pread(bs->file, block_offset, buf, 512);
|
ret = bdrv_pread(bs->file, block_offset, buf, 512);
|
||||||
if (ret != 512) {
|
if (ret < 0) {
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
memset(buf, 0, 512);
|
memset(buf, 0, 512);
|
||||||
|
}
|
||||||
nb_sectors--;
|
nb_sectors--;
|
||||||
sector_num++;
|
sector_num++;
|
||||||
buf += 512;
|
buf += 512;
|
||||||
|
@@ -72,7 +72,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
}
|
}
|
||||||
s->block_size = be32_to_cpu(s->block_size);
|
s->block_size = be32_to_cpu(s->block_size);
|
||||||
if (s->block_size % 512) {
|
if (s->block_size % 512) {
|
||||||
error_setg(errp, "block_size %u must be a multiple of 512",
|
error_setg(errp, "block_size %" PRIu32 " must be a multiple of 512",
|
||||||
s->block_size);
|
s->block_size);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
* need a buffer this big.
|
* need a buffer this big.
|
||||||
*/
|
*/
|
||||||
if (s->block_size > MAX_BLOCK_SIZE) {
|
if (s->block_size > MAX_BLOCK_SIZE) {
|
||||||
error_setg(errp, "block_size %u must be %u MB or less",
|
error_setg(errp, "block_size %" PRIu32 " must be %u MB or less",
|
||||||
s->block_size,
|
s->block_size,
|
||||||
MAX_BLOCK_SIZE / (1024 * 1024));
|
MAX_BLOCK_SIZE / (1024 * 1024));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -101,7 +101,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
/* read offsets */
|
/* read offsets */
|
||||||
if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
|
if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
|
||||||
/* Prevent integer overflow */
|
/* Prevent integer overflow */
|
||||||
error_setg(errp, "n_blocks %u must be %zu or less",
|
error_setg(errp, "n_blocks %" PRIu32 " must be %zu or less",
|
||||||
s->n_blocks,
|
s->n_blocks,
|
||||||
(UINT32_MAX - 1) / sizeof(uint64_t));
|
(UINT32_MAX - 1) / sizeof(uint64_t));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -133,7 +133,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
if (s->offsets[i] < s->offsets[i - 1]) {
|
if (s->offsets[i] < s->offsets[i - 1]) {
|
||||||
error_setg(errp, "offsets not monotonically increasing at "
|
error_setg(errp, "offsets not monotonically increasing at "
|
||||||
"index %u, image file is corrupt", i);
|
"index %" PRIu32 ", image file is corrupt", i);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -146,8 +146,8 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
* ridiculous s->compressed_block allocation.
|
* ridiculous s->compressed_block allocation.
|
||||||
*/
|
*/
|
||||||
if (size > 2 * MAX_BLOCK_SIZE) {
|
if (size > 2 * MAX_BLOCK_SIZE) {
|
||||||
error_setg(errp, "invalid compressed block size at index %u, "
|
error_setg(errp, "invalid compressed block size at index %" PRIu32
|
||||||
"image file is corrupt", i);
|
", image file is corrupt", i);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@@ -194,7 +194,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
|||||||
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
|
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
|
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
|
||||||
!bdrv_iostatus_is_enabled(bs)) {
|
!bdrv_iostatus_is_enabled(bs)) {
|
||||||
error_set(errp, QERR_INVALID_PARAMETER_COMBINATION);
|
error_setg(errp, "Invalid parameter combination");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -82,7 +82,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
if (be32_to_cpu(cow_header.version) != COW_VERSION) {
|
if (be32_to_cpu(cow_header.version) != COW_VERSION) {
|
||||||
char version[64];
|
char version[64];
|
||||||
snprintf(version, sizeof(version),
|
snprintf(version, sizeof(version),
|
||||||
"COW version %d", cow_header.version);
|
"COW version %" PRIu32, cow_header.version);
|
||||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||||
bs->device_name, "cow", version);
|
bs->device_name, "cow", version);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
|
149
block/curl.c
149
block/curl.c
@@ -71,6 +71,7 @@ typedef struct CURLState
|
|||||||
struct BDRVCURLState *s;
|
struct BDRVCURLState *s;
|
||||||
CURLAIOCB *acb[CURL_NUM_ACB];
|
CURLAIOCB *acb[CURL_NUM_ACB];
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
|
curl_socket_t sock_fd;
|
||||||
char *orig_buf;
|
char *orig_buf;
|
||||||
size_t buf_start;
|
size_t buf_start;
|
||||||
size_t buf_off;
|
size_t buf_off;
|
||||||
@@ -92,6 +93,7 @@ typedef struct BDRVCURLState {
|
|||||||
|
|
||||||
static void curl_clean_state(CURLState *s);
|
static void curl_clean_state(CURLState *s);
|
||||||
static void curl_multi_do(void *arg);
|
static void curl_multi_do(void *arg);
|
||||||
|
static void curl_multi_read(void *arg);
|
||||||
|
|
||||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||||
static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
|
static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
|
||||||
@@ -113,16 +115,20 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
|
|||||||
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
||||||
void *s, void *sp)
|
void *s, void *sp)
|
||||||
{
|
{
|
||||||
|
CURLState *state = NULL;
|
||||||
|
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
|
||||||
|
state->sock_fd = fd;
|
||||||
|
|
||||||
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
|
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CURL_POLL_IN:
|
case CURL_POLL_IN:
|
||||||
qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, s);
|
qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
|
||||||
break;
|
break;
|
||||||
case CURL_POLL_OUT:
|
case CURL_POLL_OUT:
|
||||||
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, s);
|
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
|
||||||
break;
|
break;
|
||||||
case CURL_POLL_INOUT:
|
case CURL_POLL_INOUT:
|
||||||
qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, s);
|
qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
|
||||||
break;
|
break;
|
||||||
case CURL_POLL_REMOVE:
|
case CURL_POLL_REMOVE:
|
||||||
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
|
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
|
||||||
@@ -155,7 +161,7 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
|||||||
DPRINTF("CURL: Just reading %zd bytes\n", realsize);
|
DPRINTF("CURL: Just reading %zd bytes\n", realsize);
|
||||||
|
|
||||||
if (!s || !s->orig_buf)
|
if (!s || !s->orig_buf)
|
||||||
goto read_end;
|
return 0;
|
||||||
|
|
||||||
if (s->buf_off >= s->buf_len) {
|
if (s->buf_off >= s->buf_len) {
|
||||||
/* buffer full, read nothing */
|
/* buffer full, read nothing */
|
||||||
@@ -180,7 +186,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read_end:
|
|
||||||
return realsize;
|
return realsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +220,8 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for unfinished chunks
|
// Wait for unfinished chunks
|
||||||
if ((start >= state->buf_start) &&
|
if (state->in_use &&
|
||||||
|
(start >= state->buf_start) &&
|
||||||
(start <= buf_fend) &&
|
(start <= buf_fend) &&
|
||||||
(end >= state->buf_start) &&
|
(end >= state->buf_start) &&
|
||||||
(end <= buf_fend))
|
(end <= buf_fend))
|
||||||
@@ -237,68 +243,69 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
|
|||||||
return FIND_RET_NONE;
|
return FIND_RET_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void curl_multi_read(BDRVCURLState *s)
|
static void curl_multi_check_completion(BDRVCURLState *s)
|
||||||
{
|
{
|
||||||
int msgs_in_queue;
|
int msgs_in_queue;
|
||||||
|
|
||||||
/* Try to find done transfers, so we can free the easy
|
/* Try to find done transfers, so we can free the easy
|
||||||
* handle again. */
|
* handle again. */
|
||||||
do {
|
for (;;) {
|
||||||
CURLMsg *msg;
|
CURLMsg *msg;
|
||||||
msg = curl_multi_info_read(s->multi, &msgs_in_queue);
|
msg = curl_multi_info_read(s->multi, &msgs_in_queue);
|
||||||
|
|
||||||
|
/* Quit when there are no more completions */
|
||||||
if (!msg)
|
if (!msg)
|
||||||
break;
|
break;
|
||||||
if (msg->msg == CURLMSG_NONE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (msg->msg) {
|
if (msg->msg == CURLMSG_DONE) {
|
||||||
case CURLMSG_DONE:
|
CURLState *state = NULL;
|
||||||
{
|
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
|
||||||
CURLState *state = NULL;
|
(char **)&state);
|
||||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state);
|
|
||||||
|
|
||||||
/* ACBs for successful messages get completed in curl_read_cb */
|
/* ACBs for successful messages get completed in curl_read_cb */
|
||||||
if (msg->data.result != CURLE_OK) {
|
if (msg->data.result != CURLE_OK) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < CURL_NUM_ACB; i++) {
|
for (i = 0; i < CURL_NUM_ACB; i++) {
|
||||||
CURLAIOCB *acb = state->acb[i];
|
CURLAIOCB *acb = state->acb[i];
|
||||||
|
|
||||||
if (acb == NULL) {
|
if (acb == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
acb->common.cb(acb->common.opaque, -EIO);
|
|
||||||
qemu_aio_release(acb);
|
|
||||||
state->acb[i] = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
curl_clean_state(state);
|
acb->common.cb(acb->common.opaque, -EIO);
|
||||||
break;
|
qemu_aio_release(acb);
|
||||||
|
state->acb[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
msgs_in_queue = 0;
|
curl_clean_state(state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(msgs_in_queue);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void curl_multi_do(void *arg)
|
static void curl_multi_do(void *arg)
|
||||||
{
|
{
|
||||||
BDRVCURLState *s = (BDRVCURLState *)arg;
|
CURLState *s = (CURLState *)arg;
|
||||||
int running;
|
int running;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!s->multi) {
|
if (!s->s->multi) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
r = curl_multi_socket_all(s->multi, &running);
|
r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running);
|
||||||
} while(r == CURLM_CALL_MULTI_PERFORM);
|
} while(r == CURLM_CALL_MULTI_PERFORM);
|
||||||
|
|
||||||
curl_multi_read(s);
|
}
|
||||||
|
|
||||||
|
static void curl_multi_read(void *arg)
|
||||||
|
{
|
||||||
|
CURLState *s = (CURLState *)arg;
|
||||||
|
|
||||||
|
curl_multi_do(arg);
|
||||||
|
curl_multi_check_completion(s->s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void curl_multi_timeout_do(void *arg)
|
static void curl_multi_timeout_do(void *arg)
|
||||||
@@ -313,7 +320,7 @@ static void curl_multi_timeout_do(void *arg)
|
|||||||
|
|
||||||
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
|
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
|
||||||
|
|
||||||
curl_multi_read(s);
|
curl_multi_check_completion(s);
|
||||||
#else
|
#else
|
||||||
abort();
|
abort();
|
||||||
#endif
|
#endif
|
||||||
@@ -337,44 +344,42 @@ static CURLState *curl_init_state(BDRVCURLState *s)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!state) {
|
if (!state) {
|
||||||
g_usleep(100);
|
qemu_aio_wait();
|
||||||
curl_multi_do(s);
|
|
||||||
}
|
}
|
||||||
} while(!state);
|
} while(!state);
|
||||||
|
|
||||||
if (state->curl)
|
if (!state->curl) {
|
||||||
goto has_curl;
|
state->curl = curl_easy_init();
|
||||||
|
if (!state->curl) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
|
||||||
|
(void *)curl_read_cb);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
|
||||||
|
curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
|
||||||
|
|
||||||
state->curl = curl_easy_init();
|
/* Restrict supported protocols to avoid security issues in the more
|
||||||
if (!state->curl)
|
* obscure protocols. For example, do not allow POP3/SMTP/IMAP see
|
||||||
return NULL;
|
* CVE-2013-0249.
|
||||||
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
|
*
|
||||||
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
|
* Restricting protocols is only supported from 7.19.4 upwards.
|
||||||
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb);
|
*/
|
||||||
curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
|
|
||||||
curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
|
|
||||||
curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
|
|
||||||
curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
|
|
||||||
curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
|
|
||||||
curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
|
|
||||||
|
|
||||||
/* Restrict supported protocols to avoid security issues in the more
|
|
||||||
* obscure protocols. For example, do not allow POP3/SMTP/IMAP see
|
|
||||||
* CVE-2013-0249.
|
|
||||||
*
|
|
||||||
* Restricting protocols is only supported from 7.19.4 upwards.
|
|
||||||
*/
|
|
||||||
#if LIBCURL_VERSION_NUM >= 0x071304
|
#if LIBCURL_VERSION_NUM >= 0x071304
|
||||||
curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
|
curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
|
||||||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
|
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#ifdef DEBUG_VERBOSE
|
||||||
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
|
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
has_curl:
|
|
||||||
|
|
||||||
state->s = s;
|
state->s = s;
|
||||||
|
|
||||||
@@ -531,19 +536,17 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
// initialize the multi interface!
|
// initialize the multi interface!
|
||||||
|
|
||||||
s->multi = curl_multi_init();
|
s->multi = curl_multi_init();
|
||||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
|
|
||||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
||||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
||||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
||||||
#endif
|
#endif
|
||||||
curl_multi_do(s);
|
|
||||||
|
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
fprintf(stderr, "CURL: Error opening file: %s\n", state->errmsg);
|
error_setg(errp, "CURL: Error opening file: %s", state->errmsg);
|
||||||
curl_easy_cleanup(state->curl);
|
curl_easy_cleanup(state->curl);
|
||||||
state->curl = NULL;
|
state->curl = NULL;
|
||||||
out_noclean:
|
out_noclean:
|
||||||
@@ -566,6 +569,7 @@ static const AIOCBInfo curl_aiocb_info = {
|
|||||||
static void curl_readv_bh_cb(void *p)
|
static void curl_readv_bh_cb(void *p)
|
||||||
{
|
{
|
||||||
CURLState *state;
|
CURLState *state;
|
||||||
|
int running;
|
||||||
|
|
||||||
CURLAIOCB *acb = p;
|
CURLAIOCB *acb = p;
|
||||||
BDRVCURLState *s = acb->common.bs->opaque;
|
BDRVCURLState *s = acb->common.bs->opaque;
|
||||||
@@ -614,8 +618,9 @@ static void curl_readv_bh_cb(void *p)
|
|||||||
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
|
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
|
||||||
|
|
||||||
curl_multi_add_handle(s->multi, state->curl);
|
curl_multi_add_handle(s->multi, state->curl);
|
||||||
curl_multi_do(s);
|
|
||||||
|
|
||||||
|
/* Tell curl it needs to kick things off */
|
||||||
|
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
||||||
|
@@ -248,8 +248,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
offset += 8;
|
offset += 8;
|
||||||
|
|
||||||
if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
|
if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
|
||||||
error_report("sector count %" PRIu64 " for chunk %u is "
|
error_report("sector count %" PRIu64 " for chunk %" PRIu32
|
||||||
"larger than max (%u)",
|
" is larger than max (%u)",
|
||||||
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
|
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -269,8 +269,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
offset += 8;
|
offset += 8;
|
||||||
|
|
||||||
if (s->lengths[i] > DMG_LENGTHS_MAX) {
|
if (s->lengths[i] > DMG_LENGTHS_MAX) {
|
||||||
error_report("length %" PRIu64 " for chunk %u is larger "
|
error_report("length %" PRIu64 " for chunk %" PRIu32
|
||||||
"than max (%u)",
|
" is larger than max (%u)",
|
||||||
s->lengths[i], i, DMG_LENGTHS_MAX);
|
s->lengths[i], i, DMG_LENGTHS_MAX);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@@ -1095,16 +1095,15 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
|
|||||||
*inq = scsi_datain_unmarshall(task);
|
*inq = scsi_datain_unmarshall(task);
|
||||||
if (*inq == NULL) {
|
if (*inq == NULL) {
|
||||||
error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
|
error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
|
||||||
goto fail;
|
goto fail_with_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (!error_is_set(errp)) {
|
error_setg(errp, "iSCSI: Inquiry command failed : %s",
|
||||||
error_setg(errp, "iSCSI: Inquiry command failed : %s",
|
iscsi_get_error(iscsi));
|
||||||
iscsi_get_error(iscsi));
|
fail_with_err:
|
||||||
}
|
|
||||||
if (task != NULL) {
|
if (task != NULL) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
}
|
}
|
||||||
@@ -1233,6 +1232,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
iscsi_readcapacity_sync(iscsilun, &local_err);
|
iscsi_readcapacity_sync(iscsilun, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
|
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
|
||||||
@@ -1400,7 +1400,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
IscsiLun *iscsilun = NULL;
|
IscsiLun *iscsilun = NULL;
|
||||||
QDict *bs_options;
|
QDict *bs_options;
|
||||||
|
|
||||||
bs = bdrv_new("");
|
bs = bdrv_new("", &error_abort);
|
||||||
|
|
||||||
/* Read out options */
|
/* Read out options */
|
||||||
while (options && options->name) {
|
while (options && options->name) {
|
||||||
|
@@ -325,11 +325,11 @@ static void coroutine_fn mirror_run(void *opaque)
|
|||||||
|
|
||||||
s->common.len = bdrv_getlength(bs);
|
s->common.len = bdrv_getlength(bs);
|
||||||
if (s->common.len <= 0) {
|
if (s->common.len <= 0) {
|
||||||
block_job_completed(&s->common, s->common.len);
|
ret = s->common.len;
|
||||||
return;
|
goto immediate_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = (bdrv_getlength(bs) + s->granularity - 1) / s->granularity;
|
length = DIV_ROUND_UP(s->common.len, s->granularity);
|
||||||
s->in_flight_bitmap = bitmap_new(length);
|
s->in_flight_bitmap = bitmap_new(length);
|
||||||
|
|
||||||
/* If we have no backing file yet in the destination, we cannot let
|
/* If we have no backing file yet in the destination, we cannot let
|
||||||
@@ -339,7 +339,10 @@ static void coroutine_fn mirror_run(void *opaque)
|
|||||||
bdrv_get_backing_filename(s->target, backing_filename,
|
bdrv_get_backing_filename(s->target, backing_filename,
|
||||||
sizeof(backing_filename));
|
sizeof(backing_filename));
|
||||||
if (backing_filename[0] && !s->target->backing_hd) {
|
if (backing_filename[0] && !s->target->backing_hd) {
|
||||||
bdrv_get_info(s->target, &bdi);
|
ret = bdrv_get_info(s->target, &bdi);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto immediate_exit;
|
||||||
|
}
|
||||||
if (s->granularity < bdi.cluster_size) {
|
if (s->granularity < bdi.cluster_size) {
|
||||||
s->buf_size = MAX(s->buf_size, bdi.cluster_size);
|
s->buf_size = MAX(s->buf_size, bdi.cluster_size);
|
||||||
s->cow_bitmap = bitmap_new(length);
|
s->cow_bitmap = bitmap_new(length);
|
||||||
@@ -605,7 +608,10 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
|
|||||||
s->granularity = granularity;
|
s->granularity = granularity;
|
||||||
s->buf_size = MAX(buf_size, granularity);
|
s->buf_size = MAX(buf_size, granularity);
|
||||||
|
|
||||||
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity);
|
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, errp);
|
||||||
|
if (!s->dirty_bitmap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
bdrv_set_enable_write_cache(s->target, true);
|
bdrv_set_enable_write_cache(s->target, true);
|
||||||
bdrv_set_on_error(s->target, on_target_error, on_target_error);
|
bdrv_set_on_error(s->target, on_target_error, on_target_error);
|
||||||
bdrv_iostatus_enable(s->target);
|
bdrv_iostatus_enable(s->target);
|
||||||
@@ -677,7 +683,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
|
|||||||
mirror_start_job(bs, base, speed, 0, 0,
|
mirror_start_job(bs, base, speed, 0, 0,
|
||||||
on_error, on_error, cb, opaque, &local_err,
|
on_error, on_error, cb, opaque, &local_err,
|
||||||
&commit_active_job_driver, false, base);
|
&commit_active_job_driver, false, base);
|
||||||
if (error_is_set(&local_err)) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
goto error_restore_flags;
|
goto error_restore_flags;
|
||||||
}
|
}
|
||||||
|
@@ -175,7 +175,7 @@ static void nbd_parse_filename(const char *filename, QDict *options,
|
|||||||
InetSocketAddress *addr = NULL;
|
InetSocketAddress *addr = NULL;
|
||||||
|
|
||||||
addr = inet_parse(host_spec, errp);
|
addr = inet_parse(host_spec, errp);
|
||||||
if (error_is_set(errp)) {
|
if (!addr) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -343,7 +343,7 @@ static int nfs_file_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 (error_is_set(&local_err)) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@@ -532,12 +532,11 @@ static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
|
|||||||
void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
|
void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
|
||||||
ImageInfoSpecific *info_spec)
|
ImageInfoSpecific *info_spec)
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
|
||||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||||
QObject *obj, *data;
|
QObject *obj, *data;
|
||||||
|
|
||||||
visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
|
visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
|
||||||
&local_err);
|
&error_abort);
|
||||||
obj = qmp_output_get_qobject(ov);
|
obj = qmp_output_get_qobject(ov);
|
||||||
assert(qobject_type(obj) == QTYPE_QDICT);
|
assert(qobject_type(obj) == QTYPE_QDICT);
|
||||||
data = qdict_get(qobject_to_qdict(obj), "data");
|
data = qdict_get(qobject_to_qdict(obj), "data");
|
||||||
|
@@ -119,7 +119,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
}
|
}
|
||||||
if (header.version != QCOW_VERSION) {
|
if (header.version != QCOW_VERSION) {
|
||||||
char version[64];
|
char version[64];
|
||||||
snprintf(version, sizeof(version), "QCOW version %d", header.version);
|
snprintf(version, sizeof(version), "QCOW version %" PRIu32,
|
||||||
|
header.version);
|
||||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||||
bs->device_name, "qcow", version);
|
bs->device_name, "qcow", version);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
|
@@ -42,6 +42,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
|||||||
if (min_size <= s->l1_size)
|
if (min_size <= s->l1_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* Do a sanity check on min_size before trying to calculate new_l1_size
|
||||||
|
* (this prevents overflows during the while loop for the calculation of
|
||||||
|
* new_l1_size) */
|
||||||
|
if (min_size > INT_MAX / sizeof(uint64_t)) {
|
||||||
|
return -EFBIG;
|
||||||
|
}
|
||||||
|
|
||||||
if (exact_size) {
|
if (exact_size) {
|
||||||
new_l1_size = min_size;
|
new_l1_size = min_size;
|
||||||
} else {
|
} else {
|
||||||
@@ -1360,9 +1367,9 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
|||||||
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
|
||||||
|
|
||||||
for (i = 0; i < nb_clusters; i++) {
|
for (i = 0; i < nb_clusters; i++) {
|
||||||
uint64_t old_offset;
|
uint64_t old_l2_entry;
|
||||||
|
|
||||||
old_offset = be64_to_cpu(l2_table[l2_index + i]);
|
old_l2_entry = be64_to_cpu(l2_table[l2_index + i]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure that a discarded area reads back as zeroes for v3 images
|
* Make sure that a discarded area reads back as zeroes for v3 images
|
||||||
@@ -1373,12 +1380,22 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
|||||||
* TODO We might want to use bdrv_get_block_status(bs) here, but we're
|
* TODO We might want to use bdrv_get_block_status(bs) here, but we're
|
||||||
* holding s->lock, so that doesn't work today.
|
* holding s->lock, so that doesn't work today.
|
||||||
*/
|
*/
|
||||||
if (old_offset & QCOW_OFLAG_ZERO) {
|
switch (qcow2_get_cluster_type(old_l2_entry)) {
|
||||||
continue;
|
case QCOW2_CLUSTER_UNALLOCATED:
|
||||||
}
|
if (!bs->backing_hd) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if ((old_offset & L2E_OFFSET_MASK) == 0 && !bs->backing_hd) {
|
case QCOW2_CLUSTER_ZERO:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case QCOW2_CLUSTER_NORMAL:
|
||||||
|
case QCOW2_CLUSTER_COMPRESSED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First remove L2 entries */
|
/* First remove L2 entries */
|
||||||
@@ -1390,7 +1407,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Then decrease the refcount */
|
/* Then decrease the refcount */
|
||||||
qcow2_free_any_clusters(bs, old_offset, 1, type);
|
qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||||
|
@@ -653,6 +653,13 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure that all offsets in the "allocated" range are representable
|
||||||
|
* in an int64_t */
|
||||||
|
if (s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits)) {
|
||||||
|
return -EFBIG;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ALLOC2
|
#ifdef DEBUG_ALLOC2
|
||||||
fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
|
fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
|
||||||
size,
|
size,
|
||||||
@@ -1480,6 +1487,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
size = bdrv_getlength(bs->file);
|
size = bdrv_getlength(bs->file);
|
||||||
|
if (size < 0) {
|
||||||
|
res->check_errors++;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
nb_clusters = size_to_clusters(s, size);
|
nb_clusters = size_to_clusters(s, size);
|
||||||
if (nb_clusters > INT_MAX) {
|
if (nb_clusters > INT_MAX) {
|
||||||
res->check_errors++;
|
res->check_errors++;
|
||||||
|
@@ -124,8 +124,9 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
|||||||
|
|
||||||
case QCOW2_EXT_MAGIC_BACKING_FORMAT:
|
case QCOW2_EXT_MAGIC_BACKING_FORMAT:
|
||||||
if (ext.len >= sizeof(bs->backing_format)) {
|
if (ext.len >= sizeof(bs->backing_format)) {
|
||||||
error_setg(errp, "ERROR: ext_backing_format: len=%u too large"
|
error_setg(errp, "ERROR: ext_backing_format: len=%" PRIu32
|
||||||
" (>=%zu)", ext.len, sizeof(bs->backing_format));
|
" too large (>=%zu)", ext.len,
|
||||||
|
sizeof(bs->backing_format));
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);
|
ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);
|
||||||
@@ -483,7 +484,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (header.version < 2 || header.version > 3) {
|
if (header.version < 2 || header.version > 3) {
|
||||||
report_unsupported(bs, errp, "QCOW version %d", header.version);
|
report_unsupported(bs, errp, "QCOW version %" PRIu32, header.version);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -493,7 +494,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
/* Initialise cluster size */
|
/* Initialise cluster size */
|
||||||
if (header.cluster_bits < MIN_CLUSTER_BITS ||
|
if (header.cluster_bits < MIN_CLUSTER_BITS ||
|
||||||
header.cluster_bits > MAX_CLUSTER_BITS) {
|
header.cluster_bits > MAX_CLUSTER_BITS) {
|
||||||
error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits);
|
error_setg(errp, "Unsupported cluster size: 2^%" PRIu32,
|
||||||
|
header.cluster_bits);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -591,7 +593,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
s->refcount_order = header.refcount_order;
|
s->refcount_order = header.refcount_order;
|
||||||
|
|
||||||
if (header.crypt_method > QCOW_CRYPT_AES) {
|
if (header.crypt_method > QCOW_CRYPT_AES) {
|
||||||
error_setg(errp, "Unsupported encryption method: %i",
|
error_setg(errp, "Unsupported encryption method: %" PRIu32,
|
||||||
header.crypt_method);
|
header.crypt_method);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
16
block/qed.c
16
block/qed.c
@@ -650,19 +650,21 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!qed_is_cluster_size_valid(cluster_size)) {
|
if (!qed_is_cluster_size_valid(cluster_size)) {
|
||||||
fprintf(stderr, "QED cluster size must be within range [%u, %u] and power of 2\n",
|
error_setg(errp, "QED cluster size must be within range [%u, %u] "
|
||||||
QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
|
"and power of 2",
|
||||||
|
QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!qed_is_table_size_valid(table_size)) {
|
if (!qed_is_table_size_valid(table_size)) {
|
||||||
fprintf(stderr, "QED table size must be within range [%u, %u] and power of 2\n",
|
error_setg(errp, "QED table size must be within range [%u, %u] "
|
||||||
QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
|
"and power of 2",
|
||||||
|
QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) {
|
if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) {
|
||||||
fprintf(stderr, "QED image size must be a non-zero multiple of "
|
error_setg(errp, "QED image size must be a non-zero multiple of "
|
||||||
"cluster size and less than %" PRIu64 " bytes\n",
|
"cluster size and less than %" PRIu64 " bytes",
|
||||||
qed_max_image_size(cluster_size, table_size));
|
qed_max_image_size(cluster_size, table_size));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -753,7 +753,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
opts = qemu_opts_create(&quorum_runtime_opts, NULL, 0, &error_abort);
|
opts = qemu_opts_create(&quorum_runtime_opts, NULL, 0, &error_abort);
|
||||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||||
if (error_is_set(&local_err)) {
|
if (local_err) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -828,7 +828,7 @@ close_exit:
|
|||||||
g_free(opened);
|
g_free(opened);
|
||||||
exit:
|
exit:
|
||||||
/* propagate error */
|
/* propagate error */
|
||||||
if (error_is_set(&local_err)) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
}
|
}
|
||||||
QDECREF(list);
|
QDECREF(list);
|
||||||
|
@@ -366,7 +366,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
|||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
const char *filename;
|
const char *filename = NULL;
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
@@ -446,6 +446,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
|
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
|
||||||
|
unlink(filename);
|
||||||
|
}
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -390,6 +390,9 @@ static void raw_close(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
CloseHandle(s->hfile);
|
CloseHandle(s->hfile);
|
||||||
|
if (bs->open_flags & BDRV_O_TEMPORARY) {
|
||||||
|
unlink(bs->filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
static int raw_truncate(BlockDriverState *bs, int64_t offset)
|
||||||
|
@@ -1099,7 +1099,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rsp->result != SD_RES_SUCCESS) {
|
if (rsp->result != SD_RES_SUCCESS) {
|
||||||
error_report("cannot get vdi info, %s, %s %d %s",
|
error_report("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;
|
||||||
@@ -2316,8 +2316,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
|||||||
sn_tab[found].vm_state_size = inode.vm_state_size;
|
sn_tab[found].vm_state_size = inode.vm_state_size;
|
||||||
sn_tab[found].vm_clock_nsec = inode.vm_clock_nsec;
|
sn_tab[found].vm_clock_nsec = inode.vm_clock_nsec;
|
||||||
|
|
||||||
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str), "%u",
|
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str),
|
||||||
inode.snap_id);
|
"%" PRIu32, inode.snap_id);
|
||||||
pstrcpy(sn_tab[found].name,
|
pstrcpy(sn_tab[found].name,
|
||||||
MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)),
|
MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)),
|
||||||
inode.tag);
|
inode.tag);
|
||||||
|
28
block/vdi.c
28
block/vdi.c
@@ -408,34 +408,35 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (header.signature != VDI_SIGNATURE) {
|
if (header.signature != VDI_SIGNATURE) {
|
||||||
error_setg(errp, "Image not in VDI format (bad signature %08x)", header.signature);
|
error_setg(errp, "Image not in VDI format (bad signature %08" PRIx32
|
||||||
|
")", header.signature);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (header.version != VDI_VERSION_1_1) {
|
} else if (header.version != VDI_VERSION_1_1) {
|
||||||
error_setg(errp, "unsupported VDI image (version %u.%u)",
|
error_setg(errp, "unsupported VDI image (version %" PRIu32 ".%" PRIu32
|
||||||
header.version >> 16, header.version & 0xffff);
|
")", header.version >> 16, header.version & 0xffff);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (header.offset_bmap % SECTOR_SIZE != 0) {
|
} else if (header.offset_bmap % SECTOR_SIZE != 0) {
|
||||||
/* We only support block maps which start on a sector boundary. */
|
/* We only support block maps which start on a sector boundary. */
|
||||||
error_setg(errp, "unsupported VDI image (unaligned block map offset "
|
error_setg(errp, "unsupported VDI image (unaligned block map offset "
|
||||||
"0x%x)", header.offset_bmap);
|
"0x%" PRIx32 ")", header.offset_bmap);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (header.offset_data % SECTOR_SIZE != 0) {
|
} else if (header.offset_data % SECTOR_SIZE != 0) {
|
||||||
/* We only support data blocks which start on a sector boundary. */
|
/* We only support data blocks which start on a sector boundary. */
|
||||||
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%x)",
|
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%"
|
||||||
header.offset_data);
|
PRIx32 ")", header.offset_data);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (header.sector_size != SECTOR_SIZE) {
|
} else if (header.sector_size != SECTOR_SIZE) {
|
||||||
error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
|
error_setg(errp, "unsupported VDI image (sector size %" PRIu32
|
||||||
header.sector_size, SECTOR_SIZE);
|
" is not %u)", header.sector_size, SECTOR_SIZE);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
|
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
|
||||||
error_setg(errp, "unsupported VDI image (block size %u is not %u)",
|
error_setg(errp, "unsupported VDI image (block size %" PRIu32
|
||||||
header.block_size, DEFAULT_CLUSTER_SIZE);
|
" is not %u)", header.block_size, DEFAULT_CLUSTER_SIZE);
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto fail;
|
goto fail;
|
||||||
} else if (header.disk_size >
|
} else if (header.disk_size >
|
||||||
@@ -755,6 +756,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
vdi_header_to_le(&header);
|
vdi_header_to_le(&header);
|
||||||
if (write(fd, &header, sizeof(header)) < 0) {
|
if (write(fd, &header, sizeof(header)) < 0) {
|
||||||
result = -errno;
|
result = -errno;
|
||||||
|
goto close_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bmap_size > 0) {
|
if (bmap_size > 0) {
|
||||||
@@ -768,6 +770,8 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
}
|
}
|
||||||
if (write(fd, bmap, bmap_size) < 0) {
|
if (write(fd, bmap, bmap_size) < 0) {
|
||||||
result = -errno;
|
result = -errno;
|
||||||
|
g_free(bmap);
|
||||||
|
goto close_and_exit;
|
||||||
}
|
}
|
||||||
g_free(bmap);
|
g_free(bmap);
|
||||||
}
|
}
|
||||||
@@ -775,10 +779,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
if (image_type == VDI_TYPE_STATIC) {
|
if (image_type == VDI_TYPE_STATIC) {
|
||||||
if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
|
if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
|
||||||
result = -errno;
|
result = -errno;
|
||||||
|
goto close_and_exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(fd) < 0) {
|
close_and_exit:
|
||||||
|
if ((close(fd) < 0) && !result) {
|
||||||
result = -errno;
|
result = -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
block/vmdk.c
23
block/vmdk.c
@@ -262,7 +262,7 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
|
|||||||
p_name = strstr(desc, cid_str);
|
p_name = strstr(desc, cid_str);
|
||||||
if (p_name != NULL) {
|
if (p_name != NULL) {
|
||||||
p_name += cid_str_size;
|
p_name += cid_str_size;
|
||||||
sscanf(p_name, "%x", &cid);
|
sscanf(p_name, "%" SCNx32, &cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cid;
|
return cid;
|
||||||
@@ -290,7 +290,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
|||||||
p_name = strstr(desc, "CID");
|
p_name = strstr(desc, "CID");
|
||||||
if (p_name != NULL) {
|
if (p_name != NULL) {
|
||||||
p_name += sizeof("CID");
|
p_name += sizeof("CID");
|
||||||
snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
|
snprintf(p_name, sizeof(desc) - (p_name - desc), "%" PRIx32 "\n", cid);
|
||||||
pstrcat(desc, sizeof(desc), tmp_desc);
|
pstrcat(desc, sizeof(desc), tmp_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +640,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|||||||
|
|
||||||
if (le32_to_cpu(header.version) > 3) {
|
if (le32_to_cpu(header.version) > 3) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
snprintf(buf, sizeof(buf), "VMDK version %d",
|
snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
|
||||||
le32_to_cpu(header.version));
|
le32_to_cpu(header.version));
|
||||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||||
bs->device_name, "vmdk", buf);
|
bs->device_name, "vmdk", buf);
|
||||||
@@ -671,8 +671,9 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
if (bdrv_getlength(file) <
|
if (bdrv_getlength(file) <
|
||||||
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) {
|
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) {
|
||||||
error_setg(errp, "File truncated, expecting at least %lld bytes",
|
error_setg(errp, "File truncated, expecting at least %" PRId64 " bytes",
|
||||||
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE);
|
(int64_t)(le64_to_cpu(header.grain_offset)
|
||||||
|
* BDRV_SECTOR_SIZE));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,8 +1708,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
const char desc_template[] =
|
const char desc_template[] =
|
||||||
"# Disk DescriptorFile\n"
|
"# Disk DescriptorFile\n"
|
||||||
"version=1\n"
|
"version=1\n"
|
||||||
"CID=%x\n"
|
"CID=%" PRIx32 "\n"
|
||||||
"parentCID=%x\n"
|
"parentCID=%" PRIx32 "\n"
|
||||||
"createType=\"%s\"\n"
|
"createType=\"%s\"\n"
|
||||||
"%s"
|
"%s"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -1720,7 +1721,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
"\n"
|
"\n"
|
||||||
"ddb.virtualHWVersion = \"%d\"\n"
|
"ddb.virtualHWVersion = \"%d\"\n"
|
||||||
"ddb.geometry.cylinders = \"%" PRId64 "\"\n"
|
"ddb.geometry.cylinders = \"%" PRId64 "\"\n"
|
||||||
"ddb.geometry.heads = \"%d\"\n"
|
"ddb.geometry.heads = \"%" PRIu32 "\"\n"
|
||||||
"ddb.geometry.sectors = \"63\"\n"
|
"ddb.geometry.sectors = \"63\"\n"
|
||||||
"ddb.adapterType = \"%s\"\n";
|
"ddb.adapterType = \"%s\"\n";
|
||||||
|
|
||||||
@@ -1780,9 +1781,9 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
strcmp(fmt, "twoGbMaxExtentFlat"));
|
strcmp(fmt, "twoGbMaxExtentFlat"));
|
||||||
compress = !strcmp(fmt, "streamOptimized");
|
compress = !strcmp(fmt, "streamOptimized");
|
||||||
if (flat) {
|
if (flat) {
|
||||||
desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
|
desc_extent_line = "RW %" PRId64 " FLAT \"%s\" 0\n";
|
||||||
} else {
|
} else {
|
||||||
desc_extent_line = "RW %lld SPARSE \"%s\"\n";
|
desc_extent_line = "RW %" PRId64 " SPARSE \"%s\"\n";
|
||||||
}
|
}
|
||||||
if (flat && backing_file) {
|
if (flat && backing_file) {
|
||||||
error_setg(errp, "Flat image can't have backing file");
|
error_setg(errp, "Flat image can't have backing file");
|
||||||
@@ -1850,7 +1851,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
}
|
}
|
||||||
/* generate descriptor file */
|
/* generate descriptor file */
|
||||||
desc = g_strdup_printf(desc_template,
|
desc = g_strdup_printf(desc_template,
|
||||||
(unsigned int)time(NULL),
|
(uint32_t)time(NULL),
|
||||||
parent_cid,
|
parent_cid,
|
||||||
fmt,
|
fmt,
|
||||||
parent_desc_line,
|
parent_desc_line,
|
||||||
|
@@ -2947,7 +2947,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
|||||||
unlink(s->qcow_filename);
|
unlink(s->qcow_filename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s->bs->backing_hd = bdrv_new("");
|
s->bs->backing_hd = 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;
|
||||||
|
35
blockdev.c
35
blockdev.c
@@ -452,16 +452,14 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_find_node(qemu_opts_id(opts))) {
|
|
||||||
error_setg(errp, "device id=%s is conflicting with a node-name",
|
|
||||||
qemu_opts_id(opts));
|
|
||||||
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));
|
||||||
dinfo->bdrv = bdrv_new(dinfo->id);
|
dinfo->bdrv = bdrv_new(dinfo->id, &error);
|
||||||
|
if (error) {
|
||||||
|
error_propagate(errp, error);
|
||||||
|
goto bdrv_new_err;
|
||||||
|
}
|
||||||
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->refcount = 1;
|
dinfo->refcount = 1;
|
||||||
@@ -523,8 +521,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
bdrv_unref(dinfo->bdrv);
|
bdrv_unref(dinfo->bdrv);
|
||||||
g_free(dinfo->id);
|
|
||||||
QTAILQ_REMOVE(&drives, dinfo, next);
|
QTAILQ_REMOVE(&drives, dinfo, next);
|
||||||
|
bdrv_new_err:
|
||||||
|
g_free(dinfo->id);
|
||||||
g_free(dinfo);
|
g_free(dinfo);
|
||||||
early_err:
|
early_err:
|
||||||
QDECREF(bs_opts);
|
QDECREF(bs_opts);
|
||||||
@@ -1116,6 +1115,7 @@ typedef struct InternalSnapshotState {
|
|||||||
static void internal_snapshot_prepare(BlkTransactionState *common,
|
static void internal_snapshot_prepare(BlkTransactionState *common,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
const char *device;
|
const char *device;
|
||||||
const char *name;
|
const char *name;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
@@ -1164,8 +1164,10 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check whether a snapshot with name exist */
|
/* check whether a snapshot with name exist */
|
||||||
ret = bdrv_snapshot_find_by_id_and_name(bs, NULL, name, &old_sn, errp);
|
ret = bdrv_snapshot_find_by_id_and_name(bs, NULL, name, &old_sn,
|
||||||
if (error_is_set(errp)) {
|
&local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
} else if (ret) {
|
} else if (ret) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
@@ -1521,14 +1523,16 @@ static void eject_device(BlockDriverState *bs, int force, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!bdrv_dev_has_removable_media(bs)) {
|
if (!bdrv_dev_has_removable_media(bs)) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
|
error_setg(errp, "Device '%s' is not removable",
|
||||||
|
bdrv_get_device_name(bs));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
|
if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
|
||||||
bdrv_dev_eject_request(bs, force);
|
bdrv_dev_eject_request(bs, force);
|
||||||
if (!force) {
|
if (!force) {
|
||||||
error_set(errp, QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
|
error_setg(errp, "Device '%s' is locked",
|
||||||
|
bdrv_get_device_name(bs));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1876,6 +1880,10 @@ void qmp_block_commit(const char *device,
|
|||||||
*/
|
*/
|
||||||
BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
|
BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
|
|
||||||
|
if (!has_speed) {
|
||||||
|
speed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* drain all i/o before commits */
|
/* drain all i/o before commits */
|
||||||
bdrv_drain_all();
|
bdrv_drain_all();
|
||||||
|
|
||||||
@@ -2216,7 +2224,8 @@ void qmp_block_job_cancel(const char *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (job->paused && !force) {
|
if (job->paused && !force) {
|
||||||
error_set(errp, QERR_BLOCK_JOB_PAUSED, device);
|
error_setg(errp, "The block job for device '%s' is currently paused",
|
||||||
|
device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -88,7 +88,7 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
|
|||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (!job->driver->set_speed) {
|
if (!job->driver->set_speed) {
|
||||||
error_set(errp, QERR_NOT_SUPPORTED);
|
error_set(errp, QERR_UNSUPPORTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
job->driver->set_speed(job, speed, &local_err);
|
job->driver->set_speed(job, speed, &local_err);
|
||||||
|
20
configure
vendored
20
configure
vendored
@@ -1087,7 +1087,10 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--enable-quorum) quorum="yes"
|
--enable-quorum) quorum="yes"
|
||||||
;;
|
;;
|
||||||
*) echo "ERROR: unknown option $opt"; show_help="yes"
|
*)
|
||||||
|
echo "ERROR: unknown option $opt"
|
||||||
|
echo "Try '$0 --help' for more information"
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@@ -1217,8 +1220,8 @@ Advanced options (experts only):
|
|||||||
--enable-modules enable modules support
|
--enable-modules enable modules support
|
||||||
--enable-debug-tcg enable TCG debugging
|
--enable-debug-tcg enable TCG debugging
|
||||||
--disable-debug-tcg disable TCG debugging (default)
|
--disable-debug-tcg disable TCG debugging (default)
|
||||||
--enable-debug-info enable debugging information (default)
|
--enable-debug-info enable debugging information (default)
|
||||||
--disable-debug-info disable debugging information
|
--disable-debug-info disable debugging information
|
||||||
--enable-debug enable common debug build options
|
--enable-debug enable common debug build options
|
||||||
--enable-sparse enable sparse checker
|
--enable-sparse enable sparse checker
|
||||||
--disable-sparse disable sparse checker (default)
|
--disable-sparse disable sparse checker (default)
|
||||||
@@ -1230,6 +1233,7 @@ Advanced options (experts only):
|
|||||||
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
|
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
|
||||||
--disable-gtk disable gtk UI
|
--disable-gtk disable gtk UI
|
||||||
--enable-gtk enable gtk UI
|
--enable-gtk enable gtk UI
|
||||||
|
--with-gtkabi select preferred GTK ABI 2.0 or 3.0
|
||||||
--disable-virtfs disable VirtFS
|
--disable-virtfs disable VirtFS
|
||||||
--enable-virtfs enable VirtFS
|
--enable-virtfs enable VirtFS
|
||||||
--disable-vnc disable VNC
|
--disable-vnc disable VNC
|
||||||
@@ -1353,7 +1357,7 @@ Advanced options (experts only):
|
|||||||
|
|
||||||
NOTE: The object files are built at the place where configure is launched
|
NOTE: The object files are built at the place where configure is launched
|
||||||
EOF
|
EOF
|
||||||
exit 1
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Now we have handled --enable-tcg-interpreter and know we're not just
|
# Now we have handled --enable-tcg-interpreter and know we're not just
|
||||||
@@ -1448,7 +1452,10 @@ done
|
|||||||
if test "$stack_protector" != "no" ; then
|
if test "$stack_protector" != "no" ; then
|
||||||
gcc_flags="-fstack-protector-strong -fstack-protector-all"
|
gcc_flags="-fstack-protector-strong -fstack-protector-all"
|
||||||
for flag in $gcc_flags; do
|
for flag in $gcc_flags; do
|
||||||
if do_cc $QEMU_CFLAGS -Werror $flag -c -o $TMPO $TMPC ; then
|
# We need to check both a compile and a link, since some compiler
|
||||||
|
# setups fail only on a .c->.o compile and some only at link time
|
||||||
|
if do_cc $QEMU_CFLAGS -Werror $flag -c -o $TMPO $TMPC &&
|
||||||
|
compile_prog "-Werror $flag" ""; then
|
||||||
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
|
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
|
||||||
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
|
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
|
||||||
break
|
break
|
||||||
@@ -4092,7 +4099,6 @@ echo "sparse enabled $sparse"
|
|||||||
echo "strip binaries $strip_opt"
|
echo "strip binaries $strip_opt"
|
||||||
echo "profiler $profiler"
|
echo "profiler $profiler"
|
||||||
echo "static build $static"
|
echo "static build $static"
|
||||||
echo "-Werror enabled $werror"
|
|
||||||
if test "$darwin" = "yes" ; then
|
if test "$darwin" = "yes" ; then
|
||||||
echo "Cocoa support $cocoa"
|
echo "Cocoa support $cocoa"
|
||||||
fi
|
fi
|
||||||
@@ -4344,6 +4350,7 @@ if test "$modules" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
if test "$sdl" = "yes" ; then
|
if test "$sdl" = "yes" ; then
|
||||||
echo "CONFIG_SDL=y" >> $config_host_mak
|
echo "CONFIG_SDL=y" >> $config_host_mak
|
||||||
|
echo "CONFIG_SDLABI=$sdlabi" >> $config_host_mak
|
||||||
echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak
|
echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
if test "$cocoa" = "yes" ; then
|
if test "$cocoa" = "yes" ; then
|
||||||
@@ -4427,6 +4434,7 @@ fi
|
|||||||
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||||
if test "$gtk" = "yes" ; then
|
if test "$gtk" = "yes" ; then
|
||||||
echo "CONFIG_GTK=y" >> $config_host_mak
|
echo "CONFIG_GTK=y" >> $config_host_mak
|
||||||
|
echo "CONFIG_GTKABI=$gtkabi" >> $config_host_mak
|
||||||
echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak
|
echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
if test "$vte" = "yes" ; then
|
if test "$vte" = "yes" ; then
|
||||||
|
2
cpus.c
2
cpus.c
@@ -1454,7 +1454,7 @@ void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
|
|||||||
l = sizeof(buf);
|
l = sizeof(buf);
|
||||||
if (l > size)
|
if (l > size)
|
||||||
l = size;
|
l = size;
|
||||||
cpu_physical_memory_rw(addr, buf, l, 0);
|
cpu_physical_memory_read(addr, buf, l);
|
||||||
if (fwrite(buf, 1, l, f) != l) {
|
if (fwrite(buf, 1, l, f) != l) {
|
||||||
error_set(errp, QERR_IO_ERROR);
|
error_set(errp, QERR_IO_ERROR);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
CONFIG_USB_TABLET_WACOM=y
|
CONFIG_USB_TABLET_WACOM=y
|
||||||
CONFIG_USB_STORAGE_BOT=y
|
CONFIG_USB_STORAGE_BOT=y
|
||||||
CONFIG_USB_STORAGE_UAS=y
|
CONFIG_USB_STORAGE_UAS=y
|
||||||
|
CONFIG_USB_STORAGE_MTP=y
|
||||||
CONFIG_USB_SMARTCARD=y
|
CONFIG_USB_SMARTCARD=y
|
||||||
CONFIG_USB_AUDIO=y
|
CONFIG_USB_AUDIO=y
|
||||||
CONFIG_USB_SERIAL=y
|
CONFIG_USB_SERIAL=y
|
||||||
|
@@ -5,9 +5,10 @@ QEMU Standard VGA
|
|||||||
Exists in two variants, for isa and pci.
|
Exists in two variants, for isa and pci.
|
||||||
|
|
||||||
command line switches:
|
command line switches:
|
||||||
-vga std [ picks isa for -M isapc, otherwise pci ]
|
-vga std [ picks isa for -M isapc, otherwise pci ]
|
||||||
-device VGA [ pci variant ]
|
-device VGA [ pci variant ]
|
||||||
-device isa-vga [ isa variant ]
|
-device isa-vga [ isa variant ]
|
||||||
|
-device secondary-vga [ legacy-free pci variant ]
|
||||||
|
|
||||||
|
|
||||||
PCI spec
|
PCI spec
|
||||||
@@ -31,9 +32,15 @@ PCI ROM Region:
|
|||||||
Holds the vgabios (qemu 0.14+).
|
Holds the vgabios (qemu 0.14+).
|
||||||
|
|
||||||
|
|
||||||
|
The legacy-free variant has no ROM and has PCI_CLASS_DISPLAY_OTHER
|
||||||
|
instead of PCI_CLASS_DISPLAY_VGA.
|
||||||
|
|
||||||
|
|
||||||
IO ports used
|
IO ports used
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
Doesn't apply to the legacy-free pci variant, use the MMIO bar instead.
|
||||||
|
|
||||||
03c0 - 03df : standard vga ports
|
03c0 - 03df : standard vga ports
|
||||||
01ce : bochs vbe interface index port
|
01ce : bochs vbe interface index port
|
||||||
01cf : bochs vbe interface data port (x86 only)
|
01cf : bochs vbe interface data port (x86 only)
|
||||||
|
@@ -311,7 +311,7 @@ void hmp_hello_world(Monitor *mon, const QDict *qdict)
|
|||||||
Error *errp = NULL;
|
Error *errp = NULL;
|
||||||
|
|
||||||
qmp_hello_world(!!message, message, &errp);
|
qmp_hello_world(!!message, message, &errp);
|
||||||
if (error_is_set(&errp)) {
|
if (errp) {
|
||||||
monitor_printf(mon, "%s\n", error_get_pretty(errp));
|
monitor_printf(mon, "%s\n", error_get_pretty(errp));
|
||||||
error_free(errp);
|
error_free(errp);
|
||||||
return;
|
return;
|
||||||
@@ -483,7 +483,7 @@ void hmp_info_alarm_clock(Monitor *mon)
|
|||||||
Error *errp = NULL;
|
Error *errp = NULL;
|
||||||
|
|
||||||
clock = qmp_query_alarm_clock(&errp);
|
clock = qmp_query_alarm_clock(&errp);
|
||||||
if (error_is_set(&errp)) {
|
if (errp) {
|
||||||
monitor_printf(mon, "Could not query alarm clock information\n");
|
monitor_printf(mon, "Could not query alarm clock information\n");
|
||||||
error_free(errp);
|
error_free(errp);
|
||||||
return;
|
return;
|
||||||
@@ -634,7 +634,7 @@ void hmp_info_alarm_methods(Monitor *mon)
|
|||||||
Error *errp = NULL;
|
Error *errp = NULL;
|
||||||
|
|
||||||
method_list = qmp_query_alarm_methods(&errp);
|
method_list = qmp_query_alarm_methods(&errp);
|
||||||
if (error_is_set(&errp)) {
|
if (errp) {
|
||||||
monitor_printf(mon, "Could not query alarm methods\n");
|
monitor_printf(mon, "Could not query alarm methods\n");
|
||||||
error_free(errp);
|
error_free(errp);
|
||||||
return;
|
return;
|
||||||
|
@@ -760,6 +760,7 @@ static int proxy_socket(const char *path, uid_t uid, gid_t gid)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size = sizeof(qemu);
|
||||||
client = accept(sock, (struct sockaddr *)&qemu, &size);
|
client = accept(sock, (struct sockaddr *)&qemu, &size);
|
||||||
if (client < 0) {
|
if (client < 0) {
|
||||||
do_perror("accept");
|
do_perror("accept");
|
||||||
|
@@ -176,7 +176,7 @@ ETEXI
|
|||||||
|
|
||||||
{
|
{
|
||||||
.name = "drive_del",
|
.name = "drive_del",
|
||||||
.args_type = "id:s",
|
.args_type = "id:B",
|
||||||
.params = "device",
|
.params = "device",
|
||||||
.help = "remove host block device",
|
.help = "remove host block device",
|
||||||
.user_print = monitor_user_noop,
|
.user_print = monitor_user_noop,
|
||||||
@@ -658,6 +658,7 @@ ETEXI
|
|||||||
.help = "add device, like -device on the command line",
|
.help = "add device, like -device on the command line",
|
||||||
.user_print = monitor_user_noop,
|
.user_print = monitor_user_noop,
|
||||||
.mhandler.cmd_new = do_device_add,
|
.mhandler.cmd_new = do_device_add,
|
||||||
|
.command_completion = device_add_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -673,6 +674,7 @@ ETEXI
|
|||||||
.params = "device",
|
.params = "device",
|
||||||
.help = "remove device",
|
.help = "remove device",
|
||||||
.mhandler.cmd = hmp_device_del,
|
.mhandler.cmd = hmp_device_del,
|
||||||
|
.command_completion = device_del_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -998,26 +1000,34 @@ ETEXI
|
|||||||
|
|
||||||
{
|
{
|
||||||
.name = "dump-guest-memory",
|
.name = "dump-guest-memory",
|
||||||
.args_type = "paging:-p,filename:F,begin:i?,length:i?",
|
.args_type = "paging:-p,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:i?,length:i?",
|
||||||
.params = "[-p] filename [begin] [length]",
|
.params = "[-p] [-z|-l|-s] filename [begin length]",
|
||||||
.help = "dump guest memory to file"
|
.help = "dump guest memory into file 'filename'.\n\t\t\t"
|
||||||
"\n\t\t\t begin(optional): the starting physical address"
|
"-p: do paging to get guest's memory mapping.\n\t\t\t"
|
||||||
"\n\t\t\t length(optional): the memory size, in bytes",
|
"-z: dump in kdump-compressed format, with zlib compression.\n\t\t\t"
|
||||||
|
"-l: dump in kdump-compressed format, with lzo compression.\n\t\t\t"
|
||||||
|
"-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
|
||||||
|
"begin: the starting physical address.\n\t\t\t"
|
||||||
|
"length: the memory size, in bytes.",
|
||||||
.mhandler.cmd = hmp_dump_guest_memory,
|
.mhandler.cmd = hmp_dump_guest_memory,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length}
|
@item dump-guest-memory [-p] @var{filename} @var{begin} @var{length}
|
||||||
|
@item dump-guest-memory [-z|-l|-s] @var{filename}
|
||||||
@findex dump-guest-memory
|
@findex dump-guest-memory
|
||||||
Dump guest memory to @var{protocol}. The file can be processed with crash or
|
Dump guest memory to @var{protocol}. The file can be processed with crash or
|
||||||
gdb.
|
gdb. Without -z|-l|-s, the dump format is ELF.
|
||||||
filename: dump file name
|
-p: do paging to get guest's memory mapping.
|
||||||
paging: do paging to get guest's memory mapping
|
-z: dump in kdump-compressed format, with zlib compression.
|
||||||
|
-l: dump in kdump-compressed format, with lzo compression.
|
||||||
|
-s: dump in kdump-compressed format, with snappy compression.
|
||||||
|
filename: dump file name.
|
||||||
begin: the starting physical address. It's optional, and should be
|
begin: the starting physical address. It's optional, and should be
|
||||||
specified with length together.
|
specified together with length.
|
||||||
length: the memory size, in bytes. It's optional, and should be specified
|
length: the memory size, in bytes. It's optional, and should be specified
|
||||||
with begin together.
|
together with begin.
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1254,6 +1264,7 @@ ETEXI
|
|||||||
.params = "[qom-type=]type,id=str[,prop=value][,...]",
|
.params = "[qom-type=]type,id=str[,prop=value][,...]",
|
||||||
.help = "create QOM object",
|
.help = "create QOM object",
|
||||||
.mhandler.cmd = hmp_object_add,
|
.mhandler.cmd = hmp_object_add,
|
||||||
|
.command_completion = object_add_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1268,6 +1279,7 @@ ETEXI
|
|||||||
.params = "id",
|
.params = "id",
|
||||||
.help = "destroy QOM object",
|
.help = "destroy QOM object",
|
||||||
.mhandler.cmd = hmp_object_del,
|
.mhandler.cmd = hmp_object_del,
|
||||||
|
.command_completion = object_del_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
|
25
hmp.c
25
hmp.c
@@ -1308,16 +1308,35 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
|||||||
{
|
{
|
||||||
Error *errp = NULL;
|
Error *errp = NULL;
|
||||||
int paging = qdict_get_try_bool(qdict, "paging", 0);
|
int paging = qdict_get_try_bool(qdict, "paging", 0);
|
||||||
|
int zlib = qdict_get_try_bool(qdict, "zlib", 0);
|
||||||
|
int lzo = qdict_get_try_bool(qdict, "lzo", 0);
|
||||||
|
int snappy = qdict_get_try_bool(qdict, "snappy", 0);
|
||||||
const char *file = qdict_get_str(qdict, "filename");
|
const char *file = qdict_get_str(qdict, "filename");
|
||||||
bool has_begin = qdict_haskey(qdict, "begin");
|
bool has_begin = qdict_haskey(qdict, "begin");
|
||||||
bool has_length = qdict_haskey(qdict, "length");
|
bool has_length = qdict_haskey(qdict, "length");
|
||||||
/* kdump-compressed format is not supported for HMP */
|
|
||||||
bool has_format = false;
|
|
||||||
int64_t begin = 0;
|
int64_t begin = 0;
|
||||||
int64_t length = 0;
|
int64_t length = 0;
|
||||||
enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
|
enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
|
||||||
char *prot;
|
char *prot;
|
||||||
|
|
||||||
|
if (zlib + lzo + snappy > 1) {
|
||||||
|
error_setg(&errp, "only one of '-z|-l|-s' can be set");
|
||||||
|
hmp_handle_error(mon, &errp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zlib) {
|
||||||
|
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lzo) {
|
||||||
|
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snappy) {
|
||||||
|
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
|
||||||
|
}
|
||||||
|
|
||||||
if (has_begin) {
|
if (has_begin) {
|
||||||
begin = qdict_get_int(qdict, "begin");
|
begin = qdict_get_int(qdict, "begin");
|
||||||
}
|
}
|
||||||
@@ -1328,7 +1347,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
|||||||
prot = g_strconcat("file:", file, NULL);
|
prot = g_strconcat("file:", file, NULL);
|
||||||
|
|
||||||
qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
|
qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
|
||||||
has_format, dump_format, &errp);
|
true, dump_format, &errp);
|
||||||
hmp_handle_error(mon, &errp);
|
hmp_handle_error(mon, &errp);
|
||||||
g_free(prot);
|
g_free(prot);
|
||||||
}
|
}
|
||||||
|
5
hmp.h
5
hmp.h
@@ -15,6 +15,7 @@
|
|||||||
#define HMP_H
|
#define HMP_H
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "qemu/readline.h"
|
||||||
#include "qapi-types.h"
|
#include "qapi-types.h"
|
||||||
#include "qapi/qmp/qdict.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
|
|
||||||
@@ -92,5 +93,9 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict);
|
|||||||
void hmp_cpu_add(Monitor *mon, const QDict *qdict);
|
void hmp_cpu_add(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_object_add(Monitor *mon, const QDict *qdict);
|
void hmp_object_add(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_object_del(Monitor *mon, const QDict *qdict);
|
void hmp_object_del(Monitor *mon, const QDict *qdict);
|
||||||
|
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 device_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void device_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -987,8 +987,9 @@ static void v9fs_attach(void *opaque)
|
|||||||
*/
|
*/
|
||||||
if (!s->migration_blocker) {
|
if (!s->migration_blocker) {
|
||||||
s->root_fid = fid;
|
s->root_fid = fid;
|
||||||
error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
|
error_setg(&s->migration_blocker,
|
||||||
s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
|
"Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'",
|
||||||
|
s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
|
||||||
migrate_add_blocker(s->migration_blocker);
|
migrate_add_blocker(s->migration_blocker);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
@@ -43,6 +43,19 @@ static void cubieboard_init(QEMUMachineInitArgs *args)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object_property_set_int(OBJECT(&s->a10->timer), 32768, "clk0-freq", &err);
|
||||||
|
if (err != NULL) {
|
||||||
|
error_report("Couldn't set clk0 frequency: %s", error_get_pretty(err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_property_set_int(OBJECT(&s->a10->timer), 24000000, "clk1-freq",
|
||||||
|
&err);
|
||||||
|
if (err != NULL) {
|
||||||
|
error_report("Couldn't set clk1 frequency: %s", error_get_pretty(err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
object_property_set_bool(OBJECT(s->a10), true, "realized", &err);
|
object_property_set_bool(OBJECT(s->a10), true, "realized", &err);
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
error_report("Couldn't realize Allwinner A10: %s",
|
error_report("Couldn't realize Allwinner A10: %s",
|
||||||
|
@@ -75,8 +75,6 @@ typedef struct MemMapEntry {
|
|||||||
typedef struct VirtBoardInfo {
|
typedef struct VirtBoardInfo {
|
||||||
struct arm_boot_info bootinfo;
|
struct arm_boot_info bootinfo;
|
||||||
const char *cpu_model;
|
const char *cpu_model;
|
||||||
const char *qdevname;
|
|
||||||
const char *gic_compatible;
|
|
||||||
const MemMapEntry *memmap;
|
const MemMapEntry *memmap;
|
||||||
const int *irqmap;
|
const int *irqmap;
|
||||||
int smp_cpus;
|
int smp_cpus;
|
||||||
@@ -98,10 +96,10 @@ typedef struct VirtBoardInfo {
|
|||||||
static const MemMapEntry a15memmap[] = {
|
static const MemMapEntry a15memmap[] = {
|
||||||
/* Space up to 0x8000000 is reserved for a boot ROM */
|
/* Space up to 0x8000000 is reserved for a boot ROM */
|
||||||
[VIRT_FLASH] = { 0, 0x8000000 },
|
[VIRT_FLASH] = { 0, 0x8000000 },
|
||||||
[VIRT_CPUPERIPHS] = { 0x8000000, 0x8000 },
|
[VIRT_CPUPERIPHS] = { 0x8000000, 0x20000 },
|
||||||
/* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
|
/* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
|
||||||
[VIRT_GIC_DIST] = { 0x8001000, 0x1000 },
|
[VIRT_GIC_DIST] = { 0x8000000, 0x10000 },
|
||||||
[VIRT_GIC_CPU] = { 0x8002000, 0x1000 },
|
[VIRT_GIC_CPU] = { 0x8010000, 0x10000 },
|
||||||
[VIRT_UART] = { 0x9000000, 0x1000 },
|
[VIRT_UART] = { 0x9000000, 0x1000 },
|
||||||
[VIRT_MMIO] = { 0xa000000, 0x200 },
|
[VIRT_MMIO] = { 0xa000000, 0x200 },
|
||||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||||
@@ -117,16 +115,16 @@ static const int a15irqmap[] = {
|
|||||||
static VirtBoardInfo machines[] = {
|
static VirtBoardInfo machines[] = {
|
||||||
{
|
{
|
||||||
.cpu_model = "cortex-a15",
|
.cpu_model = "cortex-a15",
|
||||||
.qdevname = "a15mpcore_priv",
|
.memmap = a15memmap,
|
||||||
.gic_compatible = "arm,cortex-a15-gic",
|
.irqmap = a15irqmap,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.cpu_model = "cortex-a57",
|
||||||
.memmap = a15memmap,
|
.memmap = a15memmap,
|
||||||
.irqmap = a15irqmap,
|
.irqmap = a15irqmap,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.cpu_model = "host",
|
.cpu_model = "host",
|
||||||
/* We use the A15 private peripheral model to get a V2 GIC */
|
|
||||||
.qdevname = "a15mpcore_priv",
|
|
||||||
.gic_compatible = "arm,cortex-a15-gic",
|
|
||||||
.memmap = a15memmap,
|
.memmap = a15memmap,
|
||||||
.irqmap = a15irqmap,
|
.irqmap = a15irqmap,
|
||||||
},
|
},
|
||||||
@@ -251,8 +249,9 @@ static void fdt_add_gic_node(const VirtBoardInfo *vbi)
|
|||||||
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle);
|
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle);
|
||||||
|
|
||||||
qemu_fdt_add_subnode(vbi->fdt, "/intc");
|
qemu_fdt_add_subnode(vbi->fdt, "/intc");
|
||||||
|
/* 'cortex-a15-gic' means 'GIC v2' */
|
||||||
qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
|
qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
|
||||||
vbi->gic_compatible);
|
"arm,cortex-a15-gic");
|
||||||
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
|
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
|
||||||
qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
|
qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
|
||||||
qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
|
qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
|
||||||
@@ -263,6 +262,56 @@ static void fdt_add_gic_node(const VirtBoardInfo *vbi)
|
|||||||
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
|
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void create_gic(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||||
|
{
|
||||||
|
/* We create a standalone GIC v2 */
|
||||||
|
DeviceState *gicdev;
|
||||||
|
SysBusDevice *gicbusdev;
|
||||||
|
const char *gictype = "arm_gic";
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (kvm_irqchip_in_kernel()) {
|
||||||
|
gictype = "kvm-arm-gic";
|
||||||
|
}
|
||||||
|
|
||||||
|
gicdev = qdev_create(NULL, gictype);
|
||||||
|
qdev_prop_set_uint32(gicdev, "revision", 2);
|
||||||
|
qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
|
||||||
|
/* Note that the num-irq property counts both internal and external
|
||||||
|
* interrupts; there are always 32 of the former (mandated by GIC spec).
|
||||||
|
*/
|
||||||
|
qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32);
|
||||||
|
qdev_init_nofail(gicdev);
|
||||||
|
gicbusdev = SYS_BUS_DEVICE(gicdev);
|
||||||
|
sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base);
|
||||||
|
sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
|
||||||
|
|
||||||
|
/* Wire the outputs from each CPU's generic timer to the
|
||||||
|
* appropriate GIC PPI inputs, and the GIC's IRQ output to
|
||||||
|
* the CPU's IRQ input.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < smp_cpus; i++) {
|
||||||
|
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
|
||||||
|
int ppibase = NUM_IRQS + i * 32;
|
||||||
|
/* physical timer; we wire it up to the non-secure timer's ID,
|
||||||
|
* since a real A15 always has TrustZone but QEMU doesn't.
|
||||||
|
*/
|
||||||
|
qdev_connect_gpio_out(cpudev, 0,
|
||||||
|
qdev_get_gpio_in(gicdev, ppibase + 30));
|
||||||
|
/* virtual timer */
|
||||||
|
qdev_connect_gpio_out(cpudev, 1,
|
||||||
|
qdev_get_gpio_in(gicdev, ppibase + 27));
|
||||||
|
|
||||||
|
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_IRQS; i++) {
|
||||||
|
pic[i] = qdev_get_gpio_in(gicdev, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt_add_gic_node(vbi);
|
||||||
|
}
|
||||||
|
|
||||||
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
|
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||||
{
|
{
|
||||||
char *nodename;
|
char *nodename;
|
||||||
@@ -340,8 +389,6 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
|||||||
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);
|
||||||
DeviceState *dev;
|
|
||||||
SysBusDevice *busdev;
|
|
||||||
const char *cpu_model = args->cpu_model;
|
const char *cpu_model = args->cpu_model;
|
||||||
VirtBoardInfo *vbi;
|
VirtBoardInfo *vbi;
|
||||||
|
|
||||||
@@ -404,25 +451,7 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
|||||||
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);
|
||||||
|
|
||||||
dev = qdev_create(NULL, vbi->qdevname);
|
create_gic(vbi, pic);
|
||||||
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
|
|
||||||
/* Note that the num-irq property counts both internal and external
|
|
||||||
* interrupts; there are always 32 of the former (mandated by GIC spec).
|
|
||||||
*/
|
|
||||||
qdev_prop_set_uint32(dev, "num-irq", NUM_IRQS + 32);
|
|
||||||
qdev_init_nofail(dev);
|
|
||||||
busdev = SYS_BUS_DEVICE(dev);
|
|
||||||
sysbus_mmio_map(busdev, 0, vbi->memmap[VIRT_CPUPERIPHS].base);
|
|
||||||
fdt_add_gic_node(vbi);
|
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
|
||||||
DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
|
|
||||||
|
|
||||||
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (n = 0; n < NUM_IRQS; n++) {
|
|
||||||
pic[n] = qdev_get_gpio_in(dev, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
create_uart(vbi, pic);
|
create_uart(vbi, pic);
|
||||||
|
|
||||||
|
@@ -261,6 +261,9 @@ static void hda_audio_set_amp(HDAAudioStream *st)
|
|||||||
left = left * 255 / QEMU_HDA_AMP_STEPS;
|
left = left * 255 / QEMU_HDA_AMP_STEPS;
|
||||||
right = right * 255 / QEMU_HDA_AMP_STEPS;
|
right = right * 255 / QEMU_HDA_AMP_STEPS;
|
||||||
|
|
||||||
|
if (!st->state->mixer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (st->output) {
|
if (st->output) {
|
||||||
AUD_set_volume_out(st->voice.out, muted, left, right);
|
AUD_set_volume_out(st->voice.out, muted, left, right);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -817,11 +817,14 @@ static int blk_connect(struct XenDevice *xendev)
|
|||||||
index = (blkdev->xendev.dev - 202 * 256) / 16;
|
index = (blkdev->xendev.dev - 202 * 256) / 16;
|
||||||
blkdev->dinfo = drive_get(IF_XEN, 0, index);
|
blkdev->dinfo = drive_get(IF_XEN, 0, index);
|
||||||
if (!blkdev->dinfo) {
|
if (!blkdev->dinfo) {
|
||||||
|
Error *local_err = NULL;
|
||||||
/* setup via xenbus -> create new block driver instance */
|
/* setup via xenbus -> create new block driver instance */
|
||||||
xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
|
xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
|
||||||
blkdev->bs = bdrv_new(blkdev->dev);
|
blkdev->bs = bdrv_new(blkdev->dev, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
blkdev->bs = NULL;
|
||||||
|
}
|
||||||
if (blkdev->bs) {
|
if (blkdev->bs) {
|
||||||
Error *local_err = NULL;
|
|
||||||
BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
|
BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
|
||||||
readonly);
|
readonly);
|
||||||
if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
|
if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
|
||||||
|
@@ -587,8 +587,9 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
|
|||||||
|
|
||||||
/* We rely on power-of-2 blocksizes for bitmasks */
|
/* We rely on power-of-2 blocksizes for bitmasks */
|
||||||
if ((value & (value - 1)) != 0) {
|
if ((value & (value - 1)) != 0) {
|
||||||
error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
|
error_setg(errp,
|
||||||
dev->id?:"", name, (int64_t)value);
|
"Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
|
||||||
|
dev->id ?: "", name, (int64_t)value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,7 +854,7 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
|
|||||||
{
|
{
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -EEXIST:
|
case -EEXIST:
|
||||||
error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
|
error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
|
||||||
object_get_typename(OBJECT(dev)), prop->name, value);
|
object_get_typename(OBJECT(dev)), prop->name, value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -862,7 +863,7 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
|
|||||||
object_get_typename(OBJECT(dev)), prop->name, value);
|
object_get_typename(OBJECT(dev)), prop->name, value);
|
||||||
break;
|
break;
|
||||||
case -ENOENT:
|
case -ENOENT:
|
||||||
error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
|
error_setg(errp, "Property '%s.%s' can't find value '%s'",
|
||||||
object_get_typename(OBJECT(dev)), prop->name, value);
|
object_get_typename(OBJECT(dev)), prop->name, value);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
|
@@ -2913,7 +2913,7 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
|
|||||||
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
|
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
|
||||||
VGACommonState *s = &d->cirrus_vga.vga;
|
VGACommonState *s = &d->cirrus_vga.vga;
|
||||||
|
|
||||||
vga_common_init(s, OBJECT(dev));
|
vga_common_init(s, OBJECT(dev), true);
|
||||||
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
|
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
|
||||||
isa_address_space(isadev),
|
isa_address_space(isadev),
|
||||||
isa_address_space_io(isadev));
|
isa_address_space_io(isadev));
|
||||||
@@ -2960,7 +2960,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
|
|||||||
int16_t device_id = pc->device_id;
|
int16_t device_id = pc->device_id;
|
||||||
|
|
||||||
/* setup VGA */
|
/* setup VGA */
|
||||||
vga_common_init(&s->vga, OBJECT(dev));
|
vga_common_init(&s->vga, OBJECT(dev), true);
|
||||||
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
|
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
|
||||||
pci_address_space_io(dev));
|
pci_address_space_io(dev));
|
||||||
s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
|
s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
|
||||||
|
@@ -2061,7 +2061,7 @@ static int qxl_init_primary(PCIDevice *dev)
|
|||||||
qxl->id = 0;
|
qxl->id = 0;
|
||||||
qxl_init_ramsize(qxl);
|
qxl_init_ramsize(qxl);
|
||||||
vga->vram_size_mb = qxl->vga.vram_size >> 20;
|
vga->vram_size_mb = qxl->vga.vram_size >> 20;
|
||||||
vga_common_init(vga, OBJECT(dev));
|
vga_common_init(vga, OBJECT(dev), true);
|
||||||
vga_init(vga, OBJECT(dev),
|
vga_init(vga, OBJECT(dev),
|
||||||
pci_address_space(dev), pci_address_space_io(dev), false);
|
pci_address_space(dev), pci_address_space_io(dev), false);
|
||||||
portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,
|
portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,
|
||||||
|
@@ -132,7 +132,7 @@ int isa_vga_mm_init(hwaddr vram_base,
|
|||||||
s = g_malloc0(sizeof(*s));
|
s = g_malloc0(sizeof(*s));
|
||||||
|
|
||||||
s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
|
s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
|
||||||
vga_common_init(&s->vga, NULL);
|
vga_common_init(&s->vga, NULL, true);
|
||||||
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
|
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
|
||||||
|
|
||||||
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
|
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
|
||||||
|
@@ -56,7 +56,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
|
|||||||
MemoryRegion *vga_io_memory;
|
MemoryRegion *vga_io_memory;
|
||||||
const MemoryRegionPortio *vga_ports, *vbe_ports;
|
const MemoryRegionPortio *vga_ports, *vbe_ports;
|
||||||
|
|
||||||
vga_common_init(s, OBJECT(dev));
|
vga_common_init(s, OBJECT(dev), true);
|
||||||
s->legacy_address_space = isa_address_space(isadev);
|
s->legacy_address_space = isa_address_space(isadev);
|
||||||
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
|
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
|
||||||
isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");
|
isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");
|
||||||
|
@@ -147,7 +147,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
|
|||||||
VGACommonState *s = &d->vga;
|
VGACommonState *s = &d->vga;
|
||||||
|
|
||||||
/* vga + console init */
|
/* vga + console init */
|
||||||
vga_common_init(s, OBJECT(dev));
|
vga_common_init(s, OBJECT(dev), true);
|
||||||
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
|
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
@@ -179,12 +179,51 @@ static int pci_std_vga_initfn(PCIDevice *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pci_secondary_vga_initfn(PCIDevice *dev)
|
||||||
|
{
|
||||||
|
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
|
||||||
|
VGACommonState *s = &d->vga;
|
||||||
|
|
||||||
|
/* vga + console init */
|
||||||
|
vga_common_init(s, OBJECT(dev), false);
|
||||||
|
s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
|
||||||
|
|
||||||
|
/* mmio bar */
|
||||||
|
memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096);
|
||||||
|
memory_region_init_io(&d->ioport, OBJECT(dev), &pci_vga_ioport_ops, d,
|
||||||
|
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
|
||||||
|
memory_region_init_io(&d->bochs, OBJECT(dev), &pci_vga_bochs_ops, d,
|
||||||
|
"bochs dispi interface", PCI_VGA_BOCHS_SIZE);
|
||||||
|
|
||||||
|
memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
|
||||||
|
&d->ioport);
|
||||||
|
memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET,
|
||||||
|
&d->bochs);
|
||||||
|
|
||||||
|
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
|
||||||
|
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pci_secondary_vga_reset(DeviceState *dev)
|
||||||
|
{
|
||||||
|
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev.qdev, dev);
|
||||||
|
|
||||||
|
vga_common_reset(&d->vga);
|
||||||
|
}
|
||||||
|
|
||||||
static Property vga_pci_properties[] = {
|
static Property vga_pci_properties[] = {
|
||||||
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
||||||
DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true),
|
DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property secondary_pci_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void vga_class_init(ObjectClass *klass, void *data)
|
static void vga_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
@@ -201,6 +240,20 @@ static void vga_class_init(ObjectClass *klass, void *data)
|
|||||||
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void secondary_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
k->init = pci_secondary_vga_initfn;
|
||||||
|
k->vendor_id = PCI_VENDOR_ID_QEMU;
|
||||||
|
k->device_id = PCI_DEVICE_ID_QEMU_VGA;
|
||||||
|
k->class_id = PCI_CLASS_DISPLAY_OTHER;
|
||||||
|
dc->vmsd = &vmstate_vga_pci;
|
||||||
|
dc->props = secondary_pci_properties;
|
||||||
|
dc->reset = pci_secondary_vga_reset;
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo vga_info = {
|
static const TypeInfo vga_info = {
|
||||||
.name = "VGA",
|
.name = "VGA",
|
||||||
.parent = TYPE_PCI_DEVICE,
|
.parent = TYPE_PCI_DEVICE,
|
||||||
@@ -208,9 +261,17 @@ static const TypeInfo vga_info = {
|
|||||||
.class_init = vga_class_init,
|
.class_init = vga_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TypeInfo secondary_info = {
|
||||||
|
.name = "secondary-vga",
|
||||||
|
.parent = TYPE_PCI_DEVICE,
|
||||||
|
.instance_size = sizeof(PCIVGAState),
|
||||||
|
.class_init = secondary_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
static void vga_register_types(void)
|
static void vga_register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&vga_info);
|
type_register_static(&vga_info);
|
||||||
|
type_register_static(&secondary_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(vga_register_types)
|
type_init(vga_register_types)
|
||||||
|
@@ -171,6 +171,10 @@ static void vga_update_memory_access(VGACommonState *s)
|
|||||||
MemoryRegion *region, *old_region = s->chain4_alias;
|
MemoryRegion *region, *old_region = s->chain4_alias;
|
||||||
hwaddr base, offset, size;
|
hwaddr base, offset, size;
|
||||||
|
|
||||||
|
if (s->legacy_address_space == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
s->chain4_alias = NULL;
|
s->chain4_alias = NULL;
|
||||||
|
|
||||||
if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
|
if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
|
||||||
@@ -2252,7 +2256,7 @@ static const GraphicHwOps vga_ops = {
|
|||||||
.text_update = vga_update_text,
|
.text_update = vga_update_text,
|
||||||
};
|
};
|
||||||
|
|
||||||
void vga_common_init(VGACommonState *s, Object *obj)
|
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
|
||||||
{
|
{
|
||||||
int i, j, v, b;
|
int i, j, v, b;
|
||||||
|
|
||||||
@@ -2289,7 +2293,7 @@ void vga_common_init(VGACommonState *s, Object *obj)
|
|||||||
|
|
||||||
s->is_vbe_vmstate = 1;
|
s->is_vbe_vmstate = 1;
|
||||||
memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
|
memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
|
||||||
vmstate_register_ram_global(&s->vram);
|
vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
|
||||||
xen_register_framebuffer(&s->vram);
|
xen_register_framebuffer(&s->vram);
|
||||||
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
|
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
|
||||||
s->get_bpp = vga_get_bpp;
|
s->get_bpp = vga_get_bpp;
|
||||||
|
@@ -177,7 +177,7 @@ static inline int c6_to_8(int v)
|
|||||||
return (v << 2) | (b << 1) | b;
|
return (v << 2) | (b << 1) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vga_common_init(VGACommonState *s, Object *obj);
|
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate);
|
||||||
void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
|
void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
|
||||||
MemoryRegion *address_space_io, bool init_vga_ports);
|
MemoryRegion *address_space_io, bool init_vga_ports);
|
||||||
MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
|
MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
|
||||||
|
@@ -1207,7 +1207,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
|
|||||||
vmstate_register_ram_global(&s->fifo_ram);
|
vmstate_register_ram_global(&s->fifo_ram);
|
||||||
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
|
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
|
||||||
|
|
||||||
vga_common_init(&s->vga, OBJECT(dev));
|
vga_common_init(&s->vga, OBJECT(dev), true);
|
||||||
vga_init(&s->vga, OBJECT(dev), address_space, io, true);
|
vga_init(&s->vga, OBJECT(dev), address_space, io, true);
|
||||||
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
|
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
|
||||||
s->new_depth = 32;
|
s->new_depth = 32;
|
||||||
|
@@ -71,7 +71,7 @@ static void eeprom_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int l
|
|||||||
printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
|
printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
|
||||||
dev->i2c.address, cmd, buf[0]);
|
dev->i2c.address, cmd, buf[0]);
|
||||||
#endif
|
#endif
|
||||||
/* An page write operation is not a valid SMBus command.
|
/* A page write operation is not a valid SMBus command.
|
||||||
It is a block write without a length byte. Fortunately we
|
It is a block write without a length byte. Fortunately we
|
||||||
get the full block anyway. */
|
get the full block anyway. */
|
||||||
/* TODO: Should this set the current location? */
|
/* TODO: Should this set the current location? */
|
||||||
|
@@ -391,7 +391,7 @@ static void build_append_int(GArray *table, uint32_t value)
|
|||||||
build_append_byte(table, 0x01); /* OneOp */
|
build_append_byte(table, 0x01); /* OneOp */
|
||||||
} else if (value <= 0xFF) {
|
} else if (value <= 0xFF) {
|
||||||
build_append_value(table, value, 1);
|
build_append_value(table, value, 1);
|
||||||
} else if (value <= 0xFFFFF) {
|
} else if (value <= 0xFFFF) {
|
||||||
build_append_value(table, value, 2);
|
build_append_value(table, value, 2);
|
||||||
} else {
|
} else {
|
||||||
build_append_value(table, value, 4);
|
build_append_value(table, value, 4);
|
||||||
|
@@ -124,14 +124,14 @@ static const TPRInstruction tpr_instr[] = {
|
|||||||
|
|
||||||
static void read_guest_rom_state(VAPICROMState *s)
|
static void read_guest_rom_state(VAPICROMState *s)
|
||||||
{
|
{
|
||||||
cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
|
cpu_physical_memory_read(s->rom_state_paddr, &s->rom_state,
|
||||||
sizeof(GuestROMState), 0);
|
sizeof(GuestROMState));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_guest_rom_state(VAPICROMState *s)
|
static void write_guest_rom_state(VAPICROMState *s)
|
||||||
{
|
{
|
||||||
cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
|
cpu_physical_memory_write(s->rom_state_paddr, &s->rom_state,
|
||||||
sizeof(GuestROMState), 1);
|
sizeof(GuestROMState));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_guest_rom_state(VAPICROMState *s)
|
static void update_guest_rom_state(VAPICROMState *s)
|
||||||
@@ -311,16 +311,14 @@ static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong i
|
|||||||
for (pos = le32_to_cpu(s->rom_state.fixup_start);
|
for (pos = le32_to_cpu(s->rom_state.fixup_start);
|
||||||
pos < le32_to_cpu(s->rom_state.fixup_end);
|
pos < le32_to_cpu(s->rom_state.fixup_end);
|
||||||
pos += 4) {
|
pos += 4) {
|
||||||
cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
|
cpu_physical_memory_read(paddr + pos - s->rom_state.vaddr,
|
||||||
(void *)&offset, sizeof(offset), 0);
|
&offset, sizeof(offset));
|
||||||
offset = le32_to_cpu(offset);
|
offset = le32_to_cpu(offset);
|
||||||
cpu_physical_memory_rw(paddr + offset, (void *)&patch,
|
cpu_physical_memory_read(paddr + offset, &patch, sizeof(patch));
|
||||||
sizeof(patch), 0);
|
|
||||||
patch = le32_to_cpu(patch);
|
patch = le32_to_cpu(patch);
|
||||||
patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
|
patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
|
||||||
patch = cpu_to_le32(patch);
|
patch = cpu_to_le32(patch);
|
||||||
cpu_physical_memory_rw(paddr + offset, (void *)&patch,
|
cpu_physical_memory_write(paddr + offset, &patch, sizeof(patch));
|
||||||
sizeof(patch), 1);
|
|
||||||
}
|
}
|
||||||
read_guest_rom_state(s);
|
read_guest_rom_state(s);
|
||||||
s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
|
s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
|
||||||
@@ -364,8 +362,8 @@ static int vapic_enable(VAPICROMState *s, X86CPU *cpu)
|
|||||||
}
|
}
|
||||||
vapic_paddr = s->vapic_paddr +
|
vapic_paddr = s->vapic_paddr +
|
||||||
(((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
|
(((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
|
||||||
cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
|
cpu_physical_memory_write(vapic_paddr + offsetof(VAPICState, enabled),
|
||||||
(void *)&enabled, sizeof(enabled), 1);
|
&enabled, sizeof(enabled));
|
||||||
apic_enable_vapic(cpu->apic_state, vapic_paddr);
|
apic_enable_vapic(cpu->apic_state, vapic_paddr);
|
||||||
|
|
||||||
s->state = VAPIC_ACTIVE;
|
s->state = VAPIC_ACTIVE;
|
||||||
@@ -535,7 +533,7 @@ static int patch_hypercalls(VAPICROMState *s)
|
|||||||
uint8_t *rom;
|
uint8_t *rom;
|
||||||
|
|
||||||
rom = g_malloc(s->rom_size);
|
rom = g_malloc(s->rom_size);
|
||||||
cpu_physical_memory_rw(rom_paddr, rom, s->rom_size, 0);
|
cpu_physical_memory_read(rom_paddr, rom, s->rom_size);
|
||||||
|
|
||||||
for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
|
for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
|
||||||
if (kvm_irqchip_in_kernel()) {
|
if (kvm_irqchip_in_kernel()) {
|
||||||
@@ -551,8 +549,7 @@ static int patch_hypercalls(VAPICROMState *s)
|
|||||||
}
|
}
|
||||||
if (memcmp(rom + pos, pattern, 7) == 0 &&
|
if (memcmp(rom + pos, pattern, 7) == 0 &&
|
||||||
(rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
|
(rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
|
||||||
cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
|
cpu_physical_memory_write(rom_paddr + pos + 5, patch, 3);
|
||||||
3, 1);
|
|
||||||
/*
|
/*
|
||||||
* Don't flush the tb here. Under ordinary conditions, the patched
|
* Don't flush the tb here. Under ordinary conditions, the patched
|
||||||
* calls are miles away from the current IP. Under malicious
|
* calls are miles away from the current IP. Under malicious
|
||||||
@@ -760,8 +757,8 @@ static int vapic_post_load(void *opaque, int version_id)
|
|||||||
run_on_cpu(first_cpu, do_vapic_enable, s);
|
run_on_cpu(first_cpu, do_vapic_enable, s);
|
||||||
} else {
|
} else {
|
||||||
zero = g_malloc0(s->rom_state.vapic_size);
|
zero = g_malloc0(s->rom_state.vapic_size);
|
||||||
cpu_physical_memory_rw(s->vapic_paddr, zero,
|
cpu_physical_memory_write(s->vapic_paddr, zero,
|
||||||
s->rom_state.vapic_size, 1);
|
s->rom_state.vapic_size);
|
||||||
g_free(zero);
|
g_free(zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
hw/i386/pc.c
39
hw/i386/pc.c
@@ -612,6 +612,21 @@ int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
|
|||||||
return e820_entries;
|
return e820_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int e820_get_num_entries(void)
|
||||||
|
{
|
||||||
|
return e820_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool e820_get_entry(int idx, uint32_t type, uint64_t *address, uint64_t *length)
|
||||||
|
{
|
||||||
|
if (idx < e820_entries && e820_table[idx].type == cpu_to_le32(type)) {
|
||||||
|
*address = le64_to_cpu(e820_table[idx].address);
|
||||||
|
*length = le64_to_cpu(e820_table[idx].length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculates the limit to CPU APIC ID values
|
/* Calculates the limit to CPU APIC ID values
|
||||||
*
|
*
|
||||||
* This function returns the limit for the APIC ID value, so that all
|
* This function returns the limit for the APIC ID value, so that all
|
||||||
@@ -627,8 +642,8 @@ static unsigned int pc_apic_id_limit(unsigned int max_cpus)
|
|||||||
static FWCfgState *bochs_bios_init(void)
|
static FWCfgState *bochs_bios_init(void)
|
||||||
{
|
{
|
||||||
FWCfgState *fw_cfg;
|
FWCfgState *fw_cfg;
|
||||||
uint8_t *smbios_table;
|
uint8_t *smbios_tables, *smbios_anchor;
|
||||||
size_t smbios_len;
|
size_t smbios_tables_len, smbios_anchor_len;
|
||||||
uint64_t *numa_fw_cfg;
|
uint64_t *numa_fw_cfg;
|
||||||
int i, j;
|
int i, j;
|
||||||
unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
|
unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
|
||||||
@@ -655,10 +670,21 @@ static FWCfgState *bochs_bios_init(void)
|
|||||||
acpi_tables, acpi_tables_len);
|
acpi_tables, acpi_tables_len);
|
||||||
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
|
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
|
||||||
|
|
||||||
smbios_table = smbios_get_table(&smbios_len);
|
smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
|
||||||
if (smbios_table)
|
if (smbios_tables) {
|
||||||
fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
|
fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
|
||||||
smbios_table, smbios_len);
|
smbios_tables, smbios_tables_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
smbios_get_tables(&smbios_tables, &smbios_tables_len,
|
||||||
|
&smbios_anchor, &smbios_anchor_len);
|
||||||
|
if (smbios_anchor) {
|
||||||
|
fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables",
|
||||||
|
smbios_tables, smbios_tables_len);
|
||||||
|
fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor",
|
||||||
|
smbios_anchor, smbios_anchor_len);
|
||||||
|
}
|
||||||
|
|
||||||
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
|
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
|
||||||
&e820_reserve, sizeof(e820_reserve));
|
&e820_reserve, sizeof(e820_reserve));
|
||||||
fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
|
fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
|
||||||
@@ -1027,6 +1053,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
|
|||||||
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
|
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
|
||||||
APIC_DEFAULT_ADDRESS, 0x1000);
|
APIC_DEFAULT_ADDRESS, 0x1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tell smbios about cpuid version and features */
|
||||||
|
smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pci-info ROM file. Little endian format */
|
/* pci-info ROM file. Little endian format */
|
||||||
|
@@ -60,7 +60,8 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
|
|||||||
|
|
||||||
static bool has_pci_info;
|
static bool has_pci_info;
|
||||||
static bool has_acpi_build = true;
|
static bool has_acpi_build = true;
|
||||||
static bool smbios_type1_defaults = true;
|
static bool smbios_defaults = true;
|
||||||
|
static bool smbios_legacy_mode;
|
||||||
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
|
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
|
||||||
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
|
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
|
||||||
* pages in the host.
|
* pages in the host.
|
||||||
@@ -143,10 +144,10 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
|||||||
guest_info->has_pci_info = has_pci_info;
|
guest_info->has_pci_info = has_pci_info;
|
||||||
guest_info->isapc_ram_fw = !pci_enabled;
|
guest_info->isapc_ram_fw = !pci_enabled;
|
||||||
|
|
||||||
if (smbios_type1_defaults) {
|
if (smbios_defaults) {
|
||||||
/* These values are guest ABI, do not change */
|
/* These values are guest ABI, do not change */
|
||||||
smbios_set_type1_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
|
smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
|
||||||
args->machine->name);
|
args->machine->name, smbios_legacy_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate ram and load rom/bios */
|
/* allocate ram and load rom/bios */
|
||||||
@@ -262,9 +263,15 @@ static void pc_init_pci(QEMUMachineInitArgs *args)
|
|||||||
pc_init1(args, 1, 1);
|
pc_init1(args, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pc_compat_2_0(QEMUMachineInitArgs *args)
|
||||||
|
{
|
||||||
|
smbios_legacy_mode = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void pc_compat_1_7(QEMUMachineInitArgs *args)
|
static void pc_compat_1_7(QEMUMachineInitArgs *args)
|
||||||
{
|
{
|
||||||
smbios_type1_defaults = false;
|
pc_compat_2_0(args);
|
||||||
|
smbios_defaults = false;
|
||||||
gigabyte_align = false;
|
gigabyte_align = false;
|
||||||
option_rom_has_mr = true;
|
option_rom_has_mr = true;
|
||||||
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
||||||
@@ -303,6 +310,12 @@ static void pc_compat_1_2(QEMUMachineInitArgs *args)
|
|||||||
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pc_init_pci_2_0(QEMUMachineInitArgs *args)
|
||||||
|
{
|
||||||
|
pc_compat_2_0(args);
|
||||||
|
pc_init_pci(args);
|
||||||
|
}
|
||||||
|
|
||||||
static void pc_init_pci_1_7(QEMUMachineInitArgs *args)
|
static void pc_init_pci_1_7(QEMUMachineInitArgs *args)
|
||||||
{
|
{
|
||||||
pc_compat_1_7(args);
|
pc_compat_1_7(args);
|
||||||
@@ -345,7 +358,7 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
|
|||||||
{
|
{
|
||||||
has_pci_info = false;
|
has_pci_info = false;
|
||||||
has_acpi_build = false;
|
has_acpi_build = false;
|
||||||
smbios_type1_defaults = false;
|
smbios_defaults = false;
|
||||||
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||||
enable_compat_apic_id_mode();
|
enable_compat_apic_id_mode();
|
||||||
pc_init1(args, 1, 0);
|
pc_init1(args, 1, 0);
|
||||||
@@ -355,7 +368,7 @@ static void pc_init_isa(QEMUMachineInitArgs *args)
|
|||||||
{
|
{
|
||||||
has_pci_info = false;
|
has_pci_info = false;
|
||||||
has_acpi_build = false;
|
has_acpi_build = false;
|
||||||
smbios_type1_defaults = false;
|
smbios_defaults = false;
|
||||||
if (!args->cpu_model) {
|
if (!args->cpu_model) {
|
||||||
args->cpu_model = "486";
|
args->cpu_model = "486";
|
||||||
}
|
}
|
||||||
@@ -383,16 +396,24 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
|
|||||||
.desc = "Standard PC (i440FX + PIIX, 1996)", \
|
.desc = "Standard PC (i440FX + PIIX, 1996)", \
|
||||||
.hot_add_cpu = pc_hot_add_cpu
|
.hot_add_cpu = pc_hot_add_cpu
|
||||||
|
|
||||||
#define PC_I440FX_2_0_MACHINE_OPTIONS \
|
#define PC_I440FX_2_1_MACHINE_OPTIONS \
|
||||||
PC_I440FX_MACHINE_OPTIONS, \
|
PC_I440FX_MACHINE_OPTIONS, \
|
||||||
.default_machine_opts = "firmware=bios-256k.bin"
|
.default_machine_opts = "firmware=bios-256k.bin"
|
||||||
|
|
||||||
|
static QEMUMachine pc_i440fx_machine_v2_1 = {
|
||||||
|
PC_I440FX_2_1_MACHINE_OPTIONS,
|
||||||
|
.name = "pc-i440fx-2.1",
|
||||||
|
.alias = "pc",
|
||||||
|
.init = pc_init_pci,
|
||||||
|
.is_default = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PC_I440FX_2_0_MACHINE_OPTIONS PC_I440FX_2_1_MACHINE_OPTIONS
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_0 = {
|
static QEMUMachine pc_i440fx_machine_v2_0 = {
|
||||||
PC_I440FX_2_0_MACHINE_OPTIONS,
|
PC_I440FX_2_0_MACHINE_OPTIONS,
|
||||||
.name = "pc-i440fx-2.0",
|
.name = "pc-i440fx-2.0",
|
||||||
.alias = "pc",
|
.init = pc_init_pci_2_0,
|
||||||
.init = pc_init_pci,
|
|
||||||
.is_default = 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
|
#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
|
||||||
@@ -817,6 +838,7 @@ static QEMUMachine xenfv_machine = {
|
|||||||
|
|
||||||
static void pc_machine_init(void)
|
static void pc_machine_init(void)
|
||||||
{
|
{
|
||||||
|
qemu_register_machine(&pc_i440fx_machine_v2_1);
|
||||||
qemu_register_machine(&pc_i440fx_machine_v2_0);
|
qemu_register_machine(&pc_i440fx_machine_v2_0);
|
||||||
qemu_register_machine(&pc_i440fx_machine_v1_7);
|
qemu_register_machine(&pc_i440fx_machine_v1_7);
|
||||||
qemu_register_machine(&pc_i440fx_machine_v1_6);
|
qemu_register_machine(&pc_i440fx_machine_v1_6);
|
||||||
|
@@ -50,7 +50,8 @@
|
|||||||
|
|
||||||
static bool has_pci_info;
|
static bool has_pci_info;
|
||||||
static bool has_acpi_build = true;
|
static bool has_acpi_build = true;
|
||||||
static bool smbios_type1_defaults = true;
|
static bool smbios_defaults = true;
|
||||||
|
static bool smbios_legacy_mode;
|
||||||
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
|
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
|
||||||
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
|
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
|
||||||
* pages in the host.
|
* pages in the host.
|
||||||
@@ -130,10 +131,10 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
|
|||||||
guest_info->isapc_ram_fw = false;
|
guest_info->isapc_ram_fw = false;
|
||||||
guest_info->has_acpi_build = has_acpi_build;
|
guest_info->has_acpi_build = has_acpi_build;
|
||||||
|
|
||||||
if (smbios_type1_defaults) {
|
if (smbios_defaults) {
|
||||||
/* These values are guest ABI, do not change */
|
/* These values are guest ABI, do not change */
|
||||||
smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
|
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
|
||||||
args->machine->name);
|
args->machine->name, smbios_legacy_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate ram and load rom/bios */
|
/* allocate ram and load rom/bios */
|
||||||
@@ -240,9 +241,15 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pc_compat_2_0(QEMUMachineInitArgs *args)
|
||||||
|
{
|
||||||
|
smbios_legacy_mode = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void pc_compat_1_7(QEMUMachineInitArgs *args)
|
static void pc_compat_1_7(QEMUMachineInitArgs *args)
|
||||||
{
|
{
|
||||||
smbios_type1_defaults = false;
|
pc_compat_2_0(args);
|
||||||
|
smbios_defaults = false;
|
||||||
gigabyte_align = false;
|
gigabyte_align = false;
|
||||||
option_rom_has_mr = true;
|
option_rom_has_mr = true;
|
||||||
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
|
||||||
@@ -268,6 +275,12 @@ static void pc_compat_1_4(QEMUMachineInitArgs *args)
|
|||||||
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
|
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pc_q35_init_2_0(QEMUMachineInitArgs *args)
|
||||||
|
{
|
||||||
|
pc_compat_2_0(args);
|
||||||
|
pc_q35_init(args);
|
||||||
|
}
|
||||||
|
|
||||||
static void pc_q35_init_1_7(QEMUMachineInitArgs *args)
|
static void pc_q35_init_1_7(QEMUMachineInitArgs *args)
|
||||||
{
|
{
|
||||||
pc_compat_1_7(args);
|
pc_compat_1_7(args);
|
||||||
@@ -297,15 +310,23 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
|
|||||||
.desc = "Standard PC (Q35 + ICH9, 2009)", \
|
.desc = "Standard PC (Q35 + ICH9, 2009)", \
|
||||||
.hot_add_cpu = pc_hot_add_cpu
|
.hot_add_cpu = pc_hot_add_cpu
|
||||||
|
|
||||||
#define PC_Q35_2_0_MACHINE_OPTIONS \
|
#define PC_Q35_2_1_MACHINE_OPTIONS \
|
||||||
PC_Q35_MACHINE_OPTIONS, \
|
PC_Q35_MACHINE_OPTIONS, \
|
||||||
.default_machine_opts = "firmware=bios-256k.bin"
|
.default_machine_opts = "firmware=bios-256k.bin"
|
||||||
|
|
||||||
|
static QEMUMachine pc_q35_machine_v2_1 = {
|
||||||
|
PC_Q35_2_1_MACHINE_OPTIONS,
|
||||||
|
.name = "pc-q35-2.1",
|
||||||
|
.alias = "q35",
|
||||||
|
.init = pc_q35_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PC_Q35_2_0_MACHINE_OPTIONS PC_Q35_2_1_MACHINE_OPTIONS
|
||||||
|
|
||||||
static QEMUMachine pc_q35_machine_v2_0 = {
|
static QEMUMachine pc_q35_machine_v2_0 = {
|
||||||
PC_Q35_2_0_MACHINE_OPTIONS,
|
PC_Q35_2_0_MACHINE_OPTIONS,
|
||||||
.name = "pc-q35-2.0",
|
.name = "pc-q35-2.0",
|
||||||
.alias = "q35",
|
.init = pc_q35_init_2_0,
|
||||||
.init = pc_q35_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
|
#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
|
||||||
@@ -358,6 +379,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
|
|||||||
|
|
||||||
static void pc_q35_machine_init(void)
|
static void pc_q35_machine_init(void)
|
||||||
{
|
{
|
||||||
|
qemu_register_machine(&pc_q35_machine_v2_1);
|
||||||
qemu_register_machine(&pc_q35_machine_v2_0);
|
qemu_register_machine(&pc_q35_machine_v2_0);
|
||||||
qemu_register_machine(&pc_q35_machine_v1_7);
|
qemu_register_machine(&pc_q35_machine_v1_7);
|
||||||
qemu_register_machine(&pc_q35_machine_v1_6);
|
qemu_register_machine(&pc_q35_machine_v1_6);
|
||||||
|
789
hw/i386/smbios.c
789
hw/i386/smbios.c
@@ -18,12 +18,13 @@
|
|||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "sysemu/cpus.h"
|
||||||
|
#include "hw/i386/pc.h"
|
||||||
#include "hw/i386/smbios.h"
|
#include "hw/i386/smbios.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Structures shared with the BIOS
|
/* legacy structures and constants for <= 2.0 machines */
|
||||||
*/
|
|
||||||
struct smbios_header {
|
struct smbios_header {
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -46,14 +47,23 @@ struct smbios_table {
|
|||||||
|
|
||||||
static uint8_t *smbios_entries;
|
static uint8_t *smbios_entries;
|
||||||
static size_t smbios_entries_len;
|
static size_t smbios_entries_len;
|
||||||
|
static bool smbios_legacy = true;
|
||||||
|
/* end: legacy structures & constants for <= 2.0 machines */
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t *smbios_tables;
|
||||||
|
static size_t smbios_tables_len;
|
||||||
|
static unsigned smbios_table_max;
|
||||||
|
static unsigned smbios_table_cnt;
|
||||||
|
static struct smbios_entry_point ep;
|
||||||
|
|
||||||
static int smbios_type4_count = 0;
|
static int smbios_type4_count = 0;
|
||||||
static bool smbios_immutable;
|
static bool smbios_immutable;
|
||||||
|
static bool smbios_have_defaults;
|
||||||
|
static uint32_t smbios_cpuid_version, smbios_cpuid_features, smbios_smp_sockets;
|
||||||
|
|
||||||
static struct {
|
static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1);
|
||||||
bool seen;
|
static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
|
||||||
int headertype;
|
|
||||||
Location loc;
|
|
||||||
} first_opt[2];
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
const char *vendor, *version, *date;
|
const char *vendor, *version, *date;
|
||||||
@@ -66,6 +76,22 @@ static struct {
|
|||||||
/* uuid is in qemu_uuid[] */
|
/* uuid is in qemu_uuid[] */
|
||||||
} type1;
|
} type1;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *manufacturer, *product, *version, *serial, *asset, *location;
|
||||||
|
} type2;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *manufacturer, *version, *serial, *asset, *sku;
|
||||||
|
} type3;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part;
|
||||||
|
} type4;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *loc_pfx, *bank, *manufacturer, *serial, *asset, *part;
|
||||||
|
} type17;
|
||||||
|
|
||||||
static QemuOptsList qemu_smbios_opts = {
|
static QemuOptsList qemu_smbios_opts = {
|
||||||
.name = "smbios",
|
.name = "smbios",
|
||||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
|
||||||
@@ -149,6 +175,134 @@ static const QemuOptDesc qemu_smbios_type1_opts[] = {
|
|||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const QemuOptDesc qemu_smbios_type2_opts[] = {
|
||||||
|
{
|
||||||
|
.name = "type",
|
||||||
|
.type = QEMU_OPT_NUMBER,
|
||||||
|
.help = "SMBIOS element type",
|
||||||
|
},{
|
||||||
|
.name = "manufacturer",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "manufacturer name",
|
||||||
|
},{
|
||||||
|
.name = "product",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "product name",
|
||||||
|
},{
|
||||||
|
.name = "version",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "version number",
|
||||||
|
},{
|
||||||
|
.name = "serial",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "serial number",
|
||||||
|
},{
|
||||||
|
.name = "asset",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "asset tag number",
|
||||||
|
},{
|
||||||
|
.name = "location",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "location in chassis",
|
||||||
|
},
|
||||||
|
{ /* end of list */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QemuOptDesc qemu_smbios_type3_opts[] = {
|
||||||
|
{
|
||||||
|
.name = "type",
|
||||||
|
.type = QEMU_OPT_NUMBER,
|
||||||
|
.help = "SMBIOS element type",
|
||||||
|
},{
|
||||||
|
.name = "manufacturer",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "manufacturer name",
|
||||||
|
},{
|
||||||
|
.name = "version",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "version number",
|
||||||
|
},{
|
||||||
|
.name = "serial",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "serial number",
|
||||||
|
},{
|
||||||
|
.name = "asset",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "asset tag number",
|
||||||
|
},{
|
||||||
|
.name = "sku",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "SKU number",
|
||||||
|
},
|
||||||
|
{ /* end of list */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QemuOptDesc qemu_smbios_type4_opts[] = {
|
||||||
|
{
|
||||||
|
.name = "type",
|
||||||
|
.type = QEMU_OPT_NUMBER,
|
||||||
|
.help = "SMBIOS element type",
|
||||||
|
},{
|
||||||
|
.name = "sock_pfx",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "socket designation string prefix",
|
||||||
|
},{
|
||||||
|
.name = "manufacturer",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "manufacturer name",
|
||||||
|
},{
|
||||||
|
.name = "version",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "version number",
|
||||||
|
},{
|
||||||
|
.name = "serial",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "serial number",
|
||||||
|
},{
|
||||||
|
.name = "asset",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "asset tag number",
|
||||||
|
},{
|
||||||
|
.name = "part",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "part number",
|
||||||
|
},
|
||||||
|
{ /* end of list */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QemuOptDesc qemu_smbios_type17_opts[] = {
|
||||||
|
{
|
||||||
|
.name = "type",
|
||||||
|
.type = QEMU_OPT_NUMBER,
|
||||||
|
.help = "SMBIOS element type",
|
||||||
|
},{
|
||||||
|
.name = "loc_pfx",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "device locator string prefix",
|
||||||
|
},{
|
||||||
|
.name = "bank",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "bank locator string",
|
||||||
|
},{
|
||||||
|
.name = "manufacturer",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "manufacturer name",
|
||||||
|
},{
|
||||||
|
.name = "serial",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "serial number",
|
||||||
|
},{
|
||||||
|
.name = "asset",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "asset tag number",
|
||||||
|
},{
|
||||||
|
.name = "part",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "part number",
|
||||||
|
},
|
||||||
|
{ /* end of list */ }
|
||||||
|
};
|
||||||
|
|
||||||
static void smbios_register_config(void)
|
static void smbios_register_config(void)
|
||||||
{
|
{
|
||||||
qemu_add_opts(&qemu_smbios_opts);
|
qemu_add_opts(&qemu_smbios_opts);
|
||||||
@@ -158,35 +312,17 @@ machine_init(smbios_register_config);
|
|||||||
|
|
||||||
static void smbios_validate_table(void)
|
static void smbios_validate_table(void)
|
||||||
{
|
{
|
||||||
if (smbios_type4_count && smbios_type4_count != smp_cpus) {
|
uint32_t expect_t4_count = smbios_legacy ? smp_cpus : smbios_smp_sockets;
|
||||||
error_report("Number of SMBIOS Type 4 tables must match cpu count");
|
|
||||||
|
if (smbios_type4_count && smbios_type4_count != expect_t4_count) {
|
||||||
|
error_report("Expected %d SMBIOS Type 4 tables, got %d instead",
|
||||||
|
expect_t4_count, smbios_type4_count);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* To avoid unresolvable overlaps in data, don't allow both
|
|
||||||
* tables and fields for the same smbios type.
|
|
||||||
*/
|
|
||||||
static void smbios_check_collision(int type, int entry)
|
|
||||||
{
|
|
||||||
if (type < ARRAY_SIZE(first_opt)) {
|
|
||||||
if (first_opt[type].seen) {
|
|
||||||
if (first_opt[type].headertype != entry) {
|
|
||||||
error_report("Can't mix file= and type= for same type");
|
|
||||||
loc_push_restore(&first_opt[type].loc);
|
|
||||||
error_report("This is the conflicting setting");
|
|
||||||
loc_pop(&first_opt[type].loc);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
first_opt[type].seen = true;
|
|
||||||
first_opt[type].headertype = entry;
|
|
||||||
loc_save(&first_opt[type].loc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* legacy setup functions for <= 2.0 machines */
|
||||||
static void smbios_add_field(int type, int offset, const void *data, size_t len)
|
static void smbios_add_field(int type, int offset, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
struct smbios_field *field;
|
struct smbios_field *field;
|
||||||
@@ -256,22 +392,13 @@ static void smbios_build_type_1_fields(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void smbios_set_type1_defaults(const char *manufacturer,
|
uint8_t *smbios_get_table_legacy(size_t *length)
|
||||||
const char *product, const char *version)
|
|
||||||
{
|
{
|
||||||
if (!type1.manufacturer) {
|
if (!smbios_legacy) {
|
||||||
type1.manufacturer = manufacturer;
|
*length = 0;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!type1.product) {
|
|
||||||
type1.product = product;
|
|
||||||
}
|
|
||||||
if (!type1.version) {
|
|
||||||
type1.version = version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *smbios_get_table(size_t *length)
|
|
||||||
{
|
|
||||||
if (!smbios_immutable) {
|
if (!smbios_immutable) {
|
||||||
smbios_build_type_0_fields();
|
smbios_build_type_0_fields();
|
||||||
smbios_build_type_1_fields();
|
smbios_build_type_1_fields();
|
||||||
@@ -281,6 +408,458 @@ uint8_t *smbios_get_table(size_t *length)
|
|||||||
*length = smbios_entries_len;
|
*length = smbios_entries_len;
|
||||||
return smbios_entries;
|
return smbios_entries;
|
||||||
}
|
}
|
||||||
|
/* end: legacy setup functions for <= 2.0 machines */
|
||||||
|
|
||||||
|
|
||||||
|
static bool smbios_skip_table(uint8_t type, bool required_table)
|
||||||
|
{
|
||||||
|
if (test_bit(type, have_binfile_bitmap)) {
|
||||||
|
return true; /* user provided their own binary blob(s) */
|
||||||
|
}
|
||||||
|
if (test_bit(type, have_fields_bitmap)) {
|
||||||
|
return false; /* user provided fields via command line */
|
||||||
|
}
|
||||||
|
if (smbios_have_defaults && required_table) {
|
||||||
|
return false; /* we're building tables, and this one's required */
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SMBIOS_BUILD_TABLE_PRE(tbl_type, tbl_handle, tbl_required) \
|
||||||
|
struct smbios_type_##tbl_type *t; \
|
||||||
|
size_t t_off; /* table offset into smbios_tables */ \
|
||||||
|
int str_index = 0; \
|
||||||
|
do { \
|
||||||
|
/* should we skip building this table ? */ \
|
||||||
|
if (smbios_skip_table(tbl_type, tbl_required)) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* use offset of table t within smbios_tables */ \
|
||||||
|
/* (pointer must be updated after each realloc) */ \
|
||||||
|
t_off = smbios_tables_len; \
|
||||||
|
smbios_tables_len += sizeof(*t); \
|
||||||
|
smbios_tables = g_realloc(smbios_tables, smbios_tables_len); \
|
||||||
|
t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
|
||||||
|
\
|
||||||
|
t->header.type = tbl_type; \
|
||||||
|
t->header.length = sizeof(*t); \
|
||||||
|
t->header.handle = tbl_handle; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \
|
||||||
|
do { \
|
||||||
|
int len = (value != NULL) ? strlen(value) + 1 : 0; \
|
||||||
|
if (len > 1) { \
|
||||||
|
smbios_tables = g_realloc(smbios_tables, \
|
||||||
|
smbios_tables_len + len); \
|
||||||
|
memcpy(smbios_tables + smbios_tables_len, value, len); \
|
||||||
|
smbios_tables_len += len; \
|
||||||
|
/* update pointer post-realloc */ \
|
||||||
|
t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
|
||||||
|
t->field = ++str_index; \
|
||||||
|
} else { \
|
||||||
|
t->field = 0; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SMBIOS_BUILD_TABLE_POST \
|
||||||
|
do { \
|
||||||
|
size_t term_cnt, t_size; \
|
||||||
|
\
|
||||||
|
/* add '\0' terminator (add two if no strings defined) */ \
|
||||||
|
term_cnt = (str_index == 0) ? 2 : 1; \
|
||||||
|
smbios_tables = g_realloc(smbios_tables, \
|
||||||
|
smbios_tables_len + term_cnt); \
|
||||||
|
memset(smbios_tables + smbios_tables_len, 0, term_cnt); \
|
||||||
|
smbios_tables_len += term_cnt; \
|
||||||
|
\
|
||||||
|
/* update smbios max. element size */ \
|
||||||
|
t_size = smbios_tables_len - t_off; \
|
||||||
|
if (t_size > smbios_table_max) { \
|
||||||
|
smbios_table_max = t_size; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* update smbios element count */ \
|
||||||
|
smbios_table_cnt++; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static void smbios_build_type_0_table(void)
|
||||||
|
{
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(0, 0x000, false); /* optional, leave up to BIOS */
|
||||||
|
|
||||||
|
SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
|
||||||
|
SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
|
||||||
|
|
||||||
|
t->bios_starting_address_segment = 0xE800; /* hardcoded in SeaBIOS */
|
||||||
|
|
||||||
|
SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date);
|
||||||
|
|
||||||
|
t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
|
||||||
|
|
||||||
|
/* BIOS characteristics not supported */
|
||||||
|
memset(t->bios_characteristics, 0, 8);
|
||||||
|
t->bios_characteristics[0] = 0x08;
|
||||||
|
|
||||||
|
/* Enable targeted content distribution (needed for SVVP, per SeaBIOS) */
|
||||||
|
t->bios_characteristics_extension_bytes[0] = 0;
|
||||||
|
t->bios_characteristics_extension_bytes[1] = 4;
|
||||||
|
|
||||||
|
if (type0.have_major_minor) {
|
||||||
|
t->system_bios_major_release = type0.major;
|
||||||
|
t->system_bios_minor_release = type0.minor;
|
||||||
|
} else {
|
||||||
|
t->system_bios_major_release = 0;
|
||||||
|
t->system_bios_minor_release = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hardcoded in SeaBIOS */
|
||||||
|
t->embedded_controller_major_release = 0xFF;
|
||||||
|
t->embedded_controller_minor_release = 0xFF;
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_build_type_1_table(void)
|
||||||
|
{
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */
|
||||||
|
|
||||||
|
SMBIOS_TABLE_SET_STR(1, manufacturer_str, type1.manufacturer);
|
||||||
|
SMBIOS_TABLE_SET_STR(1, product_name_str, type1.product);
|
||||||
|
SMBIOS_TABLE_SET_STR(1, version_str, type1.version);
|
||||||
|
SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial);
|
||||||
|
if (qemu_uuid_set) {
|
||||||
|
memcpy(t->uuid, qemu_uuid, 16);
|
||||||
|
} else {
|
||||||
|
memset(t->uuid, 0, 16);
|
||||||
|
}
|
||||||
|
t->wake_up_type = 0x06; /* power switch */
|
||||||
|
SMBIOS_TABLE_SET_STR(1, sku_number_str, type1.sku);
|
||||||
|
SMBIOS_TABLE_SET_STR(1, family_str, type1.family);
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_build_type_2_table(void)
|
||||||
|
{
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(2, 0x200, false); /* optional */
|
||||||
|
|
||||||
|
SMBIOS_TABLE_SET_STR(2, manufacturer_str, type2.manufacturer);
|
||||||
|
SMBIOS_TABLE_SET_STR(2, product_str, type2.product);
|
||||||
|
SMBIOS_TABLE_SET_STR(2, version_str, type2.version);
|
||||||
|
SMBIOS_TABLE_SET_STR(2, serial_number_str, type2.serial);
|
||||||
|
SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset);
|
||||||
|
t->feature_flags = 0x01; /* Motherboard */
|
||||||
|
SMBIOS_TABLE_SET_STR(2, location_str, type2.location);
|
||||||
|
t->chassis_handle = 0x300; /* Type 3 (System enclosure) */
|
||||||
|
t->board_type = 0x0A; /* Motherboard */
|
||||||
|
t->contained_element_count = 0;
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_build_type_3_table(void)
|
||||||
|
{
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(3, 0x300, true); /* required */
|
||||||
|
|
||||||
|
SMBIOS_TABLE_SET_STR(3, manufacturer_str, type3.manufacturer);
|
||||||
|
t->type = 0x01; /* Other */
|
||||||
|
SMBIOS_TABLE_SET_STR(3, version_str, type3.version);
|
||||||
|
SMBIOS_TABLE_SET_STR(3, serial_number_str, type3.serial);
|
||||||
|
SMBIOS_TABLE_SET_STR(3, asset_tag_number_str, type3.asset);
|
||||||
|
t->boot_up_state = 0x03; /* Safe */
|
||||||
|
t->power_supply_state = 0x03; /* Safe */
|
||||||
|
t->thermal_state = 0x03; /* Safe */
|
||||||
|
t->security_status = 0x02; /* Unknown */
|
||||||
|
t->oem_defined = 0;
|
||||||
|
t->height = 0;
|
||||||
|
t->number_of_power_cords = 0;
|
||||||
|
t->contained_element_count = 0;
|
||||||
|
SMBIOS_TABLE_SET_STR(3, sku_number_str, type3.sku);
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_build_type_4_table(unsigned instance)
|
||||||
|
{
|
||||||
|
char sock_str[128];
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(4, 0x400 + instance, true); /* required */
|
||||||
|
|
||||||
|
snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
|
||||||
|
SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
|
||||||
|
t->processor_type = 0x03; /* CPU */
|
||||||
|
SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
|
||||||
|
t->processor_id[0] = smbios_cpuid_version;
|
||||||
|
t->processor_id[1] = smbios_cpuid_features;
|
||||||
|
SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
|
||||||
|
t->voltage = 0;
|
||||||
|
t->external_clock = 0; /* Unknown */
|
||||||
|
t->max_speed = 0; /* Unknown */
|
||||||
|
t->current_speed = 0; /* Unknown */
|
||||||
|
t->status = 0x41; /* Socket populated, CPU enabled */
|
||||||
|
t->processor_upgrade = 0x01; /* Other */
|
||||||
|
t->l1_cache_handle = 0xFFFF; /* N/A */
|
||||||
|
t->l2_cache_handle = 0xFFFF; /* N/A */
|
||||||
|
t->l3_cache_handle = 0xFFFF; /* N/A */
|
||||||
|
SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
|
||||||
|
SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
|
||||||
|
SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
|
||||||
|
t->core_count = t->core_enabled = smp_cores;
|
||||||
|
t->thread_count = smp_threads;
|
||||||
|
t->processor_characteristics = 0x02; /* Unknown */
|
||||||
|
t->processor_family = t->processor_family2 = 0x01; /* Other */
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
smbios_type4_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ONE_KB ((ram_addr_t)1 << 10)
|
||||||
|
#define ONE_MB ((ram_addr_t)1 << 20)
|
||||||
|
#define ONE_GB ((ram_addr_t)1 << 30)
|
||||||
|
|
||||||
|
#define MAX_T16_STD_SZ 0x80000000 /* 2T in Kilobytes */
|
||||||
|
|
||||||
|
static void smbios_build_type_16_table(unsigned dimm_cnt)
|
||||||
|
{
|
||||||
|
ram_addr_t size_kb;
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(16, 0x1000, true); /* required */
|
||||||
|
|
||||||
|
t->location = 0x01; /* Other */
|
||||||
|
t->use = 0x03; /* System memory */
|
||||||
|
t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */
|
||||||
|
size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB;
|
||||||
|
if (size_kb < MAX_T16_STD_SZ) {
|
||||||
|
t->maximum_capacity = size_kb;
|
||||||
|
t->extended_maximum_capacity = 0;
|
||||||
|
} else {
|
||||||
|
t->maximum_capacity = MAX_T16_STD_SZ;
|
||||||
|
t->extended_maximum_capacity = ram_size;
|
||||||
|
}
|
||||||
|
t->memory_error_information_handle = 0xFFFE; /* Not provided */
|
||||||
|
t->number_of_memory_devices = dimm_cnt;
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_T17_STD_SZ 0x7FFF /* (32G - 1M), in Megabytes */
|
||||||
|
#define MAX_T17_EXT_SZ 0x80000000 /* 2P, in Megabytes */
|
||||||
|
|
||||||
|
static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
|
||||||
|
{
|
||||||
|
char loc_str[128];
|
||||||
|
ram_addr_t size_mb;
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
|
||||||
|
|
||||||
|
t->physical_memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
|
||||||
|
t->memory_error_information_handle = 0xFFFE; /* Not provided */
|
||||||
|
t->total_width = 0xFFFF; /* Unknown */
|
||||||
|
t->data_width = 0xFFFF; /* Unknown */
|
||||||
|
size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB;
|
||||||
|
if (size_mb < MAX_T17_STD_SZ) {
|
||||||
|
t->size = size_mb;
|
||||||
|
t->extended_size = 0;
|
||||||
|
} else {
|
||||||
|
assert(size_mb < MAX_T17_EXT_SZ);
|
||||||
|
t->size = MAX_T17_STD_SZ;
|
||||||
|
t->extended_size = size_mb;
|
||||||
|
}
|
||||||
|
t->form_factor = 0x09; /* DIMM */
|
||||||
|
t->device_set = 0; /* Not in a set */
|
||||||
|
snprintf(loc_str, sizeof(loc_str), "%s %d", type17.loc_pfx, instance);
|
||||||
|
SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str);
|
||||||
|
SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank);
|
||||||
|
t->memory_type = 0x07; /* RAM */
|
||||||
|
t->type_detail = 0x02; /* Other */
|
||||||
|
t->speed = 0; /* Unknown */
|
||||||
|
SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer);
|
||||||
|
SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial);
|
||||||
|
SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset);
|
||||||
|
SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part);
|
||||||
|
t->attributes = 0; /* Unknown */
|
||||||
|
t->configured_clock_speed = 0; /* Unknown */
|
||||||
|
t->minimum_voltage = 0; /* Unknown */
|
||||||
|
t->maximum_voltage = 0; /* Unknown */
|
||||||
|
t->configured_voltage = 0; /* Unknown */
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_build_type_19_table(unsigned instance,
|
||||||
|
ram_addr_t start, ram_addr_t size)
|
||||||
|
{
|
||||||
|
ram_addr_t end, start_kb, end_kb;
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */
|
||||||
|
|
||||||
|
end = start + size - 1;
|
||||||
|
assert(end > start);
|
||||||
|
start_kb = start / ONE_KB;
|
||||||
|
end_kb = end / ONE_KB;
|
||||||
|
if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) {
|
||||||
|
t->starting_address = start_kb;
|
||||||
|
t->ending_address = end_kb;
|
||||||
|
t->extended_starting_address = t->extended_ending_address = 0;
|
||||||
|
} else {
|
||||||
|
t->starting_address = t->ending_address = UINT32_MAX;
|
||||||
|
t->extended_starting_address = start;
|
||||||
|
t->extended_ending_address = end;
|
||||||
|
}
|
||||||
|
t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
|
||||||
|
t->partition_width = 1; /* One device per row */
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_build_type_32_table(void)
|
||||||
|
{
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(32, 0x2000, true); /* required */
|
||||||
|
|
||||||
|
memset(t->reserved, 0, 6);
|
||||||
|
t->boot_status = 0; /* No errors detected */
|
||||||
|
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_build_type_127_table(void)
|
||||||
|
{
|
||||||
|
SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */
|
||||||
|
SMBIOS_BUILD_TABLE_POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
void smbios_set_cpuid(uint32_t version, uint32_t features)
|
||||||
|
{
|
||||||
|
smbios_cpuid_version = version;
|
||||||
|
smbios_cpuid_features = features;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SMBIOS_SET_DEFAULT(field, value) \
|
||||||
|
if (!field) { \
|
||||||
|
field = value; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define G_FREE_UNLESS_NULL(ptr) \
|
||||||
|
if (ptr != NULL) { \
|
||||||
|
g_free(ptr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void smbios_set_defaults(const char *manufacturer, const char *product,
|
||||||
|
const char *version, bool legacy_mode)
|
||||||
|
{
|
||||||
|
smbios_have_defaults = true;
|
||||||
|
smbios_legacy = legacy_mode;
|
||||||
|
|
||||||
|
/* drop unwanted version of command-line file blob(s) */
|
||||||
|
if (smbios_legacy) {
|
||||||
|
G_FREE_UNLESS_NULL(smbios_tables);
|
||||||
|
/* in legacy mode, also complain if fields were given for types > 1 */
|
||||||
|
if (find_next_bit(have_fields_bitmap,
|
||||||
|
SMBIOS_MAX_TYPE+1, 2) < SMBIOS_MAX_TYPE+1) {
|
||||||
|
error_report("can't process fields for smbios "
|
||||||
|
"types > 1 on machine versions < 2.1!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
G_FREE_UNLESS_NULL(smbios_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer);
|
||||||
|
SMBIOS_SET_DEFAULT(type1.product, product);
|
||||||
|
SMBIOS_SET_DEFAULT(type1.version, version);
|
||||||
|
SMBIOS_SET_DEFAULT(type2.manufacturer, manufacturer);
|
||||||
|
SMBIOS_SET_DEFAULT(type2.product, product);
|
||||||
|
SMBIOS_SET_DEFAULT(type2.version, version);
|
||||||
|
SMBIOS_SET_DEFAULT(type3.manufacturer, manufacturer);
|
||||||
|
SMBIOS_SET_DEFAULT(type3.version, version);
|
||||||
|
SMBIOS_SET_DEFAULT(type4.sock_pfx, "CPU");
|
||||||
|
SMBIOS_SET_DEFAULT(type4.manufacturer, manufacturer);
|
||||||
|
SMBIOS_SET_DEFAULT(type4.version, version);
|
||||||
|
SMBIOS_SET_DEFAULT(type17.loc_pfx, "DIMM");
|
||||||
|
SMBIOS_SET_DEFAULT(type17.manufacturer, manufacturer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smbios_entry_point_setup(void)
|
||||||
|
{
|
||||||
|
memcpy(ep.anchor_string, "_SM_", 4);
|
||||||
|
memcpy(ep.intermediate_anchor_string, "_DMI_", 5);
|
||||||
|
ep.length = sizeof(struct smbios_entry_point);
|
||||||
|
ep.entry_point_revision = 0; /* formatted_area reserved, per spec v2.1+ */
|
||||||
|
memset(ep.formatted_area, 0, 5);
|
||||||
|
|
||||||
|
/* compliant with smbios spec v2.8 */
|
||||||
|
ep.smbios_major_version = 2;
|
||||||
|
ep.smbios_minor_version = 8;
|
||||||
|
ep.smbios_bcd_revision = 0x28;
|
||||||
|
|
||||||
|
/* set during table construction, but BIOS may override: */
|
||||||
|
ep.structure_table_length = smbios_tables_len;
|
||||||
|
ep.max_structure_size = smbios_table_max;
|
||||||
|
ep.number_of_structures = smbios_table_cnt;
|
||||||
|
|
||||||
|
/* BIOS must recalculate: */
|
||||||
|
ep.checksum = 0;
|
||||||
|
ep.intermediate_checksum = 0;
|
||||||
|
ep.structure_table_address = 0; /* where BIOS has copied smbios_tables */
|
||||||
|
}
|
||||||
|
|
||||||
|
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
|
||||||
|
uint8_t **anchor, size_t *anchor_len)
|
||||||
|
{
|
||||||
|
unsigned i, dimm_cnt, instance;
|
||||||
|
|
||||||
|
if (smbios_legacy) {
|
||||||
|
*tables = *anchor = NULL;
|
||||||
|
*tables_len = *anchor_len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!smbios_immutable) {
|
||||||
|
smbios_build_type_0_table();
|
||||||
|
smbios_build_type_1_table();
|
||||||
|
smbios_build_type_2_table();
|
||||||
|
smbios_build_type_3_table();
|
||||||
|
|
||||||
|
smbios_smp_sockets = smp_cpus / (smp_cores * smp_threads);
|
||||||
|
assert(smbios_smp_sockets >= 1);
|
||||||
|
|
||||||
|
for (i = 0; i < smbios_smp_sockets; i++) {
|
||||||
|
smbios_build_type_4_table(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_DIMM_SZ (16ll * ONE_GB)
|
||||||
|
#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ : ram_size % MAX_DIMM_SZ)
|
||||||
|
|
||||||
|
dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ;
|
||||||
|
|
||||||
|
smbios_build_type_16_table(dimm_cnt);
|
||||||
|
|
||||||
|
for (i = 0; i < dimm_cnt; i++) {
|
||||||
|
smbios_build_type_17_table(i, GET_DIMM_SZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, instance = 0; i < e820_get_num_entries(); i++) {
|
||||||
|
uint64_t address, length;
|
||||||
|
if (e820_get_entry(i, E820_RAM, &address, &length)) {
|
||||||
|
smbios_build_type_19_table(instance++, address, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
smbios_build_type_32_table();
|
||||||
|
smbios_build_type_127_table();
|
||||||
|
|
||||||
|
smbios_validate_table();
|
||||||
|
smbios_entry_point_setup();
|
||||||
|
smbios_immutable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return tables blob and entry point (anchor), and their sizes */
|
||||||
|
*tables = smbios_tables;
|
||||||
|
*tables_len = smbios_tables_len;
|
||||||
|
*anchor = (uint8_t *)&ep;
|
||||||
|
*anchor_len = sizeof(struct smbios_entry_point);
|
||||||
|
}
|
||||||
|
|
||||||
static void save_opt(const char **dest, QemuOpts *opts, const char *name)
|
static void save_opt(const char **dest, QemuOpts *opts, const char *name)
|
||||||
{
|
{
|
||||||
@@ -297,11 +876,12 @@ void smbios_entry_add(QemuOpts *opts)
|
|||||||
const char *val;
|
const char *val;
|
||||||
|
|
||||||
assert(!smbios_immutable);
|
assert(!smbios_immutable);
|
||||||
|
|
||||||
val = qemu_opt_get(opts, "file");
|
val = qemu_opt_get(opts, "file");
|
||||||
if (val) {
|
if (val) {
|
||||||
struct smbios_structure_header *header;
|
struct smbios_structure_header *header;
|
||||||
struct smbios_table *table;
|
|
||||||
int size;
|
int size;
|
||||||
|
struct smbios_table *table; /* legacy mode only */
|
||||||
|
|
||||||
qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
|
qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
@@ -315,31 +895,60 @@ void smbios_entry_add(QemuOpts *opts)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!smbios_entries) {
|
/*
|
||||||
smbios_entries_len = sizeof(uint16_t);
|
* NOTE: standard double '\0' terminator expected, per smbios spec.
|
||||||
smbios_entries = g_malloc0(smbios_entries_len);
|
* (except in legacy mode, where the second '\0' is implicit and
|
||||||
}
|
* will be inserted by the BIOS).
|
||||||
|
*/
|
||||||
|
smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size);
|
||||||
|
header = (struct smbios_structure_header *)(smbios_tables +
|
||||||
|
smbios_tables_len);
|
||||||
|
|
||||||
smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
|
if (load_image(val, (uint8_t *)header) != size) {
|
||||||
sizeof(*table) + size);
|
|
||||||
table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
|
|
||||||
table->header.type = SMBIOS_TABLE_ENTRY;
|
|
||||||
table->header.length = cpu_to_le16(sizeof(*table) + size);
|
|
||||||
|
|
||||||
if (load_image(val, table->data) != size) {
|
|
||||||
error_report("Failed to load SMBIOS file %s", val);
|
error_report("Failed to load SMBIOS file %s", val);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
header = (struct smbios_structure_header *)(table->data);
|
if (test_bit(header->type, have_fields_bitmap)) {
|
||||||
smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
|
error_report("can't load type %d struct, fields already specified!",
|
||||||
|
header->type);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
set_bit(header->type, have_binfile_bitmap);
|
||||||
|
|
||||||
if (header->type == 4) {
|
if (header->type == 4) {
|
||||||
smbios_type4_count++;
|
smbios_type4_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smbios_tables_len += size;
|
||||||
|
if (size > smbios_table_max) {
|
||||||
|
smbios_table_max = size;
|
||||||
|
}
|
||||||
|
smbios_table_cnt++;
|
||||||
|
|
||||||
|
/* add a copy of the newly loaded blob to legacy smbios_entries */
|
||||||
|
/* NOTE: This code runs before smbios_set_defaults(), so we don't
|
||||||
|
* yet know which mode (legacy vs. aggregate-table) will be
|
||||||
|
* required. We therefore add the binary blob to both legacy
|
||||||
|
* (smbios_entries) and aggregate (smbios_tables) tables, and
|
||||||
|
* delete the one we don't need from smbios_set_defaults(),
|
||||||
|
* once we know which machine version has been requested.
|
||||||
|
*/
|
||||||
|
if (!smbios_entries) {
|
||||||
|
smbios_entries_len = sizeof(uint16_t);
|
||||||
|
smbios_entries = g_malloc0(smbios_entries_len);
|
||||||
|
}
|
||||||
|
smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
|
||||||
|
size + sizeof(*table));
|
||||||
|
table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
|
||||||
|
table->header.type = SMBIOS_TABLE_ENTRY;
|
||||||
|
table->header.length = cpu_to_le16(sizeof(*table) + size);
|
||||||
|
memcpy(table->data, header, size);
|
||||||
smbios_entries_len += sizeof(*table) + size;
|
smbios_entries_len += sizeof(*table) + size;
|
||||||
(*(uint16_t *)smbios_entries) =
|
(*(uint16_t *)smbios_entries) =
|
||||||
cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
|
cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
|
||||||
|
/* end: add a copy of the newly loaded blob to legacy smbios_entries */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +956,16 @@ void smbios_entry_add(QemuOpts *opts)
|
|||||||
if (val) {
|
if (val) {
|
||||||
unsigned long type = strtoul(val, NULL, 0);
|
unsigned long type = strtoul(val, NULL, 0);
|
||||||
|
|
||||||
smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
|
if (type > SMBIOS_MAX_TYPE) {
|
||||||
|
error_report("out of range!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(type, have_binfile_bitmap)) {
|
||||||
|
error_report("can't add fields, binary file already loaded!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
set_bit(type, have_fields_bitmap);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -391,6 +1009,57 @@ void smbios_entry_add(QemuOpts *opts)
|
|||||||
qemu_uuid_set = true;
|
qemu_uuid_set = true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
case 2:
|
||||||
|
qemu_opts_validate(opts, qemu_smbios_type2_opts, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
save_opt(&type2.manufacturer, opts, "manufacturer");
|
||||||
|
save_opt(&type2.product, opts, "product");
|
||||||
|
save_opt(&type2.version, opts, "version");
|
||||||
|
save_opt(&type2.serial, opts, "serial");
|
||||||
|
save_opt(&type2.asset, opts, "asset");
|
||||||
|
save_opt(&type2.location, opts, "location");
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
qemu_opts_validate(opts, qemu_smbios_type3_opts, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
save_opt(&type3.manufacturer, opts, "manufacturer");
|
||||||
|
save_opt(&type3.version, opts, "version");
|
||||||
|
save_opt(&type3.serial, opts, "serial");
|
||||||
|
save_opt(&type3.asset, opts, "asset");
|
||||||
|
save_opt(&type3.sku, opts, "sku");
|
||||||
|
return;
|
||||||
|
case 4:
|
||||||
|
qemu_opts_validate(opts, qemu_smbios_type4_opts, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
save_opt(&type4.sock_pfx, opts, "sock_pfx");
|
||||||
|
save_opt(&type4.manufacturer, opts, "manufacturer");
|
||||||
|
save_opt(&type4.version, opts, "version");
|
||||||
|
save_opt(&type4.serial, opts, "serial");
|
||||||
|
save_opt(&type4.asset, opts, "asset");
|
||||||
|
save_opt(&type4.part, opts, "part");
|
||||||
|
return;
|
||||||
|
case 17:
|
||||||
|
qemu_opts_validate(opts, qemu_smbios_type17_opts, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_report("%s", error_get_pretty(local_err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
save_opt(&type17.loc_pfx, opts, "loc_pfx");
|
||||||
|
save_opt(&type17.bank, opts, "bank");
|
||||||
|
save_opt(&type17.manufacturer, opts, "manufacturer");
|
||||||
|
save_opt(&type17.serial, opts, "serial");
|
||||||
|
save_opt(&type17.asset, opts, "asset");
|
||||||
|
save_opt(&type17.part, opts, "part");
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
error_report("Don't know how to build fields for SMBIOS type %ld",
|
error_report("Don't know how to build fields for SMBIOS type %ld",
|
||||||
type);
|
type);
|
||||||
|
@@ -438,9 +438,9 @@ static void check_cmd(AHCIState *s, int port)
|
|||||||
|
|
||||||
if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {
|
if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {
|
||||||
for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {
|
for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {
|
||||||
if ((pr->cmd_issue & (1 << slot)) &&
|
if ((pr->cmd_issue & (1U << slot)) &&
|
||||||
!handle_cmd(s, port, slot)) {
|
!handle_cmd(s, port, slot)) {
|
||||||
pr->cmd_issue &= ~(1 << slot);
|
pr->cmd_issue &= ~(1U << slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1602,7 +1602,7 @@ static bool cmd_smart(IDEState *s, uint8_t cmd)
|
|||||||
case 2: /* extended self test */
|
case 2: /* extended self test */
|
||||||
s->smart_selftest_count++;
|
s->smart_selftest_count++;
|
||||||
if (s->smart_selftest_count > 21) {
|
if (s->smart_selftest_count > 21) {
|
||||||
s->smart_selftest_count = 0;
|
s->smart_selftest_count = 1;
|
||||||
}
|
}
|
||||||
n = 2 + (s->smart_selftest_count - 1) * 24;
|
n = 2 + (s->smart_selftest_count - 1) * 24;
|
||||||
s->smart_selftest_data[n] = s->sector;
|
s->smart_selftest_data[n] = s->sector;
|
||||||
|
@@ -23,11 +23,20 @@
|
|||||||
static void aw_a10_pic_update(AwA10PICState *s)
|
static void aw_a10_pic_update(AwA10PICState *s)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
int irq = 0, fiq = 0;
|
int irq = 0, fiq = 0, pending;
|
||||||
|
|
||||||
|
s->vector = 0;
|
||||||
|
|
||||||
for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
|
for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
|
||||||
irq |= s->irq_pending[i] & ~s->mask[i];
|
irq |= s->irq_pending[i] & ~s->mask[i];
|
||||||
fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
|
fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
|
||||||
|
|
||||||
|
if (!s->vector) {
|
||||||
|
pending = ffs(s->irq_pending[i] & ~s->mask[i]);
|
||||||
|
if (pending) {
|
||||||
|
s->vector = (i * 32 + pending - 1) * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_set_irq(s->parent_irq, !!irq);
|
qemu_set_irq(s->parent_irq, !!irq);
|
||||||
@@ -40,6 +49,8 @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
|
|||||||
|
|
||||||
if (level) {
|
if (level) {
|
||||||
set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
||||||
|
} else {
|
||||||
|
clear_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
||||||
}
|
}
|
||||||
aw_a10_pic_update(s);
|
aw_a10_pic_update(s);
|
||||||
}
|
}
|
||||||
@@ -84,9 +95,6 @@ static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
uint8_t index = (offset & 0xc) / 4;
|
uint8_t index = (offset & 0xc) / 4;
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case AW_A10_PIC_VECTOR:
|
|
||||||
s->vector = value & ~0x3;
|
|
||||||
break;
|
|
||||||
case AW_A10_PIC_BASE_ADDR:
|
case AW_A10_PIC_BASE_ADDR:
|
||||||
s->base_addr = value & ~0x3;
|
s->base_addr = value & ~0x3;
|
||||||
case AW_A10_PIC_PROTECT:
|
case AW_A10_PIC_PROTECT:
|
||||||
@@ -96,7 +104,11 @@ static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
s->nmi = value;
|
s->nmi = value;
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
|
case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
|
||||||
s->irq_pending[index] &= ~value;
|
/*
|
||||||
|
* The register is read-only; nevertheless, Linux (including
|
||||||
|
* the version originally shipped by Allwinner) pretends to
|
||||||
|
* write to the register. Just ignore it.
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
|
case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
|
||||||
s->fiq_pending[index] &= ~value;
|
s->fiq_pending[index] &= ~value;
|
||||||
|
@@ -98,8 +98,8 @@ static void apic_sync_vapic(APICCommonState *s, int sync_type)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sync_type & SYNC_FROM_VAPIC) {
|
if (sync_type & SYNC_FROM_VAPIC) {
|
||||||
cpu_physical_memory_rw(s->vapic_paddr, (void *)&vapic_state,
|
cpu_physical_memory_read(s->vapic_paddr, &vapic_state,
|
||||||
sizeof(vapic_state), 0);
|
sizeof(vapic_state));
|
||||||
s->tpr = vapic_state.tpr;
|
s->tpr = vapic_state.tpr;
|
||||||
}
|
}
|
||||||
if (sync_type & (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) {
|
if (sync_type & (SYNC_TO_VAPIC | SYNC_ISR_IRR_TO_VAPIC)) {
|
||||||
|
@@ -173,7 +173,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
|
|||||||
return 10000;
|
return 10000;
|
||||||
case 0xd00: /* CPUID Base. */
|
case 0xd00: /* CPUID Base. */
|
||||||
cpu = ARM_CPU(current_cpu);
|
cpu = ARM_CPU(current_cpu);
|
||||||
return cpu->env.cp15.c0_cpuid;
|
return cpu->midr;
|
||||||
case 0xd04: /* Interrupt Control State. */
|
case 0xd04: /* Interrupt Control State. */
|
||||||
/* VECTACTIVE */
|
/* VECTACTIVE */
|
||||||
val = s->gic.running_irq[0];
|
val = s->gic.running_irq[0];
|
||||||
|
@@ -234,13 +234,9 @@ static void kvm_openpic_realize(DeviceState *dev, Error **errp)
|
|||||||
int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
|
int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
|
||||||
{
|
{
|
||||||
KVMOpenPICState *opp = KVM_OPENPIC(d);
|
KVMOpenPICState *opp = KVM_OPENPIC(d);
|
||||||
struct kvm_enable_cap encap = {};
|
|
||||||
|
|
||||||
encap.cap = KVM_CAP_IRQ_MPIC;
|
return kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_MPIC, 0, opp->fd,
|
||||||
encap.args[0] = opp->fd;
|
kvm_arch_vcpu_id(cs));
|
||||||
encap.args[1] = kvm_arch_vcpu_id(cs);
|
|
||||||
|
|
||||||
return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property kvm_openpic_properties[] = {
|
static Property kvm_openpic_properties[] = {
|
||||||
|
@@ -331,15 +331,11 @@ static void xics_kvm_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
|
|||||||
|
|
||||||
if (icpkvm->kernel_xics_fd != -1) {
|
if (icpkvm->kernel_xics_fd != -1) {
|
||||||
int ret;
|
int ret;
|
||||||
struct kvm_enable_cap xics_enable_cap = {
|
|
||||||
.cap = KVM_CAP_IRQ_XICS,
|
|
||||||
.flags = 0,
|
|
||||||
.args = {icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs), 0, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
ss->cs = cs;
|
ss->cs = cs;
|
||||||
|
|
||||||
ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap);
|
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0,
|
||||||
|
icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
||||||
kvm_arch_vcpu_id(cs), strerror(errno));
|
kvm_arch_vcpu_id(cs), strerror(errno));
|
||||||
|
@@ -684,8 +684,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s->role_val == IVSHMEM_PEER) {
|
if (s->role_val == IVSHMEM_PEER) {
|
||||||
error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION,
|
error_setg(&s->migration_blocker,
|
||||||
"peer mode", "ivshmem");
|
"Migration is disabled when using feature 'peer mode' in device 'ivshmem'");
|
||||||
migrate_add_blocker(s->migration_blocker);
|
migrate_add_blocker(s->migration_blocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,102 +19,155 @@
|
|||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
#ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
|
#ifndef ZYNQ_SLCR_ERR_DEBUG
|
||||||
#define DB_PRINT(...) do { \
|
#define ZYNQ_SLCR_ERR_DEBUG 0
|
||||||
fprintf(stderr, ": %s: ", __func__); \
|
|
||||||
fprintf(stderr, ## __VA_ARGS__); \
|
|
||||||
} while (0);
|
|
||||||
#else
|
|
||||||
#define DB_PRINT(...)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DB_PRINT(...) do { \
|
||||||
|
if (ZYNQ_SLCR_ERR_DEBUG) { \
|
||||||
|
fprintf(stderr, ": %s: ", __func__); \
|
||||||
|
fprintf(stderr, ## __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
#define XILINX_LOCK_KEY 0x767b
|
#define XILINX_LOCK_KEY 0x767b
|
||||||
#define XILINX_UNLOCK_KEY 0xdf0d
|
#define XILINX_UNLOCK_KEY 0xdf0d
|
||||||
|
|
||||||
#define R_PSS_RST_CTRL_SOFT_RST 0x1
|
#define R_PSS_RST_CTRL_SOFT_RST 0x1
|
||||||
|
|
||||||
typedef enum {
|
enum {
|
||||||
ARM_PLL_CTRL,
|
SCL = 0x000 / 4,
|
||||||
DDR_PLL_CTRL,
|
LOCK,
|
||||||
IO_PLL_CTRL,
|
UNLOCK,
|
||||||
PLL_STATUS,
|
LOCKSTA,
|
||||||
ARM_PPL_CFG,
|
|
||||||
DDR_PLL_CFG,
|
|
||||||
IO_PLL_CFG,
|
|
||||||
PLL_BG_CTRL,
|
|
||||||
PLL_MAX
|
|
||||||
} PLLValues;
|
|
||||||
|
|
||||||
typedef enum {
|
ARM_PLL_CTRL = 0x100 / 4,
|
||||||
ARM_CLK_CTRL,
|
DDR_PLL_CTRL,
|
||||||
DDR_CLK_CTRL,
|
IO_PLL_CTRL,
|
||||||
DCI_CLK_CTRL,
|
PLL_STATUS,
|
||||||
APER_CLK_CTRL,
|
ARM_PLL_CFG,
|
||||||
USB0_CLK_CTRL,
|
DDR_PLL_CFG,
|
||||||
USB1_CLK_CTRL,
|
IO_PLL_CFG,
|
||||||
GEM0_RCLK_CTRL,
|
|
||||||
GEM1_RCLK_CTRL,
|
|
||||||
GEM0_CLK_CTRL,
|
|
||||||
GEM1_CLK_CTRL,
|
|
||||||
SMC_CLK_CTRL,
|
|
||||||
LQSPI_CLK_CTRL,
|
|
||||||
SDIO_CLK_CTRL,
|
|
||||||
UART_CLK_CTRL,
|
|
||||||
SPI_CLK_CTRL,
|
|
||||||
CAN_CLK_CTRL,
|
|
||||||
CAN_MIOCLK_CTRL,
|
|
||||||
DBG_CLK_CTRL,
|
|
||||||
PCAP_CLK_CTRL,
|
|
||||||
TOPSW_CLK_CTRL,
|
|
||||||
CLK_MAX
|
|
||||||
} ClkValues;
|
|
||||||
|
|
||||||
typedef enum {
|
ARM_CLK_CTRL = 0x120 / 4,
|
||||||
CLK_CTRL,
|
DDR_CLK_CTRL,
|
||||||
THR_CTRL,
|
DCI_CLK_CTRL,
|
||||||
THR_CNT,
|
APER_CLK_CTRL,
|
||||||
THR_STA,
|
USB0_CLK_CTRL,
|
||||||
FPGA_MAX
|
USB1_CLK_CTRL,
|
||||||
} FPGAValues;
|
GEM0_RCLK_CTRL,
|
||||||
|
GEM1_RCLK_CTRL,
|
||||||
|
GEM0_CLK_CTRL,
|
||||||
|
GEM1_CLK_CTRL,
|
||||||
|
SMC_CLK_CTRL,
|
||||||
|
LQSPI_CLK_CTRL,
|
||||||
|
SDIO_CLK_CTRL,
|
||||||
|
UART_CLK_CTRL,
|
||||||
|
SPI_CLK_CTRL,
|
||||||
|
CAN_CLK_CTRL,
|
||||||
|
CAN_MIOCLK_CTRL,
|
||||||
|
DBG_CLK_CTRL,
|
||||||
|
PCAP_CLK_CTRL,
|
||||||
|
TOPSW_CLK_CTRL,
|
||||||
|
|
||||||
typedef enum {
|
#define FPGA_CTRL_REGS(n, start) \
|
||||||
SYNC_CTRL,
|
FPGA ## n ## _CLK_CTRL = (start) / 4, \
|
||||||
SYNC_STATUS,
|
FPGA ## n ## _THR_CTRL, \
|
||||||
BANDGAP_TRIP,
|
FPGA ## n ## _THR_CNT, \
|
||||||
CC_TEST,
|
FPGA ## n ## _THR_STA,
|
||||||
PLL_PREDIVISOR,
|
FPGA_CTRL_REGS(0, 0x170)
|
||||||
CLK_621_TRUE,
|
FPGA_CTRL_REGS(1, 0x180)
|
||||||
PICTURE_DBG,
|
FPGA_CTRL_REGS(2, 0x190)
|
||||||
PICTURE_DBG_UCNT,
|
FPGA_CTRL_REGS(3, 0x1a0)
|
||||||
PICTURE_DBG_LCNT,
|
|
||||||
MISC_MAX
|
|
||||||
} MiscValues;
|
|
||||||
|
|
||||||
typedef enum {
|
BANDGAP_TRIP = 0x1b8 / 4,
|
||||||
PSS,
|
PLL_PREDIVISOR = 0x1c0 / 4,
|
||||||
DDDR,
|
CLK_621_TRUE,
|
||||||
DMAC = 3,
|
|
||||||
USB,
|
PSS_RST_CTRL = 0x200 / 4,
|
||||||
GEM,
|
DDR_RST_CTRL,
|
||||||
SDIO,
|
TOPSW_RESET_CTRL,
|
||||||
SPI,
|
DMAC_RST_CTRL,
|
||||||
CAN,
|
USB_RST_CTRL,
|
||||||
I2C,
|
GEM_RST_CTRL,
|
||||||
UART,
|
SDIO_RST_CTRL,
|
||||||
GPIO,
|
SPI_RST_CTRL,
|
||||||
LQSPI,
|
CAN_RST_CTRL,
|
||||||
SMC,
|
I2C_RST_CTRL,
|
||||||
OCM,
|
UART_RST_CTRL,
|
||||||
DEVCI,
|
GPIO_RST_CTRL,
|
||||||
FPGA,
|
LQSPI_RST_CTRL,
|
||||||
A9_CPU,
|
SMC_RST_CTRL,
|
||||||
RS_AWDT,
|
OCM_RST_CTRL,
|
||||||
RST_REASON,
|
FPGA_RST_CTRL = 0x240 / 4,
|
||||||
RST_REASON_CLR,
|
A9_CPU_RST_CTRL,
|
||||||
REBOOT_STATUS,
|
|
||||||
BOOT_MODE,
|
RS_AWDT_CTRL = 0x24c / 4,
|
||||||
RESET_MAX
|
RST_REASON,
|
||||||
} ResetValues;
|
|
||||||
|
REBOOT_STATUS = 0x258 / 4,
|
||||||
|
BOOT_MODE,
|
||||||
|
|
||||||
|
APU_CTRL = 0x300 / 4,
|
||||||
|
WDT_CLK_SEL,
|
||||||
|
|
||||||
|
TZ_DMA_NS = 0x440 / 4,
|
||||||
|
TZ_DMA_IRQ_NS,
|
||||||
|
TZ_DMA_PERIPH_NS,
|
||||||
|
|
||||||
|
PSS_IDCODE = 0x530 / 4,
|
||||||
|
|
||||||
|
DDR_URGENT = 0x600 / 4,
|
||||||
|
DDR_CAL_START = 0x60c / 4,
|
||||||
|
DDR_REF_START = 0x614 / 4,
|
||||||
|
DDR_CMD_STA,
|
||||||
|
DDR_URGENT_SEL,
|
||||||
|
DDR_DFI_STATUS,
|
||||||
|
|
||||||
|
MIO = 0x700 / 4,
|
||||||
|
#define MIO_LENGTH 54
|
||||||
|
|
||||||
|
MIO_LOOPBACK = 0x804 / 4,
|
||||||
|
MIO_MST_TRI0,
|
||||||
|
MIO_MST_TRI1,
|
||||||
|
|
||||||
|
SD0_WP_CD_SEL = 0x830 / 4,
|
||||||
|
SD1_WP_CD_SEL,
|
||||||
|
|
||||||
|
LVL_SHFTR_EN = 0x900 / 4,
|
||||||
|
OCM_CFG = 0x910 / 4,
|
||||||
|
|
||||||
|
CPU_RAM = 0xa00 / 4,
|
||||||
|
|
||||||
|
IOU = 0xa30 / 4,
|
||||||
|
|
||||||
|
DMAC_RAM = 0xa50 / 4,
|
||||||
|
|
||||||
|
AFI0 = 0xa60 / 4,
|
||||||
|
AFI1 = AFI0 + 3,
|
||||||
|
AFI2 = AFI1 + 3,
|
||||||
|
AFI3 = AFI2 + 3,
|
||||||
|
#define AFI_LENGTH 3
|
||||||
|
|
||||||
|
OCM = 0xa90 / 4,
|
||||||
|
|
||||||
|
DEVCI_RAM = 0xaa0 / 4,
|
||||||
|
|
||||||
|
CSG_RAM = 0xab0 / 4,
|
||||||
|
|
||||||
|
GPIOB_CTRL = 0xb00 / 4,
|
||||||
|
GPIOB_CFG_CMOS18,
|
||||||
|
GPIOB_CFG_CMOS25,
|
||||||
|
GPIOB_CFG_CMOS33,
|
||||||
|
GPIOB_CFG_HSTL = 0xb14 / 4,
|
||||||
|
GPIOB_DRVR_BIAS_CTRL,
|
||||||
|
|
||||||
|
DDRIOB = 0xb40 / 4,
|
||||||
|
#define DDRIOB_LENGTH 14
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ZYNQ_SLCR_MMIO_SIZE 0x1000
|
||||||
|
#define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4)
|
||||||
|
|
||||||
#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
|
#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
|
||||||
#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
|
#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
|
||||||
@@ -124,42 +177,7 @@ typedef struct ZynqSLCRState {
|
|||||||
|
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
|
||||||
union {
|
uint32_t regs[ZYNQ_SLCR_NUM_REGS];
|
||||||
struct {
|
|
||||||
uint16_t scl;
|
|
||||||
uint16_t lockval;
|
|
||||||
uint32_t pll[PLL_MAX]; /* 0x100 - 0x11C */
|
|
||||||
uint32_t clk[CLK_MAX]; /* 0x120 - 0x16C */
|
|
||||||
uint32_t fpga[4][FPGA_MAX]; /* 0x170 - 0x1AC */
|
|
||||||
uint32_t misc[MISC_MAX]; /* 0x1B0 - 0x1D8 */
|
|
||||||
uint32_t reset[RESET_MAX]; /* 0x200 - 0x25C */
|
|
||||||
uint32_t apu_ctrl; /* 0x300 */
|
|
||||||
uint32_t wdt_clk_sel; /* 0x304 */
|
|
||||||
uint32_t tz_ocm[3]; /* 0x400 - 0x408 */
|
|
||||||
uint32_t tz_ddr; /* 0x430 */
|
|
||||||
uint32_t tz_dma[3]; /* 0x440 - 0x448 */
|
|
||||||
uint32_t tz_misc[3]; /* 0x450 - 0x458 */
|
|
||||||
uint32_t tz_fpga[2]; /* 0x484 - 0x488 */
|
|
||||||
uint32_t dbg_ctrl; /* 0x500 */
|
|
||||||
uint32_t pss_idcode; /* 0x530 */
|
|
||||||
uint32_t ddr[8]; /* 0x600 - 0x620 - 0x604-missing */
|
|
||||||
uint32_t mio[54]; /* 0x700 - 0x7D4 */
|
|
||||||
uint32_t mio_func[4]; /* 0x800 - 0x810 */
|
|
||||||
uint32_t sd[2]; /* 0x830 - 0x834 */
|
|
||||||
uint32_t lvl_shftr_en; /* 0x900 */
|
|
||||||
uint32_t ocm_cfg; /* 0x910 */
|
|
||||||
uint32_t cpu_ram[8]; /* 0xA00 - 0xA1C */
|
|
||||||
uint32_t iou[7]; /* 0xA30 - 0xA48 */
|
|
||||||
uint32_t dmac_ram; /* 0xA50 */
|
|
||||||
uint32_t afi[4][3]; /* 0xA60 - 0xA8C */
|
|
||||||
uint32_t ocm[3]; /* 0xA90 - 0xA98 */
|
|
||||||
uint32_t devci_ram; /* 0xAA0 */
|
|
||||||
uint32_t csg_ram; /* 0xAB0 */
|
|
||||||
uint32_t gpiob[12]; /* 0xB00 - 0xB2C */
|
|
||||||
uint32_t ddriob[14]; /* 0xB40 - 0xB74 */
|
|
||||||
};
|
|
||||||
uint8_t data[0x1000];
|
|
||||||
};
|
|
||||||
} ZynqSLCRState;
|
} ZynqSLCRState;
|
||||||
|
|
||||||
static void zynq_slcr_reset(DeviceState *d)
|
static void zynq_slcr_reset(DeviceState *d)
|
||||||
@@ -169,177 +187,169 @@ static void zynq_slcr_reset(DeviceState *d)
|
|||||||
|
|
||||||
DB_PRINT("RESET\n");
|
DB_PRINT("RESET\n");
|
||||||
|
|
||||||
s->lockval = 1;
|
s->regs[LOCKSTA] = 1;
|
||||||
/* 0x100 - 0x11C */
|
/* 0x100 - 0x11C */
|
||||||
s->pll[ARM_PLL_CTRL] = 0x0001A008;
|
s->regs[ARM_PLL_CTRL] = 0x0001A008;
|
||||||
s->pll[DDR_PLL_CTRL] = 0x0001A008;
|
s->regs[DDR_PLL_CTRL] = 0x0001A008;
|
||||||
s->pll[IO_PLL_CTRL] = 0x0001A008;
|
s->regs[IO_PLL_CTRL] = 0x0001A008;
|
||||||
s->pll[PLL_STATUS] = 0x0000003F;
|
s->regs[PLL_STATUS] = 0x0000003F;
|
||||||
s->pll[ARM_PPL_CFG] = 0x00014000;
|
s->regs[ARM_PLL_CFG] = 0x00014000;
|
||||||
s->pll[DDR_PLL_CFG] = 0x00014000;
|
s->regs[DDR_PLL_CFG] = 0x00014000;
|
||||||
s->pll[IO_PLL_CFG] = 0x00014000;
|
s->regs[IO_PLL_CFG] = 0x00014000;
|
||||||
|
|
||||||
/* 0x120 - 0x16C */
|
/* 0x120 - 0x16C */
|
||||||
s->clk[ARM_CLK_CTRL] = 0x1F000400;
|
s->regs[ARM_CLK_CTRL] = 0x1F000400;
|
||||||
s->clk[DDR_CLK_CTRL] = 0x18400003;
|
s->regs[DDR_CLK_CTRL] = 0x18400003;
|
||||||
s->clk[DCI_CLK_CTRL] = 0x01E03201;
|
s->regs[DCI_CLK_CTRL] = 0x01E03201;
|
||||||
s->clk[APER_CLK_CTRL] = 0x01FFCCCD;
|
s->regs[APER_CLK_CTRL] = 0x01FFCCCD;
|
||||||
s->clk[USB0_CLK_CTRL] = s->clk[USB1_CLK_CTRL] = 0x00101941;
|
s->regs[USB0_CLK_CTRL] = s->regs[USB1_CLK_CTRL] = 0x00101941;
|
||||||
s->clk[GEM0_RCLK_CTRL] = s->clk[GEM1_RCLK_CTRL] = 0x00000001;
|
s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL] = 0x00000001;
|
||||||
s->clk[GEM0_CLK_CTRL] = s->clk[GEM1_CLK_CTRL] = 0x00003C01;
|
s->regs[GEM0_CLK_CTRL] = s->regs[GEM1_CLK_CTRL] = 0x00003C01;
|
||||||
s->clk[SMC_CLK_CTRL] = 0x00003C01;
|
s->regs[SMC_CLK_CTRL] = 0x00003C01;
|
||||||
s->clk[LQSPI_CLK_CTRL] = 0x00002821;
|
s->regs[LQSPI_CLK_CTRL] = 0x00002821;
|
||||||
s->clk[SDIO_CLK_CTRL] = 0x00001E03;
|
s->regs[SDIO_CLK_CTRL] = 0x00001E03;
|
||||||
s->clk[UART_CLK_CTRL] = 0x00003F03;
|
s->regs[UART_CLK_CTRL] = 0x00003F03;
|
||||||
s->clk[SPI_CLK_CTRL] = 0x00003F03;
|
s->regs[SPI_CLK_CTRL] = 0x00003F03;
|
||||||
s->clk[CAN_CLK_CTRL] = 0x00501903;
|
s->regs[CAN_CLK_CTRL] = 0x00501903;
|
||||||
s->clk[DBG_CLK_CTRL] = 0x00000F03;
|
s->regs[DBG_CLK_CTRL] = 0x00000F03;
|
||||||
s->clk[PCAP_CLK_CTRL] = 0x00000F01;
|
s->regs[PCAP_CLK_CTRL] = 0x00000F01;
|
||||||
|
|
||||||
/* 0x170 - 0x1AC */
|
/* 0x170 - 0x1AC */
|
||||||
s->fpga[0][CLK_CTRL] = s->fpga[1][CLK_CTRL] = s->fpga[2][CLK_CTRL] =
|
s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL]
|
||||||
s->fpga[3][CLK_CTRL] = 0x00101800;
|
= s->regs[FPGA3_CLK_CTRL] = 0x00101800;
|
||||||
s->fpga[0][THR_STA] = s->fpga[1][THR_STA] = s->fpga[2][THR_STA] =
|
s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA]
|
||||||
s->fpga[3][THR_STA] = 0x00010000;
|
= s->regs[FPGA3_THR_STA] = 0x00010000;
|
||||||
|
|
||||||
/* 0x1B0 - 0x1D8 */
|
/* 0x1B0 - 0x1D8 */
|
||||||
s->misc[BANDGAP_TRIP] = 0x0000001F;
|
s->regs[BANDGAP_TRIP] = 0x0000001F;
|
||||||
s->misc[PLL_PREDIVISOR] = 0x00000001;
|
s->regs[PLL_PREDIVISOR] = 0x00000001;
|
||||||
s->misc[CLK_621_TRUE] = 0x00000001;
|
s->regs[CLK_621_TRUE] = 0x00000001;
|
||||||
|
|
||||||
/* 0x200 - 0x25C */
|
/* 0x200 - 0x25C */
|
||||||
s->reset[FPGA] = 0x01F33F0F;
|
s->regs[FPGA_RST_CTRL] = 0x01F33F0F;
|
||||||
s->reset[RST_REASON] = 0x00000040;
|
s->regs[RST_REASON] = 0x00000040;
|
||||||
|
|
||||||
|
s->regs[BOOT_MODE] = 0x00000001;
|
||||||
|
|
||||||
/* 0x700 - 0x7D4 */
|
/* 0x700 - 0x7D4 */
|
||||||
for (i = 0; i < 54; i++) {
|
for (i = 0; i < 54; i++) {
|
||||||
s->mio[i] = 0x00001601;
|
s->regs[MIO + i] = 0x00001601;
|
||||||
}
|
}
|
||||||
for (i = 2; i <= 8; i++) {
|
for (i = 2; i <= 8; i++) {
|
||||||
s->mio[i] = 0x00000601;
|
s->regs[MIO + i] = 0x00000601;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MIO_MST_TRI0, MIO_MST_TRI1 */
|
s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF;
|
||||||
s->mio_func[2] = s->mio_func[3] = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
s->cpu_ram[0] = s->cpu_ram[1] = s->cpu_ram[3] =
|
s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3]
|
||||||
s->cpu_ram[4] = s->cpu_ram[7] = 0x00010101;
|
= s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7]
|
||||||
s->cpu_ram[2] = s->cpu_ram[5] = 0x01010101;
|
= 0x00010101;
|
||||||
s->cpu_ram[6] = 0x00000001;
|
s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101;
|
||||||
|
s->regs[CPU_RAM + 6] = 0x00000001;
|
||||||
|
|
||||||
s->iou[0] = s->iou[1] = s->iou[2] = s->iou[3] = 0x09090909;
|
s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3]
|
||||||
s->iou[4] = s->iou[5] = 0x00090909;
|
= 0x09090909;
|
||||||
s->iou[6] = 0x00000909;
|
s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909;
|
||||||
|
s->regs[IOU + 6] = 0x00000909;
|
||||||
|
|
||||||
s->dmac_ram = 0x00000009;
|
s->regs[DMAC_RAM] = 0x00000009;
|
||||||
|
|
||||||
s->afi[0][0] = s->afi[0][1] = 0x09090909;
|
s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909;
|
||||||
s->afi[1][0] = s->afi[1][1] = 0x09090909;
|
s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909;
|
||||||
s->afi[2][0] = s->afi[2][1] = 0x09090909;
|
s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909;
|
||||||
s->afi[3][0] = s->afi[3][1] = 0x09090909;
|
s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909;
|
||||||
s->afi[0][2] = s->afi[1][2] = s->afi[2][2] = s->afi[3][2] = 0x00000909;
|
s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2]
|
||||||
|
= s->regs[AFI3 + 2] = 0x00000909;
|
||||||
|
|
||||||
s->ocm[0] = 0x01010101;
|
s->regs[OCM + 0] = 0x01010101;
|
||||||
s->ocm[1] = s->ocm[2] = 0x09090909;
|
s->regs[OCM + 1] = s->regs[OCM + 2] = 0x09090909;
|
||||||
|
|
||||||
s->devci_ram = 0x00000909;
|
s->regs[DEVCI_RAM] = 0x00000909;
|
||||||
s->csg_ram = 0x00000001;
|
s->regs[CSG_RAM] = 0x00000001;
|
||||||
|
|
||||||
s->ddriob[0] = s->ddriob[1] = s->ddriob[2] = s->ddriob[3] = 0x00000e00;
|
s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2]
|
||||||
s->ddriob[4] = s->ddriob[5] = s->ddriob[6] = 0x00000e00;
|
= s->regs[DDRIOB + 3] = 0x00000e00;
|
||||||
s->ddriob[12] = 0x00000021;
|
s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6]
|
||||||
|
= 0x00000e00;
|
||||||
|
s->regs[DDRIOB + 12] = 0x00000021;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t zynq_slcr_read_imp(void *opaque,
|
|
||||||
hwaddr offset)
|
|
||||||
{
|
|
||||||
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
|
|
||||||
|
|
||||||
|
static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
|
||||||
|
{
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case 0x0: /* SCL */
|
case LOCK:
|
||||||
return s->scl;
|
case UNLOCK:
|
||||||
case 0x4: /* LOCK */
|
case DDR_CAL_START:
|
||||||
case 0x8: /* UNLOCK */
|
case DDR_REF_START:
|
||||||
DB_PRINT("Reading SCLR_LOCK/UNLOCK is not enabled\n");
|
return !rnw; /* Write only */
|
||||||
return 0;
|
case LOCKSTA:
|
||||||
case 0x0C: /* LOCKSTA */
|
case FPGA0_THR_STA:
|
||||||
return s->lockval;
|
case FPGA1_THR_STA:
|
||||||
case 0x100 ... 0x11C:
|
case FPGA2_THR_STA:
|
||||||
return s->pll[(offset - 0x100) / 4];
|
case FPGA3_THR_STA:
|
||||||
case 0x120 ... 0x16C:
|
case BOOT_MODE:
|
||||||
return s->clk[(offset - 0x120) / 4];
|
case PSS_IDCODE:
|
||||||
case 0x170 ... 0x1AC:
|
case DDR_CMD_STA:
|
||||||
return s->fpga[0][(offset - 0x170) / 4];
|
case DDR_DFI_STATUS:
|
||||||
case 0x1B0 ... 0x1D8:
|
case PLL_STATUS:
|
||||||
return s->misc[(offset - 0x1B0) / 4];
|
return rnw;/* read only */
|
||||||
case 0x200 ... 0x258:
|
case SCL:
|
||||||
return s->reset[(offset - 0x200) / 4];
|
case ARM_PLL_CTRL ... IO_PLL_CTRL:
|
||||||
case 0x25c:
|
case ARM_PLL_CFG ... IO_PLL_CFG:
|
||||||
return 1;
|
case ARM_CLK_CTRL ... TOPSW_CLK_CTRL:
|
||||||
case 0x300:
|
case FPGA0_CLK_CTRL ... FPGA0_THR_CNT:
|
||||||
return s->apu_ctrl;
|
case FPGA1_CLK_CTRL ... FPGA1_THR_CNT:
|
||||||
case 0x304:
|
case FPGA2_CLK_CTRL ... FPGA2_THR_CNT:
|
||||||
return s->wdt_clk_sel;
|
case FPGA3_CLK_CTRL ... FPGA3_THR_CNT:
|
||||||
case 0x400 ... 0x408:
|
case BANDGAP_TRIP:
|
||||||
return s->tz_ocm[(offset - 0x400) / 4];
|
case PLL_PREDIVISOR:
|
||||||
case 0x430:
|
case CLK_621_TRUE:
|
||||||
return s->tz_ddr;
|
case PSS_RST_CTRL ... A9_CPU_RST_CTRL:
|
||||||
case 0x440 ... 0x448:
|
case RS_AWDT_CTRL:
|
||||||
return s->tz_dma[(offset - 0x440) / 4];
|
case RST_REASON:
|
||||||
case 0x450 ... 0x458:
|
case REBOOT_STATUS:
|
||||||
return s->tz_misc[(offset - 0x450) / 4];
|
case APU_CTRL:
|
||||||
case 0x484 ... 0x488:
|
case WDT_CLK_SEL:
|
||||||
return s->tz_fpga[(offset - 0x484) / 4];
|
case TZ_DMA_NS ... TZ_DMA_PERIPH_NS:
|
||||||
case 0x500:
|
case DDR_URGENT:
|
||||||
return s->dbg_ctrl;
|
case DDR_URGENT_SEL:
|
||||||
case 0x530:
|
case MIO ... MIO + MIO_LENGTH - 1:
|
||||||
return s->pss_idcode;
|
case MIO_LOOPBACK ... MIO_MST_TRI1:
|
||||||
case 0x600 ... 0x620:
|
case SD0_WP_CD_SEL:
|
||||||
if (offset == 0x604) {
|
case SD1_WP_CD_SEL:
|
||||||
goto bad_reg;
|
case LVL_SHFTR_EN:
|
||||||
}
|
case OCM_CFG:
|
||||||
return s->ddr[(offset - 0x600) / 4];
|
case CPU_RAM:
|
||||||
case 0x700 ... 0x7D4:
|
case IOU:
|
||||||
return s->mio[(offset - 0x700) / 4];
|
case DMAC_RAM:
|
||||||
case 0x800 ... 0x810:
|
case AFI0 ... AFI3 + AFI_LENGTH - 1:
|
||||||
return s->mio_func[(offset - 0x800) / 4];
|
case OCM:
|
||||||
case 0x830 ... 0x834:
|
case DEVCI_RAM:
|
||||||
return s->sd[(offset - 0x830) / 4];
|
case CSG_RAM:
|
||||||
case 0x900:
|
case GPIOB_CTRL ... GPIOB_CFG_CMOS33:
|
||||||
return s->lvl_shftr_en;
|
case GPIOB_CFG_HSTL:
|
||||||
case 0x910:
|
case GPIOB_DRVR_BIAS_CTRL:
|
||||||
return s->ocm_cfg;
|
case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1:
|
||||||
case 0xA00 ... 0xA1C:
|
return true;
|
||||||
return s->cpu_ram[(offset - 0xA00) / 4];
|
|
||||||
case 0xA30 ... 0xA48:
|
|
||||||
return s->iou[(offset - 0xA30) / 4];
|
|
||||||
case 0xA50:
|
|
||||||
return s->dmac_ram;
|
|
||||||
case 0xA60 ... 0xA8C:
|
|
||||||
return s->afi[0][(offset - 0xA60) / 4];
|
|
||||||
case 0xA90 ... 0xA98:
|
|
||||||
return s->ocm[(offset - 0xA90) / 4];
|
|
||||||
case 0xAA0:
|
|
||||||
return s->devci_ram;
|
|
||||||
case 0xAB0:
|
|
||||||
return s->csg_ram;
|
|
||||||
case 0xB00 ... 0xB2C:
|
|
||||||
return s->gpiob[(offset - 0xB00) / 4];
|
|
||||||
case 0xB40 ... 0xB74:
|
|
||||||
return s->ddriob[(offset - 0xB40) / 4];
|
|
||||||
default:
|
default:
|
||||||
bad_reg:
|
return false;
|
||||||
DB_PRINT("Bad register offset 0x%x\n", (int)offset);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
|
static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
uint32_t ret = zynq_slcr_read_imp(opaque, offset);
|
ZynqSLCRState *s = opaque;
|
||||||
|
offset /= 4;
|
||||||
|
uint32_t ret = s->regs[offset];
|
||||||
|
|
||||||
DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)ret);
|
if (!zynq_slcr_check_offset(offset, true)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to "
|
||||||
|
" addr %" HWADDR_PRIx "\n", offset * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset * 4, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,148 +357,55 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
|
|||||||
uint64_t val, unsigned size)
|
uint64_t val, unsigned size)
|
||||||
{
|
{
|
||||||
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
|
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
|
||||||
|
offset /= 4;
|
||||||
|
|
||||||
DB_PRINT("offset: %08x data: %08x\n", (unsigned)offset, (unsigned)val);
|
DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n", offset * 4, val);
|
||||||
|
|
||||||
|
if (!zynq_slcr_check_offset(offset, false)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid write access to "
|
||||||
|
"addr %" HWADDR_PRIx "\n", offset * 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case 0x00: /* SCL */
|
case SCL:
|
||||||
s->scl = val & 0x1;
|
s->regs[SCL] = val & 0x1;
|
||||||
return;
|
return;
|
||||||
case 0x4: /* SLCR_LOCK */
|
case LOCK:
|
||||||
if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
|
if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
|
||||||
DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
||||||
(unsigned)val & 0xFFFF);
|
(unsigned)val & 0xFFFF);
|
||||||
s->lockval = 1;
|
s->regs[LOCKSTA] = 1;
|
||||||
} else {
|
} else {
|
||||||
DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
||||||
(int)offset, (unsigned)val & 0xFFFF);
|
(int)offset, (unsigned)val & 0xFFFF);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0x8: /* SLCR_UNLOCK */
|
case UNLOCK:
|
||||||
if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
|
if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
|
||||||
DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
||||||
(unsigned)val & 0xFFFF);
|
(unsigned)val & 0xFFFF);
|
||||||
s->lockval = 0;
|
s->regs[LOCKSTA] = 0;
|
||||||
} else {
|
} else {
|
||||||
DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
||||||
(int)offset, (unsigned)val & 0xFFFF);
|
(int)offset, (unsigned)val & 0xFFFF);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0xc: /* LOCKSTA */
|
}
|
||||||
DB_PRINT("Writing SCLR_LOCKSTA is not enabled\n");
|
|
||||||
|
if (!s->regs[LOCKSTA]) {
|
||||||
|
s->regs[offset / 4] = val;
|
||||||
|
} else {
|
||||||
|
DB_PRINT("SCLR registers are locked. Unlock them first\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->lockval) {
|
switch (offset) {
|
||||||
switch (offset) {
|
case PSS_RST_CTRL:
|
||||||
case 0x100 ... 0x11C:
|
if (val & R_PSS_RST_CTRL_SOFT_RST) {
|
||||||
if (offset == 0x10C) {
|
qemu_system_reset_request();
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->pll[(offset - 0x100) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x120 ... 0x16C:
|
|
||||||
s->clk[(offset - 0x120) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x170 ... 0x1AC:
|
|
||||||
s->fpga[0][(offset - 0x170) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x1B0 ... 0x1D8:
|
|
||||||
s->misc[(offset - 0x1B0) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x200 ... 0x25C:
|
|
||||||
if (offset == 0x250) {
|
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->reset[(offset - 0x200) / 4] = val;
|
|
||||||
if (offset == 0x200 && (val & R_PSS_RST_CTRL_SOFT_RST)) {
|
|
||||||
qemu_system_reset_request();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x300:
|
|
||||||
s->apu_ctrl = val;
|
|
||||||
break;
|
|
||||||
case 0x304:
|
|
||||||
s->wdt_clk_sel = val;
|
|
||||||
break;
|
|
||||||
case 0x400 ... 0x408:
|
|
||||||
s->tz_ocm[(offset - 0x400) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x430:
|
|
||||||
s->tz_ddr = val;
|
|
||||||
break;
|
|
||||||
case 0x440 ... 0x448:
|
|
||||||
s->tz_dma[(offset - 0x440) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x450 ... 0x458:
|
|
||||||
s->tz_misc[(offset - 0x450) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x484 ... 0x488:
|
|
||||||
s->tz_fpga[(offset - 0x484) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x500:
|
|
||||||
s->dbg_ctrl = val;
|
|
||||||
break;
|
|
||||||
case 0x530:
|
|
||||||
s->pss_idcode = val;
|
|
||||||
break;
|
|
||||||
case 0x600 ... 0x620:
|
|
||||||
if (offset == 0x604) {
|
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->ddr[(offset - 0x600) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x700 ... 0x7D4:
|
|
||||||
s->mio[(offset - 0x700) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x800 ... 0x810:
|
|
||||||
s->mio_func[(offset - 0x800) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x830 ... 0x834:
|
|
||||||
s->sd[(offset - 0x830) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x900:
|
|
||||||
s->lvl_shftr_en = val;
|
|
||||||
break;
|
|
||||||
case 0x910:
|
|
||||||
break;
|
|
||||||
case 0xA00 ... 0xA1C:
|
|
||||||
s->cpu_ram[(offset - 0xA00) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xA30 ... 0xA48:
|
|
||||||
s->iou[(offset - 0xA30) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xA50:
|
|
||||||
s->dmac_ram = val;
|
|
||||||
break;
|
|
||||||
case 0xA60 ... 0xA8C:
|
|
||||||
s->afi[0][(offset - 0xA60) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xA90:
|
|
||||||
s->ocm[0] = val;
|
|
||||||
break;
|
|
||||||
case 0xAA0:
|
|
||||||
s->devci_ram = val;
|
|
||||||
break;
|
|
||||||
case 0xAB0:
|
|
||||||
s->csg_ram = val;
|
|
||||||
break;
|
|
||||||
case 0xB00 ... 0xB2C:
|
|
||||||
if (offset == 0xB20 || offset == 0xB2C) {
|
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->gpiob[(offset - 0xB00) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xB40 ... 0xB74:
|
|
||||||
s->ddriob[(offset - 0xB40) / 4] = val;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
bad_reg:
|
|
||||||
DB_PRINT("Bad register write %x <= %08x\n", (int)offset,
|
|
||||||
(unsigned)val);
|
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
DB_PRINT("SCLR registers are locked. Unlock them first\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,23 +415,22 @@ static const MemoryRegionOps slcr_ops = {
|
|||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int zynq_slcr_init(SysBusDevice *dev)
|
static void zynq_slcr_init(Object *obj)
|
||||||
{
|
{
|
||||||
ZynqSLCRState *s = ZYNQ_SLCR(dev);
|
ZynqSLCRState *s = ZYNQ_SLCR(obj);
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, OBJECT(s), &slcr_ops, s, "slcr", 0x1000);
|
memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr",
|
||||||
sysbus_init_mmio(dev, &s->iomem);
|
ZYNQ_SLCR_MMIO_SIZE);
|
||||||
|
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_zynq_slcr = {
|
static const VMStateDescription vmstate_zynq_slcr = {
|
||||||
.name = "zynq_slcr",
|
.name = "zynq_slcr",
|
||||||
.version_id = 1,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 2,
|
||||||
.minimum_version_id_old = 1,
|
.minimum_version_id_old = 2,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8_ARRAY(data, ZynqSLCRState, 0x1000),
|
VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -522,9 +438,7 @@ static const VMStateDescription vmstate_zynq_slcr = {
|
|||||||
static void zynq_slcr_class_init(ObjectClass *klass, void *data)
|
static void zynq_slcr_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
sdc->init = zynq_slcr_init;
|
|
||||||
dc->vmsd = &vmstate_zynq_slcr;
|
dc->vmsd = &vmstate_zynq_slcr;
|
||||||
dc->reset = zynq_slcr_reset;
|
dc->reset = zynq_slcr_reset;
|
||||||
}
|
}
|
||||||
@@ -534,6 +448,7 @@ static const TypeInfo zynq_slcr_info = {
|
|||||||
.name = TYPE_ZYNQ_SLCR,
|
.name = TYPE_ZYNQ_SLCR,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(ZynqSLCRState),
|
.instance_size = sizeof(ZynqSLCRState),
|
||||||
|
.instance_init = zynq_slcr_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void zynq_slcr_register_types(void)
|
static void zynq_slcr_register_types(void)
|
||||||
|
@@ -27,11 +27,11 @@ static uint8_t padding[60];
|
|||||||
static void mii_set_link(RTL8201CPState *mii, bool link_ok)
|
static void mii_set_link(RTL8201CPState *mii, bool link_ok)
|
||||||
{
|
{
|
||||||
if (link_ok) {
|
if (link_ok) {
|
||||||
mii->bmsr |= MII_BMSR_LINK_ST;
|
mii->bmsr |= MII_BMSR_LINK_ST | MII_BMSR_AN_COMP;
|
||||||
mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 |
|
mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 |
|
||||||
MII_ANAR_CSMACD;
|
MII_ANAR_CSMACD;
|
||||||
} else {
|
} else {
|
||||||
mii->bmsr &= ~MII_BMSR_LINK_ST;
|
mii->bmsr &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
|
||||||
mii->anlpar = MII_ANAR_TX;
|
mii->anlpar = MII_ANAR_TX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -391,9 +391,11 @@ static void aw_emac_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
break;
|
break;
|
||||||
case EMAC_INT_CTL_REG:
|
case EMAC_INT_CTL_REG:
|
||||||
s->int_ctl = value;
|
s->int_ctl = value;
|
||||||
|
aw_emac_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case EMAC_INT_STA_REG:
|
case EMAC_INT_STA_REG:
|
||||||
s->int_sta &= ~value;
|
s->int_sta &= ~value;
|
||||||
|
aw_emac_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case EMAC_MAC_MADR_REG:
|
case EMAC_MAC_MADR_REG:
|
||||||
s->phy_target = value;
|
s->phy_target = value;
|
||||||
|
@@ -1093,7 +1093,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
|
|||||||
uint32_t phy_addr, reg_num;
|
uint32_t phy_addr, reg_num;
|
||||||
|
|
||||||
phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
||||||
if (phy_addr == BOARD_PHY_ADDRESS) {
|
if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
|
||||||
reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
||||||
retval &= 0xFFFF0000;
|
retval &= 0xFFFF0000;
|
||||||
retval |= gem_phy_read(s, reg_num);
|
retval |= gem_phy_read(s, reg_num);
|
||||||
@@ -1193,7 +1193,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
|
|||||||
uint32_t phy_addr, reg_num;
|
uint32_t phy_addr, reg_num;
|
||||||
|
|
||||||
phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
||||||
if (phy_addr == BOARD_PHY_ADDRESS) {
|
if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
|
||||||
reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
||||||
gem_phy_write(s, reg_num, val);
|
gem_phy_write(s, reg_num, val);
|
||||||
}
|
}
|
||||||
|
@@ -718,7 +718,6 @@ static void pcnet_s_reset(PCNetState *s)
|
|||||||
s->csr[94] = 0x0000;
|
s->csr[94] = 0x0000;
|
||||||
s->csr[100] = 0x0200;
|
s->csr[100] = 0x0200;
|
||||||
s->csr[103] = 0x0105;
|
s->csr[103] = 0x0105;
|
||||||
s->csr[103] = 0x0105;
|
|
||||||
s->csr[112] = 0x0000;
|
s->csr[112] = 0x0000;
|
||||||
s->csr[114] = 0x0000;
|
s->csr[114] = 0x0000;
|
||||||
s->csr[122] = 0x0000;
|
s->csr[122] = 0x0000;
|
||||||
|
@@ -677,7 +677,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
|
if (mac_data.entries <= MAC_TABLE_ENTRIES - in_use) {
|
||||||
s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],
|
s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],
|
||||||
mac_data.entries * ETH_ALEN);
|
mac_data.entries * ETH_ALEN);
|
||||||
if (s != mac_data.entries * ETH_ALEN) {
|
if (s != mac_data.entries * ETH_ALEN) {
|
||||||
|
@@ -52,6 +52,9 @@
|
|||||||
#define VMXNET3_DEVICE_VERSION 0x1
|
#define VMXNET3_DEVICE_VERSION 0x1
|
||||||
#define VMXNET3_DEVICE_REVISION 0x1
|
#define VMXNET3_DEVICE_REVISION 0x1
|
||||||
|
|
||||||
|
/* Number of interrupt vectors for non-MSIx modes */
|
||||||
|
#define VMXNET3_MAX_NMSIX_INTRS (1)
|
||||||
|
|
||||||
/* Macros for rings descriptors access */
|
/* Macros for rings descriptors access */
|
||||||
#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
|
#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
|
||||||
(vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
|
(vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
|
||||||
@@ -1305,6 +1308,51 @@ static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
|
|||||||
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
|
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
|
||||||
|
{
|
||||||
|
int max_ints = is_msix ? VMXNET3_MAX_INTRS : VMXNET3_MAX_NMSIX_INTRS;
|
||||||
|
if (idx >= max_ints) {
|
||||||
|
hw_error("Bad interrupt index: %d\n", idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vmxnet3_validate_interrupts(VMXNET3State *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
VMW_CFPRN("Verifying event interrupt index (%d)", s->event_int_idx);
|
||||||
|
vmxnet3_validate_interrupt_idx(s->msix_used, s->event_int_idx);
|
||||||
|
|
||||||
|
for (i = 0; i < s->txq_num; i++) {
|
||||||
|
int idx = s->txq_descr[i].intr_idx;
|
||||||
|
VMW_CFPRN("Verifying TX queue %d interrupt index (%d)", i, idx);
|
||||||
|
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < s->rxq_num; i++) {
|
||||||
|
int idx = s->rxq_descr[i].intr_idx;
|
||||||
|
VMW_CFPRN("Verifying RX queue %d interrupt index (%d)", i, idx);
|
||||||
|
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vmxnet3_validate_queues(VMXNET3State *s)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* txq_num and rxq_num are total number of queues
|
||||||
|
* configured by guest. These numbers must not
|
||||||
|
* exceed corresponding maximal values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (s->txq_num > VMXNET3_DEVICE_MAX_TX_QUEUES) {
|
||||||
|
hw_error("Bad TX queues number: %d\n", s->txq_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->rxq_num > VMXNET3_DEVICE_MAX_RX_QUEUES) {
|
||||||
|
hw_error("Bad RX queues number: %d\n", s->rxq_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void vmxnet3_activate_device(VMXNET3State *s)
|
static void vmxnet3_activate_device(VMXNET3State *s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -1351,7 +1399,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
|||||||
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
|
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
|
||||||
|
|
||||||
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
|
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
|
||||||
assert(s->txq_num <= VMXNET3_DEVICE_MAX_TX_QUEUES);
|
vmxnet3_validate_queues(s);
|
||||||
|
|
||||||
qdescr_table_pa =
|
qdescr_table_pa =
|
||||||
VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
|
VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
|
||||||
@@ -1447,6 +1495,8 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
|||||||
sizeof(s->rxq_descr[i].rxq_stats));
|
sizeof(s->rxq_descr[i].rxq_stats));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vmxnet3_validate_interrupts(s);
|
||||||
|
|
||||||
/* Make sure everything is in place before device activation */
|
/* Make sure everything is in place before device activation */
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
||||||
@@ -2005,7 +2055,6 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VMXNET3_MSI_NUM_VECTORS (1)
|
|
||||||
#define VMXNET3_MSI_OFFSET (0x50)
|
#define VMXNET3_MSI_OFFSET (0x50)
|
||||||
#define VMXNET3_USE_64BIT (true)
|
#define VMXNET3_USE_64BIT (true)
|
||||||
#define VMXNET3_PER_VECTOR_MASK (false)
|
#define VMXNET3_PER_VECTOR_MASK (false)
|
||||||
@@ -2016,7 +2065,7 @@ vmxnet3_init_msi(VMXNET3State *s)
|
|||||||
PCIDevice *d = PCI_DEVICE(s);
|
PCIDevice *d = PCI_DEVICE(s);
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MSI_NUM_VECTORS,
|
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MAX_NMSIX_INTRS,
|
||||||
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
|
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
|
||||||
if (0 > res) {
|
if (0 > res) {
|
||||||
VMW_WRPRN("Failed to initialize MSI, error %d", res);
|
VMW_WRPRN("Failed to initialize MSI, error %d", res);
|
||||||
@@ -2342,6 +2391,9 @@ static int vmxnet3_post_load(void *opaque, int version_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vmxnet3_validate_queues(s);
|
||||||
|
vmxnet3_validate_interrupts(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -98,7 +98,7 @@ static unsigned int tdk_read(struct PHY *phy, unsigned int req)
|
|||||||
r |= 1;
|
r |= 1;
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 17:
|
||||||
/* Marvel PHY on many xilinx boards. */
|
/* Marvell PHY on many xilinx boards. */
|
||||||
r = 0x8000; /* 1000Mb */
|
r = 0x8000; /* 1000Mb */
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
@@ -142,6 +142,9 @@ tdk_write(struct PHY *phy, unsigned int req, unsigned int data)
|
|||||||
phy->regs[regnum] = data;
|
phy->regs[regnum] = data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unconditionally clear regs[BMCR][BMCR_RESET] */
|
||||||
|
phy->regs[0] &= ~0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -19,6 +19,15 @@
|
|||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "hw/timer/allwinner-a10-pit.h"
|
#include "hw/timer/allwinner-a10-pit.h"
|
||||||
|
|
||||||
|
static void a10_pit_update_irq(AwA10PITState *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
||||||
|
qemu_set_irq(s->irq[i], !!(s->irq_status & s->irq_enable & (1 << i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
{
|
{
|
||||||
AwA10PITState *s = AW_A10_PIT(opaque);
|
AwA10PITState *s = AW_A10_PIT(opaque);
|
||||||
@@ -65,6 +74,22 @@ static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void a10_pit_set_freq(AwA10PITState *s, int index)
|
||||||
|
{
|
||||||
|
uint32_t prescaler, source, source_freq;
|
||||||
|
|
||||||
|
prescaler = 1 << extract32(s->control[index], 4, 3);
|
||||||
|
source = extract32(s->control[index], 2, 2);
|
||||||
|
source_freq = s->clk_freq[source];
|
||||||
|
|
||||||
|
if (source_freq) {
|
||||||
|
ptimer_set_freq(s->timer[index], source_freq / prescaler);
|
||||||
|
} else {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid clock source %u\n",
|
||||||
|
__func__, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
@@ -74,9 +99,11 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
switch (offset) {
|
switch (offset) {
|
||||||
case AW_A10_PIT_TIMER_IRQ_EN:
|
case AW_A10_PIT_TIMER_IRQ_EN:
|
||||||
s->irq_enable = value;
|
s->irq_enable = value;
|
||||||
|
a10_pit_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIT_TIMER_IRQ_ST:
|
case AW_A10_PIT_TIMER_IRQ_ST:
|
||||||
s->irq_status &= ~value;
|
s->irq_status &= ~value;
|
||||||
|
a10_pit_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
|
case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
|
||||||
index = offset & 0xf0;
|
index = offset & 0xf0;
|
||||||
@@ -85,6 +112,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
switch (offset & 0x0f) {
|
switch (offset & 0x0f) {
|
||||||
case AW_A10_PIT_TIMER_CONTROL:
|
case AW_A10_PIT_TIMER_CONTROL:
|
||||||
s->control[index] = value;
|
s->control[index] = value;
|
||||||
|
a10_pit_set_freq(s, index);
|
||||||
if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
|
if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
|
||||||
ptimer_set_count(s->timer[index], s->interval[index]);
|
ptimer_set_count(s->timer[index], s->interval[index]);
|
||||||
}
|
}
|
||||||
@@ -150,6 +178,14 @@ static const MemoryRegionOps a10_pit_ops = {
|
|||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property a10_pit_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("clk0-freq", AwA10PITState, clk_freq[0], 0),
|
||||||
|
DEFINE_PROP_UINT32("clk1-freq", AwA10PITState, clk_freq[1], 0),
|
||||||
|
DEFINE_PROP_UINT32("clk2-freq", AwA10PITState, clk_freq[2], 0),
|
||||||
|
DEFINE_PROP_UINT32("clk3-freq", AwA10PITState, clk_freq[3], 0),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_a10_pit = {
|
static const VMStateDescription vmstate_a10_pit = {
|
||||||
.name = "a10.pit",
|
.name = "a10.pit",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
@@ -178,11 +214,14 @@ static void a10_pit_reset(DeviceState *dev)
|
|||||||
|
|
||||||
s->irq_enable = 0;
|
s->irq_enable = 0;
|
||||||
s->irq_status = 0;
|
s->irq_status = 0;
|
||||||
|
a10_pit_update_irq(s);
|
||||||
|
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
|
s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
|
||||||
s->interval[i] = 0;
|
s->interval[i] = 0;
|
||||||
s->count[i] = 0;
|
s->count[i] = 0;
|
||||||
ptimer_stop(s->timer[i]);
|
ptimer_stop(s->timer[i]);
|
||||||
|
a10_pit_set_freq(s, i);
|
||||||
}
|
}
|
||||||
s->watch_dog_mode = 0;
|
s->watch_dog_mode = 0;
|
||||||
s->watch_dog_control = 0;
|
s->watch_dog_control = 0;
|
||||||
@@ -193,18 +232,17 @@ static void a10_pit_reset(DeviceState *dev)
|
|||||||
|
|
||||||
static void a10_pit_timer_cb(void *opaque)
|
static void a10_pit_timer_cb(void *opaque)
|
||||||
{
|
{
|
||||||
AwA10PITState *s = AW_A10_PIT(opaque);
|
AwA10TimerContext *tc = opaque;
|
||||||
uint8_t i;
|
AwA10PITState *s = tc->container;
|
||||||
|
uint8_t i = tc->index;
|
||||||
|
|
||||||
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
if (s->control[i] & AW_A10_PIT_TIMER_EN) {
|
||||||
if (s->control[i] & AW_A10_PIT_TIMER_EN) {
|
s->irq_status |= 1 << i;
|
||||||
s->irq_status |= 1 << i;
|
if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
|
||||||
if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
|
ptimer_stop(s->timer[i]);
|
||||||
ptimer_stop(s->timer[i]);
|
s->control[i] &= ~AW_A10_PIT_TIMER_EN;
|
||||||
s->control[i] &= ~AW_A10_PIT_TIMER_EN;
|
|
||||||
}
|
|
||||||
qemu_irq_pulse(s->irq[i]);
|
|
||||||
}
|
}
|
||||||
|
a10_pit_update_irq(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,9 +261,12 @@ static void a10_pit_init(Object *obj)
|
|||||||
sysbus_init_mmio(sbd, &s->iomem);
|
sysbus_init_mmio(sbd, &s->iomem);
|
||||||
|
|
||||||
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
||||||
bh[i] = qemu_bh_new(a10_pit_timer_cb, s);
|
AwA10TimerContext *tc = &s->timer_context[i];
|
||||||
|
|
||||||
|
tc->container = s;
|
||||||
|
tc->index = i;
|
||||||
|
bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
|
||||||
s->timer[i] = ptimer_init(bh[i]);
|
s->timer[i] = ptimer_init(bh[i]);
|
||||||
ptimer_set_freq(s->timer[i], 240000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +275,7 @@ static void a10_pit_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->reset = a10_pit_reset;
|
dc->reset = a10_pit_reset;
|
||||||
|
dc->props = a10_pit_properties;
|
||||||
dc->desc = "allwinner a10 timer";
|
dc->desc = "allwinner a10 timer";
|
||||||
dc->vmsd = &vmstate_a10_pit;
|
dc->vmsd = &vmstate_a10_pit;
|
||||||
}
|
}
|
||||||
|
@@ -346,11 +346,13 @@ static void cadence_ttc_write(void *opaque, hwaddr offset,
|
|||||||
case 0x34:
|
case 0x34:
|
||||||
case 0x38:
|
case 0x38:
|
||||||
s->reg_match[0] = value & 0xffff;
|
s->reg_match[0] = value & 0xffff;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x3c: /* match register */
|
case 0x3c: /* match register */
|
||||||
case 0x40:
|
case 0x40:
|
||||||
case 0x44:
|
case 0x44:
|
||||||
s->reg_match[1] = value & 0xffff;
|
s->reg_match[1] = value & 0xffff;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x48: /* match register */
|
case 0x48: /* match register */
|
||||||
case 0x4c:
|
case 0x4c:
|
||||||
|
@@ -26,6 +26,10 @@ common-obj-y += ccid-card-passthru.o
|
|||||||
common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
|
common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_POSIX),y)
|
||||||
|
common-obj-$(CONFIG_USB_STORAGE_MTP) += dev-mtp.o
|
||||||
|
endif
|
||||||
|
|
||||||
# usb redirection
|
# usb redirection
|
||||||
common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o
|
common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o
|
||||||
|
|
||||||
|
@@ -44,7 +44,7 @@ typedef struct msos_compat_hdr {
|
|||||||
typedef struct msos_compat_func {
|
typedef struct msos_compat_func {
|
||||||
uint8_t bFirstInterfaceNumber;
|
uint8_t bFirstInterfaceNumber;
|
||||||
uint8_t reserved_1;
|
uint8_t reserved_1;
|
||||||
uint8_t compatibleId[8];
|
char compatibleId[8];
|
||||||
uint8_t subCompatibleId[8];
|
uint8_t subCompatibleId[8];
|
||||||
uint8_t reserved_2[6];
|
uint8_t reserved_2[6];
|
||||||
} QEMU_PACKED msos_compat_func;
|
} QEMU_PACKED msos_compat_func;
|
||||||
@@ -59,6 +59,10 @@ static int usb_desc_msos_compat(const USBDesc *desc, uint8_t *dest)
|
|||||||
func = (void *)(dest + length);
|
func = (void *)(dest + length);
|
||||||
func->bFirstInterfaceNumber = 0;
|
func->bFirstInterfaceNumber = 0;
|
||||||
func->reserved_1 = 0x01;
|
func->reserved_1 = 0x01;
|
||||||
|
if (desc->msos->CompatibleID) {
|
||||||
|
snprintf(func->compatibleId, sizeof(func->compatibleId),
|
||||||
|
"%s", desc->msos->CompatibleID);
|
||||||
|
}
|
||||||
length += sizeof(*func);
|
length += sizeof(*func);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
@@ -184,6 +184,7 @@ struct USBDescOther {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescMSOS {
|
struct USBDescMSOS {
|
||||||
|
const char *CompatibleID;
|
||||||
const wchar_t *Label;
|
const wchar_t *Label;
|
||||||
bool SelectiveSuspendEnabled;
|
bool SelectiveSuspendEnabled;
|
||||||
};
|
};
|
||||||
|
1103
hw/usb/dev-mtp.c
Normal file
1103
hw/usb/dev-mtp.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -92,6 +92,7 @@ typedef enum {
|
|||||||
|
|
||||||
#define BDRV_O_RDWR 0x0002
|
#define BDRV_O_RDWR 0x0002
|
||||||
#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */
|
#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */
|
||||||
|
#define BDRV_O_TEMPORARY 0x0010 /* delete the file after use */
|
||||||
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
|
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
|
||||||
#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */
|
#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */
|
||||||
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */
|
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */
|
||||||
@@ -180,7 +181,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
|
|||||||
QEMUOptionParameter *options, Error **errp);
|
QEMUOptionParameter *options, Error **errp);
|
||||||
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
BlockDriverState *bdrv_new(const char *device_name);
|
BlockDriverState *bdrv_new(const char *device_name, Error **errp);
|
||||||
void bdrv_make_anon(BlockDriverState *bs);
|
void bdrv_make_anon(BlockDriverState *bs);
|
||||||
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
|
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
|
||||||
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
|
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
|
||||||
@@ -429,7 +430,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
|
|||||||
|
|
||||||
struct HBitmapIter;
|
struct HBitmapIter;
|
||||||
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
|
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
|
||||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity);
|
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||||
|
Error **errp);
|
||||||
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
|
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
|
||||||
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
|
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
|
||||||
int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
|
int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
|
||||||
|
@@ -299,7 +299,6 @@ struct BlockDriverState {
|
|||||||
char backing_file[1024]; /* if non zero, the image is a diff of
|
char backing_file[1024]; /* if non zero, the image is a diff of
|
||||||
this file image */
|
this file image */
|
||||||
char backing_format[16]; /* if non-zero and backing_file exists */
|
char backing_format[16]; /* if non-zero and backing_file exists */
|
||||||
int is_temporary;
|
|
||||||
|
|
||||||
BlockDriverState *backing_hd;
|
BlockDriverState *backing_hd;
|
||||||
BlockDriverState *file;
|
BlockDriverState *file;
|
||||||
|
@@ -84,7 +84,7 @@
|
|||||||
#define dh_is_64bit_noreturn 0
|
#define dh_is_64bit_noreturn 0
|
||||||
#define dh_is_64bit_i32 0
|
#define dh_is_64bit_i32 0
|
||||||
#define dh_is_64bit_i64 1
|
#define dh_is_64bit_i64 1
|
||||||
#define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64)
|
#define dh_is_64bit_ptr (sizeof(void *) == 8)
|
||||||
#define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
|
#define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
|
||||||
|
|
||||||
#define dh_is_signed_void 0
|
#define dh_is_signed_void 0
|
||||||
|
@@ -162,3 +162,55 @@
|
|||||||
#define stw(p, v) stw_data(p, v)
|
#define stw(p, v) stw_data(p, v)
|
||||||
#define stl(p, v) stl_data(p, v)
|
#define stl(p, v) stl_data(p, v)
|
||||||
#define stq(p, v) stq_data(p, v)
|
#define stq(p, v) stq_data(p, v)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tlb_vaddr_to_host:
|
||||||
|
* @env: CPUArchState
|
||||||
|
* @addr: guest virtual address to look up
|
||||||
|
* @access_type: 0 for read, 1 for write, 2 for execute
|
||||||
|
* @mmu_idx: MMU index to use for lookup
|
||||||
|
*
|
||||||
|
* Look up the specified guest virtual index in the TCG softmmu TLB.
|
||||||
|
* If the TLB contains a host virtual address suitable for direct RAM
|
||||||
|
* access, then return it. Otherwise (TLB miss, TLB entry is for an
|
||||||
|
* I/O access, etc) return NULL.
|
||||||
|
*
|
||||||
|
* This is the equivalent of the initial fast-path code used by
|
||||||
|
* TCG backends for guest load and store accesses.
|
||||||
|
*/
|
||||||
|
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
|
||||||
|
int access_type, int mmu_idx)
|
||||||
|
{
|
||||||
|
int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
|
CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
|
||||||
|
target_ulong tlb_addr;
|
||||||
|
uintptr_t haddr;
|
||||||
|
|
||||||
|
switch (access_type) {
|
||||||
|
case 0:
|
||||||
|
tlb_addr = tlbentry->addr_read;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tlb_addr = tlbentry->addr_write;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tlb_addr = tlbentry->addr_code;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((addr & TARGET_PAGE_MASK)
|
||||||
|
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||||
|
/* TLB entry is for a different page */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tlb_addr & ~TARGET_PAGE_MASK) {
|
||||||
|
/* IO access */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
haddr = addr + env->tlb_table[mmu_idx][index].addend;
|
||||||
|
return (void *)haddr;
|
||||||
|
}
|
||||||
|
@@ -239,6 +239,8 @@ uint16_t pvpanic_port(void);
|
|||||||
#define E820_UNUSABLE 5
|
#define E820_UNUSABLE 5
|
||||||
|
|
||||||
int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
||||||
|
int e820_get_num_entries(void);
|
||||||
|
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
|
|
||||||
#define PC_Q35_COMPAT_1_7 \
|
#define PC_Q35_COMPAT_1_7 \
|
||||||
PC_COMPAT_1_7, \
|
PC_COMPAT_1_7, \
|
||||||
|
@@ -15,15 +15,40 @@
|
|||||||
|
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
|
|
||||||
|
#define SMBIOS_MAX_TYPE 127
|
||||||
|
|
||||||
void smbios_entry_add(QemuOpts *opts);
|
void smbios_entry_add(QemuOpts *opts);
|
||||||
void smbios_set_type1_defaults(const char *manufacturer,
|
void smbios_set_cpuid(uint32_t version, uint32_t features);
|
||||||
const char *product, const char *version);
|
void smbios_set_defaults(const char *manufacturer, const char *product,
|
||||||
uint8_t *smbios_get_table(size_t *length);
|
const char *version, bool legacy_mode);
|
||||||
|
uint8_t *smbios_get_table_legacy(size_t *length);
|
||||||
|
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
|
||||||
|
uint8_t **anchor, size_t *anchor_len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SMBIOS spec defined tables
|
* SMBIOS spec defined tables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* SMBIOS entry point (anchor).
|
||||||
|
* BIOS must place this at a 16-bit-aligned address between 0xf0000 and 0xfffff.
|
||||||
|
*/
|
||||||
|
struct smbios_entry_point {
|
||||||
|
uint8_t anchor_string[4];
|
||||||
|
uint8_t checksum;
|
||||||
|
uint8_t length;
|
||||||
|
uint8_t smbios_major_version;
|
||||||
|
uint8_t smbios_minor_version;
|
||||||
|
uint16_t max_structure_size;
|
||||||
|
uint8_t entry_point_revision;
|
||||||
|
uint8_t formatted_area[5];
|
||||||
|
uint8_t intermediate_anchor_string[5];
|
||||||
|
uint8_t intermediate_checksum;
|
||||||
|
uint16_t structure_table_length;
|
||||||
|
uint32_t structure_table_address;
|
||||||
|
uint16_t number_of_structures;
|
||||||
|
uint8_t smbios_bcd_revision;
|
||||||
|
} QEMU_PACKED;
|
||||||
|
|
||||||
/* This goes at the beginning of every SMBIOS structure. */
|
/* This goes at the beginning of every SMBIOS structure. */
|
||||||
struct smbios_structure_header {
|
struct smbios_structure_header {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -60,7 +85,23 @@ struct smbios_type_1 {
|
|||||||
uint8_t family_str;
|
uint8_t family_str;
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
|
|
||||||
/* SMBIOS type 3 - System Enclosure (v2.3) */
|
/* SMBIOS type 2 - Base Board */
|
||||||
|
struct smbios_type_2 {
|
||||||
|
struct smbios_structure_header header;
|
||||||
|
uint8_t manufacturer_str;
|
||||||
|
uint8_t product_str;
|
||||||
|
uint8_t version_str;
|
||||||
|
uint8_t serial_number_str;
|
||||||
|
uint8_t asset_tag_number_str;
|
||||||
|
uint8_t feature_flags;
|
||||||
|
uint8_t location_str;
|
||||||
|
uint16_t chassis_handle;
|
||||||
|
uint8_t board_type;
|
||||||
|
uint8_t contained_element_count;
|
||||||
|
/* contained elements follow */
|
||||||
|
} QEMU_PACKED;
|
||||||
|
|
||||||
|
/* SMBIOS type 3 - System Enclosure (v2.7) */
|
||||||
struct smbios_type_3 {
|
struct smbios_type_3 {
|
||||||
struct smbios_structure_header header;
|
struct smbios_structure_header header;
|
||||||
uint8_t manufacturer_str;
|
uint8_t manufacturer_str;
|
||||||
@@ -76,10 +117,11 @@ struct smbios_type_3 {
|
|||||||
uint8_t height;
|
uint8_t height;
|
||||||
uint8_t number_of_power_cords;
|
uint8_t number_of_power_cords;
|
||||||
uint8_t contained_element_count;
|
uint8_t contained_element_count;
|
||||||
// contained elements follow
|
uint8_t sku_number_str;
|
||||||
|
/* contained elements follow */
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
|
|
||||||
/* SMBIOS type 4 - Processor Information (v2.0) */
|
/* SMBIOS type 4 - Processor Information (v2.6) */
|
||||||
struct smbios_type_4 {
|
struct smbios_type_4 {
|
||||||
struct smbios_structure_header header;
|
struct smbios_structure_header header;
|
||||||
uint8_t socket_designation_str;
|
uint8_t socket_designation_str;
|
||||||
@@ -97,11 +139,17 @@ struct smbios_type_4 {
|
|||||||
uint16_t l1_cache_handle;
|
uint16_t l1_cache_handle;
|
||||||
uint16_t l2_cache_handle;
|
uint16_t l2_cache_handle;
|
||||||
uint16_t l3_cache_handle;
|
uint16_t l3_cache_handle;
|
||||||
|
uint8_t serial_number_str;
|
||||||
|
uint8_t asset_tag_number_str;
|
||||||
|
uint8_t part_number_str;
|
||||||
|
uint8_t core_count;
|
||||||
|
uint8_t core_enabled;
|
||||||
|
uint8_t thread_count;
|
||||||
|
uint16_t processor_characteristics;
|
||||||
|
uint16_t processor_family2;
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
|
|
||||||
/* SMBIOS type 16 - Physical Memory Array
|
/* SMBIOS type 16 - Physical Memory Array (v2.7) */
|
||||||
* Associated with one type 17 (Memory Device).
|
|
||||||
*/
|
|
||||||
struct smbios_type_16 {
|
struct smbios_type_16 {
|
||||||
struct smbios_structure_header header;
|
struct smbios_structure_header header;
|
||||||
uint8_t location;
|
uint8_t location;
|
||||||
@@ -110,10 +158,10 @@ struct smbios_type_16 {
|
|||||||
uint32_t maximum_capacity;
|
uint32_t maximum_capacity;
|
||||||
uint16_t memory_error_information_handle;
|
uint16_t memory_error_information_handle;
|
||||||
uint16_t number_of_memory_devices;
|
uint16_t number_of_memory_devices;
|
||||||
|
uint64_t extended_maximum_capacity;
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
/* SMBIOS type 17 - Memory Device
|
|
||||||
* Associated with one type 19
|
/* SMBIOS type 17 - Memory Device (v2.8) */
|
||||||
*/
|
|
||||||
struct smbios_type_17 {
|
struct smbios_type_17 {
|
||||||
struct smbios_structure_header header;
|
struct smbios_structure_header header;
|
||||||
uint16_t physical_memory_array_handle;
|
uint16_t physical_memory_array_handle;
|
||||||
@@ -127,27 +175,28 @@ struct smbios_type_17 {
|
|||||||
uint8_t bank_locator_str;
|
uint8_t bank_locator_str;
|
||||||
uint8_t memory_type;
|
uint8_t memory_type;
|
||||||
uint16_t type_detail;
|
uint16_t type_detail;
|
||||||
|
uint16_t speed;
|
||||||
|
uint8_t manufacturer_str;
|
||||||
|
uint8_t serial_number_str;
|
||||||
|
uint8_t asset_tag_number_str;
|
||||||
|
uint8_t part_number_str;
|
||||||
|
uint8_t attributes;
|
||||||
|
uint32_t extended_size;
|
||||||
|
uint32_t configured_clock_speed;
|
||||||
|
uint32_t minimum_voltage;
|
||||||
|
uint32_t maximum_voltage;
|
||||||
|
uint32_t configured_voltage;
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
|
|
||||||
/* SMBIOS type 19 - Memory Array Mapped Address */
|
/* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */
|
||||||
struct smbios_type_19 {
|
struct smbios_type_19 {
|
||||||
struct smbios_structure_header header;
|
struct smbios_structure_header header;
|
||||||
uint32_t starting_address;
|
uint32_t starting_address;
|
||||||
uint32_t ending_address;
|
uint32_t ending_address;
|
||||||
uint16_t memory_array_handle;
|
uint16_t memory_array_handle;
|
||||||
uint8_t partition_width;
|
uint8_t partition_width;
|
||||||
} QEMU_PACKED;
|
uint64_t extended_starting_address;
|
||||||
|
uint64_t extended_ending_address;
|
||||||
/* SMBIOS type 20 - Memory Device Mapped Address */
|
|
||||||
struct smbios_type_20 {
|
|
||||||
struct smbios_structure_header header;
|
|
||||||
uint32_t starting_address;
|
|
||||||
uint32_t ending_address;
|
|
||||||
uint16_t memory_device_handle;
|
|
||||||
uint16_t memory_array_mapped_address_handle;
|
|
||||||
uint8_t partition_row_position;
|
|
||||||
uint8_t interleave_position;
|
|
||||||
uint8_t interleaved_data_depth;
|
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
|
|
||||||
/* SMBIOS type 32 - System Boot Information */
|
/* SMBIOS type 32 - System Boot Information */
|
||||||
|
@@ -144,6 +144,7 @@
|
|||||||
#define MII_BMSR_10T_FD (1 << 12)
|
#define MII_BMSR_10T_FD (1 << 12)
|
||||||
#define MII_BMSR_10T_HD (1 << 11)
|
#define MII_BMSR_10T_HD (1 << 11)
|
||||||
#define MII_BMSR_MFPS (1 << 6)
|
#define MII_BMSR_MFPS (1 << 6)
|
||||||
|
#define MII_BMSR_AN_COMP (1 << 5)
|
||||||
#define MII_BMSR_AUTONEG (1 << 3)
|
#define MII_BMSR_AUTONEG (1 << 3)
|
||||||
#define MII_BMSR_LINK_ST (1 << 2)
|
#define MII_BMSR_LINK_ST (1 << 2)
|
||||||
|
|
||||||
|
@@ -35,13 +35,22 @@
|
|||||||
|
|
||||||
#define AW_A10_PIT_DEFAULT_CLOCK 0x4
|
#define AW_A10_PIT_DEFAULT_CLOCK 0x4
|
||||||
|
|
||||||
typedef struct AwA10PITState {
|
typedef struct AwA10PITState AwA10PITState;
|
||||||
|
|
||||||
|
typedef struct AwA10TimerContext {
|
||||||
|
AwA10PITState *container;
|
||||||
|
int index;
|
||||||
|
} AwA10TimerContext;
|
||||||
|
|
||||||
|
struct AwA10PITState {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
qemu_irq irq[AW_A10_PIT_TIMER_NR];
|
qemu_irq irq[AW_A10_PIT_TIMER_NR];
|
||||||
ptimer_state * timer[AW_A10_PIT_TIMER_NR];
|
ptimer_state * timer[AW_A10_PIT_TIMER_NR];
|
||||||
|
AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR];
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
uint32_t clk_freq[4];
|
||||||
|
|
||||||
uint32_t irq_enable;
|
uint32_t irq_enable;
|
||||||
uint32_t irq_status;
|
uint32_t irq_status;
|
||||||
@@ -53,6 +62,6 @@ typedef struct AwA10PITState {
|
|||||||
uint32_t count_lo;
|
uint32_t count_lo;
|
||||||
uint32_t count_hi;
|
uint32_t count_hi;
|
||||||
uint32_t count_ctl;
|
uint32_t count_ctl;
|
||||||
} AwA10PITState;
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -79,7 +79,6 @@ int monitor_handle_fd_param(Monitor *mon, const char *fdname);
|
|||||||
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
|
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
|
||||||
GCC_FMT_ATTR(2, 0);
|
GCC_FMT_ATTR(2, 0);
|
||||||
void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||||
void monitor_print_filename(Monitor *mon, const char *filename);
|
|
||||||
void monitor_flush(Monitor *mon);
|
void monitor_flush(Monitor *mon);
|
||||||
int monitor_set_cpu(int cpu_index);
|
int monitor_set_cpu(int cpu_index);
|
||||||
int monitor_get_cpu_index(void);
|
int monitor_get_cpu_index(void);
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
#ifndef QERROR_H
|
#ifndef QERROR_H
|
||||||
#define QERROR_H
|
#define QERROR_H
|
||||||
|
|
||||||
#include "qapi/qmp/qdict.h"
|
|
||||||
#include "qapi/qmp/qstring.h"
|
#include "qapi/qmp/qstring.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
@@ -35,51 +34,30 @@ void qerror_report_err(Error *err);
|
|||||||
* Please keep the definitions in alphabetical order.
|
* Please keep the definitions in alphabetical order.
|
||||||
* Use scripts/check-qerror.sh to check.
|
* Use scripts/check-qerror.sh to check.
|
||||||
*/
|
*/
|
||||||
#define QERR_ADD_CLIENT_FAILED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Could not add client"
|
|
||||||
|
|
||||||
#define QERR_AMBIGUOUS_PATH \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Path '%s' does not uniquely identify an object"
|
|
||||||
|
|
||||||
#define QERR_BAD_BUS_FOR_DEVICE \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' can't go on a %s bus"
|
|
||||||
|
|
||||||
#define QERR_BASE_NOT_FOUND \
|
#define QERR_BASE_NOT_FOUND \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found"
|
ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found"
|
||||||
|
|
||||||
#define QERR_BLOCK_JOB_NOT_ACTIVE \
|
#define QERR_BLOCK_JOB_NOT_ACTIVE \
|
||||||
ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'"
|
ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'"
|
||||||
|
|
||||||
#define QERR_BLOCK_JOB_PAUSED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "The block job for device '%s' is currently paused"
|
|
||||||
|
|
||||||
#define QERR_BLOCK_JOB_NOT_READY \
|
#define QERR_BLOCK_JOB_NOT_READY \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed"
|
ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed"
|
||||||
|
|
||||||
#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
|
#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'"
|
ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'"
|
||||||
|
|
||||||
#define QERR_BUFFER_OVERRUN \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "An internal buffer overran"
|
|
||||||
|
|
||||||
#define QERR_BUS_NO_HOTPLUG \
|
#define QERR_BUS_NO_HOTPLUG \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging"
|
ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging"
|
||||||
|
|
||||||
#define QERR_BUS_NOT_FOUND \
|
#define QERR_BUS_NOT_FOUND \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Bus '%s' not found"
|
ERROR_CLASS_GENERIC_ERROR, "Bus '%s' not found"
|
||||||
|
|
||||||
#define QERR_COMMAND_DISABLED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "The command %s has been disabled for this instance"
|
|
||||||
|
|
||||||
#define QERR_COMMAND_NOT_FOUND \
|
#define QERR_COMMAND_NOT_FOUND \
|
||||||
ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found"
|
ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found"
|
||||||
|
|
||||||
#define QERR_DEVICE_ENCRYPTED \
|
#define QERR_DEVICE_ENCRYPTED \
|
||||||
ERROR_CLASS_DEVICE_ENCRYPTED, "'%s' (%s) is encrypted"
|
ERROR_CLASS_DEVICE_ENCRYPTED, "'%s' (%s) is encrypted"
|
||||||
|
|
||||||
#define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when using feature '%s' in device '%s'"
|
|
||||||
|
|
||||||
#define QERR_DEVICE_HAS_NO_MEDIUM \
|
#define QERR_DEVICE_HAS_NO_MEDIUM \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no medium"
|
ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no medium"
|
||||||
|
|
||||||
@@ -92,15 +70,6 @@ void qerror_report_err(Error *err);
|
|||||||
#define QERR_DEVICE_IS_READ_ONLY \
|
#define QERR_DEVICE_IS_READ_ONLY \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is read only"
|
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is read only"
|
||||||
|
|
||||||
#define QERR_DEVICE_LOCKED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is locked"
|
|
||||||
|
|
||||||
#define QERR_DEVICE_MULTIPLE_BUSSES \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' has multiple child busses"
|
|
||||||
|
|
||||||
#define QERR_DEVICE_NO_BUS \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no child bus"
|
|
||||||
|
|
||||||
#define QERR_DEVICE_NO_HOTPLUG \
|
#define QERR_DEVICE_NO_HOTPLUG \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging"
|
ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging"
|
||||||
|
|
||||||
@@ -113,12 +82,6 @@ void qerror_report_err(Error *err);
|
|||||||
#define QERR_DEVICE_NOT_FOUND \
|
#define QERR_DEVICE_NOT_FOUND \
|
||||||
ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found"
|
ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found"
|
||||||
|
|
||||||
#define QERR_DEVICE_NOT_REMOVABLE \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not removable"
|
|
||||||
|
|
||||||
#define QERR_DUPLICATE_ID \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Duplicate ID '%s' for %s"
|
|
||||||
|
|
||||||
#define QERR_FD_NOT_FOUND \
|
#define QERR_FD_NOT_FOUND \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "File descriptor named '%s' not found"
|
ERROR_CLASS_GENERIC_ERROR, "File descriptor named '%s' not found"
|
||||||
|
|
||||||
@@ -131,15 +94,9 @@ void qerror_report_err(Error *err);
|
|||||||
#define QERR_INVALID_BLOCK_FORMAT \
|
#define QERR_INVALID_BLOCK_FORMAT \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'"
|
ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'"
|
||||||
|
|
||||||
#define QERR_INVALID_OPTION_GROUP \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "There is no option group '%s'"
|
|
||||||
|
|
||||||
#define QERR_INVALID_PARAMETER \
|
#define QERR_INVALID_PARAMETER \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'"
|
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'"
|
||||||
|
|
||||||
#define QERR_INVALID_PARAMETER_COMBINATION \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter combination"
|
|
||||||
|
|
||||||
#define QERR_INVALID_PARAMETER_TYPE \
|
#define QERR_INVALID_PARAMETER_TYPE \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter type for '%s', expected: %s"
|
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter type for '%s', expected: %s"
|
||||||
|
|
||||||
@@ -152,9 +109,6 @@ void qerror_report_err(Error *err);
|
|||||||
#define QERR_IO_ERROR \
|
#define QERR_IO_ERROR \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "An IO error has occurred"
|
ERROR_CLASS_GENERIC_ERROR, "An IO error has occurred"
|
||||||
|
|
||||||
#define QERR_JSON_PARSE_ERROR \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "JSON parse error, %s"
|
|
||||||
|
|
||||||
#define QERR_JSON_PARSING \
|
#define QERR_JSON_PARSING \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax"
|
ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax"
|
||||||
|
|
||||||
@@ -164,45 +118,21 @@ void qerror_report_err(Error *err);
|
|||||||
#define QERR_MIGRATION_ACTIVE \
|
#define QERR_MIGRATION_ACTIVE \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress"
|
ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress"
|
||||||
|
|
||||||
#define QERR_MIGRATION_NOT_SUPPORTED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "State blocked by non-migratable device '%s'"
|
|
||||||
|
|
||||||
#define QERR_MISSING_PARAMETER \
|
#define QERR_MISSING_PARAMETER \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing"
|
ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing"
|
||||||
|
|
||||||
#define QERR_NO_BUS_FOR_DEVICE \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "No '%s' bus found for device '%s'"
|
|
||||||
|
|
||||||
#define QERR_NOT_SUPPORTED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Not supported"
|
|
||||||
|
|
||||||
#define QERR_PERMISSION_DENIED \
|
#define QERR_PERMISSION_DENIED \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation"
|
ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation"
|
||||||
|
|
||||||
#define QERR_PROPERTY_NOT_FOUND \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' not found"
|
|
||||||
|
|
||||||
#define QERR_PROPERTY_VALUE_BAD \
|
#define QERR_PROPERTY_VALUE_BAD \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' doesn't take value '%s'"
|
ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' doesn't take value '%s'"
|
||||||
|
|
||||||
#define QERR_PROPERTY_VALUE_IN_USE \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't take value '%s', it's in use"
|
|
||||||
|
|
||||||
#define QERR_PROPERTY_VALUE_NOT_FOUND \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't find value '%s'"
|
|
||||||
|
|
||||||
#define QERR_PROPERTY_VALUE_NOT_POWER_OF_2 \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2"
|
|
||||||
|
|
||||||
#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \
|
#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")"
|
ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")"
|
||||||
|
|
||||||
#define QERR_QGA_COMMAND_FAILED \
|
#define QERR_QGA_COMMAND_FAILED \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Guest agent command failed, error was '%s'"
|
ERROR_CLASS_GENERIC_ERROR, "Guest agent command failed, error was '%s'"
|
||||||
|
|
||||||
#define QERR_QGA_LOGGING_FAILED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Guest agent failed to log non-optional log statement"
|
|
||||||
|
|
||||||
#define QERR_QMP_BAD_INPUT_OBJECT \
|
#define QERR_QMP_BAD_INPUT_OBJECT \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input"
|
ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input"
|
||||||
|
|
||||||
@@ -212,15 +142,9 @@ void qerror_report_err(Error *err);
|
|||||||
#define QERR_QMP_EXTRA_MEMBER \
|
#define QERR_QMP_EXTRA_MEMBER \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' is unexpected"
|
ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' is unexpected"
|
||||||
|
|
||||||
#define QERR_RESET_REQUIRED \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Resetting the Virtual Machine is required"
|
|
||||||
|
|
||||||
#define QERR_SET_PASSWD_FAILED \
|
#define QERR_SET_PASSWD_FAILED \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Could not set password"
|
ERROR_CLASS_GENERIC_ERROR, "Could not set password"
|
||||||
|
|
||||||
#define QERR_TOO_MANY_FILES \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Too many open files"
|
|
||||||
|
|
||||||
#define QERR_UNDEFINED_ERROR \
|
#define QERR_UNDEFINED_ERROR \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred"
|
ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred"
|
||||||
|
|
||||||
@@ -230,9 +154,6 @@ void qerror_report_err(Error *err);
|
|||||||
#define QERR_UNSUPPORTED \
|
#define QERR_UNSUPPORTED \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "this feature or command is not currently supported"
|
ERROR_CLASS_GENERIC_ERROR, "this feature or command is not currently supported"
|
||||||
|
|
||||||
#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \
|
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'"
|
|
||||||
|
|
||||||
#define QERR_SOCKET_CONNECT_FAILED \
|
#define QERR_SOCKET_CONNECT_FAILED \
|
||||||
ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket"
|
ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket"
|
||||||
|
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
QemuOptsList *qemu_find_opts(const char *group);
|
QemuOptsList *qemu_find_opts(const char *group);
|
||||||
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
|
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
|
||||||
|
QemuOpts *qemu_find_opts_singleton(const char *group);
|
||||||
|
|
||||||
void qemu_add_opts(QemuOptsList *list);
|
void qemu_add_opts(QemuOptsList *list);
|
||||||
void qemu_add_drive_opts(QemuOptsList *list);
|
void qemu_add_drive_opts(QemuOptsList *list);
|
||||||
int qemu_set_option(const char *str);
|
int qemu_set_option(const char *str);
|
||||||
|
@@ -37,7 +37,6 @@ void loc_set_file(const char *fname, int lno);
|
|||||||
void error_vprintf(const char *fmt, va_list ap) GCC_FMT_ATTR(1, 0);
|
void error_vprintf(const char *fmt, va_list ap) GCC_FMT_ATTR(1, 0);
|
||||||
void error_printf(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
void error_printf(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||||
void error_printf_unless_qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
void error_printf_unless_qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||||
void error_print_loc(void);
|
|
||||||
void error_set_progname(const char *argv0);
|
void error_set_progname(const char *argv0);
|
||||||
void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||||
const char *error_get_progname(void);
|
const char *error_get_progname(void);
|
||||||
|
@@ -53,7 +53,7 @@ static inline Int128 int128_rshift(Int128 a, int n)
|
|||||||
if (n >= 64) {
|
if (n >= 64) {
|
||||||
return (Int128) { h, h >> 63 };
|
return (Int128) { h, h >> 63 };
|
||||||
} else {
|
} else {
|
||||||
return (Int128) { (a.lo >> n) | (a.hi << (64 - n)), h };
|
return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ static inline Int128 int128_neg(Int128 a)
|
|||||||
|
|
||||||
static inline Int128 int128_sub(Int128 a, Int128 b)
|
static inline Int128 int128_sub(Int128 a, Int128 b)
|
||||||
{
|
{
|
||||||
return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
|
return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool int128_nonneg(Int128 a)
|
static inline bool int128_nonneg(Int128 a)
|
||||||
|
@@ -294,6 +294,36 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu);
|
|||||||
|
|
||||||
int kvm_check_extension(KVMState *s, unsigned int extension);
|
int kvm_check_extension(KVMState *s, unsigned int extension);
|
||||||
|
|
||||||
|
#define kvm_vm_enable_cap(s, capability, cap_flags, ...) \
|
||||||
|
({ \
|
||||||
|
struct kvm_enable_cap cap = { \
|
||||||
|
.cap = capability, \
|
||||||
|
.flags = cap_flags, \
|
||||||
|
}; \
|
||||||
|
uint64_t args_tmp[] = { __VA_ARGS__ }; \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < ARRAY_SIZE(args_tmp) && \
|
||||||
|
i < ARRAY_SIZE(cap.args); i++) { \
|
||||||
|
cap.args[i] = args_tmp[i]; \
|
||||||
|
} \
|
||||||
|
kvm_vm_ioctl(s, KVM_ENABLE_CAP, &cap); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define kvm_vcpu_enable_cap(cpu, capability, cap_flags, ...) \
|
||||||
|
({ \
|
||||||
|
struct kvm_enable_cap cap = { \
|
||||||
|
.cap = capability, \
|
||||||
|
.flags = cap_flags, \
|
||||||
|
}; \
|
||||||
|
uint64_t args_tmp[] = { __VA_ARGS__ }; \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < ARRAY_SIZE(args_tmp) && \
|
||||||
|
i < ARRAY_SIZE(cap.args); i++) { \
|
||||||
|
cap.args[i] = args_tmp[i]; \
|
||||||
|
} \
|
||||||
|
kvm_vcpu_ioctl(cpu, KVM_ENABLE_CAP, &cap); \
|
||||||
|
})
|
||||||
|
|
||||||
uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
|
uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
|
||||||
uint32_t index, int reg);
|
uint32_t index, int reg);
|
||||||
|
|
||||||
|
@@ -441,7 +441,7 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section)
|
|||||||
|
|
||||||
d.slot = mem->slot;
|
d.slot = mem->slot;
|
||||||
|
|
||||||
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) < 0) {
|
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
|
||||||
DPRINTF("ioctl failed %d\n", errno);
|
DPRINTF("ioctl failed %d\n", errno);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
|
@@ -22,6 +22,8 @@
|
|||||||
#define KVM_DEV_FLIC_CLEAR_IRQS 3
|
#define KVM_DEV_FLIC_CLEAR_IRQS 3
|
||||||
#define KVM_DEV_FLIC_APF_ENABLE 4
|
#define KVM_DEV_FLIC_APF_ENABLE 4
|
||||||
#define KVM_DEV_FLIC_APF_DISABLE_WAIT 5
|
#define KVM_DEV_FLIC_APF_DISABLE_WAIT 5
|
||||||
|
#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
|
||||||
|
#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
|
||||||
/*
|
/*
|
||||||
* We can have up to 4*64k pending subchannels + 8 adapter interrupts,
|
* We can have up to 4*64k pending subchannels + 8 adapter interrupts,
|
||||||
* as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
|
* as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
|
||||||
@@ -32,6 +34,26 @@
|
|||||||
#define KVM_S390_MAX_FLOAT_IRQS 266250
|
#define KVM_S390_MAX_FLOAT_IRQS 266250
|
||||||
#define KVM_S390_FLIC_MAX_BUFFER 0x2000000
|
#define KVM_S390_FLIC_MAX_BUFFER 0x2000000
|
||||||
|
|
||||||
|
struct kvm_s390_io_adapter {
|
||||||
|
__u32 id;
|
||||||
|
__u8 isc;
|
||||||
|
__u8 maskable;
|
||||||
|
__u8 swap;
|
||||||
|
__u8 pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define KVM_S390_IO_ADAPTER_MASK 1
|
||||||
|
#define KVM_S390_IO_ADAPTER_MAP 2
|
||||||
|
#define KVM_S390_IO_ADAPTER_UNMAP 3
|
||||||
|
|
||||||
|
struct kvm_s390_io_adapter_req {
|
||||||
|
__u32 id;
|
||||||
|
__u8 type;
|
||||||
|
__u8 mask;
|
||||||
|
__u16 pad0;
|
||||||
|
__u64 addr;
|
||||||
|
};
|
||||||
|
|
||||||
/* for KVM_GET_REGS and KVM_SET_REGS */
|
/* for KVM_GET_REGS and KVM_SET_REGS */
|
||||||
struct kvm_regs {
|
struct kvm_regs {
|
||||||
/* general purpose regs for s390 */
|
/* general purpose regs for s390 */
|
||||||
@@ -76,4 +98,6 @@ struct kvm_sync_regs {
|
|||||||
#define KVM_REG_S390_PFTOKEN (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5)
|
#define KVM_REG_S390_PFTOKEN (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5)
|
||||||
#define KVM_REG_S390_PFCOMPARE (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6)
|
#define KVM_REG_S390_PFCOMPARE (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6)
|
||||||
#define KVM_REG_S390_PFSELECT (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7)
|
#define KVM_REG_S390_PFSELECT (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7)
|
||||||
|
#define KVM_REG_S390_PP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x8)
|
||||||
|
#define KVM_REG_S390_GBEA (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x9)
|
||||||
#endif
|
#endif
|
||||||
|
@@ -740,6 +740,9 @@ struct kvm_ppc_smmu_info {
|
|||||||
#define KVM_CAP_SPAPR_MULTITCE 94
|
#define KVM_CAP_SPAPR_MULTITCE 94
|
||||||
#define KVM_CAP_EXT_EMUL_CPUID 95
|
#define KVM_CAP_EXT_EMUL_CPUID 95
|
||||||
#define KVM_CAP_HYPERV_TIME 96
|
#define KVM_CAP_HYPERV_TIME 96
|
||||||
|
#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
|
||||||
|
#define KVM_CAP_ENABLE_CAP_VM 98
|
||||||
|
#define KVM_CAP_S390_IRQCHIP 99
|
||||||
|
|
||||||
#ifdef KVM_CAP_IRQ_ROUTING
|
#ifdef KVM_CAP_IRQ_ROUTING
|
||||||
|
|
||||||
@@ -755,9 +758,18 @@ struct kvm_irq_routing_msi {
|
|||||||
__u32 pad;
|
__u32 pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct kvm_irq_routing_s390_adapter {
|
||||||
|
__u64 ind_addr;
|
||||||
|
__u64 summary_addr;
|
||||||
|
__u64 ind_offset;
|
||||||
|
__u32 summary_offset;
|
||||||
|
__u32 adapter_id;
|
||||||
|
};
|
||||||
|
|
||||||
/* gsi routing entry types */
|
/* gsi routing entry types */
|
||||||
#define KVM_IRQ_ROUTING_IRQCHIP 1
|
#define KVM_IRQ_ROUTING_IRQCHIP 1
|
||||||
#define KVM_IRQ_ROUTING_MSI 2
|
#define KVM_IRQ_ROUTING_MSI 2
|
||||||
|
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
|
||||||
|
|
||||||
struct kvm_irq_routing_entry {
|
struct kvm_irq_routing_entry {
|
||||||
__u32 gsi;
|
__u32 gsi;
|
||||||
@@ -767,6 +779,7 @@ struct kvm_irq_routing_entry {
|
|||||||
union {
|
union {
|
||||||
struct kvm_irq_routing_irqchip irqchip;
|
struct kvm_irq_routing_irqchip irqchip;
|
||||||
struct kvm_irq_routing_msi msi;
|
struct kvm_irq_routing_msi msi;
|
||||||
|
struct kvm_irq_routing_s390_adapter adapter;
|
||||||
__u32 pad[8];
|
__u32 pad[8];
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
@@ -1075,6 +1088,10 @@ struct kvm_s390_ucas_mapping {
|
|||||||
/* Available with KVM_CAP_DEBUGREGS */
|
/* Available with KVM_CAP_DEBUGREGS */
|
||||||
#define KVM_GET_DEBUGREGS _IOR(KVMIO, 0xa1, struct kvm_debugregs)
|
#define KVM_GET_DEBUGREGS _IOR(KVMIO, 0xa1, struct kvm_debugregs)
|
||||||
#define KVM_SET_DEBUGREGS _IOW(KVMIO, 0xa2, struct kvm_debugregs)
|
#define KVM_SET_DEBUGREGS _IOW(KVMIO, 0xa2, struct kvm_debugregs)
|
||||||
|
/*
|
||||||
|
* vcpu version available with KVM_ENABLE_CAP
|
||||||
|
* vm version available with KVM_CAP_ENABLE_CAP_VM
|
||||||
|
*/
|
||||||
#define KVM_ENABLE_CAP _IOW(KVMIO, 0xa3, struct kvm_enable_cap)
|
#define KVM_ENABLE_CAP _IOW(KVMIO, 0xa3, struct kvm_enable_cap)
|
||||||
/* Available with KVM_CAP_XSAVE */
|
/* Available with KVM_CAP_XSAVE */
|
||||||
#define KVM_GET_XSAVE _IOR(KVMIO, 0xa4, struct kvm_xsave)
|
#define KVM_GET_XSAVE _IOR(KVMIO, 0xa4, struct kvm_xsave)
|
||||||
|
@@ -23,6 +23,12 @@
|
|||||||
|
|
||||||
#define VFIO_TYPE1_IOMMU 1
|
#define VFIO_TYPE1_IOMMU 1
|
||||||
#define VFIO_SPAPR_TCE_IOMMU 2
|
#define VFIO_SPAPR_TCE_IOMMU 2
|
||||||
|
#define VFIO_TYPE1v2_IOMMU 3
|
||||||
|
/*
|
||||||
|
* IOMMU enforces DMA cache coherence (ex. PCIe NoSnoop stripping). This
|
||||||
|
* capability is subject to change as groups are added or removed.
|
||||||
|
*/
|
||||||
|
#define VFIO_DMA_CC_IOMMU 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The IOCTL interface is designed for extensibility by embedding the
|
* The IOCTL interface is designed for extensibility by embedding the
|
||||||
|
@@ -483,17 +483,17 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
|
|||||||
addr = env->regs[2];
|
addr = env->regs[2];
|
||||||
|
|
||||||
if (get_user_u64(oldval, env->regs[0])) {
|
if (get_user_u64(oldval, env->regs[0])) {
|
||||||
env->cp15.c6_data = env->regs[0];
|
env->exception.vaddress = env->regs[0];
|
||||||
goto segv;
|
goto segv;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (get_user_u64(newval, env->regs[1])) {
|
if (get_user_u64(newval, env->regs[1])) {
|
||||||
env->cp15.c6_data = env->regs[1];
|
env->exception.vaddress = env->regs[1];
|
||||||
goto segv;
|
goto segv;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (get_user_u64(val, addr)) {
|
if (get_user_u64(val, addr)) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto segv;
|
goto segv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,7 +501,7 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
|
|||||||
val = newval;
|
val = newval;
|
||||||
|
|
||||||
if (put_user_u64(val, addr)) {
|
if (put_user_u64(val, addr)) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto segv;
|
goto segv;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -523,7 +523,7 @@ segv:
|
|||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
/* XXX: check env->error_code */
|
/* XXX: check env->error_code */
|
||||||
info.si_code = TARGET_SEGV_MAPERR;
|
info.si_code = TARGET_SEGV_MAPERR;
|
||||||
info._sifields._sigfault._addr = env->cp15.c6_data;
|
info._sifields._sigfault._addr = env->exception.vaddress;
|
||||||
queue_signal(env, info.si_signo, &info);
|
queue_signal(env, info.si_signo, &info);
|
||||||
|
|
||||||
end_exclusive();
|
end_exclusive();
|
||||||
@@ -620,14 +620,14 @@ static int do_strex(CPUARMState *env)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (size == 3) {
|
if (size == 3) {
|
||||||
uint32_t valhi;
|
uint32_t valhi;
|
||||||
segv = get_user_u32(valhi, addr + 4);
|
segv = get_user_u32(valhi, addr + 4);
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + 4;
|
env->exception.vaddress = addr + 4;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
val = deposit64(val, 32, 32, valhi);
|
val = deposit64(val, 32, 32, valhi);
|
||||||
@@ -650,14 +650,14 @@ static int do_strex(CPUARMState *env)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (size == 3) {
|
if (size == 3) {
|
||||||
val = env->regs[(env->exclusive_info >> 12) & 0xf];
|
val = env->regs[(env->exclusive_info >> 12) & 0xf];
|
||||||
segv = put_user_u32(val, addr + 4);
|
segv = put_user_u32(val, addr + 4);
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + 4;
|
env->exception.vaddress = addr + 4;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -832,12 +832,14 @@ void cpu_loop(CPUARMState *env)
|
|||||||
case EXCP_INTERRUPT:
|
case EXCP_INTERRUPT:
|
||||||
/* just indicate that signals should be handled asap */
|
/* just indicate that signals should be handled asap */
|
||||||
break;
|
break;
|
||||||
|
case EXCP_STREX:
|
||||||
|
if (!do_strex(env)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through for segv */
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
addr = env->cp15.c6_insn;
|
|
||||||
goto do_segv;
|
|
||||||
case EXCP_DATA_ABORT:
|
case EXCP_DATA_ABORT:
|
||||||
addr = env->cp15.c6_data;
|
addr = env->exception.vaddress;
|
||||||
do_segv:
|
|
||||||
{
|
{
|
||||||
info.si_signo = SIGSEGV;
|
info.si_signo = SIGSEGV;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
@@ -865,12 +867,6 @@ void cpu_loop(CPUARMState *env)
|
|||||||
if (do_kernel_trap(env))
|
if (do_kernel_trap(env))
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
case EXCP_STREX:
|
|
||||||
if (do_strex(env)) {
|
|
||||||
addr = env->cp15.c6_data;
|
|
||||||
goto do_segv;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
error:
|
error:
|
||||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||||
@@ -933,7 +929,7 @@ static int do_strex_a64(CPUARMState *env)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (val != env->exclusive_val) {
|
if (val != env->exclusive_val) {
|
||||||
@@ -946,7 +942,7 @@ static int do_strex_a64(CPUARMState *env)
|
|||||||
segv = get_user_u64(val, addr + 8);
|
segv = get_user_u64(val, addr + 8);
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
|
env->exception.vaddress = addr + (size == 2 ? 4 : 8);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (val != env->exclusive_high) {
|
if (val != env->exclusive_high) {
|
||||||
@@ -981,7 +977,7 @@ static int do_strex_a64(CPUARMState *env)
|
|||||||
segv = put_user_u64(val, addr + 8);
|
segv = put_user_u64(val, addr + 8);
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
|
env->exception.vaddress = addr + (size == 2 ? 4 : 8);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1037,12 +1033,14 @@ void cpu_loop(CPUARMState *env)
|
|||||||
info._sifields._sigfault._addr = env->pc;
|
info._sifields._sigfault._addr = env->pc;
|
||||||
queue_signal(env, info.si_signo, &info);
|
queue_signal(env, info.si_signo, &info);
|
||||||
break;
|
break;
|
||||||
|
case EXCP_STREX:
|
||||||
|
if (!do_strex_a64(env)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through for segv */
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
addr = env->cp15.c6_insn;
|
|
||||||
goto do_segv;
|
|
||||||
case EXCP_DATA_ABORT:
|
case EXCP_DATA_ABORT:
|
||||||
addr = env->cp15.c6_data;
|
addr = env->exception.vaddress;
|
||||||
do_segv:
|
|
||||||
info.si_signo = SIGSEGV;
|
info.si_signo = SIGSEGV;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
/* XXX: check env->error_code */
|
/* XXX: check env->error_code */
|
||||||
@@ -1060,12 +1058,6 @@ void cpu_loop(CPUARMState *env)
|
|||||||
queue_signal(env, info.si_signo, &info);
|
queue_signal(env, info.si_signo, &info);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXCP_STREX:
|
|
||||||
if (do_strex_a64(env)) {
|
|
||||||
addr = env->cp15.c6_data;
|
|
||||||
goto do_segv;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||||
trapnr);
|
trapnr);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user