Compare commits
145 Commits
pull-vga-2
...
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 | ||
|
|
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 | ||
|
|
f663faac3e | ||
|
|
b925965294 | ||
|
|
16cf0b2b34 | ||
|
|
13a12f869b | ||
|
|
44b0c0bbb5 | ||
|
|
860643bc5a | ||
|
|
9ffd26859d | ||
|
|
8c0124490b |
18
.gitignore
vendored
18
.gitignore
vendored
@@ -18,8 +18,8 @@
|
||||
/*-darwin-user
|
||||
/*-linux-user
|
||||
/*-bsd-user
|
||||
libdis*
|
||||
libuser
|
||||
/libdis*
|
||||
/libuser
|
||||
/linux-headers/asm
|
||||
/qga/qapi-generated
|
||||
/qapi-generated
|
||||
@@ -49,19 +49,9 @@ libuser
|
||||
/qemu-monitor.texi
|
||||
/qmp-commands.txt
|
||||
/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.1
|
||||
/fsdev/virtfs-proxy-helper.pod
|
||||
/.gdbinit
|
||||
*.a
|
||||
*.aux
|
||||
*.cp
|
||||
@@ -90,12 +80,8 @@ libuser
|
||||
*.pc
|
||||
.libs
|
||||
.sdk
|
||||
*.swp
|
||||
*.orig
|
||||
.pc
|
||||
*.gcda
|
||||
*.gcno
|
||||
patches
|
||||
/pc-bios/bios-pq/status
|
||||
/pc-bios/vgabios-pq/status
|
||||
/pc-bios/optionrom/linuxboot.asm
|
||||
|
||||
@@ -674,6 +674,8 @@ S: Supported
|
||||
F: block*
|
||||
F: block/
|
||||
F: hw/block/
|
||||
F: qemu-img*
|
||||
F: qemu-io*
|
||||
T: git git://repo.or.cz/qemu/kevin.git block
|
||||
T: git git://github.com/stefanha/qemu.git block
|
||||
|
||||
|
||||
141
block.c
141
block.c
@@ -774,6 +774,45 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
||||
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)
|
||||
{
|
||||
int open_flags = flags | BDRV_O_CACHE_WB;
|
||||
@@ -792,7 +831,7 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||
/*
|
||||
* Snapshots should be writable.
|
||||
*/
|
||||
if (bs->is_temporary) {
|
||||
if (flags & BDRV_O_TEMPORARY) {
|
||||
open_flags |= BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
@@ -864,7 +903,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||
|
||||
node_name = qdict_get_try_str(options, "node-name");
|
||||
bdrv_assign_node_name(bs, node_name, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -951,13 +990,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||
bdrv_refresh_limits(bs);
|
||||
assert(bdrv_opt_mem_align(bs) != 0);
|
||||
assert((bs->request_alignment != 0) || bs->sg);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (bs->is_temporary) {
|
||||
assert(bs->filename[0] != '\0');
|
||||
unlink(bs->filename);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
free_and_fail:
|
||||
@@ -1068,14 +1100,14 @@ fail:
|
||||
*/
|
||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
{
|
||||
char backing_filename[PATH_MAX];
|
||||
int back_flags, ret;
|
||||
char *backing_filename = g_malloc0(PATH_MAX);
|
||||
int ret = 0;
|
||||
BlockDriver *back_drv = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (bs->backing_hd != NULL) {
|
||||
QDECREF(options);
|
||||
return 0;
|
||||
goto free_exit;
|
||||
}
|
||||
|
||||
/* NULL means an empty set of options */
|
||||
@@ -1088,31 +1120,26 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
backing_filename[0] = '\0';
|
||||
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
|
||||
QDECREF(options);
|
||||
return 0;
|
||||
goto free_exit;
|
||||
} else {
|
||||
bdrv_get_full_backing_filename(bs, backing_filename,
|
||||
sizeof(backing_filename));
|
||||
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX);
|
||||
}
|
||||
|
||||
if (bs->backing_format[0] != '\0') {
|
||||
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);
|
||||
ret = bdrv_open(&bs->backing_hd,
|
||||
*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) {
|
||||
bs->backing_hd = NULL;
|
||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||
error_setg(errp, "Could not open backing file: %s",
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
return ret;
|
||||
goto free_exit;
|
||||
}
|
||||
|
||||
if (bs->backing_hd->file) {
|
||||
@@ -1123,7 +1150,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
/* Recalculate the BlockLimits with the backing file */
|
||||
bdrv_refresh_limits(bs);
|
||||
|
||||
return 0;
|
||||
free_exit:
|
||||
g_free(backing_filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1180,8 +1209,7 @@ done:
|
||||
void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
/* 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;
|
||||
BlockDriver *bdrv_qcow2;
|
||||
QEMUOptionParameter *create_options;
|
||||
@@ -1197,15 +1225,15 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
total_size = bdrv_getlength(bs);
|
||||
if (total_size < 0) {
|
||||
error_setg_errno(errp, -total_size, "Could not get image size");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
total_size &= BDRV_SECTOR_MASK;
|
||||
|
||||
/* 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) {
|
||||
error_setg_errno(errp, -ret, "Could not get temporary filename");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdrv_qcow2 = bdrv_find_format("qcow2");
|
||||
@@ -1221,7 +1249,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
"'%s': %s", tmp_filename,
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Prepare a new options QDict for the temporary file */
|
||||
@@ -1232,16 +1260,19 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
qstring_from_str(tmp_filename));
|
||||
|
||||
bs_snapshot = bdrv_new("", &error_abort);
|
||||
bs_snapshot->is_temporary = 1;
|
||||
|
||||
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) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdrv_append(bs_snapshot, bs);
|
||||
|
||||
out:
|
||||
g_free(tmp_filename);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1330,10 +1361,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
|
||||
assert(file == NULL);
|
||||
ret = bdrv_open_image(&file, filename, options, "file",
|
||||
bdrv_open_flags(bs, flags | BDRV_O_UNMAP) |
|
||||
BDRV_O_PROTOCOL, true, &local_err);
|
||||
bdrv_inherited_flags(flags),
|
||||
true, &local_err);
|
||||
if (ret < 0) {
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Find the right image format driver */
|
||||
@@ -1344,7 +1375,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
if (!drv) {
|
||||
error_setg(errp, "Invalid driver: '%s'", drvname);
|
||||
ret = -EINVAL;
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1354,18 +1385,18 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
} else {
|
||||
error_setg(errp, "Must specify either driver or file");
|
||||
ret = -EINVAL;
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!drv) {
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Open the image */
|
||||
ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
|
||||
if (ret < 0) {
|
||||
goto unlink_and_fail;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (file && (bs->file != file)) {
|
||||
@@ -1427,14 +1458,10 @@ done:
|
||||
*pbs = bs;
|
||||
return 0;
|
||||
|
||||
unlink_and_fail:
|
||||
fail:
|
||||
if (file != NULL) {
|
||||
bdrv_unref(file);
|
||||
}
|
||||
if (bs->is_temporary) {
|
||||
unlink(filename);
|
||||
}
|
||||
fail:
|
||||
QDECREF(bs->options);
|
||||
QDECREF(options);
|
||||
bs->options = NULL;
|
||||
@@ -1498,8 +1525,11 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||
QSIMPLEQ_INIT(bs_queue);
|
||||
}
|
||||
|
||||
/* bdrv_open() masks this flag out */
|
||||
flags &= ~BDRV_O_PROTOCOL;
|
||||
|
||||
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);
|
||||
@@ -1714,11 +1744,6 @@ void bdrv_close(BlockDriverState *bs)
|
||||
}
|
||||
bs->drv->bdrv_close(bs);
|
||||
g_free(bs->opaque);
|
||||
#ifdef _WIN32
|
||||
if (bs->is_temporary) {
|
||||
unlink(bs->filename);
|
||||
}
|
||||
#endif
|
||||
bs->opaque = NULL;
|
||||
bs->drv = NULL;
|
||||
bs->copy_on_read = 0;
|
||||
@@ -1842,7 +1867,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
|
||||
BlockDriverState *bs_src)
|
||||
{
|
||||
/* move some fields that need to stay attached to the device */
|
||||
bs_dest->open_flags = bs_src->open_flags;
|
||||
|
||||
/* dev info */
|
||||
bs_dest->dev_ops = bs_src->dev_ops;
|
||||
@@ -3598,10 +3622,25 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
||||
void *opaque)
|
||||
{
|
||||
BlockDriver *drv;
|
||||
int count = 0;
|
||||
const char **formats = NULL;
|
||||
|
||||
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 */
|
||||
|
||||
@@ -187,13 +187,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
||||
uint64_t offset = sector_num * 512;
|
||||
uint64_t extent_index, extent_offset, bitmap_offset;
|
||||
char bitmap_entry;
|
||||
int ret;
|
||||
|
||||
// seek to sector
|
||||
extent_index = offset / s->extent_size;
|
||||
extent_offset = (offset % s->extent_size) / 512;
|
||||
|
||||
if (s->catalog_bitmap[extent_index] == 0xffffffff) {
|
||||
return -1; /* not allocated */
|
||||
return 0; /* not allocated */
|
||||
}
|
||||
|
||||
bitmap_offset = s->data_offset +
|
||||
@@ -201,13 +202,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
||||
(s->extent_blocks + s->bitmap_blocks));
|
||||
|
||||
/* read in bitmap for current extent */
|
||||
if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
|
||||
&bitmap_entry, 1) != 1) {
|
||||
return -1;
|
||||
ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
|
||||
&bitmap_entry, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
|
||||
return -1; /* not allocated */
|
||||
return 0; /* not allocated */
|
||||
}
|
||||
|
||||
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
|
||||
@@ -220,13 +222,16 @@ static int bochs_read(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
while (nb_sectors > 0) {
|
||||
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);
|
||||
if (ret != 512) {
|
||||
return -1;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
memset(buf, 0, 512);
|
||||
}
|
||||
nb_sectors--;
|
||||
sector_num++;
|
||||
buf += 512;
|
||||
|
||||
@@ -194,7 +194,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
||||
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
|
||||
!bdrv_iostatus_is_enabled(bs)) {
|
||||
error_set(errp, QERR_INVALID_PARAMETER_COMBINATION);
|
||||
error_setg(errp, "Invalid parameter combination");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
if (be32_to_cpu(cow_header.version) != COW_VERSION) {
|
||||
char version[64];
|
||||
snprintf(version, sizeof(version),
|
||||
"COW version %d", cow_header.version);
|
||||
"COW version %" PRIu32, cow_header.version);
|
||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||
bs->device_name, "cow", version);
|
||||
ret = -ENOTSUP;
|
||||
|
||||
147
block/curl.c
147
block/curl.c
@@ -71,6 +71,7 @@ typedef struct CURLState
|
||||
struct BDRVCURLState *s;
|
||||
CURLAIOCB *acb[CURL_NUM_ACB];
|
||||
CURL *curl;
|
||||
curl_socket_t sock_fd;
|
||||
char *orig_buf;
|
||||
size_t buf_start;
|
||||
size_t buf_off;
|
||||
@@ -92,6 +93,7 @@ typedef struct BDRVCURLState {
|
||||
|
||||
static void curl_clean_state(CURLState *s);
|
||||
static void curl_multi_do(void *arg);
|
||||
static void curl_multi_read(void *arg);
|
||||
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
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,
|
||||
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);
|
||||
switch (action) {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
case CURL_POLL_REMOVE:
|
||||
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);
|
||||
|
||||
if (!s || !s->orig_buf)
|
||||
goto read_end;
|
||||
return 0;
|
||||
|
||||
if (s->buf_off >= s->buf_len) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -215,7 +220,8 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
|
||||
}
|
||||
|
||||
// Wait for unfinished chunks
|
||||
if ((start >= state->buf_start) &&
|
||||
if (state->in_use &&
|
||||
(start >= state->buf_start) &&
|
||||
(start <= buf_fend) &&
|
||||
(end >= state->buf_start) &&
|
||||
(end <= buf_fend))
|
||||
@@ -237,68 +243,69 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
|
||||
return FIND_RET_NONE;
|
||||
}
|
||||
|
||||
static void curl_multi_read(BDRVCURLState *s)
|
||||
static void curl_multi_check_completion(BDRVCURLState *s)
|
||||
{
|
||||
int msgs_in_queue;
|
||||
|
||||
/* Try to find done transfers, so we can free the easy
|
||||
* handle again. */
|
||||
do {
|
||||
for (;;) {
|
||||
CURLMsg *msg;
|
||||
msg = curl_multi_info_read(s->multi, &msgs_in_queue);
|
||||
|
||||
/* Quit when there are no more completions */
|
||||
if (!msg)
|
||||
break;
|
||||
if (msg->msg == CURLMSG_NONE)
|
||||
break;
|
||||
|
||||
switch (msg->msg) {
|
||||
case CURLMSG_DONE:
|
||||
{
|
||||
CURLState *state = NULL;
|
||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state);
|
||||
if (msg->msg == CURLMSG_DONE) {
|
||||
CURLState *state = NULL;
|
||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
|
||||
(char **)&state);
|
||||
|
||||
/* ACBs for successful messages get completed in curl_read_cb */
|
||||
if (msg->data.result != CURLE_OK) {
|
||||
int i;
|
||||
for (i = 0; i < CURL_NUM_ACB; i++) {
|
||||
CURLAIOCB *acb = state->acb[i];
|
||||
/* ACBs for successful messages get completed in curl_read_cb */
|
||||
if (msg->data.result != CURLE_OK) {
|
||||
int i;
|
||||
for (i = 0; i < CURL_NUM_ACB; i++) {
|
||||
CURLAIOCB *acb = state->acb[i];
|
||||
|
||||
if (acb == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
acb->common.cb(acb->common.opaque, -EIO);
|
||||
qemu_aio_release(acb);
|
||||
state->acb[i] = NULL;
|
||||
if (acb == NULL) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
curl_clean_state(state);
|
||||
break;
|
||||
acb->common.cb(acb->common.opaque, -EIO);
|
||||
qemu_aio_release(acb);
|
||||
state->acb[i] = NULL;
|
||||
}
|
||||
}
|
||||
default:
|
||||
msgs_in_queue = 0;
|
||||
break;
|
||||
|
||||
curl_clean_state(state);
|
||||
break;
|
||||
}
|
||||
} while(msgs_in_queue);
|
||||
}
|
||||
}
|
||||
|
||||
static void curl_multi_do(void *arg)
|
||||
{
|
||||
BDRVCURLState *s = (BDRVCURLState *)arg;
|
||||
CURLState *s = (CURLState *)arg;
|
||||
int running;
|
||||
int r;
|
||||
|
||||
if (!s->multi) {
|
||||
if (!s->s->multi) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
@@ -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_read(s);
|
||||
curl_multi_check_completion(s);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
@@ -337,44 +344,42 @@ static CURLState *curl_init_state(BDRVCURLState *s)
|
||||
break;
|
||||
}
|
||||
if (!state) {
|
||||
g_usleep(100);
|
||||
curl_multi_do(s);
|
||||
qemu_aio_wait();
|
||||
}
|
||||
} while(!state);
|
||||
|
||||
if (state->curl)
|
||||
goto has_curl;
|
||||
if (!state->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();
|
||||
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);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
/* 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
|
||||
curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
|
||||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
|
||||
curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
|
||||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
|
||||
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
|
||||
#endif
|
||||
|
||||
has_curl:
|
||||
}
|
||||
|
||||
state->s = s;
|
||||
|
||||
@@ -531,13 +536,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
// initialize the multi interface!
|
||||
|
||||
s->multi = curl_multi_init();
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
||||
#endif
|
||||
curl_multi_do(s);
|
||||
|
||||
qemu_opts_del(opts);
|
||||
return 0;
|
||||
@@ -566,6 +569,7 @@ static const AIOCBInfo curl_aiocb_info = {
|
||||
static void curl_readv_bh_cb(void *p)
|
||||
{
|
||||
CURLState *state;
|
||||
int running;
|
||||
|
||||
CURLAIOCB *acb = p;
|
||||
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_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,
|
||||
|
||||
@@ -248,8 +248,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
offset += 8;
|
||||
|
||||
if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
|
||||
error_report("sector count %" PRIu64 " for chunk %u is "
|
||||
"larger than max (%u)",
|
||||
error_report("sector count %" PRIu64 " for chunk %" PRIu32
|
||||
" is larger than max (%u)",
|
||||
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
@@ -269,8 +269,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
offset += 8;
|
||||
|
||||
if (s->lengths[i] > DMG_LENGTHS_MAX) {
|
||||
error_report("length %" PRIu64 " for chunk %u is larger "
|
||||
"than max (%u)",
|
||||
error_report("length %" PRIu64 " for chunk %" PRIu32
|
||||
" is larger than max (%u)",
|
||||
s->lengths[i], i, DMG_LENGTHS_MAX);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
||||
@@ -1095,16 +1095,15 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
|
||||
*inq = scsi_datain_unmarshall(task);
|
||||
if (*inq == NULL) {
|
||||
error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
|
||||
goto fail;
|
||||
goto fail_with_err;
|
||||
}
|
||||
|
||||
return task;
|
||||
|
||||
fail:
|
||||
if (!error_is_set(errp)) {
|
||||
error_setg(errp, "iSCSI: Inquiry command failed : %s",
|
||||
iscsi_get_error(iscsi));
|
||||
}
|
||||
error_setg(errp, "iSCSI: Inquiry command failed : %s",
|
||||
iscsi_get_error(iscsi));
|
||||
fail_with_err:
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
}
|
||||
|
||||
@@ -325,11 +325,11 @@ static void coroutine_fn mirror_run(void *opaque)
|
||||
|
||||
s->common.len = bdrv_getlength(bs);
|
||||
if (s->common.len <= 0) {
|
||||
block_job_completed(&s->common, s->common.len);
|
||||
return;
|
||||
ret = s->common.len;
|
||||
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);
|
||||
|
||||
/* 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,
|
||||
sizeof(backing_filename));
|
||||
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) {
|
||||
s->buf_size = MAX(s->buf_size, bdi.cluster_size);
|
||||
s->cow_bitmap = bitmap_new(length);
|
||||
@@ -680,7 +683,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
|
||||
mirror_start_job(bs, base, speed, 0, 0,
|
||||
on_error, on_error, cb, opaque, &local_err,
|
||||
&commit_active_job_driver, false, base);
|
||||
if (error_is_set(&local_err)) {
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto error_restore_flags;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ static void nbd_parse_filename(const char *filename, QDict *options,
|
||||
InetSocketAddress *addr = NULL;
|
||||
|
||||
addr = inet_parse(host_spec, errp);
|
||||
if (error_is_set(errp)) {
|
||||
if (!addr) {
|
||||
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);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
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,
|
||||
ImageInfoSpecific *info_spec)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
QObject *obj, *data;
|
||||
|
||||
visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
|
||||
&local_err);
|
||||
&error_abort);
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
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) {
|
||||
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,
|
||||
bs->device_name, "qcow", version);
|
||||
ret = -ENOTSUP;
|
||||
|
||||
@@ -42,6 +42,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
if (min_size <= s->l1_size)
|
||||
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) {
|
||||
new_l1_size = min_size;
|
||||
} 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);
|
||||
|
||||
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
|
||||
@@ -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
|
||||
* holding s->lock, so that doesn't work today.
|
||||
*/
|
||||
if (old_offset & QCOW_OFLAG_ZERO) {
|
||||
continue;
|
||||
}
|
||||
switch (qcow2_get_cluster_type(old_l2_entry)) {
|
||||
case QCOW2_CLUSTER_UNALLOCATED:
|
||||
if (!bs->backing_hd) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
if ((old_offset & L2E_OFFSET_MASK) == 0 && !bs->backing_hd) {
|
||||
continue;
|
||||
case QCOW2_CLUSTER_ZERO:
|
||||
continue;
|
||||
|
||||
case QCOW2_CLUSTER_NORMAL:
|
||||
case QCOW2_CLUSTER_COMPRESSED:
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
/* First remove L2 entries */
|
||||
@@ -1390,7 +1407,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -653,6 +653,13 @@ 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
|
||||
fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
|
||||
size,
|
||||
@@ -1480,6 +1487,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
int ret;
|
||||
|
||||
size = bdrv_getlength(bs->file);
|
||||
if (size < 0) {
|
||||
res->check_errors++;
|
||||
return size;
|
||||
}
|
||||
|
||||
nb_clusters = size_to_clusters(s, size);
|
||||
if (nb_clusters > INT_MAX) {
|
||||
res->check_errors++;
|
||||
|
||||
@@ -124,8 +124,9 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
|
||||
case QCOW2_EXT_MAGIC_BACKING_FORMAT:
|
||||
if (ext.len >= sizeof(bs->backing_format)) {
|
||||
error_setg(errp, "ERROR: ext_backing_format: len=%u too large"
|
||||
" (>=%zu)", ext.len, sizeof(bs->backing_format));
|
||||
error_setg(errp, "ERROR: ext_backing_format: len=%" PRIu32
|
||||
" too large (>=%zu)", ext.len,
|
||||
sizeof(bs->backing_format));
|
||||
return 2;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
goto fail;
|
||||
}
|
||||
@@ -493,7 +494,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
/* Initialise cluster size */
|
||||
if (header.cluster_bits < MIN_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;
|
||||
goto fail;
|
||||
}
|
||||
@@ -591,7 +593,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->refcount_order = header.refcount_order;
|
||||
|
||||
if (header.crypt_method > QCOW_CRYPT_AES) {
|
||||
error_setg(errp, "Unsupported encryption method: %i",
|
||||
error_setg(errp, "Unsupported encryption method: %" PRIu32,
|
||||
header.crypt_method);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
||||
@@ -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);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
if (local_err) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
@@ -828,7 +828,7 @@ close_exit:
|
||||
g_free(opened);
|
||||
exit:
|
||||
/* propagate error */
|
||||
if (error_is_set(&local_err)) {
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
QDECREF(list);
|
||||
|
||||
@@ -366,7 +366,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
BDRVRawState *s = bs->opaque;
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
const char *filename = NULL;
|
||||
int fd, ret;
|
||||
struct stat st;
|
||||
|
||||
@@ -446,6 +446,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
|
||||
unlink(filename);
|
||||
}
|
||||
qemu_opts_del(opts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -390,6 +390,9 @@ static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
CloseHandle(s->hfile);
|
||||
if (bs->open_flags & BDRV_O_TEMPORARY) {
|
||||
unlink(bs->filename);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
if (rsp->result == SD_RES_NO_VDI) {
|
||||
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_clock_nsec = inode.vm_clock_nsec;
|
||||
|
||||
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str), "%u",
|
||||
inode.snap_id);
|
||||
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str),
|
||||
"%" PRIu32, inode.snap_id);
|
||||
pstrcpy(sn_tab[found].name,
|
||||
MIN(sizeof(sn_tab[found].name), sizeof(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) {
|
||||
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;
|
||||
goto fail;
|
||||
} else if (header.version != VDI_VERSION_1_1) {
|
||||
error_setg(errp, "unsupported VDI image (version %u.%u)",
|
||||
header.version >> 16, header.version & 0xffff);
|
||||
error_setg(errp, "unsupported VDI image (version %" PRIu32 ".%" PRIu32
|
||||
")", header.version >> 16, header.version & 0xffff);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.offset_bmap % SECTOR_SIZE != 0) {
|
||||
/* We only support block maps which start on a sector boundary. */
|
||||
error_setg(errp, "unsupported VDI image (unaligned block map offset "
|
||||
"0x%x)", header.offset_bmap);
|
||||
"0x%" PRIx32 ")", header.offset_bmap);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.offset_data % SECTOR_SIZE != 0) {
|
||||
/* We only support data blocks which start on a sector boundary. */
|
||||
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%x)",
|
||||
header.offset_data);
|
||||
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%"
|
||||
PRIx32 ")", header.offset_data);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.sector_size != SECTOR_SIZE) {
|
||||
error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
|
||||
header.sector_size, SECTOR_SIZE);
|
||||
error_setg(errp, "unsupported VDI image (sector size %" PRIu32
|
||||
" is not %u)", header.sector_size, SECTOR_SIZE);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
|
||||
error_setg(errp, "unsupported VDI image (block size %u is not %u)",
|
||||
header.block_size, DEFAULT_CLUSTER_SIZE);
|
||||
error_setg(errp, "unsupported VDI image (block size %" PRIu32
|
||||
" is not %u)", header.block_size, DEFAULT_CLUSTER_SIZE);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
} else if (header.disk_size >
|
||||
@@ -755,6 +756,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
vdi_header_to_le(&header);
|
||||
if (write(fd, &header, sizeof(header)) < 0) {
|
||||
result = -errno;
|
||||
goto close_and_exit;
|
||||
}
|
||||
|
||||
if (bmap_size > 0) {
|
||||
@@ -768,6 +770,8 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
if (write(fd, bmap, bmap_size) < 0) {
|
||||
result = -errno;
|
||||
g_free(bmap);
|
||||
goto close_and_exit;
|
||||
}
|
||||
g_free(bmap);
|
||||
}
|
||||
@@ -775,10 +779,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (image_type == VDI_TYPE_STATIC) {
|
||||
if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
|
||||
result = -errno;
|
||||
goto close_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (close(fd) < 0) {
|
||||
close_and_exit:
|
||||
if ((close(fd) < 0) && !result) {
|
||||
result = -errno;
|
||||
}
|
||||
|
||||
|
||||
16
blockdev.c
16
blockdev.c
@@ -1115,6 +1115,7 @@ typedef struct InternalSnapshotState {
|
||||
static void internal_snapshot_prepare(BlkTransactionState *common,
|
||||
Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
const char *device;
|
||||
const char *name;
|
||||
BlockDriverState *bs;
|
||||
@@ -1163,8 +1164,10 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
|
||||
}
|
||||
|
||||
/* check whether a snapshot with name exist */
|
||||
ret = bdrv_snapshot_find_by_id_and_name(bs, NULL, name, &old_sn, errp);
|
||||
if (error_is_set(errp)) {
|
||||
ret = bdrv_snapshot_find_by_id_and_name(bs, NULL, name, &old_sn,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
} else if (ret) {
|
||||
error_setg(errp,
|
||||
@@ -1520,14 +1523,16 @@ static void eject_device(BlockDriverState *bs, int force, Error **errp)
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
|
||||
bdrv_dev_eject_request(bs, 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;
|
||||
}
|
||||
}
|
||||
@@ -2219,7 +2224,8 @@ void qmp_block_job_cancel(const char *device,
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!job->driver->set_speed) {
|
||||
error_set(errp, QERR_NOT_SUPPORTED);
|
||||
error_set(errp, QERR_UNSUPPORTED);
|
||||
return;
|
||||
}
|
||||
job->driver->set_speed(job, speed, &local_err);
|
||||
|
||||
10
configure
vendored
10
configure
vendored
@@ -1087,7 +1087,10 @@ for opt do
|
||||
;;
|
||||
--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
|
||||
done
|
||||
@@ -1230,6 +1233,7 @@ Advanced options (experts only):
|
||||
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
|
||||
--disable-gtk disable gtk UI
|
||||
--enable-gtk enable gtk UI
|
||||
--with-gtkabi select preferred GTK ABI 2.0 or 3.0
|
||||
--disable-virtfs disable VirtFS
|
||||
--enable-virtfs enable VirtFS
|
||||
--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
|
||||
EOF
|
||||
exit 1
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Now we have handled --enable-tcg-interpreter and know we're not just
|
||||
@@ -4346,6 +4350,7 @@ if test "$modules" = "yes"; then
|
||||
fi
|
||||
if test "$sdl" = "yes" ; then
|
||||
echo "CONFIG_SDL=y" >> $config_host_mak
|
||||
echo "CONFIG_SDLABI=$sdlabi" >> $config_host_mak
|
||||
echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak
|
||||
fi
|
||||
if test "$cocoa" = "yes" ; then
|
||||
@@ -4429,6 +4434,7 @@ fi
|
||||
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||
if test "$gtk" = "yes" ; then
|
||||
echo "CONFIG_GTK=y" >> $config_host_mak
|
||||
echo "CONFIG_GTKABI=$gtkabi" >> $config_host_mak
|
||||
echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak
|
||||
fi
|
||||
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);
|
||||
if (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) {
|
||||
error_set(errp, QERR_IO_ERROR);
|
||||
goto exit;
|
||||
|
||||
@@ -311,7 +311,7 @@ void hmp_hello_world(Monitor *mon, const QDict *qdict)
|
||||
Error *errp = NULL;
|
||||
|
||||
qmp_hello_world(!!message, message, &errp);
|
||||
if (error_is_set(&errp)) {
|
||||
if (errp) {
|
||||
monitor_printf(mon, "%s\n", error_get_pretty(errp));
|
||||
error_free(errp);
|
||||
return;
|
||||
@@ -483,7 +483,7 @@ void hmp_info_alarm_clock(Monitor *mon)
|
||||
Error *errp = NULL;
|
||||
|
||||
clock = qmp_query_alarm_clock(&errp);
|
||||
if (error_is_set(&errp)) {
|
||||
if (errp) {
|
||||
monitor_printf(mon, "Could not query alarm clock information\n");
|
||||
error_free(errp);
|
||||
return;
|
||||
@@ -634,7 +634,7 @@ void hmp_info_alarm_methods(Monitor *mon)
|
||||
Error *errp = NULL;
|
||||
|
||||
method_list = qmp_query_alarm_methods(&errp);
|
||||
if (error_is_set(&errp)) {
|
||||
if (errp) {
|
||||
monitor_printf(mon, "Could not query alarm methods\n");
|
||||
error_free(errp);
|
||||
return;
|
||||
|
||||
@@ -760,6 +760,7 @@ static int proxy_socket(const char *path, uid_t uid, gid_t gid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = sizeof(qemu);
|
||||
client = accept(sock, (struct sockaddr *)&qemu, &size);
|
||||
if (client < 0) {
|
||||
do_perror("accept");
|
||||
|
||||
@@ -176,7 +176,7 @@ ETEXI
|
||||
|
||||
{
|
||||
.name = "drive_del",
|
||||
.args_type = "id:s",
|
||||
.args_type = "id:B",
|
||||
.params = "device",
|
||||
.help = "remove host block device",
|
||||
.user_print = monitor_user_noop,
|
||||
@@ -658,6 +658,7 @@ ETEXI
|
||||
.help = "add device, like -device on the command line",
|
||||
.user_print = monitor_user_noop,
|
||||
.mhandler.cmd_new = do_device_add,
|
||||
.command_completion = device_add_completion,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@@ -673,6 +674,7 @@ ETEXI
|
||||
.params = "device",
|
||||
.help = "remove device",
|
||||
.mhandler.cmd = hmp_device_del,
|
||||
.command_completion = device_del_completion,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@@ -998,26 +1000,34 @@ ETEXI
|
||||
|
||||
{
|
||||
.name = "dump-guest-memory",
|
||||
.args_type = "paging:-p,filename:F,begin:i?,length:i?",
|
||||
.params = "[-p] filename [begin] [length]",
|
||||
.help = "dump guest memory to file"
|
||||
"\n\t\t\t begin(optional): the starting physical address"
|
||||
"\n\t\t\t length(optional): the memory size, in bytes",
|
||||
.args_type = "paging:-p,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:i?,length:i?",
|
||||
.params = "[-p] [-z|-l|-s] filename [begin length]",
|
||||
.help = "dump guest memory into file 'filename'.\n\t\t\t"
|
||||
"-p: do paging to get guest's memory mapping.\n\t\t\t"
|
||||
"-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,
|
||||
},
|
||||
|
||||
|
||||
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
|
||||
Dump guest memory to @var{protocol}. The file can be processed with crash or
|
||||
gdb.
|
||||
filename: dump file name
|
||||
paging: do paging to get guest's memory mapping
|
||||
gdb. Without -z|-l|-s, the dump format is ELF.
|
||||
-p: 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
|
||||
specified with length together.
|
||||
specified together with length.
|
||||
length: the memory size, in bytes. It's optional, and should be specified
|
||||
with begin together.
|
||||
together with begin.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
@@ -1254,6 +1264,7 @@ ETEXI
|
||||
.params = "[qom-type=]type,id=str[,prop=value][,...]",
|
||||
.help = "create QOM object",
|
||||
.mhandler.cmd = hmp_object_add,
|
||||
.command_completion = object_add_completion,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@@ -1268,6 +1279,7 @@ ETEXI
|
||||
.params = "id",
|
||||
.help = "destroy QOM object",
|
||||
.mhandler.cmd = hmp_object_del,
|
||||
.command_completion = object_del_completion,
|
||||
},
|
||||
|
||||
STEXI
|
||||
|
||||
25
hmp.c
25
hmp.c
@@ -1308,16 +1308,35 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
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");
|
||||
bool has_begin = qdict_haskey(qdict, "begin");
|
||||
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 length = 0;
|
||||
enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
|
||||
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) {
|
||||
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);
|
||||
|
||||
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);
|
||||
g_free(prot);
|
||||
}
|
||||
|
||||
5
hmp.h
5
hmp.h
@@ -15,6 +15,7 @@
|
||||
#define HMP_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/readline.h"
|
||||
#include "qapi-types.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_object_add(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
|
||||
|
||||
@@ -987,8 +987,9 @@ static void v9fs_attach(void *opaque)
|
||||
*/
|
||||
if (!s->migration_blocker) {
|
||||
s->root_fid = fid;
|
||||
error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
|
||||
s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
|
||||
error_setg(&s->migration_blocker,
|
||||
"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);
|
||||
}
|
||||
out:
|
||||
|
||||
@@ -75,8 +75,6 @@ typedef struct MemMapEntry {
|
||||
typedef struct VirtBoardInfo {
|
||||
struct arm_boot_info bootinfo;
|
||||
const char *cpu_model;
|
||||
const char *qdevname;
|
||||
const char *gic_compatible;
|
||||
const MemMapEntry *memmap;
|
||||
const int *irqmap;
|
||||
int smp_cpus;
|
||||
@@ -98,10 +96,10 @@ typedef struct VirtBoardInfo {
|
||||
static const MemMapEntry a15memmap[] = {
|
||||
/* Space up to 0x8000000 is reserved for a boot ROM */
|
||||
[VIRT_FLASH] = { 0, 0x8000000 },
|
||||
[VIRT_CPUPERIPHS] = { 0x8000000, 0x8000 },
|
||||
[VIRT_CPUPERIPHS] = { 0x8000000, 0x20000 },
|
||||
/* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
|
||||
[VIRT_GIC_DIST] = { 0x8001000, 0x1000 },
|
||||
[VIRT_GIC_CPU] = { 0x8002000, 0x1000 },
|
||||
[VIRT_GIC_DIST] = { 0x8000000, 0x10000 },
|
||||
[VIRT_GIC_CPU] = { 0x8010000, 0x10000 },
|
||||
[VIRT_UART] = { 0x9000000, 0x1000 },
|
||||
[VIRT_MMIO] = { 0xa000000, 0x200 },
|
||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||
@@ -117,16 +115,16 @@ static const int a15irqmap[] = {
|
||||
static VirtBoardInfo machines[] = {
|
||||
{
|
||||
.cpu_model = "cortex-a15",
|
||||
.qdevname = "a15mpcore_priv",
|
||||
.gic_compatible = "arm,cortex-a15-gic",
|
||||
.memmap = a15memmap,
|
||||
.irqmap = a15irqmap,
|
||||
},
|
||||
{
|
||||
.cpu_model = "cortex-a57",
|
||||
.memmap = a15memmap,
|
||||
.irqmap = a15irqmap,
|
||||
},
|
||||
{
|
||||
.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,
|
||||
.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_add_subnode(vbi->fdt, "/intc");
|
||||
/* 'cortex-a15-gic' means 'GIC v2' */
|
||||
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(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char *nodename;
|
||||
@@ -340,8 +389,6 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
int n;
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
DeviceState *dev;
|
||||
SysBusDevice *busdev;
|
||||
const char *cpu_model = args->cpu_model;
|
||||
VirtBoardInfo *vbi;
|
||||
|
||||
@@ -404,25 +451,7 @@ static void machvirt_init(QEMUMachineInitArgs *args)
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
|
||||
|
||||
dev = qdev_create(NULL, vbi->qdevname);
|
||||
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_gic(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;
|
||||
right = right * 255 / QEMU_HDA_AMP_STEPS;
|
||||
|
||||
if (!st->state->mixer) {
|
||||
return;
|
||||
}
|
||||
if (st->output) {
|
||||
AUD_set_volume_out(st->voice.out, muted, left, right);
|
||||
} else {
|
||||
|
||||
@@ -587,8 +587,9 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
|
||||
|
||||
/* We rely on power-of-2 blocksizes for bitmasks */
|
||||
if ((value & (value - 1)) != 0) {
|
||||
error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
|
||||
dev->id?:"", name, (int64_t)value);
|
||||
error_setg(errp,
|
||||
"Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
|
||||
dev->id ?: "", name, (int64_t)value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -853,7 +854,7 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
|
||||
{
|
||||
switch (ret) {
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
case 0:
|
||||
|
||||
@@ -124,14 +124,14 @@ static const TPRInstruction tpr_instr[] = {
|
||||
|
||||
static void read_guest_rom_state(VAPICROMState *s)
|
||||
{
|
||||
cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
|
||||
sizeof(GuestROMState), 0);
|
||||
cpu_physical_memory_read(s->rom_state_paddr, &s->rom_state,
|
||||
sizeof(GuestROMState));
|
||||
}
|
||||
|
||||
static void write_guest_rom_state(VAPICROMState *s)
|
||||
{
|
||||
cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
|
||||
sizeof(GuestROMState), 1);
|
||||
cpu_physical_memory_write(s->rom_state_paddr, &s->rom_state,
|
||||
sizeof(GuestROMState));
|
||||
}
|
||||
|
||||
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);
|
||||
pos < le32_to_cpu(s->rom_state.fixup_end);
|
||||
pos += 4) {
|
||||
cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
|
||||
(void *)&offset, sizeof(offset), 0);
|
||||
cpu_physical_memory_read(paddr + pos - s->rom_state.vaddr,
|
||||
&offset, sizeof(offset));
|
||||
offset = le32_to_cpu(offset);
|
||||
cpu_physical_memory_rw(paddr + offset, (void *)&patch,
|
||||
sizeof(patch), 0);
|
||||
cpu_physical_memory_read(paddr + offset, &patch, sizeof(patch));
|
||||
patch = le32_to_cpu(patch);
|
||||
patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
|
||||
patch = cpu_to_le32(patch);
|
||||
cpu_physical_memory_rw(paddr + offset, (void *)&patch,
|
||||
sizeof(patch), 1);
|
||||
cpu_physical_memory_write(paddr + offset, &patch, sizeof(patch));
|
||||
}
|
||||
read_guest_rom_state(s);
|
||||
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 +
|
||||
(((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
|
||||
cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
|
||||
(void *)&enabled, sizeof(enabled), 1);
|
||||
cpu_physical_memory_write(vapic_paddr + offsetof(VAPICState, enabled),
|
||||
&enabled, sizeof(enabled));
|
||||
apic_enable_vapic(cpu->apic_state, vapic_paddr);
|
||||
|
||||
s->state = VAPIC_ACTIVE;
|
||||
@@ -535,7 +533,7 @@ static int patch_hypercalls(VAPICROMState *s)
|
||||
uint8_t *rom;
|
||||
|
||||
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++) {
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
@@ -551,8 +549,7 @@ static int patch_hypercalls(VAPICROMState *s)
|
||||
}
|
||||
if (memcmp(rom + pos, pattern, 7) == 0 &&
|
||||
(rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
|
||||
cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
|
||||
3, 1);
|
||||
cpu_physical_memory_write(rom_paddr + pos + 5, patch, 3);
|
||||
/*
|
||||
* Don't flush the tb here. Under ordinary conditions, the patched
|
||||
* 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);
|
||||
} else {
|
||||
zero = g_malloc0(s->rom_state.vapic_size);
|
||||
cpu_physical_memory_rw(s->vapic_paddr, zero,
|
||||
s->rom_state.vapic_size, 1);
|
||||
cpu_physical_memory_write(s->vapic_paddr, zero,
|
||||
s->rom_state.vapic_size);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
FWCfgState *fw_cfg;
|
||||
uint8_t *smbios_table;
|
||||
size_t smbios_len;
|
||||
uint8_t *smbios_tables, *smbios_anchor;
|
||||
size_t smbios_tables_len, smbios_anchor_len;
|
||||
uint64_t *numa_fw_cfg;
|
||||
int i, j;
|
||||
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);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
|
||||
|
||||
smbios_table = smbios_get_table(&smbios_len);
|
||||
if (smbios_table)
|
||||
smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
|
||||
if (smbios_tables) {
|
||||
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,
|
||||
&e820_reserve, sizeof(e820_reserve));
|
||||
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,
|
||||
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 */
|
||||
|
||||
@@ -60,7 +60,8 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
|
||||
|
||||
static bool has_pci_info;
|
||||
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
|
||||
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
|
||||
* pages in the host.
|
||||
@@ -143,10 +144,10 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
||||
guest_info->has_pci_info = has_pci_info;
|
||||
guest_info->isapc_ram_fw = !pci_enabled;
|
||||
|
||||
if (smbios_type1_defaults) {
|
||||
if (smbios_defaults) {
|
||||
/* These values are guest ABI, do not change */
|
||||
smbios_set_type1_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
|
||||
args->machine->name);
|
||||
smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
|
||||
args->machine->name, smbios_legacy_mode);
|
||||
}
|
||||
|
||||
/* allocate ram and load rom/bios */
|
||||
@@ -262,9 +263,15 @@ static void pc_init_pci(QEMUMachineInitArgs *args)
|
||||
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)
|
||||
{
|
||||
smbios_type1_defaults = false;
|
||||
pc_compat_2_0(args);
|
||||
smbios_defaults = false;
|
||||
gigabyte_align = false;
|
||||
option_rom_has_mr = true;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
pc_compat_1_7(args);
|
||||
@@ -345,7 +358,7 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
|
||||
{
|
||||
has_pci_info = false;
|
||||
has_acpi_build = false;
|
||||
smbios_type1_defaults = false;
|
||||
smbios_defaults = false;
|
||||
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
|
||||
enable_compat_apic_id_mode();
|
||||
pc_init1(args, 1, 0);
|
||||
@@ -355,7 +368,7 @@ static void pc_init_isa(QEMUMachineInitArgs *args)
|
||||
{
|
||||
has_pci_info = false;
|
||||
has_acpi_build = false;
|
||||
smbios_type1_defaults = false;
|
||||
smbios_defaults = false;
|
||||
if (!args->cpu_model) {
|
||||
args->cpu_model = "486";
|
||||
}
|
||||
@@ -383,16 +396,24 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
|
||||
.desc = "Standard PC (i440FX + PIIX, 1996)", \
|
||||
.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, \
|
||||
.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 = {
|
||||
PC_I440FX_2_0_MACHINE_OPTIONS,
|
||||
.name = "pc-i440fx-2.0",
|
||||
.alias = "pc",
|
||||
.init = pc_init_pci,
|
||||
.is_default = 1,
|
||||
.init = pc_init_pci_2_0,
|
||||
};
|
||||
|
||||
#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)
|
||||
{
|
||||
qemu_register_machine(&pc_i440fx_machine_v2_1);
|
||||
qemu_register_machine(&pc_i440fx_machine_v2_0);
|
||||
qemu_register_machine(&pc_i440fx_machine_v1_7);
|
||||
qemu_register_machine(&pc_i440fx_machine_v1_6);
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
|
||||
static bool has_pci_info;
|
||||
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
|
||||
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
|
||||
* pages in the host.
|
||||
@@ -130,10 +131,10 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
|
||||
guest_info->isapc_ram_fw = false;
|
||||
guest_info->has_acpi_build = has_acpi_build;
|
||||
|
||||
if (smbios_type1_defaults) {
|
||||
if (smbios_defaults) {
|
||||
/* These values are guest ABI, do not change */
|
||||
smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
|
||||
args->machine->name);
|
||||
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
|
||||
args->machine->name, smbios_legacy_mode);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
smbios_type1_defaults = false;
|
||||
pc_compat_2_0(args);
|
||||
smbios_defaults = false;
|
||||
gigabyte_align = false;
|
||||
option_rom_has_mr = true;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
pc_compat_1_7(args);
|
||||
@@ -297,15 +310,23 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
|
||||
.desc = "Standard PC (Q35 + ICH9, 2009)", \
|
||||
.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, \
|
||||
.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 = {
|
||||
PC_Q35_2_0_MACHINE_OPTIONS,
|
||||
.name = "pc-q35-2.0",
|
||||
.alias = "q35",
|
||||
.init = pc_q35_init,
|
||||
.init = pc_q35_init_2_0,
|
||||
};
|
||||
|
||||
#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)
|
||||
{
|
||||
qemu_register_machine(&pc_q35_machine_v2_1);
|
||||
qemu_register_machine(&pc_q35_machine_v2_0);
|
||||
qemu_register_machine(&pc_q35_machine_v1_7);
|
||||
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/error-report.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/i386/smbios.h"
|
||||
#include "hw/loader.h"
|
||||
|
||||
/*
|
||||
* Structures shared with the BIOS
|
||||
*/
|
||||
|
||||
/* legacy structures and constants for <= 2.0 machines */
|
||||
struct smbios_header {
|
||||
uint16_t length;
|
||||
uint8_t type;
|
||||
@@ -46,14 +47,23 @@ struct smbios_table {
|
||||
|
||||
static uint8_t *smbios_entries;
|
||||
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 bool smbios_immutable;
|
||||
static bool smbios_have_defaults;
|
||||
static uint32_t smbios_cpuid_version, smbios_cpuid_features, smbios_smp_sockets;
|
||||
|
||||
static struct {
|
||||
bool seen;
|
||||
int headertype;
|
||||
Location loc;
|
||||
} first_opt[2];
|
||||
static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1);
|
||||
static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
|
||||
|
||||
static struct {
|
||||
const char *vendor, *version, *date;
|
||||
@@ -66,6 +76,22 @@ static struct {
|
||||
/* uuid is in qemu_uuid[] */
|
||||
} 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 = {
|
||||
.name = "smbios",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
|
||||
@@ -149,6 +175,134 @@ static const QemuOptDesc qemu_smbios_type1_opts[] = {
|
||||
{ /* 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)
|
||||
{
|
||||
qemu_add_opts(&qemu_smbios_opts);
|
||||
@@ -158,35 +312,17 @@ machine_init(smbios_register_config);
|
||||
|
||||
static void smbios_validate_table(void)
|
||||
{
|
||||
if (smbios_type4_count && smbios_type4_count != smp_cpus) {
|
||||
error_report("Number of SMBIOS Type 4 tables must match cpu count");
|
||||
uint32_t expect_t4_count = smbios_legacy ? smp_cpus : smbios_smp_sockets;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct smbios_field *field;
|
||||
@@ -256,22 +392,13 @@ static void smbios_build_type_1_fields(void)
|
||||
}
|
||||
}
|
||||
|
||||
void smbios_set_type1_defaults(const char *manufacturer,
|
||||
const char *product, const char *version)
|
||||
uint8_t *smbios_get_table_legacy(size_t *length)
|
||||
{
|
||||
if (!type1.manufacturer) {
|
||||
type1.manufacturer = manufacturer;
|
||||
if (!smbios_legacy) {
|
||||
*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) {
|
||||
smbios_build_type_0_fields();
|
||||
smbios_build_type_1_fields();
|
||||
@@ -281,6 +408,458 @@ uint8_t *smbios_get_table(size_t *length)
|
||||
*length = smbios_entries_len;
|
||||
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)
|
||||
{
|
||||
@@ -297,11 +876,12 @@ void smbios_entry_add(QemuOpts *opts)
|
||||
const char *val;
|
||||
|
||||
assert(!smbios_immutable);
|
||||
|
||||
val = qemu_opt_get(opts, "file");
|
||||
if (val) {
|
||||
struct smbios_structure_header *header;
|
||||
struct smbios_table *table;
|
||||
int size;
|
||||
struct smbios_table *table; /* legacy mode only */
|
||||
|
||||
qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
|
||||
if (local_err) {
|
||||
@@ -315,31 +895,60 @@ void smbios_entry_add(QemuOpts *opts)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!smbios_entries) {
|
||||
smbios_entries_len = sizeof(uint16_t);
|
||||
smbios_entries = g_malloc0(smbios_entries_len);
|
||||
}
|
||||
/*
|
||||
* NOTE: standard double '\0' terminator expected, per smbios spec.
|
||||
* (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 +
|
||||
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) {
|
||||
if (load_image(val, (uint8_t *)header) != size) {
|
||||
error_report("Failed to load SMBIOS file %s", val);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
header = (struct smbios_structure_header *)(table->data);
|
||||
smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
|
||||
if (test_bit(header->type, have_fields_bitmap)) {
|
||||
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) {
|
||||
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;
|
||||
(*(uint16_t *)smbios_entries) =
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -347,7 +956,16 @@ void smbios_entry_add(QemuOpts *opts)
|
||||
if (val) {
|
||||
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) {
|
||||
case 0:
|
||||
@@ -391,6 +1009,57 @@ void smbios_entry_add(QemuOpts *opts)
|
||||
qemu_uuid_set = true;
|
||||
}
|
||||
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:
|
||||
error_report("Don't know how to build fields for SMBIOS type %ld",
|
||||
type);
|
||||
|
||||
@@ -98,8 +98,8 @@ static void apic_sync_vapic(APICCommonState *s, int sync_type)
|
||||
return;
|
||||
}
|
||||
if (sync_type & SYNC_FROM_VAPIC) {
|
||||
cpu_physical_memory_rw(s->vapic_paddr, (void *)&vapic_state,
|
||||
sizeof(vapic_state), 0);
|
||||
cpu_physical_memory_read(s->vapic_paddr, &vapic_state,
|
||||
sizeof(vapic_state));
|
||||
s->tpr = vapic_state.tpr;
|
||||
}
|
||||
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;
|
||||
case 0xd00: /* CPUID Base. */
|
||||
cpu = ARM_CPU(current_cpu);
|
||||
return cpu->env.cp15.c0_cpuid;
|
||||
return cpu->midr;
|
||||
case 0xd04: /* Interrupt Control State. */
|
||||
/* VECTACTIVE */
|
||||
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)
|
||||
{
|
||||
KVMOpenPICState *opp = KVM_OPENPIC(d);
|
||||
struct kvm_enable_cap encap = {};
|
||||
|
||||
encap.cap = KVM_CAP_IRQ_MPIC;
|
||||
encap.args[0] = opp->fd;
|
||||
encap.args[1] = kvm_arch_vcpu_id(cs);
|
||||
|
||||
return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
|
||||
return kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_MPIC, 0, opp->fd,
|
||||
kvm_arch_vcpu_id(cs));
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
|
||||
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) {
|
||||
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
||||
kvm_arch_vcpu_id(cs), strerror(errno));
|
||||
|
||||
@@ -684,8 +684,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
}
|
||||
|
||||
if (s->role_val == IVSHMEM_PEER) {
|
||||
error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION,
|
||||
"peer mode", "ivshmem");
|
||||
error_setg(&s->migration_blocker,
|
||||
"Migration is disabled when using feature 'peer mode' in device 'ivshmem'");
|
||||
migrate_add_blocker(s->migration_blocker);
|
||||
}
|
||||
|
||||
|
||||
@@ -718,7 +718,6 @@ static void pcnet_s_reset(PCNetState *s)
|
||||
s->csr[94] = 0x0000;
|
||||
s->csr[100] = 0x0200;
|
||||
s->csr[103] = 0x0105;
|
||||
s->csr[103] = 0x0105;
|
||||
s->csr[112] = 0x0000;
|
||||
s->csr[114] = 0x0000;
|
||||
s->csr[122] = 0x0000;
|
||||
|
||||
@@ -98,7 +98,7 @@ static unsigned int tdk_read(struct PHY *phy, unsigned int req)
|
||||
r |= 1;
|
||||
break;
|
||||
case 17:
|
||||
/* Marvel PHY on many xilinx boards. */
|
||||
/* Marvell PHY on many xilinx boards. */
|
||||
r = 0x8000; /* 1000Mb */
|
||||
break;
|
||||
case 18:
|
||||
@@ -142,6 +142,9 @@ tdk_write(struct PHY *phy, unsigned int req, unsigned int data)
|
||||
phy->regs[regnum] = data;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unconditionally clear regs[BMCR][BMCR_RESET] */
|
||||
phy->regs[0] &= ~0x8000;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -92,6 +92,7 @@ typedef enum {
|
||||
|
||||
#define BDRV_O_RDWR 0x0002
|
||||
#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_CACHE_WB 0x0040 /* use write-back caching */
|
||||
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */
|
||||
|
||||
@@ -299,7 +299,6 @@ struct BlockDriverState {
|
||||
char backing_file[1024]; /* if non zero, the image is a diff of
|
||||
this file image */
|
||||
char backing_format[16]; /* if non-zero and backing_file exists */
|
||||
int is_temporary;
|
||||
|
||||
BlockDriverState *backing_hd;
|
||||
BlockDriverState *file;
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
#define dh_is_64bit_noreturn 0
|
||||
#define dh_is_64bit_i32 0
|
||||
#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_signed_void 0
|
||||
|
||||
@@ -239,6 +239,8 @@ uint16_t pvpanic_port(void);
|
||||
#define E820_UNUSABLE 5
|
||||
|
||||
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 \
|
||||
PC_COMPAT_1_7, \
|
||||
|
||||
@@ -15,15 +15,40 @@
|
||||
|
||||
#include "qemu/option.h"
|
||||
|
||||
#define SMBIOS_MAX_TYPE 127
|
||||
|
||||
void smbios_entry_add(QemuOpts *opts);
|
||||
void smbios_set_type1_defaults(const char *manufacturer,
|
||||
const char *product, const char *version);
|
||||
uint8_t *smbios_get_table(size_t *length);
|
||||
void smbios_set_cpuid(uint32_t version, uint32_t features);
|
||||
void smbios_set_defaults(const char *manufacturer, const char *product,
|
||||
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 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. */
|
||||
struct smbios_structure_header {
|
||||
uint8_t type;
|
||||
@@ -60,7 +85,23 @@ struct smbios_type_1 {
|
||||
uint8_t family_str;
|
||||
} 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_structure_header header;
|
||||
uint8_t manufacturer_str;
|
||||
@@ -76,10 +117,11 @@ struct smbios_type_3 {
|
||||
uint8_t height;
|
||||
uint8_t number_of_power_cords;
|
||||
uint8_t contained_element_count;
|
||||
// contained elements follow
|
||||
uint8_t sku_number_str;
|
||||
/* contained elements follow */
|
||||
} QEMU_PACKED;
|
||||
|
||||
/* SMBIOS type 4 - Processor Information (v2.0) */
|
||||
/* SMBIOS type 4 - Processor Information (v2.6) */
|
||||
struct smbios_type_4 {
|
||||
struct smbios_structure_header header;
|
||||
uint8_t socket_designation_str;
|
||||
@@ -97,11 +139,17 @@ struct smbios_type_4 {
|
||||
uint16_t l1_cache_handle;
|
||||
uint16_t l2_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;
|
||||
|
||||
/* SMBIOS type 16 - Physical Memory Array
|
||||
* Associated with one type 17 (Memory Device).
|
||||
*/
|
||||
/* SMBIOS type 16 - Physical Memory Array (v2.7) */
|
||||
struct smbios_type_16 {
|
||||
struct smbios_structure_header header;
|
||||
uint8_t location;
|
||||
@@ -110,10 +158,10 @@ struct smbios_type_16 {
|
||||
uint32_t maximum_capacity;
|
||||
uint16_t memory_error_information_handle;
|
||||
uint16_t number_of_memory_devices;
|
||||
uint64_t extended_maximum_capacity;
|
||||
} 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_structure_header header;
|
||||
uint16_t physical_memory_array_handle;
|
||||
@@ -127,27 +175,28 @@ struct smbios_type_17 {
|
||||
uint8_t bank_locator_str;
|
||||
uint8_t memory_type;
|
||||
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;
|
||||
|
||||
/* SMBIOS type 19 - Memory Array Mapped Address */
|
||||
/* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */
|
||||
struct smbios_type_19 {
|
||||
struct smbios_structure_header header;
|
||||
uint32_t starting_address;
|
||||
uint32_t ending_address;
|
||||
uint16_t memory_array_handle;
|
||||
uint8_t partition_width;
|
||||
} QEMU_PACKED;
|
||||
|
||||
/* 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;
|
||||
uint64_t extended_starting_address;
|
||||
uint64_t extended_ending_address;
|
||||
} QEMU_PACKED;
|
||||
|
||||
/* SMBIOS type 32 - System Boot Information */
|
||||
|
||||
@@ -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)
|
||||
GCC_FMT_ATTR(2, 0);
|
||||
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);
|
||||
int monitor_set_cpu(int cpu_index);
|
||||
int monitor_get_cpu_index(void);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#ifndef QERROR_H
|
||||
#define QERROR_H
|
||||
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
@@ -35,51 +34,30 @@ void qerror_report_err(Error *err);
|
||||
* Please keep the definitions in alphabetical order.
|
||||
* 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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found"
|
||||
|
||||
#define QERR_BLOCK_JOB_NOT_ACTIVE \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed"
|
||||
|
||||
#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging"
|
||||
|
||||
#define QERR_BUS_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 \
|
||||
ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found"
|
||||
|
||||
#define QERR_DEVICE_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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'"
|
||||
|
||||
#define QERR_INVALID_PARAMETER_COMBINATION \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter combination"
|
||||
|
||||
#define QERR_INVALID_PARAMETER_TYPE \
|
||||
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 \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax"
|
||||
|
||||
@@ -164,45 +118,21 @@ void qerror_report_err(Error *err);
|
||||
#define QERR_MIGRATION_ACTIVE \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")"
|
||||
|
||||
#define QERR_QGA_COMMAND_FAILED \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input"
|
||||
|
||||
@@ -212,15 +142,9 @@ void qerror_report_err(Error *err);
|
||||
#define QERR_QMP_EXTRA_MEMBER \
|
||||
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 \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred"
|
||||
|
||||
@@ -230,9 +154,6 @@ void qerror_report_err(Error *err);
|
||||
#define QERR_UNSUPPORTED \
|
||||
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 \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket"
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
QemuOptsList *qemu_find_opts(const char *group);
|
||||
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_drive_opts(QemuOptsList *list);
|
||||
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_printf(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_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
const char *error_get_progname(void);
|
||||
|
||||
@@ -294,6 +294,36 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu);
|
||||
|
||||
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 index, int reg);
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#define KVM_DEV_FLIC_CLEAR_IRQS 3
|
||||
#define KVM_DEV_FLIC_APF_ENABLE 4
|
||||
#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,
|
||||
* 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_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 */
|
||||
struct kvm_regs {
|
||||
/* 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_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_PP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x8)
|
||||
#define KVM_REG_S390_GBEA (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x9)
|
||||
#endif
|
||||
|
||||
@@ -740,6 +740,9 @@ struct kvm_ppc_smmu_info {
|
||||
#define KVM_CAP_SPAPR_MULTITCE 94
|
||||
#define KVM_CAP_EXT_EMUL_CPUID 95
|
||||
#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
|
||||
|
||||
@@ -755,9 +758,18 @@ struct kvm_irq_routing_msi {
|
||||
__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 */
|
||||
#define KVM_IRQ_ROUTING_IRQCHIP 1
|
||||
#define KVM_IRQ_ROUTING_MSI 2
|
||||
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
|
||||
|
||||
struct kvm_irq_routing_entry {
|
||||
__u32 gsi;
|
||||
@@ -767,6 +779,7 @@ struct kvm_irq_routing_entry {
|
||||
union {
|
||||
struct kvm_irq_routing_irqchip irqchip;
|
||||
struct kvm_irq_routing_msi msi;
|
||||
struct kvm_irq_routing_s390_adapter adapter;
|
||||
__u32 pad[8];
|
||||
} u;
|
||||
};
|
||||
@@ -1075,6 +1088,10 @@ struct kvm_s390_ucas_mapping {
|
||||
/* Available with KVM_CAP_DEBUGREGS */
|
||||
#define KVM_GET_DEBUGREGS _IOR(KVMIO, 0xa1, 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)
|
||||
/* Available with KVM_CAP_XSAVE */
|
||||
#define KVM_GET_XSAVE _IOR(KVMIO, 0xa4, struct kvm_xsave)
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
|
||||
#define VFIO_TYPE1_IOMMU 1
|
||||
#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
|
||||
|
||||
85
monitor.c
85
monitor.c
@@ -137,6 +137,7 @@ typedef struct mon_cmd_t {
|
||||
* used, and mhandler of 1st level plays the role of help function.
|
||||
*/
|
||||
struct mon_cmd_t *sub_table;
|
||||
void (*command_completion)(ReadLineState *rs, int nb_args, const char *str);
|
||||
} mon_cmd_t;
|
||||
|
||||
/* file descriptors passed via SCM_RIGHTS */
|
||||
@@ -352,33 +353,6 @@ void monitor_printf(Monitor *mon, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void monitor_print_filename(Monitor *mon, const char *filename)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; filename[i]; i++) {
|
||||
switch (filename[i]) {
|
||||
case ' ':
|
||||
case '"':
|
||||
case '\\':
|
||||
monitor_printf(mon, "\\%c", filename[i]);
|
||||
break;
|
||||
case '\t':
|
||||
monitor_printf(mon, "\\t");
|
||||
break;
|
||||
case '\r':
|
||||
monitor_printf(mon, "\\r");
|
||||
break;
|
||||
case '\n':
|
||||
monitor_printf(mon, "\\n");
|
||||
break;
|
||||
default:
|
||||
monitor_printf(mon, "%c", filename[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
@@ -2254,6 +2228,7 @@ void qmp_getfd(const char *fdname, Error **errp)
|
||||
}
|
||||
|
||||
if (qemu_isdigit(fdname[0])) {
|
||||
close(fd);
|
||||
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdname",
|
||||
"a name not starting with a digit");
|
||||
return;
|
||||
@@ -4277,11 +4252,15 @@ static const char *next_arg_type(const char *typestr)
|
||||
return (p != NULL ? ++p : typestr);
|
||||
}
|
||||
|
||||
static void device_add_completion(ReadLineState *rs, const char *str)
|
||||
void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
GSList *list, *elt;
|
||||
size_t len;
|
||||
|
||||
if (nb_args != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
list = elt = object_class_get_list(TYPE_DEVICE, false);
|
||||
@@ -4290,7 +4269,9 @@ static void device_add_completion(ReadLineState *rs, const char *str)
|
||||
DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
|
||||
TYPE_DEVICE);
|
||||
name = object_class_get_name(OBJECT_CLASS(dc));
|
||||
if (!strncmp(name, str, len)) {
|
||||
|
||||
if (!dc->cannot_instantiate_with_device_add_yet
|
||||
&& !strncmp(name, str, len)) {
|
||||
readline_add_completion(rs, name);
|
||||
}
|
||||
elt = elt->next;
|
||||
@@ -4298,11 +4279,15 @@ static void device_add_completion(ReadLineState *rs, const char *str)
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
static void object_add_completion(ReadLineState *rs, const char *str)
|
||||
void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
GSList *list, *elt;
|
||||
size_t len;
|
||||
|
||||
if (nb_args != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
list = elt = object_class_get_list(TYPE_USER_CREATABLE, false);
|
||||
@@ -4318,8 +4303,8 @@ static void object_add_completion(ReadLineState *rs, const char *str)
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
static void device_del_completion(ReadLineState *rs, BusState *bus,
|
||||
const char *str, size_t len)
|
||||
static void device_del_bus_completion(ReadLineState *rs, BusState *bus,
|
||||
const char *str, size_t len)
|
||||
{
|
||||
BusChild *kid;
|
||||
|
||||
@@ -4332,16 +4317,32 @@ static void device_del_completion(ReadLineState *rs, BusState *bus,
|
||||
}
|
||||
|
||||
QLIST_FOREACH(dev_child, &dev->child_bus, sibling) {
|
||||
device_del_completion(rs, dev_child, str, len);
|
||||
device_del_bus_completion(rs, dev_child, str, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void object_del_completion(ReadLineState *rs, const char *str)
|
||||
void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (nb_args != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
device_del_bus_completion(rs, sysbus_get_default(), str, len);
|
||||
}
|
||||
|
||||
void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
ObjectPropertyInfoList *list, *start;
|
||||
size_t len;
|
||||
|
||||
if (nb_args != 2) {
|
||||
return;
|
||||
}
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
|
||||
@@ -4395,6 +4396,9 @@ static void monitor_find_completion_by_table(Monitor *mon,
|
||||
return monitor_find_completion_by_table(mon, cmd->sub_table,
|
||||
&args[1], nb_args - 1);
|
||||
}
|
||||
if (cmd->command_completion) {
|
||||
return cmd->command_completion(mon->rs, nb_args, args[nb_args - 1]);
|
||||
}
|
||||
|
||||
ptype = next_arg_type(cmd->args_type);
|
||||
for(i = 0; i < nb_args - 2; i++) {
|
||||
@@ -4421,13 +4425,6 @@ static void monitor_find_completion_by_table(Monitor *mon,
|
||||
readline_set_completion_index(mon->rs, strlen(str));
|
||||
bdrv_iterate(block_completion_it, &mbs);
|
||||
break;
|
||||
case 'O':
|
||||
if (!strcmp(cmd->name, "device_add") && nb_args == 2) {
|
||||
device_add_completion(mon->rs, str);
|
||||
} else if (!strcmp(cmd->name, "object_add") && nb_args == 2) {
|
||||
object_add_completion(mon->rs, str);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
if (!strcmp(cmd->name, "sendkey")) {
|
||||
@@ -4441,12 +4438,6 @@ static void monitor_find_completion_by_table(Monitor *mon,
|
||||
} else if (!strcmp(cmd->name, "help|?")) {
|
||||
monitor_find_completion_by_table(mon, cmd_table,
|
||||
&args[1], nb_args - 1);
|
||||
} else if (!strcmp(cmd->name, "device_del") && nb_args == 2) {
|
||||
size_t len = strlen(str);
|
||||
readline_set_completion_index(mon->rs, len);
|
||||
device_del_completion(mon->rs, sysbus_get_default(), str, len);
|
||||
} else if (!strcmp(cmd->name, "object_del") && nb_args == 2) {
|
||||
object_del_completion(mon->rs, str);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
10
net/net.c
10
net/net.c
@@ -473,7 +473,7 @@ ssize_t qemu_deliver_packet(NetClientState *sender,
|
||||
|
||||
if (ret == 0) {
|
||||
nc->receive_disabled = 1;
|
||||
};
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1045,7 +1045,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
|
||||
if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) {
|
||||
if (has_name) {
|
||||
error_setg(errp, "net client(%s) isn't a NIC", name);
|
||||
break;
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1064,11 +1064,15 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
|
||||
} else if (has_name) {
|
||||
error_setg(errp, "net client(%s) doesn't support"
|
||||
" rx-filter querying", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (has_name) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter_list == NULL && !error_is_set(errp) && has_name) {
|
||||
if (filter_list == NULL && has_name) {
|
||||
error_setg(errp, "invalid net client name: %s", name);
|
||||
}
|
||||
|
||||
|
||||
@@ -527,6 +527,7 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
|
||||
"pid directory=%s\n"
|
||||
"lock directory=%s\n"
|
||||
"state directory=%s\n"
|
||||
"ncalrpc dir=%s/ncalrpc\n"
|
||||
"log file=%s/log.smbd\n"
|
||||
"smb passwd file=%s/smbpasswd\n"
|
||||
"security = user\n"
|
||||
@@ -542,6 +543,7 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
|
||||
s->smb_dir,
|
||||
s->smb_dir,
|
||||
s->smb_dir,
|
||||
s->smb_dir,
|
||||
exported_dir,
|
||||
passwd->pw_name
|
||||
);
|
||||
|
||||
14
net/tap.c
14
net/tap.c
@@ -367,11 +367,8 @@ static int launch_script(const char *setup_script, const char *ifname, int fd)
|
||||
if (pid == 0) {
|
||||
int open_max = sysconf(_SC_OPEN_MAX), i;
|
||||
|
||||
for (i = 0; i < open_max; i++) {
|
||||
if (i != STDIN_FILENO &&
|
||||
i != STDOUT_FILENO &&
|
||||
i != STDERR_FILENO &&
|
||||
i != fd) {
|
||||
for (i = 3; i < open_max; i++) {
|
||||
if (i != fd) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
@@ -452,11 +449,8 @@ static int net_bridge_run_helper(const char *helper, const char *bridge)
|
||||
char br_buf[6+IFNAMSIZ] = {0};
|
||||
char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15];
|
||||
|
||||
for (i = 0; i < open_max; i++) {
|
||||
if (i != STDIN_FILENO &&
|
||||
i != STDOUT_FILENO &&
|
||||
i != STDERR_FILENO &&
|
||||
i != sv[1]) {
|
||||
for (i = 3; i < open_max; i++) {
|
||||
if (i != sv[1]) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
|
||||
1010
pc-bios/qemu_logo.svg
Normal file
1010
pc-bios/qemu_logo.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 32 KiB |
@@ -37,8 +37,8 @@ install: $(OBJS)
|
||||
$(call quiet-command, msgfmt -o $@ $<, " GEN $@")
|
||||
|
||||
$(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c
|
||||
$(call quiet-command, cd $(SRC_PATH) && \
|
||||
(xgettext -o - --from-code=UTF-8 --foreign-user \
|
||||
$(call quiet-command, ( cd $(SRC_PATH) && \
|
||||
xgettext -o - --from-code=UTF-8 --foreign-user \
|
||||
--package-name=QEMU --package-version=$(VERSION) \
|
||||
--msgid-bugs-address=qemu-devel@nongnu.org -k_ -C ui/gtk.c | \
|
||||
sed -e s/CHARSET/UTF-8/) >$@, " GEN $@")
|
||||
|
||||
@@ -10,7 +10,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2012-02-28 16:00+0100\n"
|
||||
"Last-Translator: Kevin Wolf <kwolf@redhat.com>\n"
|
||||
"Language-Team: Deutsch <de@li.org>\n"
|
||||
"Language: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -10,7 +10,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2013-03-31 19:39+0200\n"
|
||||
"Last-Translator: Aurelien Jarno <aurelien@aurel32.net>\n"
|
||||
"Language-Team: French <FR@li.org>\n"
|
||||
"Language: \n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/hu.po
2
po/hu.po
@@ -10,7 +10,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2013-05-06 20:42+0200\n"
|
||||
"Last-Translator: Ákos Kovács <akoskovacs@gmx.com>\n"
|
||||
"Language-Team: Hungarian <hu@li.org>\n"
|
||||
"Language: \n"
|
||||
"Language: hu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/it.po
2
po/it.po
@@ -10,7 +10,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2012-02-27 08:23+0100\n"
|
||||
"Last-Translator: Paolo Bonzini <pbonzini@redhat.com>\n"
|
||||
"Language-Team: Italian <it@li.org>\n"
|
||||
"Language: \n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/tr.po
2
po/tr.po
@@ -10,7 +10,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2013-04-22 18:35+0300\n"
|
||||
"Last-Translator: Ozan Çağlayan <ozancag@gmail.com>\n"
|
||||
"Language-Team: Türkçe <>\n"
|
||||
"Language: \n"
|
||||
"Language: tr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -4285,10 +4285,13 @@
|
||||
#
|
||||
# Drivers that are supported in block device operations.
|
||||
#
|
||||
# @host_device, @host_cdrom, @host_floppy: Since 2.1
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'enum': 'BlockdevDriver',
|
||||
'data': [ 'file', 'http', 'https', 'ftp', 'ftps', 'tftp', 'vvfat', 'blkdebug',
|
||||
'data': [ 'file', 'host_device', 'host_cdrom', 'host_floppy',
|
||||
'http', 'https', 'ftp', 'ftps', 'tftp', 'vvfat', 'blkdebug',
|
||||
'blkverify', 'bochs', 'cloop', 'cow', 'dmg', 'parallels', 'qcow',
|
||||
'qcow2', 'qed', 'raw', 'vdi', 'vhdx', 'vmdk', 'vpc', 'quorum' ] }
|
||||
|
||||
@@ -4555,6 +4558,9 @@
|
||||
'discriminator': 'driver',
|
||||
'data': {
|
||||
'file': 'BlockdevOptionsFile',
|
||||
'host_device':'BlockdevOptionsFile',
|
||||
'host_cdrom': 'BlockdevOptionsFile',
|
||||
'host_floppy':'BlockdevOptionsFile',
|
||||
'http': 'BlockdevOptionsFile',
|
||||
'https': 'BlockdevOptionsFile',
|
||||
'ftp': 'BlockdevOptionsFile',
|
||||
|
||||
@@ -80,7 +80,8 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
|
||||
return NULL;
|
||||
}
|
||||
if (!cmd->enabled) {
|
||||
error_set(errp, QERR_COMMAND_DISABLED, command);
|
||||
error_setg(errp, "The command %s has been disabled for this instance",
|
||||
command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
|
||||
GHashTable *h;
|
||||
|
||||
if (qiv->nb_stack >= QIV_STACK_SIZE) {
|
||||
error_set(errp, QERR_BUFFER_OVERRUN);
|
||||
error_setg(errp, "An internal buffer overran");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -422,12 +422,14 @@ static BusState *qbus_find(const char *path)
|
||||
* one child bus accept it nevertheless */
|
||||
switch (dev->num_child_bus) {
|
||||
case 0:
|
||||
qerror_report(QERR_DEVICE_NO_BUS, elem);
|
||||
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||
"Device '%s' has no child bus", elem);
|
||||
return NULL;
|
||||
case 1:
|
||||
return QLIST_FIRST(&dev->child_bus);
|
||||
default:
|
||||
qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
|
||||
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||
"Device '%s' has multiple child busses", elem);
|
||||
if (!monitor_cur_is_qmp()) {
|
||||
qbus_list_bus(dev);
|
||||
}
|
||||
@@ -505,14 +507,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
|
||||
return NULL;
|
||||
}
|
||||
if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
|
||||
qerror_report(QERR_BAD_BUS_FOR_DEVICE,
|
||||
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||
"Device '%s' can't go on a %s bus",
|
||||
driver, object_get_typename(OBJECT(bus)));
|
||||
return NULL;
|
||||
}
|
||||
} else if (dc->bus_type != NULL) {
|
||||
bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
|
||||
if (!bus) {
|
||||
qerror_report(QERR_NO_BUS_FOR_DEVICE,
|
||||
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||
"No '%s' bus found for device '%s'",
|
||||
dc->bus_type, driver);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
38
qemu-img.c
38
qemu-img.c
@@ -33,6 +33,9 @@
|
||||
#include "block/qapi.h"
|
||||
#include <getopt.h>
|
||||
|
||||
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
|
||||
", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
||||
|
||||
typedef struct img_cmd_t {
|
||||
const char *name;
|
||||
int (*handler)(int argc, char **argv);
|
||||
@@ -75,7 +78,7 @@ static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
|
||||
static void QEMU_NORETURN help(void)
|
||||
{
|
||||
const char *help_msg =
|
||||
"qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
||||
QEMU_IMG_VERSION
|
||||
"usage: qemu-img command [command options]\n"
|
||||
"QEMU disk image utility\n"
|
||||
"\n"
|
||||
@@ -457,12 +460,12 @@ fail:
|
||||
|
||||
static void dump_json_image_check(ImageCheck *check, bool quiet)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
Error *local_err = NULL;
|
||||
QString *str;
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
QObject *obj;
|
||||
visit_type_ImageCheck(qmp_output_get_visitor(ov),
|
||||
&check, NULL, &errp);
|
||||
&check, NULL, &local_err);
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
assert(str != NULL);
|
||||
@@ -1731,12 +1734,12 @@ static void dump_snapshots(BlockDriverState *bs)
|
||||
|
||||
static void dump_json_image_info_list(ImageInfoList *list)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
Error *local_err = NULL;
|
||||
QString *str;
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
QObject *obj;
|
||||
visit_type_ImageInfoList(qmp_output_get_visitor(ov),
|
||||
&list, NULL, &errp);
|
||||
&list, NULL, &local_err);
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
assert(str != NULL);
|
||||
@@ -1748,12 +1751,12 @@ static void dump_json_image_info_list(ImageInfoList *list)
|
||||
|
||||
static void dump_json_image_info(ImageInfo *info)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
Error *local_err = NULL;
|
||||
QString *str;
|
||||
QmpOutputVisitor *ov = qmp_output_visitor_new();
|
||||
QObject *obj;
|
||||
visit_type_ImageInfo(qmp_output_get_visitor(ov),
|
||||
&info, NULL, &errp);
|
||||
&info, NULL, &local_err);
|
||||
obj = qmp_output_get_qobject(ov);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
assert(str != NULL);
|
||||
@@ -2789,6 +2792,12 @@ int main(int argc, char **argv)
|
||||
{
|
||||
const img_cmd_t *cmd;
|
||||
const char *cmdname;
|
||||
int c;
|
||||
static const struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_POSIX
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
@@ -2803,15 +2812,24 @@ int main(int argc, char **argv)
|
||||
error_exit("Not enough arguments");
|
||||
}
|
||||
cmdname = argv[1];
|
||||
argc--; argv++;
|
||||
|
||||
/* find the command */
|
||||
for(cmd = img_cmds; cmd->name != NULL; cmd++) {
|
||||
for (cmd = img_cmds; cmd->name != NULL; cmd++) {
|
||||
if (!strcmp(cmdname, cmd->name)) {
|
||||
return cmd->handler(argc, argv);
|
||||
return cmd->handler(argc - 1, argv + 1);
|
||||
}
|
||||
}
|
||||
|
||||
c = getopt_long(argc, argv, "h", long_options, NULL);
|
||||
|
||||
if (c == 'h') {
|
||||
help();
|
||||
}
|
||||
if (c == 'v') {
|
||||
printf(QEMU_IMG_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
error_exit("Command not found: %s", cmdname);
|
||||
}
|
||||
|
||||
@@ -210,10 +210,13 @@ use is discouraged as it may be removed from future versions.
|
||||
ETEXI
|
||||
|
||||
DEF("m", HAS_ARG, QEMU_OPTION_m,
|
||||
"-m megs set virtual RAM size to megs MB [default="
|
||||
stringify(DEFAULT_RAM_SIZE) "]\n", QEMU_ARCH_ALL)
|
||||
"-m [size=]megs\n"
|
||||
" configure guest RAM\n"
|
||||
" size: initial amount of guest memory (default: "
|
||||
stringify(DEFAULT_RAM_SIZE) "MiB)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item -m @var{megs}
|
||||
@item -m [size=]@var{megs}
|
||||
@findex -m
|
||||
Set virtual RAM size to @var{megs} megabytes. Default is 128 MiB. Optionally,
|
||||
a suffix of ``M'' or ``G'' can be used to signify a value in megabytes or
|
||||
@@ -408,7 +411,8 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive,
|
||||
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
|
||||
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
|
||||
" [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
|
||||
" [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
|
||||
" [,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
|
||||
" [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
|
||||
" [,readonly=on|off][,copy-on-read=on|off]\n"
|
||||
" [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]]\n"
|
||||
" [[,iops=i]|[[,iops_rd=r][,iops_wr=w]]]\n"
|
||||
|
||||
@@ -143,6 +143,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
|
||||
{ SCMP_SYS(getsockname), 242 },
|
||||
{ SCMP_SYS(getpeername), 242 },
|
||||
{ SCMP_SYS(accept4), 242 },
|
||||
{ SCMP_SYS(timerfd_settime), 242 },
|
||||
{ SCMP_SYS(newfstatat), 241 },
|
||||
{ SCMP_SYS(shutdown), 241 },
|
||||
{ SCMP_SYS(getsockopt), 241 },
|
||||
@@ -225,7 +226,11 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
|
||||
{ SCMP_SYS(fchmod), 240 },
|
||||
{ SCMP_SYS(shmget), 240 },
|
||||
{ SCMP_SYS(shmat), 240 },
|
||||
{ SCMP_SYS(shmdt), 240 }
|
||||
{ SCMP_SYS(shmdt), 240 },
|
||||
{ SCMP_SYS(timerfd_create), 240 },
|
||||
{ SCMP_SYS(shmctl), 240 },
|
||||
{ SCMP_SYS(mlock), 240 },
|
||||
{ SCMP_SYS(munlock), 240 }
|
||||
};
|
||||
|
||||
int seccomp_start(void)
|
||||
|
||||
23
qmp.c
23
qmp.c
@@ -166,7 +166,7 @@ void qmp_cont(Error **errp)
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (runstate_needs_reset()) {
|
||||
error_set(errp, QERR_RESET_REQUIRED);
|
||||
error_setg(errp, "Resetting the Virtual Machine is required");
|
||||
return;
|
||||
} else if (runstate_check(RUN_STATE_SUSPENDED)) {
|
||||
return;
|
||||
@@ -540,14 +540,27 @@ void object_add(const char *type, const char *id, const QDict *qdict,
|
||||
Visitor *v, Error **errp)
|
||||
{
|
||||
Object *obj;
|
||||
ObjectClass *klass;
|
||||
const QDictEntry *e;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!object_class_by_name(type)) {
|
||||
klass = object_class_by_name(type);
|
||||
if (!klass) {
|
||||
error_setg(errp, "invalid class name");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
|
||||
error_setg(errp, "object type '%s' isn't supported by object-add",
|
||||
type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object_class_is_abstract(klass)) {
|
||||
error_setg(errp, "object type '%s' is abstract", type);
|
||||
return;
|
||||
}
|
||||
|
||||
obj = object_new(type);
|
||||
if (qdict) {
|
||||
for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
|
||||
@@ -558,12 +571,6 @@ void object_add(const char *type, const char *id, const QDict *qdict,
|
||||
}
|
||||
}
|
||||
|
||||
if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
|
||||
error_setg(&local_err, "object type '%s' isn't supported by object-add",
|
||||
type);
|
||||
goto out;
|
||||
}
|
||||
|
||||
user_creatable_complete(obj, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
|
||||
@@ -110,7 +110,7 @@ static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt,
|
||||
error_free(ctxt->err);
|
||||
ctxt->err = NULL;
|
||||
}
|
||||
error_set(&ctxt->err, QERR_JSON_PARSE_ERROR, message);
|
||||
error_setg(&ctxt->err, "JSON parse error, %s", message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -768,7 +768,7 @@ ObjectProperty *object_property_find(Object *obj, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
|
||||
error_setg(errp, "Property '.%s' not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1075,7 +1075,8 @@ static Object *object_resolve_link(Object *obj, const char *name,
|
||||
target = object_resolve_path_type(path, target_type, &ambiguous);
|
||||
|
||||
if (ambiguous) {
|
||||
error_set(errp, QERR_AMBIGUOUS_PATH, path);
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"Path '%s' does not uniquely identify an object", path);
|
||||
} else if (!target) {
|
||||
target = object_resolve_path(path, &ambiguous);
|
||||
if (target || ambiguous) {
|
||||
|
||||
3
savevm.c
3
savevm.c
@@ -453,7 +453,8 @@ bool qemu_savevm_state_blocked(Error **errp)
|
||||
|
||||
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
||||
if (se->no_migrate) {
|
||||
error_set(errp, QERR_MIGRATION_NOT_SUPPORTED, se->idstr);
|
||||
error_setg(errp, "State blocked by non-migratable device '%s'",
|
||||
se->idstr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
13
slirp/misc.c
13
slirp/misc.c
@@ -136,7 +136,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
|
||||
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
|
||||
listen(s, 1) < 0) {
|
||||
lprint("Error: inet socket: %s\n", strerror(errno));
|
||||
error_report("Error: inet socket: %s", strerror(errno));
|
||||
closesocket(s);
|
||||
|
||||
return 0;
|
||||
@@ -146,7 +146,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
pid = fork();
|
||||
switch(pid) {
|
||||
case -1:
|
||||
lprint("Error: fork failed: %s\n", strerror(errno));
|
||||
error_report("Error: fork failed: %s", strerror(errno));
|
||||
close(s);
|
||||
return 0;
|
||||
|
||||
@@ -242,15 +242,6 @@ strdup(str)
|
||||
}
|
||||
#endif
|
||||
|
||||
void lprint(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
monitor_vprintf(default_mon, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void slirp_connection_info(Slirp *slirp, Monitor *mon)
|
||||
{
|
||||
const char * const tcpstates[] = {
|
||||
|
||||
@@ -139,7 +139,7 @@ int get_dns_addr(struct in_addr *pdns_addr)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
lprint("IP address of your DNS(s): ");
|
||||
fprintf(stderr, "IP address of your DNS(s): ");
|
||||
#endif
|
||||
while (fgets(buff, 512, f) != NULL) {
|
||||
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
|
||||
@@ -153,17 +153,17 @@ int get_dns_addr(struct in_addr *pdns_addr)
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
lprint(", ");
|
||||
fprintf(stderr, ", ");
|
||||
#endif
|
||||
if (++found > 3) {
|
||||
#ifdef DEBUG
|
||||
lprint("(more)");
|
||||
fprintf(stderr, "(more)");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
lprint("%s", inet_ntoa(tmp_addr));
|
||||
fprintf(stderr, "%s", inet_ntoa(tmp_addr));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,8 +287,6 @@ void if_start(struct ttys *);
|
||||
long gethostid(void);
|
||||
#endif
|
||||
|
||||
void lprint(const char *, ...) GCC_FMT_ATTR(1, 2);
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,6 @@ stub-obj-y += iothread-lock.o
|
||||
stub-obj-y += migr-blocker.o
|
||||
stub-obj-y += mon-is-qmp.o
|
||||
stub-obj-y += mon-printf.o
|
||||
stub-obj-y += mon-print-filename.o
|
||||
stub-obj-y += mon-protocol-event.o
|
||||
stub-obj-y += mon-set-error.o
|
||||
stub-obj-y += pci-drive-hot-add.o
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
|
||||
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
|
||||
{
|
||||
error_set(errp, QERR_NOT_SUPPORTED);
|
||||
error_set(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "qemu-common.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
void monitor_print_filename(Monitor *mon, const char *filename)
|
||||
{
|
||||
}
|
||||
@@ -657,7 +657,7 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
* contexts. (ARMv8 would permit us to do no masking at all, but ARMv7
|
||||
* requires the bottom five bits to be RAZ/WI because they're UNK/SBZP.)
|
||||
*/
|
||||
env->cp15.c12_vbar = value & ~0x1Ful;
|
||||
env->cp15.c12_vbar = value & ~0x1FULL;
|
||||
}
|
||||
|
||||
static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
@@ -1578,6 +1578,21 @@ static const ARMCPRegInfo xscale_cp_reginfo[] = {
|
||||
.cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.c1_xscaleauxcr),
|
||||
.resetvalue = 0, },
|
||||
/* XScale specific cache-lockdown: since we have no cache we NOP these
|
||||
* and hope the guest does not really rely on cache behaviour.
|
||||
*/
|
||||
{ .name = "XSCALE_LOCK_ICACHE_LINE",
|
||||
.cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
|
||||
.access = PL1_W, .type = ARM_CP_NOP },
|
||||
{ .name = "XSCALE_UNLOCK_ICACHE",
|
||||
.cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NOP },
|
||||
{ .name = "XSCALE_DCACHE_LOCK",
|
||||
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 0,
|
||||
.access = PL1_RW, .type = ARM_CP_NOP },
|
||||
{ .name = "XSCALE_UNLOCK_DCACHE",
|
||||
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NOP },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
@@ -1893,51 +1908,51 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
|
||||
.access = PL1_W, .type = ARM_CP_NOP },
|
||||
/* TLBI operations */
|
||||
{ .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 0,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbiall_write },
|
||||
{ .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 1,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_va_write },
|
||||
{ .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 2,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_asid_write },
|
||||
{ .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 3,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_vaa_write },
|
||||
{ .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 5,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_va_write },
|
||||
{ .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 7,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_vaa_write },
|
||||
{ .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 0,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbiall_write },
|
||||
{ .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 1,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_va_write },
|
||||
{ .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 2,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_asid_write },
|
||||
{ .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 3,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_vaa_write },
|
||||
{ .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 5,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_va_write },
|
||||
{ .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 7,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
|
||||
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
|
||||
.writefn = tlbi_aa64_vaa_write },
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
@@ -418,7 +418,7 @@ void HELPER(exception_return)(CPUARMState *env)
|
||||
goto illegal_return;
|
||||
}
|
||||
if (new_el == 0 && (spsr & PSTATE_SP)) {
|
||||
/* Return to EL1 with M[0] bit set */
|
||||
/* Return to EL0 with M[0] bit set */
|
||||
goto illegal_return;
|
||||
}
|
||||
env->aarch64 = 1;
|
||||
|
||||
@@ -1151,6 +1151,8 @@ static void handle_hint(DisasContext *s, uint32_t insn,
|
||||
return;
|
||||
case 1: /* YIELD */
|
||||
case 2: /* WFE */
|
||||
s->is_jmp = DISAS_WFE;
|
||||
return;
|
||||
case 4: /* SEV */
|
||||
case 5: /* SEVL */
|
||||
/* we treat all as NOP at least for now */
|
||||
@@ -1507,8 +1509,10 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
|
||||
switch (opc) {
|
||||
case 0: /* BR */
|
||||
case 2: /* RET */
|
||||
tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
|
||||
break;
|
||||
case 1: /* BLR */
|
||||
tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
|
||||
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
|
||||
break;
|
||||
case 4: /* ERET */
|
||||
@@ -1527,7 +1531,6 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
|
||||
return;
|
||||
}
|
||||
|
||||
tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
}
|
||||
|
||||
@@ -10765,6 +10768,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
|
||||
case DISAS_EXC:
|
||||
case DISAS_SWI:
|
||||
break;
|
||||
case DISAS_WFE:
|
||||
gen_a64_set_pc_im(dc->pc);
|
||||
gen_helper_wfe(cpu_env);
|
||||
break;
|
||||
case DISAS_WFI:
|
||||
/* This is a special case because we don't want to just halt the CPU
|
||||
* if trying to debug across a WFI.
|
||||
|
||||
@@ -151,7 +151,6 @@ static int kvm_booke206_tlb_init(PowerPCCPU *cpu)
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_book3e_206_tlb_params params = {};
|
||||
struct kvm_config_tlb cfg = {};
|
||||
struct kvm_enable_cap encap = {};
|
||||
unsigned int entries = 0;
|
||||
int ret, i;
|
||||
|
||||
@@ -178,10 +177,7 @@ static int kvm_booke206_tlb_init(PowerPCCPU *cpu)
|
||||
cfg.params = (uintptr_t)¶ms;
|
||||
cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV;
|
||||
|
||||
encap.cap = KVM_CAP_SW_TLB;
|
||||
encap.args[0] = (uintptr_t)&cfg;
|
||||
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
|
||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_SW_TLB, 0, (uintptr_t)&cfg);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n",
|
||||
__func__, strerror(-ret));
|
||||
@@ -1292,7 +1288,6 @@ int kvmppc_set_tcr(PowerPCCPU *cpu)
|
||||
int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_enable_cap encap = {};
|
||||
int ret;
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
@@ -1304,8 +1299,7 @@ int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
encap.cap = KVM_CAP_PPC_BOOKE_WATCHDOG;
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
|
||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_BOOKE_WATCHDOG, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n",
|
||||
__func__, strerror(-ret));
|
||||
@@ -1505,12 +1499,9 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
|
||||
void kvmppc_set_papr(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_enable_cap cap = {};
|
||||
int ret;
|
||||
|
||||
cap.cap = KVM_CAP_PPC_PAPR;
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &cap);
|
||||
|
||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0);
|
||||
if (ret) {
|
||||
cpu_abort(cs, "This KVM version does not support PAPR\n");
|
||||
}
|
||||
@@ -1523,13 +1514,9 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
|
||||
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_enable_cap cap = {};
|
||||
int ret;
|
||||
|
||||
cap.cap = KVM_CAP_PPC_EPR;
|
||||
cap.args[0] = mpic_proxy;
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &cap);
|
||||
|
||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_EPR, 0, mpic_proxy);
|
||||
if (ret && mpic_proxy) {
|
||||
cpu_abort(cs, "This KVM version does not support EPR\n");
|
||||
}
|
||||
|
||||
@@ -126,6 +126,9 @@ typedef struct CPUS390XState {
|
||||
uint64_t pfault_compare;
|
||||
uint64_t pfault_select;
|
||||
|
||||
uint64_t gbea;
|
||||
uint64_t pp;
|
||||
|
||||
CPU_COMMON
|
||||
|
||||
/* reset does memset(0) up to here */
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* #define DEBUG_KVM */
|
||||
|
||||
@@ -128,14 +129,42 @@ void kvm_arch_reset_vcpu(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source)
|
||||
{
|
||||
struct kvm_one_reg reg;
|
||||
int r;
|
||||
|
||||
reg.id = id;
|
||||
reg.addr = (uint64_t) source;
|
||||
r = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (r) {
|
||||
trace_kvm_failed_reg_set(id, strerror(errno));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target)
|
||||
{
|
||||
struct kvm_one_reg reg;
|
||||
int r;
|
||||
|
||||
reg.id = id;
|
||||
reg.addr = (uint64_t) target;
|
||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
if (r) {
|
||||
trace_kvm_failed_reg_get(id, strerror(errno));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
struct kvm_one_reg reg;
|
||||
struct kvm_sregs sregs;
|
||||
struct kvm_regs regs;
|
||||
int ret;
|
||||
int r;
|
||||
int i;
|
||||
|
||||
/* always save the PSW and the GPRS*/
|
||||
@@ -151,9 +180,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
for (i = 0; i < 16; i++) {
|
||||
regs.gprs[i] = env->regs[i];
|
||||
}
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
r = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,47 +191,29 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_CPU_TIMER;
|
||||
reg.addr = (__u64)&(env->cputm);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_CLOCK_COMP;
|
||||
reg.addr = (__u64)&(env->ckc);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_TODPR;
|
||||
reg.addr = (__u64)&(env->todpr);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* These ONE_REGS are not protected by a capability. As they are only
|
||||
* necessary for migration we just trace a possible error, but don't
|
||||
* return with an error return code.
|
||||
*/
|
||||
kvm_set_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
|
||||
kvm_set_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
|
||||
kvm_set_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
|
||||
kvm_set_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
|
||||
kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp);
|
||||
|
||||
if (cap_async_pf) {
|
||||
reg.id = KVM_REG_S390_PFTOKEN;
|
||||
reg.addr = (__u64)&(env->pfault_token);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
r = kvm_set_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_PFCOMPARE;
|
||||
reg.addr = (__u64)&(env->pfault_compare);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
r = kvm_set_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_PFSELECT;
|
||||
reg.addr = (__u64)&(env->pfault_select);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
r = kvm_set_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,9 +231,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
sregs.acrs[i] = env->aregs[i];
|
||||
sregs.crs[i] = env->cregs[i];
|
||||
}
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
r = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +251,6 @@ int kvm_arch_get_registers(CPUState *cs)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
struct kvm_one_reg reg;
|
||||
struct kvm_sregs sregs;
|
||||
struct kvm_regs regs;
|
||||
int i, r;
|
||||
@@ -288,46 +298,27 @@ int kvm_arch_get_registers(CPUState *cs)
|
||||
env->psa = cs->kvm_run->s.regs.prefix;
|
||||
}
|
||||
|
||||
/* One Regs */
|
||||
reg.id = KVM_REG_S390_CPU_TIMER;
|
||||
reg.addr = (__u64)&(env->cputm);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_CLOCK_COMP;
|
||||
reg.addr = (__u64)&(env->ckc);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_TODPR;
|
||||
reg.addr = (__u64)&(env->todpr);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
/*
|
||||
* These ONE_REGS are not protected by a capability. As they are only
|
||||
* necessary for migration we just trace a possible error, but don't
|
||||
* return with an error return code.
|
||||
*/
|
||||
kvm_get_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
|
||||
kvm_get_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
|
||||
kvm_get_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
|
||||
kvm_get_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
|
||||
kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp);
|
||||
|
||||
if (cap_async_pf) {
|
||||
reg.id = KVM_REG_S390_PFTOKEN;
|
||||
reg.addr = (__u64)&(env->pfault_token);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
r = kvm_get_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_PFCOMPARE;
|
||||
reg.addr = (__u64)&(env->pfault_compare);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
r = kvm_get_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
reg.id = KVM_REG_S390_PFSELECT;
|
||||
reg.addr = (__u64)&(env->pfault_select);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
r = kvm_get_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
@@ -383,6 +374,26 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_insert_hw_breakpoint(target_ulong addr,
|
||||
target_ulong len, int type)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_arch_remove_hw_breakpoint(target_ulong addr,
|
||||
target_ulong len, int type)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void kvm_arch_remove_all_hw_breakpoints(void)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
||||
{
|
||||
}
|
||||
@@ -844,6 +855,11 @@ static int handle_tsch(S390CPU *cpu)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_arch_handle_debug_exit(S390CPU *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
@@ -859,6 +875,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
case KVM_EXIT_S390_TSCH:
|
||||
ret = handle_tsch(cpu);
|
||||
break;
|
||||
case KVM_EXIT_DEBUG:
|
||||
ret = kvm_arch_handle_debug_exit(cpu);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
|
||||
break;
|
||||
@@ -910,12 +929,10 @@ void kvm_s390_crw_mchk(S390CPU *cpu)
|
||||
|
||||
void kvm_s390_enable_css_support(S390CPU *cpu)
|
||||
{
|
||||
struct kvm_enable_cap cap = {};
|
||||
int r;
|
||||
|
||||
/* Activate host kernel channel subsystem support. */
|
||||
cap.cap = KVM_CAP_S390_CSS_SUPPORT;
|
||||
r = kvm_vcpu_ioctl(CPU(cpu), KVM_ENABLE_CAP, &cap);
|
||||
r = kvm_vcpu_enable_cap(CPU(cpu), KVM_CAP_S390_CSS_SUPPORT, 0);
|
||||
assert(r == 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
|
||||
ebcdic_put(sysib.model, "QEMU ", 16);
|
||||
ebcdic_put(sysib.sequence, "QEMU ", 16);
|
||||
ebcdic_put(sysib.plant, "QEMU", 4);
|
||||
cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
|
||||
cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
|
||||
} else if ((sel1 == 2) && (sel2 == 1)) {
|
||||
/* Basic Machine CPU */
|
||||
struct sysib_121 sysib;
|
||||
@@ -346,7 +346,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
|
||||
ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
|
||||
ebcdic_put(sysib.plant, "QEMU", 4);
|
||||
stw_p(&sysib.cpu_addr, env->cpu_num);
|
||||
cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
|
||||
cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
|
||||
} else if ((sel1 == 2) && (sel2 == 2)) {
|
||||
/* Basic Machine CPUs */
|
||||
struct sysib_122 sysib;
|
||||
@@ -358,7 +358,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
|
||||
stw_p(&sysib.active_cpus, 1);
|
||||
stw_p(&sysib.standby_cpus, 0);
|
||||
stw_p(&sysib.reserved_cpus, 0);
|
||||
cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
|
||||
cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
|
||||
} else {
|
||||
cc = 3;
|
||||
}
|
||||
@@ -375,7 +375,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
|
||||
ebcdic_put(sysib.plant, "QEMU", 4);
|
||||
stw_p(&sysib.cpu_addr, env->cpu_num);
|
||||
stw_p(&sysib.cpu_id, 0);
|
||||
cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
|
||||
cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
|
||||
} else if ((sel1 == 2) && (sel2 == 2)) {
|
||||
/* LPAR CPUs */
|
||||
struct sysib_222 sysib;
|
||||
@@ -392,7 +392,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
|
||||
stl_p(&sysib.caf, 1000);
|
||||
stw_p(&sysib.dedicated_cpus, 0);
|
||||
stw_p(&sysib.shared_cpus, 0);
|
||||
cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
|
||||
cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
|
||||
} else {
|
||||
cc = 3;
|
||||
}
|
||||
@@ -414,7 +414,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
|
||||
ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
|
||||
stl_p(&sysib.vm[0].caf, 1000);
|
||||
ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16);
|
||||
cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
|
||||
cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
|
||||
} else {
|
||||
cc = 3;
|
||||
}
|
||||
|
||||
@@ -314,6 +314,11 @@ This operation would be equivalent to
|
||||
|
||||
dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00)
|
||||
|
||||
* trunc_shr_i32 t0, t1, pos
|
||||
|
||||
For 64-bit hosts only, right shift the 64-bit input T1 by POS and
|
||||
truncate to 32-bit output T0. Depending on the host, this may be
|
||||
a simple mov/shift, or may require additional canonicalization.
|
||||
|
||||
********* Conditional moves
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 1
|
||||
|
||||
@@ -99,6 +99,7 @@ extern bool have_bmi1;
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
#define TCG_TARGET_HAS_div2_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
|
||||
@@ -152,6 +152,7 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_muluh_i64 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
|
||||
#define TCG_TARGET_HAS_new_ldst 1
|
||||
|
||||
|
||||
@@ -228,6 +228,7 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
|
||||
case INDEX_op_shr_i32:
|
||||
return (uint32_t)x >> (y & 31);
|
||||
|
||||
case INDEX_op_trunc_shr_i32:
|
||||
case INDEX_op_shr_i64:
|
||||
return (uint64_t)x >> (y & 63);
|
||||
|
||||
@@ -830,6 +831,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||
}
|
||||
break;
|
||||
|
||||
case INDEX_op_trunc_shr_i32:
|
||||
mask = (uint64_t)temps[args[1]].mask >> args[2];
|
||||
break;
|
||||
|
||||
CASE_OP_32_64(shl):
|
||||
if (temps[args[2]].state == TCG_TEMP_CONST) {
|
||||
tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
|
||||
@@ -1021,6 +1026,17 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||
}
|
||||
goto do_default;
|
||||
|
||||
case INDEX_op_trunc_shr_i32:
|
||||
if (temps[args[1]].state == TCG_TEMP_CONST) {
|
||||
s->gen_opc_buf[op_index] = op_to_movi(op);
|
||||
tmp = do_constant_folding(op, temps[args[1]].val, args[2]);
|
||||
tcg_opt_gen_movi(gen_args, args[0], tmp);
|
||||
gen_args += 2;
|
||||
args += 3;
|
||||
break;
|
||||
}
|
||||
goto do_default;
|
||||
|
||||
CASE_OP_32_64(add):
|
||||
CASE_OP_32_64(sub):
|
||||
CASE_OP_32_64(mul):
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user