Compare commits
259 Commits
v2.0.0-rc1
...
pull-vga-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a889bc2bb2 | ||
|
|
0850fd583f | ||
|
|
63e3e24db2 | ||
|
|
e2bbfc8ee2 | ||
|
|
411f491e0a | ||
|
|
7931b05987 | ||
|
|
0e96643c98 | ||
|
|
ad600a4d49 | ||
|
|
ba3627ec38 | ||
|
|
4b8abfb78e | ||
|
|
370e681629 | ||
|
|
840a178c94 | ||
|
|
9b17031ac4 | ||
|
|
ac1307abfe | ||
|
|
409951f552 | ||
|
|
90d9d30152 | ||
|
|
f2d953ec31 | ||
|
|
9ffe333276 | ||
|
|
98522f63f4 | ||
|
|
5ff679b47d | ||
|
|
636ea3708c | ||
|
|
acd7fdc6d8 | ||
|
|
b8afb520e4 | ||
|
|
4ab9dab5b9 | ||
|
|
9ce10c0bdc | ||
|
|
da15ee5134 | ||
|
|
1dd3a44753 | ||
|
|
54db38a479 | ||
|
|
02eb19d0ec | ||
|
|
662deb908f | ||
|
|
f46fc4e6a9 | ||
|
|
df9ebea53e | ||
|
|
671c835b7d | ||
|
|
4b304cfae1 | ||
|
|
1194dcba22 | ||
|
|
170bf9315b | ||
|
|
f6c6afc1d4 | ||
|
|
d998e555d2 | ||
|
|
1976cccec8 | ||
|
|
50c5c4d125 | ||
|
|
20022fa15f | ||
|
|
ad5171dbd4 | ||
|
|
b36dc67b95 | ||
|
|
9d85d55732 | ||
|
|
2300aed15d | ||
|
|
e40cdb0e6e | ||
|
|
968fc24d84 | ||
|
|
423d00c857 | ||
|
|
ee25595f01 | ||
|
|
86e117724a | ||
|
|
d61ce900b9 | ||
|
|
1634df567d | ||
|
|
b321afbefd | ||
|
|
0374f5089a | ||
|
|
3bf16cb31a | ||
|
|
4bdd547aaa | ||
|
|
af9fe31070 | ||
|
|
1f91f39219 | ||
|
|
b672cf66c3 | ||
|
|
4c186ee2cf | ||
|
|
dcf91778ca | ||
|
|
2d03b49c3f | ||
|
|
e44a90c596 | ||
|
|
33bbd75a7c | ||
|
|
5538937368 | ||
|
|
6954a1cd97 | ||
|
|
15e3611e1c | ||
|
|
db302f8f93 | ||
|
|
6619bc5c55 | ||
|
|
103db49a10 | ||
|
|
286226a479 | ||
|
|
a63f9f85e3 | ||
|
|
323a8771cf | ||
|
|
2237094d96 | ||
|
|
1c70aa6264 | ||
|
|
f727d0e621 | ||
|
|
b5cde1da0a | ||
|
|
177311157c | ||
|
|
7633378d5f | ||
|
|
c29f9a0a29 | ||
|
|
f318cec6ad | ||
|
|
377a44ec8f | ||
|
|
3933443e38 | ||
|
|
19525524a7 | ||
|
|
f32cdad55d | ||
|
|
9449fdf61f | ||
|
|
00a29f3ddc | ||
|
|
85acfa9c38 | ||
|
|
1090b9c6cc | ||
|
|
2eef0bf821 | ||
|
|
014406b510 | ||
|
|
0ff644a786 | ||
|
|
cb1fa941c1 | ||
|
|
a50c0f5133 | ||
|
|
52e60cdd34 | ||
|
|
2f2a00aec9 | ||
|
|
a65f1de982 | ||
|
|
f502cfc207 | ||
|
|
a0618a1990 | ||
|
|
6cd8a2649a | ||
|
|
7e09797c29 | ||
|
|
aca3f40b37 | ||
|
|
9225d739e7 | ||
|
|
2c8dd31863 | ||
|
|
2c7ffc414d | ||
|
|
90e496386f | ||
|
|
8c6afa6ab1 | ||
|
|
00892383c9 | ||
|
|
d4a2dc675b | ||
|
|
8bcbf37caa | ||
|
|
abf1172fc6 | ||
|
|
c2b820fe58 | ||
|
|
ccd380876b | ||
|
|
c6138aabfb | ||
|
|
5149e557d7 | ||
|
|
06ef8604e9 | ||
|
|
39acc64741 | ||
|
|
e566be049a | ||
|
|
8f811b9a4a | ||
|
|
a9e05a1ceb | ||
|
|
0e154fe92c | ||
|
|
ef3765cb95 | ||
|
|
e8d8fef48f | ||
|
|
6580935246 | ||
|
|
76bff4f82f | ||
|
|
e20b8c04a3 | ||
|
|
8b0190bbde | ||
|
|
f477ed3c11 | ||
|
|
cd2754addc | ||
|
|
3d045dbca5 | ||
|
|
baee04abba | ||
|
|
b144be9e06 | ||
|
|
5e5863ecf1 | ||
|
|
9a734d64f9 | ||
|
|
9a8fa1bdad | ||
|
|
83ebb7cd01 | ||
|
|
42774a56ec | ||
|
|
958683482c | ||
|
|
cd2d46fd21 | ||
|
|
595b8fdd54 | ||
|
|
a4af30447b | ||
|
|
46010969f3 | ||
|
|
c67b67e511 | ||
|
|
1eaa1da7e4 | ||
|
|
8f56ced8aa | ||
|
|
89fe090bb3 | ||
|
|
6b88b37c0e | ||
|
|
075b8ddb9b | ||
|
|
de4d3555fa | ||
|
|
3bd67b7dab | ||
|
|
db4a16458c | ||
|
|
194cfb43d5 | ||
|
|
64f45e4991 | ||
|
|
5238c88657 | ||
|
|
67debe3ae5 | ||
|
|
a9e8aeb375 | ||
|
|
b825025f08 | ||
|
|
a056c9faa4 | ||
|
|
3d4299f425 | ||
|
|
dc73dfd4bc | ||
|
|
edd8824cd4 | ||
|
|
e81864a109 | ||
|
|
de61d14fa7 | ||
|
|
667b1cdd4e | ||
|
|
9e4177ad6d | ||
|
|
dc0c8aaf2c | ||
|
|
ae7ab46aa8 | ||
|
|
6f4724672c | ||
|
|
38d195aa05 | ||
|
|
95f72aa90a | ||
|
|
d82b78e48b | ||
|
|
3d9e69a238 | ||
|
|
cae1f6f3e6 | ||
|
|
81d8a5ee19 | ||
|
|
c6e310d938 | ||
|
|
d8918df577 | ||
|
|
4ec4f0bd56 | ||
|
|
dfeb5fe770 | ||
|
|
929f8b5550 | ||
|
|
8bf56493f1 | ||
|
|
661f7fa4b0 | ||
|
|
851627352c | ||
|
|
50212d6346 | ||
|
|
c2b9af1d6c | ||
|
|
940973ae0b | ||
|
|
8611224a7b | ||
|
|
482f38b948 | ||
|
|
590e5dd98f | ||
|
|
f12d048a52 | ||
|
|
3c99afc779 | ||
|
|
9878d173f5 | ||
|
|
8c6c047899 | ||
|
|
92b3eeadd9 | ||
|
|
edc2438512 | ||
|
|
21e2db7260 | ||
|
|
80fc7b1755 | ||
|
|
5450466394 | ||
|
|
cd82b6fb4d | ||
|
|
715c3f60ef | ||
|
|
28ec11bc88 | ||
|
|
2d968ffbae | ||
|
|
afbc0dd649 | ||
|
|
f516a5cc05 | ||
|
|
0a9077ea14 | ||
|
|
775478418a | ||
|
|
50329d3418 | ||
|
|
efcc87d9ae | ||
|
|
7dc176bce4 | ||
|
|
9bc1a1d817 | ||
|
|
f2ccc311df | ||
|
|
093de72b9c | ||
|
|
800b0e814b | ||
|
|
9a4fb6aa19 | ||
|
|
e792933ce1 | ||
|
|
06f6e12491 | ||
|
|
6a2b3d89fa | ||
|
|
05edc26c61 | ||
|
|
e81a982aa5 | ||
|
|
6cd7db3d92 | ||
|
|
d1dec5ef55 | ||
|
|
6bbad7a91e | ||
|
|
50fc89e7b1 | ||
|
|
bcb7652e8d | ||
|
|
d359db00e6 | ||
|
|
80189035de | ||
|
|
0453099b7d | ||
|
|
a13d448968 | ||
|
|
3636226ae4 | ||
|
|
6a450df9b8 | ||
|
|
9854202b57 | ||
|
|
577a67234d | ||
|
|
55519a4b24 | ||
|
|
f85e3457ce | ||
|
|
9c269f6d7b | ||
|
|
dffacd4654 | ||
|
|
20c50a955f | ||
|
|
bd7ce902ab | ||
|
|
e20c016e32 | ||
|
|
dc491cfc14 | ||
|
|
25eccc37ff | ||
|
|
ecce1929bc | ||
|
|
e61031cdd8 | ||
|
|
0d0e044dee | ||
|
|
466e6e9d13 | ||
|
|
8ae60ee85c | ||
|
|
54bee5c2b4 | ||
|
|
8c2664d869 | ||
|
|
4d1cb6e6f5 | ||
|
|
f187743acd | ||
|
|
b998875dcf | ||
|
|
bae2c27090 | ||
|
|
cd7ccc8351 | ||
|
|
d097696eba | ||
|
|
3b418d0c45 | ||
|
|
cd40890816 | ||
|
|
e3fa4bfa72 | ||
|
|
8885eadedd | ||
|
|
4c2e5f8f46 | ||
|
|
cbee81f6de |
@@ -717,7 +717,8 @@ F: hw/display/qxl*
|
|||||||
|
|
||||||
Graphics
|
Graphics
|
||||||
M: Anthony Liguori <aliguori@amazon.com>
|
M: Anthony Liguori <aliguori@amazon.com>
|
||||||
S: Maintained
|
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
S: Odd Fixes
|
||||||
F: ui/
|
F: ui/
|
||||||
|
|
||||||
Cocoa graphics
|
Cocoa graphics
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -133,6 +133,7 @@ dummy := $(call unnest-vars,, \
|
|||||||
stub-obj-y \
|
stub-obj-y \
|
||||||
util-obj-y \
|
util-obj-y \
|
||||||
qga-obj-y \
|
qga-obj-y \
|
||||||
|
qga-vss-dll-obj-y \
|
||||||
block-obj-y \
|
block-obj-y \
|
||||||
block-obj-m \
|
block-obj-m \
|
||||||
common-obj-y \
|
common-obj-y \
|
||||||
@@ -376,7 +377,7 @@ endif
|
|||||||
ifneq ($(CONFIG_MODULES),)
|
ifneq ($(CONFIG_MODULES),)
|
||||||
$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
|
$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
|
||||||
for s in $(patsubst %.mo,%$(DSOSUF),$(modules-m)); do \
|
for s in $(patsubst %.mo,%$(DSOSUF),$(modules-m)); do \
|
||||||
$(INSTALL_PROG) $(STRIP_OPT) $$s "$(DESTDIR)$(qemu_moddir)/$${s//\//-}"; \
|
$(INSTALL_PROG) $(STRIP_OPT) $$s "$(DESTDIR)$(qemu_moddir)/$$(echo $$s | tr / -)"; \
|
||||||
done
|
done
|
||||||
endif
|
endif
|
||||||
ifneq ($(HELPERS-y),)
|
ifneq ($(HELPERS-y),)
|
||||||
|
|||||||
@@ -310,13 +310,28 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
|
|||||||
|
|
||||||
/* Called with iothread lock taken. */
|
/* Called with iothread lock taken. */
|
||||||
|
|
||||||
static void set_dirty_tracking(void)
|
static int set_dirty_tracking(void)
|
||||||
{
|
{
|
||||||
BlkMigDevState *bmds;
|
BlkMigDevState *bmds;
|
||||||
|
int ret;
|
||||||
|
|
||||||
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
||||||
bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE);
|
bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,
|
||||||
|
NULL);
|
||||||
|
if (!bmds->dirty_bitmap) {
|
||||||
|
ret = -errno;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
||||||
|
if (bmds->dirty_bitmap) {
|
||||||
|
bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unset_dirty_tracking(void)
|
static void unset_dirty_tracking(void)
|
||||||
@@ -611,10 +626,17 @@ static int block_save_setup(QEMUFile *f, void *opaque)
|
|||||||
block_mig_state.submitted, block_mig_state.transferred);
|
block_mig_state.submitted, block_mig_state.transferred);
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
init_blk_migration(f);
|
|
||||||
|
|
||||||
/* start track dirty blocks */
|
/* start track dirty blocks */
|
||||||
set_dirty_tracking();
|
ret = set_dirty_tracking();
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_blk_migration(f);
|
||||||
|
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
ret = flush_blks(f);
|
ret = flush_blks(f);
|
||||||
|
|||||||
228
block.c
228
block.c
@@ -332,10 +332,21 @@ void bdrv_register(BlockDriver *bdrv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create a new block device (by default it is empty) */
|
/* create a new block device (by default it is empty) */
|
||||||
BlockDriverState *bdrv_new(const char *device_name)
|
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
|
||||||
|
if (bdrv_find(device_name)) {
|
||||||
|
error_setg(errp, "Device with id '%s' already exists",
|
||||||
|
device_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (bdrv_find_node(device_name)) {
|
||||||
|
error_setg(errp, "Device with node-name '%s' already exists",
|
||||||
|
device_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bs = g_malloc0(sizeof(BlockDriverState));
|
bs = g_malloc0(sizeof(BlockDriverState));
|
||||||
QLIST_INIT(&bs->dirty_bitmaps);
|
QLIST_INIT(&bs->dirty_bitmaps);
|
||||||
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
|
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
|
||||||
@@ -767,6 +778,11 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
|||||||
{
|
{
|
||||||
int open_flags = flags | BDRV_O_CACHE_WB;
|
int open_flags = flags | BDRV_O_CACHE_WB;
|
||||||
|
|
||||||
|
/* The backing file of a temporary snapshot is read-only */
|
||||||
|
if (flags & BDRV_O_SNAPSHOT) {
|
||||||
|
open_flags &= ~BDRV_O_RDWR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear flags that are internal to the block layer before opening the
|
* Clear flags that are internal to the block layer before opening the
|
||||||
* image.
|
* image.
|
||||||
@@ -783,38 +799,36 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
|||||||
return open_flags;
|
return open_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdrv_assign_node_name(BlockDriverState *bs,
|
static void bdrv_assign_node_name(BlockDriverState *bs,
|
||||||
const char *node_name,
|
const char *node_name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (!node_name) {
|
if (!node_name) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* empty string node name is invalid */
|
/* empty string node name is invalid */
|
||||||
if (node_name[0] == '\0') {
|
if (node_name[0] == '\0') {
|
||||||
error_setg(errp, "Empty node name");
|
error_setg(errp, "Empty node name");
|
||||||
return -EINVAL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* takes care of avoiding namespaces collisions */
|
/* takes care of avoiding namespaces collisions */
|
||||||
if (bdrv_find(node_name)) {
|
if (bdrv_find(node_name)) {
|
||||||
error_setg(errp, "node-name=%s is conflicting with a device id",
|
error_setg(errp, "node-name=%s is conflicting with a device id",
|
||||||
node_name);
|
node_name);
|
||||||
return -EINVAL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* takes care of avoiding duplicates node names */
|
/* takes care of avoiding duplicates node names */
|
||||||
if (bdrv_find_node(node_name)) {
|
if (bdrv_find_node(node_name)) {
|
||||||
error_setg(errp, "Duplicate node name");
|
error_setg(errp, "Duplicate node name");
|
||||||
return -EINVAL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy node name into the bs and insert it into the graph list */
|
/* copy node name into the bs and insert it into the graph list */
|
||||||
pstrcpy(bs->node_name, sizeof(bs->node_name), node_name);
|
pstrcpy(bs->node_name, sizeof(bs->node_name), node_name);
|
||||||
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs, node_list);
|
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs, node_list);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -849,9 +863,10 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
|
trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
|
||||||
|
|
||||||
node_name = qdict_get_try_str(options, "node-name");
|
node_name = qdict_get_try_str(options, "node-name");
|
||||||
ret = bdrv_assign_node_name(bs, node_name, errp);
|
bdrv_assign_node_name(bs, node_name, &local_err);
|
||||||
if (ret < 0) {
|
if (error_is_set(&local_err)) {
|
||||||
return ret;
|
error_propagate(errp, local_err);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
qdict_del(options, "node-name");
|
qdict_del(options, "node-name");
|
||||||
|
|
||||||
@@ -968,7 +983,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
|||||||
{
|
{
|
||||||
BlockDriver *drv;
|
BlockDriver *drv;
|
||||||
const char *drvname;
|
const char *drvname;
|
||||||
bool allow_protocol_prefix = false;
|
bool parse_filename = false;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -977,7 +992,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
|||||||
filename = qdict_get_try_str(*options, "filename");
|
filename = qdict_get_try_str(*options, "filename");
|
||||||
} else if (filename && !qdict_haskey(*options, "filename")) {
|
} else if (filename && !qdict_haskey(*options, "filename")) {
|
||||||
qdict_put(*options, "filename", qstring_from_str(filename));
|
qdict_put(*options, "filename", qstring_from_str(filename));
|
||||||
allow_protocol_prefix = true;
|
parse_filename = true;
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Can't specify 'file' and 'filename' options at the "
|
error_setg(errp, "Can't specify 'file' and 'filename' options at the "
|
||||||
"same time");
|
"same time");
|
||||||
@@ -994,7 +1009,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
|||||||
}
|
}
|
||||||
qdict_del(*options, "driver");
|
qdict_del(*options, "driver");
|
||||||
} else if (filename) {
|
} else if (filename) {
|
||||||
drv = bdrv_find_protocol(filename, allow_protocol_prefix);
|
drv = bdrv_find_protocol(filename, parse_filename);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
error_setg(errp, "Unknown protocol");
|
error_setg(errp, "Unknown protocol");
|
||||||
}
|
}
|
||||||
@@ -1010,7 +1025,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the filename and open it */
|
/* Parse the filename and open it */
|
||||||
if (drv->bdrv_parse_filename && filename) {
|
if (drv->bdrv_parse_filename && parse_filename) {
|
||||||
drv->bdrv_parse_filename(filename, *options, &local_err);
|
drv->bdrv_parse_filename(filename, *options, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
@@ -1162,6 +1177,73 @@ done:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
int64_t total_size;
|
||||||
|
BlockDriver *bdrv_qcow2;
|
||||||
|
QEMUOptionParameter *create_options;
|
||||||
|
QDict *snapshot_options;
|
||||||
|
BlockDriverState *bs_snapshot;
|
||||||
|
Error *local_err;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* if snapshot, we create a temporary backing file and open it
|
||||||
|
instead of opening 'filename' directly */
|
||||||
|
|
||||||
|
/* Get the required size from the image */
|
||||||
|
total_size = bdrv_getlength(bs);
|
||||||
|
if (total_size < 0) {
|
||||||
|
error_setg_errno(errp, -total_size, "Could not get image size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
total_size &= BDRV_SECTOR_MASK;
|
||||||
|
|
||||||
|
/* Create the temporary image */
|
||||||
|
ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Could not get temporary filename");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdrv_qcow2 = bdrv_find_format("qcow2");
|
||||||
|
create_options = parse_option_parameters("", bdrv_qcow2->create_options,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
|
||||||
|
|
||||||
|
ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
|
||||||
|
free_option_parameters(create_options);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Could not create temporary overlay "
|
||||||
|
"'%s': %s", tmp_filename,
|
||||||
|
error_get_pretty(local_err));
|
||||||
|
error_free(local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare a new options QDict for the temporary file */
|
||||||
|
snapshot_options = qdict_new();
|
||||||
|
qdict_put(snapshot_options, "file.driver",
|
||||||
|
qstring_from_str("file"));
|
||||||
|
qdict_put(snapshot_options, "file.filename",
|
||||||
|
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);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdrv_append(bs_snapshot, bs);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opens a disk image (raw, qcow2, vmdk, ...)
|
* Opens a disk image (raw, qcow2, vmdk, ...)
|
||||||
*
|
*
|
||||||
@@ -1182,8 +1264,6 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
BlockDriver *drv, Error **errp)
|
BlockDriver *drv, Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
|
|
||||||
char tmp_filename[PATH_MAX + 1];
|
|
||||||
BlockDriverState *file = NULL, *bs;
|
BlockDriverState *file = NULL, *bs;
|
||||||
const char *drvname;
|
const char *drvname;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@@ -1218,7 +1298,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
if (*pbs) {
|
if (*pbs) {
|
||||||
bs = *pbs;
|
bs = *pbs;
|
||||||
} else {
|
} else {
|
||||||
bs = bdrv_new("");
|
bs = bdrv_new("", &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NULL means an empty set of options */
|
/* NULL means an empty set of options */
|
||||||
@@ -1243,74 +1323,6 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For snapshot=on, create a temporary qcow2 overlay */
|
|
||||||
if (flags & BDRV_O_SNAPSHOT) {
|
|
||||||
BlockDriverState *bs1;
|
|
||||||
int64_t total_size;
|
|
||||||
BlockDriver *bdrv_qcow2;
|
|
||||||
QEMUOptionParameter *create_options;
|
|
||||||
QDict *snapshot_options;
|
|
||||||
|
|
||||||
/* if snapshot, we create a temporary backing file and open it
|
|
||||||
instead of opening 'filename' directly */
|
|
||||||
|
|
||||||
/* Get the required size from the image */
|
|
||||||
QINCREF(options);
|
|
||||||
bs1 = NULL;
|
|
||||||
ret = bdrv_open(&bs1, filename, NULL, options, BDRV_O_NO_BACKING,
|
|
||||||
drv, &local_err);
|
|
||||||
if (ret < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
|
|
||||||
|
|
||||||
bdrv_unref(bs1);
|
|
||||||
|
|
||||||
/* Create the temporary image */
|
|
||||||
ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
|
|
||||||
if (ret < 0) {
|
|
||||||
error_setg_errno(errp, -ret, "Could not get temporary filename");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
bdrv_qcow2 = bdrv_find_format("qcow2");
|
|
||||||
create_options = parse_option_parameters("", bdrv_qcow2->create_options,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
|
|
||||||
|
|
||||||
ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
|
|
||||||
free_option_parameters(create_options);
|
|
||||||
if (ret < 0) {
|
|
||||||
error_setg_errno(errp, -ret, "Could not create temporary overlay "
|
|
||||||
"'%s': %s", tmp_filename,
|
|
||||||
error_get_pretty(local_err));
|
|
||||||
error_free(local_err);
|
|
||||||
local_err = NULL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare a new options QDict for the temporary file, where user
|
|
||||||
* options refer to the backing file */
|
|
||||||
if (filename) {
|
|
||||||
qdict_put(options, "file.filename", qstring_from_str(filename));
|
|
||||||
}
|
|
||||||
if (drv) {
|
|
||||||
qdict_put(options, "driver", qstring_from_str(drv->format_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
snapshot_options = qdict_new();
|
|
||||||
qdict_put(snapshot_options, "backing", options);
|
|
||||||
qdict_flatten(snapshot_options);
|
|
||||||
|
|
||||||
bs->options = snapshot_options;
|
|
||||||
options = qdict_clone_shallow(bs->options);
|
|
||||||
|
|
||||||
filename = tmp_filename;
|
|
||||||
drv = bdrv_qcow2;
|
|
||||||
bs->is_temporary = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open image file without format layer */
|
/* Open image file without format layer */
|
||||||
if (flags & BDRV_O_RDWR) {
|
if (flags & BDRV_O_RDWR) {
|
||||||
flags |= BDRV_O_ALLOW_RDWR;
|
flags |= BDRV_O_ALLOW_RDWR;
|
||||||
@@ -1372,6 +1384,17 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For snapshot=on, create a temporary qcow2 overlay. bs points to the
|
||||||
|
* temporary snapshot afterwards. */
|
||||||
|
if (flags & BDRV_O_SNAPSHOT) {
|
||||||
|
bdrv_append_temp_snapshot(bs, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
goto close_and_fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* Check if any unknown options were used */
|
/* Check if any unknown options were used */
|
||||||
if (options && (qdict_size(options) != 0)) {
|
if (options && (qdict_size(options) != 0)) {
|
||||||
@@ -2568,6 +2591,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
|||||||
{
|
{
|
||||||
int64_t len;
|
int64_t len;
|
||||||
|
|
||||||
|
if (size > INT_MAX) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (!bdrv_is_inserted(bs))
|
if (!bdrv_is_inserted(bs))
|
||||||
return -ENOMEDIUM;
|
return -ENOMEDIUM;
|
||||||
|
|
||||||
@@ -2588,7 +2615,7 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
|||||||
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
||||||
int nb_sectors)
|
int nb_sectors)
|
||||||
{
|
{
|
||||||
if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2673,6 +2700,10 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
|||||||
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||||
return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
|
return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
|
||||||
&qiov, is_write, flags);
|
&qiov, is_write, flags);
|
||||||
@@ -2728,10 +2759,16 @@ int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
|||||||
*/
|
*/
|
||||||
int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
int64_t target_size = bdrv_getlength(bs) / BDRV_SECTOR_SIZE;
|
int64_t target_size;
|
||||||
int64_t ret, nb_sectors, sector_num = 0;
|
int64_t ret, nb_sectors, sector_num = 0;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
target_size = bdrv_getlength(bs);
|
||||||
|
if (target_size < 0) {
|
||||||
|
return target_size;
|
||||||
|
}
|
||||||
|
target_size /= BDRV_SECTOR_SIZE;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
nb_sectors = target_size - sector_num;
|
nb_sectors = target_size - sector_num;
|
||||||
if (nb_sectors <= 0) {
|
if (nb_sectors <= 0) {
|
||||||
@@ -5083,7 +5120,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
|
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int64_t bitmap_size;
|
int64_t bitmap_size;
|
||||||
BdrvDirtyBitmap *bitmap;
|
BdrvDirtyBitmap *bitmap;
|
||||||
@@ -5092,7 +5130,13 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
|
|||||||
|
|
||||||
granularity >>= BDRV_SECTOR_BITS;
|
granularity >>= BDRV_SECTOR_BITS;
|
||||||
assert(granularity);
|
assert(granularity);
|
||||||
bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
|
bitmap_size = bdrv_getlength(bs);
|
||||||
|
if (bitmap_size < 0) {
|
||||||
|
error_setg_errno(errp, -bitmap_size, "could not get length of device");
|
||||||
|
errno = -bitmap_size;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bitmap_size >>= BDRV_SECTOR_BITS;
|
||||||
bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
|
bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
|
||||||
bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
|
bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
|
||||||
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
||||||
|
|||||||
@@ -148,16 +148,26 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
|
s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
|
||||||
|
|
||||||
s->extent_size = le32_to_cpu(bochs.extent);
|
s->extent_size = le32_to_cpu(bochs.extent);
|
||||||
if (s->extent_size == 0) {
|
if (s->extent_size < BDRV_SECTOR_SIZE) {
|
||||||
error_setg(errp, "Extent size may not be zero");
|
/* bximage actually never creates extents smaller than 4k */
|
||||||
return -EINVAL;
|
error_setg(errp, "Extent size must be at least 512");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
} else if (!is_power_of_2(s->extent_size)) {
|
||||||
|
error_setg(errp, "Extent size %" PRIu32 " is not a power of two",
|
||||||
|
s->extent_size);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
} else if (s->extent_size > 0x800000) {
|
} else if (s->extent_size > 0x800000) {
|
||||||
error_setg(errp, "Extent size %" PRIu32 " is too large",
|
error_setg(errp, "Extent size %" PRIu32 " is too large",
|
||||||
s->extent_size);
|
s->extent_size);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->catalog_size < bs->total_sectors / s->extent_size) {
|
if (s->catalog_size < DIV_ROUND_UP(bs->total_sectors,
|
||||||
|
s->extent_size / BDRV_SECTOR_SIZE))
|
||||||
|
{
|
||||||
error_setg(errp, "Catalog size is too small for this disk size");
|
error_setg(errp, "Catalog size is too small for this disk size");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
}
|
}
|
||||||
s->block_size = be32_to_cpu(s->block_size);
|
s->block_size = be32_to_cpu(s->block_size);
|
||||||
if (s->block_size % 512) {
|
if (s->block_size % 512) {
|
||||||
error_setg(errp, "block_size %u must be a multiple of 512",
|
error_setg(errp, "block_size %" PRIu32 " must be a multiple of 512",
|
||||||
s->block_size);
|
s->block_size);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
* need a buffer this big.
|
* need a buffer this big.
|
||||||
*/
|
*/
|
||||||
if (s->block_size > MAX_BLOCK_SIZE) {
|
if (s->block_size > MAX_BLOCK_SIZE) {
|
||||||
error_setg(errp, "block_size %u must be %u MB or less",
|
error_setg(errp, "block_size %" PRIu32 " must be %u MB or less",
|
||||||
s->block_size,
|
s->block_size,
|
||||||
MAX_BLOCK_SIZE / (1024 * 1024));
|
MAX_BLOCK_SIZE / (1024 * 1024));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -101,7 +101,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
/* read offsets */
|
/* read offsets */
|
||||||
if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
|
if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
|
||||||
/* Prevent integer overflow */
|
/* Prevent integer overflow */
|
||||||
error_setg(errp, "n_blocks %u must be %zu or less",
|
error_setg(errp, "n_blocks %" PRIu32 " must be %zu or less",
|
||||||
s->n_blocks,
|
s->n_blocks,
|
||||||
(UINT32_MAX - 1) / sizeof(uint64_t));
|
(UINT32_MAX - 1) / sizeof(uint64_t));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -133,7 +133,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
if (s->offsets[i] < s->offsets[i - 1]) {
|
if (s->offsets[i] < s->offsets[i - 1]) {
|
||||||
error_setg(errp, "offsets not monotonically increasing at "
|
error_setg(errp, "offsets not monotonically increasing at "
|
||||||
"index %u, image file is corrupt", i);
|
"index %" PRIu32 ", image file is corrupt", i);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -146,8 +146,8 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
* ridiculous s->compressed_block allocation.
|
* ridiculous s->compressed_block allocation.
|
||||||
*/
|
*/
|
||||||
if (size > 2 * MAX_BLOCK_SIZE) {
|
if (size > 2 * MAX_BLOCK_SIZE) {
|
||||||
error_setg(errp, "invalid compressed block size at index %u, "
|
error_setg(errp, "invalid compressed block size at index %" PRIu32
|
||||||
"image file is corrupt", i);
|
", image file is corrupt", i);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -543,7 +543,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
fprintf(stderr, "CURL: Error opening file: %s\n", state->errmsg);
|
error_setg(errp, "CURL: Error opening file: %s", state->errmsg);
|
||||||
curl_easy_cleanup(state->curl);
|
curl_easy_cleanup(state->curl);
|
||||||
state->curl = NULL;
|
state->curl = NULL;
|
||||||
out_noclean:
|
out_noclean:
|
||||||
|
|||||||
@@ -1101,8 +1101,10 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
|
|||||||
return task;
|
return task;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
error_setg(errp, "iSCSI: Inquiry command failed : %s",
|
if (!error_is_set(errp)) {
|
||||||
iscsi_get_error(iscsi));
|
error_setg(errp, "iSCSI: Inquiry command failed : %s",
|
||||||
|
iscsi_get_error(iscsi));
|
||||||
|
}
|
||||||
if (task != NULL) {
|
if (task != NULL) {
|
||||||
scsi_free_scsi_task(task);
|
scsi_free_scsi_task(task);
|
||||||
}
|
}
|
||||||
@@ -1231,6 +1233,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
iscsi_readcapacity_sync(iscsilun, &local_err);
|
iscsi_readcapacity_sync(iscsilun, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
|
bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
|
||||||
@@ -1398,7 +1401,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
IscsiLun *iscsilun = NULL;
|
IscsiLun *iscsilun = NULL;
|
||||||
QDict *bs_options;
|
QDict *bs_options;
|
||||||
|
|
||||||
bs = bdrv_new("");
|
bs = bdrv_new("", &error_abort);
|
||||||
|
|
||||||
/* Read out options */
|
/* Read out options */
|
||||||
while (options && options->name) {
|
while (options && options->name) {
|
||||||
|
|||||||
@@ -605,7 +605,10 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
|
|||||||
s->granularity = granularity;
|
s->granularity = granularity;
|
||||||
s->buf_size = MAX(buf_size, granularity);
|
s->buf_size = MAX(buf_size, granularity);
|
||||||
|
|
||||||
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity);
|
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, errp);
|
||||||
|
if (!s->dirty_bitmap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
bdrv_set_enable_write_cache(s->target, true);
|
bdrv_set_enable_write_cache(s->target, true);
|
||||||
bdrv_set_on_error(s->target, on_target_error, on_target_error);
|
bdrv_set_on_error(s->target, on_target_error, on_target_error);
|
||||||
bdrv_iostatus_enable(s->target);
|
bdrv_iostatus_enable(s->target);
|
||||||
|
|||||||
@@ -491,6 +491,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
|||||||
break;
|
break;
|
||||||
case QCOW2_CLUSTER_ZERO:
|
case QCOW2_CLUSTER_ZERO:
|
||||||
if (s->qcow_version < 3) {
|
if (s->qcow_version < 3) {
|
||||||
|
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
|
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
|
||||||
|
|||||||
@@ -269,12 +269,15 @@ static int qcow2_mark_clean(BlockDriverState *bs)
|
|||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
|
|
||||||
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
|
if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
|
||||||
int ret = bdrv_flush(bs);
|
int ret;
|
||||||
|
|
||||||
|
s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY;
|
||||||
|
|
||||||
|
ret = bdrv_flush(bs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY;
|
|
||||||
return qcow2_update_header(bs);
|
return qcow2_update_header(bs);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -900,11 +903,25 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have nothing to do for QCOW2 reopen, stubs just return
|
/* We have no actual commit/abort logic for qcow2, but we need to write out any
|
||||||
* success */
|
* unwritten data if we reopen read-only. */
|
||||||
static int qcow2_reopen_prepare(BDRVReopenState *state,
|
static int qcow2_reopen_prepare(BDRVReopenState *state,
|
||||||
BlockReopenQueue *queue, Error **errp)
|
BlockReopenQueue *queue, Error **errp)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((state->flags & BDRV_O_RDWR) == 0) {
|
||||||
|
ret = bdrv_flush(state->bs);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = qcow2_mark_clean(state->bs);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
block/qed.c
16
block/qed.c
@@ -650,19 +650,21 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!qed_is_cluster_size_valid(cluster_size)) {
|
if (!qed_is_cluster_size_valid(cluster_size)) {
|
||||||
fprintf(stderr, "QED cluster size must be within range [%u, %u] and power of 2\n",
|
error_setg(errp, "QED cluster size must be within range [%u, %u] "
|
||||||
QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
|
"and power of 2",
|
||||||
|
QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!qed_is_table_size_valid(table_size)) {
|
if (!qed_is_table_size_valid(table_size)) {
|
||||||
fprintf(stderr, "QED table size must be within range [%u, %u] and power of 2\n",
|
error_setg(errp, "QED table size must be within range [%u, %u] "
|
||||||
QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
|
"and power of 2",
|
||||||
|
QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) {
|
if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) {
|
||||||
fprintf(stderr, "QED image size must be a non-zero multiple of "
|
error_setg(errp, "QED image size must be a non-zero multiple of "
|
||||||
"cluster size and less than %" PRIu64 " bytes\n",
|
"cluster size and less than %" PRIu64 " bytes",
|
||||||
qed_max_image_size(cluster_size, table_size));
|
qed_max_image_size(cluster_size, table_size));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
block/vmdk.c
23
block/vmdk.c
@@ -262,7 +262,7 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
|
|||||||
p_name = strstr(desc, cid_str);
|
p_name = strstr(desc, cid_str);
|
||||||
if (p_name != NULL) {
|
if (p_name != NULL) {
|
||||||
p_name += cid_str_size;
|
p_name += cid_str_size;
|
||||||
sscanf(p_name, "%x", &cid);
|
sscanf(p_name, "%" SCNx32, &cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cid;
|
return cid;
|
||||||
@@ -290,7 +290,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
|||||||
p_name = strstr(desc, "CID");
|
p_name = strstr(desc, "CID");
|
||||||
if (p_name != NULL) {
|
if (p_name != NULL) {
|
||||||
p_name += sizeof("CID");
|
p_name += sizeof("CID");
|
||||||
snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
|
snprintf(p_name, sizeof(desc) - (p_name - desc), "%" PRIx32 "\n", cid);
|
||||||
pstrcat(desc, sizeof(desc), tmp_desc);
|
pstrcat(desc, sizeof(desc), tmp_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +640,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|||||||
|
|
||||||
if (le32_to_cpu(header.version) > 3) {
|
if (le32_to_cpu(header.version) > 3) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
snprintf(buf, sizeof(buf), "VMDK version %d",
|
snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
|
||||||
le32_to_cpu(header.version));
|
le32_to_cpu(header.version));
|
||||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||||
bs->device_name, "vmdk", buf);
|
bs->device_name, "vmdk", buf);
|
||||||
@@ -671,8 +671,9 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
if (bdrv_getlength(file) <
|
if (bdrv_getlength(file) <
|
||||||
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) {
|
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) {
|
||||||
error_setg(errp, "File truncated, expecting at least %lld bytes",
|
error_setg(errp, "File truncated, expecting at least %" PRId64 " bytes",
|
||||||
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE);
|
(int64_t)(le64_to_cpu(header.grain_offset)
|
||||||
|
* BDRV_SECTOR_SIZE));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,8 +1708,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
const char desc_template[] =
|
const char desc_template[] =
|
||||||
"# Disk DescriptorFile\n"
|
"# Disk DescriptorFile\n"
|
||||||
"version=1\n"
|
"version=1\n"
|
||||||
"CID=%x\n"
|
"CID=%" PRIx32 "\n"
|
||||||
"parentCID=%x\n"
|
"parentCID=%" PRIx32 "\n"
|
||||||
"createType=\"%s\"\n"
|
"createType=\"%s\"\n"
|
||||||
"%s"
|
"%s"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -1720,7 +1721,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
"\n"
|
"\n"
|
||||||
"ddb.virtualHWVersion = \"%d\"\n"
|
"ddb.virtualHWVersion = \"%d\"\n"
|
||||||
"ddb.geometry.cylinders = \"%" PRId64 "\"\n"
|
"ddb.geometry.cylinders = \"%" PRId64 "\"\n"
|
||||||
"ddb.geometry.heads = \"%d\"\n"
|
"ddb.geometry.heads = \"%" PRIu32 "\"\n"
|
||||||
"ddb.geometry.sectors = \"63\"\n"
|
"ddb.geometry.sectors = \"63\"\n"
|
||||||
"ddb.adapterType = \"%s\"\n";
|
"ddb.adapterType = \"%s\"\n";
|
||||||
|
|
||||||
@@ -1780,9 +1781,9 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
strcmp(fmt, "twoGbMaxExtentFlat"));
|
strcmp(fmt, "twoGbMaxExtentFlat"));
|
||||||
compress = !strcmp(fmt, "streamOptimized");
|
compress = !strcmp(fmt, "streamOptimized");
|
||||||
if (flat) {
|
if (flat) {
|
||||||
desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
|
desc_extent_line = "RW %" PRId64 " FLAT \"%s\" 0\n";
|
||||||
} else {
|
} else {
|
||||||
desc_extent_line = "RW %lld SPARSE \"%s\"\n";
|
desc_extent_line = "RW %" PRId64 " SPARSE \"%s\"\n";
|
||||||
}
|
}
|
||||||
if (flat && backing_file) {
|
if (flat && backing_file) {
|
||||||
error_setg(errp, "Flat image can't have backing file");
|
error_setg(errp, "Flat image can't have backing file");
|
||||||
@@ -1850,7 +1851,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||||||
}
|
}
|
||||||
/* generate descriptor file */
|
/* generate descriptor file */
|
||||||
desc = g_strdup_printf(desc_template,
|
desc = g_strdup_printf(desc_template,
|
||||||
(unsigned int)time(NULL),
|
(uint32_t)time(NULL),
|
||||||
parent_cid,
|
parent_cid,
|
||||||
fmt,
|
fmt,
|
||||||
parent_desc_line,
|
parent_desc_line,
|
||||||
|
|||||||
@@ -2947,7 +2947,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
|||||||
unlink(s->qcow_filename);
|
unlink(s->qcow_filename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s->bs->backing_hd = bdrv_new("");
|
s->bs->backing_hd = bdrv_new("", &error_abort);
|
||||||
s->bs->backing_hd->drv = &vvfat_write_target;
|
s->bs->backing_hd->drv = &vvfat_write_target;
|
||||||
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
|
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
|
||||||
*(void**)s->bs->backing_hd->opaque = s;
|
*(void**)s->bs->backing_hd->opaque = s;
|
||||||
|
|||||||
19
blockdev.c
19
blockdev.c
@@ -452,16 +452,14 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_find_node(qemu_opts_id(opts))) {
|
|
||||||
error_setg(errp, "device id=%s is conflicting with a node-name",
|
|
||||||
qemu_opts_id(opts));
|
|
||||||
goto early_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
dinfo = g_malloc0(sizeof(*dinfo));
|
dinfo = g_malloc0(sizeof(*dinfo));
|
||||||
dinfo->id = g_strdup(qemu_opts_id(opts));
|
dinfo->id = g_strdup(qemu_opts_id(opts));
|
||||||
dinfo->bdrv = bdrv_new(dinfo->id);
|
dinfo->bdrv = bdrv_new(dinfo->id, &error);
|
||||||
|
if (error) {
|
||||||
|
error_propagate(errp, error);
|
||||||
|
goto bdrv_new_err;
|
||||||
|
}
|
||||||
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
|
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
|
||||||
dinfo->bdrv->read_only = ro;
|
dinfo->bdrv->read_only = ro;
|
||||||
dinfo->refcount = 1;
|
dinfo->refcount = 1;
|
||||||
@@ -523,8 +521,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
bdrv_unref(dinfo->bdrv);
|
bdrv_unref(dinfo->bdrv);
|
||||||
g_free(dinfo->id);
|
|
||||||
QTAILQ_REMOVE(&drives, dinfo, next);
|
QTAILQ_REMOVE(&drives, dinfo, next);
|
||||||
|
bdrv_new_err:
|
||||||
|
g_free(dinfo->id);
|
||||||
g_free(dinfo);
|
g_free(dinfo);
|
||||||
early_err:
|
early_err:
|
||||||
QDECREF(bs_opts);
|
QDECREF(bs_opts);
|
||||||
@@ -1876,6 +1875,10 @@ void qmp_block_commit(const char *device,
|
|||||||
*/
|
*/
|
||||||
BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
|
BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
|
|
||||||
|
if (!has_speed) {
|
||||||
|
speed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* drain all i/o before commits */
|
/* drain all i/o before commits */
|
||||||
bdrv_drain_all();
|
bdrv_drain_all();
|
||||||
|
|
||||||
|
|||||||
10
configure
vendored
10
configure
vendored
@@ -1217,8 +1217,8 @@ Advanced options (experts only):
|
|||||||
--enable-modules enable modules support
|
--enable-modules enable modules support
|
||||||
--enable-debug-tcg enable TCG debugging
|
--enable-debug-tcg enable TCG debugging
|
||||||
--disable-debug-tcg disable TCG debugging (default)
|
--disable-debug-tcg disable TCG debugging (default)
|
||||||
--enable-debug-info enable debugging information (default)
|
--enable-debug-info enable debugging information (default)
|
||||||
--disable-debug-info disable debugging information
|
--disable-debug-info disable debugging information
|
||||||
--enable-debug enable common debug build options
|
--enable-debug enable common debug build options
|
||||||
--enable-sparse enable sparse checker
|
--enable-sparse enable sparse checker
|
||||||
--disable-sparse disable sparse checker (default)
|
--disable-sparse disable sparse checker (default)
|
||||||
@@ -1448,7 +1448,10 @@ done
|
|||||||
if test "$stack_protector" != "no" ; then
|
if test "$stack_protector" != "no" ; then
|
||||||
gcc_flags="-fstack-protector-strong -fstack-protector-all"
|
gcc_flags="-fstack-protector-strong -fstack-protector-all"
|
||||||
for flag in $gcc_flags; do
|
for flag in $gcc_flags; do
|
||||||
if compile_prog "-Werror $flag" "" ; then
|
# We need to check both a compile and a link, since some compiler
|
||||||
|
# setups fail only on a .c->.o compile and some only at link time
|
||||||
|
if do_cc $QEMU_CFLAGS -Werror $flag -c -o $TMPO $TMPC &&
|
||||||
|
compile_prog "-Werror $flag" ""; then
|
||||||
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
|
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
|
||||||
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
|
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
|
||||||
break
|
break
|
||||||
@@ -4092,7 +4095,6 @@ echo "sparse enabled $sparse"
|
|||||||
echo "strip binaries $strip_opt"
|
echo "strip binaries $strip_opt"
|
||||||
echo "profiler $profiler"
|
echo "profiler $profiler"
|
||||||
echo "static build $static"
|
echo "static build $static"
|
||||||
echo "-Werror enabled $werror"
|
|
||||||
if test "$darwin" = "yes" ; then
|
if test "$darwin" = "yes" ; then
|
||||||
echo "Cocoa support $cocoa"
|
echo "Cocoa support $cocoa"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ int cpu_exec(CPUArchState *env)
|
|||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
uint8_t *tc_ptr;
|
uint8_t *tc_ptr;
|
||||||
uintptr_t next_tb;
|
uintptr_t next_tb;
|
||||||
|
/* This must be volatile so it is not trashed by longjmp() */
|
||||||
|
volatile bool have_tb_lock = false;
|
||||||
|
|
||||||
if (cpu->halted) {
|
if (cpu->halted) {
|
||||||
if (!cpu_has_work(cpu)) {
|
if (!cpu_has_work(cpu)) {
|
||||||
@@ -600,6 +602,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
spin_lock(&tcg_ctx.tb_ctx.tb_lock);
|
spin_lock(&tcg_ctx.tb_ctx.tb_lock);
|
||||||
|
have_tb_lock = true;
|
||||||
tb = tb_find_fast(env);
|
tb = tb_find_fast(env);
|
||||||
/* Note: we do it here to avoid a gcc bug on Mac OS X when
|
/* Note: we do it here to avoid a gcc bug on Mac OS X when
|
||||||
doing it in tb_find_slow */
|
doing it in tb_find_slow */
|
||||||
@@ -621,6 +624,7 @@ int cpu_exec(CPUArchState *env)
|
|||||||
tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
|
tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
|
||||||
next_tb & TB_EXIT_MASK, tb);
|
next_tb & TB_EXIT_MASK, tb);
|
||||||
}
|
}
|
||||||
|
have_tb_lock = false;
|
||||||
spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
|
spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
|
||||||
|
|
||||||
/* cpu_interrupt might be called while translating the
|
/* cpu_interrupt might be called while translating the
|
||||||
@@ -692,6 +696,10 @@ int cpu_exec(CPUArchState *env)
|
|||||||
#ifdef TARGET_I386
|
#ifdef TARGET_I386
|
||||||
x86_cpu = X86_CPU(cpu);
|
x86_cpu = X86_CPU(cpu);
|
||||||
#endif
|
#endif
|
||||||
|
if (have_tb_lock) {
|
||||||
|
spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
|
||||||
|
have_tb_lock = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} /* for(;;) */
|
} /* for(;;) */
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
CONFIG_USB_TABLET_WACOM=y
|
CONFIG_USB_TABLET_WACOM=y
|
||||||
CONFIG_USB_STORAGE_BOT=y
|
CONFIG_USB_STORAGE_BOT=y
|
||||||
CONFIG_USB_STORAGE_UAS=y
|
CONFIG_USB_STORAGE_UAS=y
|
||||||
|
CONFIG_USB_STORAGE_MTP=y
|
||||||
CONFIG_USB_SMARTCARD=y
|
CONFIG_USB_SMARTCARD=y
|
||||||
CONFIG_USB_AUDIO=y
|
CONFIG_USB_AUDIO=y
|
||||||
CONFIG_USB_SERIAL=y
|
CONFIG_USB_SERIAL=y
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ BlockDriverAIOCB *dma_bdrv_io(
|
|||||||
dbs->sg_cur_index = 0;
|
dbs->sg_cur_index = 0;
|
||||||
dbs->sg_cur_byte = 0;
|
dbs->sg_cur_byte = 0;
|
||||||
dbs->dir = dir;
|
dbs->dir = dir;
|
||||||
|
dbs->in_cancel = false;
|
||||||
dbs->io_func = io_func;
|
dbs->io_func = io_func;
|
||||||
dbs->bh = NULL;
|
dbs->bh = NULL;
|
||||||
qemu_iovec_init(&dbs->iov, sg->nsg);
|
qemu_iovec_init(&dbs->iov, sg->nsg);
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ QEMU Standard VGA
|
|||||||
Exists in two variants, for isa and pci.
|
Exists in two variants, for isa and pci.
|
||||||
|
|
||||||
command line switches:
|
command line switches:
|
||||||
-vga std [ picks isa for -M isapc, otherwise pci ]
|
-vga std [ picks isa for -M isapc, otherwise pci ]
|
||||||
-device VGA [ pci variant ]
|
-device VGA [ pci variant ]
|
||||||
-device isa-vga [ isa variant ]
|
-device isa-vga [ isa variant ]
|
||||||
|
-device secondary-vga [ legacy-free pci variant ]
|
||||||
|
|
||||||
|
|
||||||
PCI spec
|
PCI spec
|
||||||
@@ -31,9 +32,15 @@ PCI ROM Region:
|
|||||||
Holds the vgabios (qemu 0.14+).
|
Holds the vgabios (qemu 0.14+).
|
||||||
|
|
||||||
|
|
||||||
|
The legacy-free variant has no ROM and has PCI_CLASS_DISPLAY_OTHER
|
||||||
|
instead of PCI_CLASS_DISPLAY_VGA.
|
||||||
|
|
||||||
|
|
||||||
IO ports used
|
IO ports used
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
Doesn't apply to the legacy-free pci variant, use the MMIO bar instead.
|
||||||
|
|
||||||
03c0 - 03df : standard vga ports
|
03c0 - 03df : standard vga ports
|
||||||
01ce : bochs vbe interface index port
|
01ce : bochs vbe interface index port
|
||||||
01cf : bochs vbe interface data port (x86 only)
|
01cf : bochs vbe interface data port (x86 only)
|
||||||
|
|||||||
@@ -1626,6 +1626,26 @@ uint64 float32_to_uint64(float32 a STATUS_PARAM)
|
|||||||
return roundAndPackUint64(aSign, aSig64, aSigExtra STATUS_VAR);
|
return roundAndPackUint64(aSign, aSig64, aSigExtra STATUS_VAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Returns the result of converting the single-precision floating-point value
|
||||||
|
| `a' to the 64-bit unsigned integer format. The conversion is
|
||||||
|
| performed according to the IEC/IEEE Standard for Binary Floating-Point
|
||||||
|
| Arithmetic, except that the conversion is always rounded toward zero. If
|
||||||
|
| `a' is a NaN, the largest unsigned integer is returned. Otherwise, if the
|
||||||
|
| conversion overflows, the largest unsigned integer is returned. If the
|
||||||
|
| 'a' is negative, the result is rounded and zero is returned; values that do
|
||||||
|
| not round to zero will raise the inexact flag.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint64 float32_to_uint64_round_to_zero(float32 a STATUS_PARAM)
|
||||||
|
{
|
||||||
|
signed char current_rounding_mode = STATUS(float_rounding_mode);
|
||||||
|
set_float_rounding_mode(float_round_to_zero STATUS_VAR);
|
||||||
|
int64_t v = float32_to_uint64(a STATUS_VAR);
|
||||||
|
set_float_rounding_mode(current_rounding_mode STATUS_VAR);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Returns the result of converting the single-precision floating-point value
|
| Returns the result of converting the single-precision floating-point value
|
||||||
| `a' to the 64-bit two's complement integer format. The conversion is
|
| `a' to the 64-bit two's complement integer format. The conversion is
|
||||||
|
|||||||
@@ -43,6 +43,19 @@ static void cubieboard_init(QEMUMachineInitArgs *args)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object_property_set_int(OBJECT(&s->a10->timer), 32768, "clk0-freq", &err);
|
||||||
|
if (err != NULL) {
|
||||||
|
error_report("Couldn't set clk0 frequency: %s", error_get_pretty(err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_property_set_int(OBJECT(&s->a10->timer), 24000000, "clk1-freq",
|
||||||
|
&err);
|
||||||
|
if (err != NULL) {
|
||||||
|
error_report("Couldn't set clk1 frequency: %s", error_get_pretty(err));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
object_property_set_bool(OBJECT(s->a10), true, "realized", &err);
|
object_property_set_bool(OBJECT(s->a10), true, "realized", &err);
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
error_report("Couldn't realize Allwinner A10: %s",
|
error_report("Couldn't realize Allwinner A10: %s",
|
||||||
|
|||||||
@@ -230,18 +230,23 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
|
|||||||
|
|
||||||
for (n = 0; n < smp_cpus; n++) {
|
for (n = 0; n < smp_cpus; n++) {
|
||||||
ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
|
ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
|
||||||
|
Object *cpuobj;
|
||||||
ARMCPU *cpu;
|
ARMCPU *cpu;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
cpu = ARM_CPU(object_new(object_class_get_name(oc)));
|
if (!oc) {
|
||||||
|
error_report("Unable to find CPU definition");
|
||||||
object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, "reset-cbar",
|
|
||||||
&err);
|
|
||||||
if (err) {
|
|
||||||
error_report("%s", error_get_pretty(err));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
object_property_set_bool(OBJECT(cpu), true, "realized", &err);
|
|
||||||
|
cpuobj = object_new(object_class_get_name(oc));
|
||||||
|
cpu = ARM_CPU(cpuobj);
|
||||||
|
|
||||||
|
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||||
|
object_property_set_int(cpuobj, MPCORE_PERIPHBASE,
|
||||||
|
"reset-cbar", &error_abort);
|
||||||
|
}
|
||||||
|
object_property_set_bool(cpuobj, true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_report("%s", error_get_pretty(err));
|
error_report("%s", error_get_pretty(err));
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@@ -192,10 +192,9 @@ static void init_cpus(const char *cpu_model, const char *privdev,
|
|||||||
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
|
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||||
if (err) {
|
object_property_set_int(cpuobj, periphbase,
|
||||||
error_report("%s", error_get_pretty(err));
|
"reset-cbar", &error_abort);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
object_property_set_bool(cpuobj, true, "realized", &err);
|
object_property_set_bool(cpuobj, true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "virtio-blk.h"
|
#include "virtio-blk.h"
|
||||||
#include "block/aio.h"
|
#include "block/aio.h"
|
||||||
#include "hw/virtio/virtio-bus.h"
|
#include "hw/virtio/virtio-bus.h"
|
||||||
#include "monitor/monitor.h" /* for object_add() */
|
#include "qom/object_interfaces.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SEG_MAX = 126, /* maximum number of I/O segments */
|
SEG_MAX = 126, /* maximum number of I/O segments */
|
||||||
@@ -59,7 +59,7 @@ struct VirtIOBlockDataPlane {
|
|||||||
* use it).
|
* use it).
|
||||||
*/
|
*/
|
||||||
IOThread *iothread;
|
IOThread *iothread;
|
||||||
bool internal_iothread;
|
IOThread internal_iothread_obj;
|
||||||
AioContext *ctx;
|
AioContext *ctx;
|
||||||
EventNotifier io_notifier; /* Linux AIO completion */
|
EventNotifier io_notifier; /* Linux AIO completion */
|
||||||
EventNotifier host_notifier; /* doorbell */
|
EventNotifier host_notifier; /* doorbell */
|
||||||
@@ -391,23 +391,19 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
|||||||
s->blk = blk;
|
s->blk = blk;
|
||||||
|
|
||||||
if (blk->iothread) {
|
if (blk->iothread) {
|
||||||
s->internal_iothread = false;
|
|
||||||
s->iothread = blk->iothread;
|
s->iothread = blk->iothread;
|
||||||
|
object_ref(OBJECT(s->iothread));
|
||||||
} else {
|
} else {
|
||||||
/* Create per-device IOThread if none specified */
|
/* Create per-device IOThread if none specified. This is for
|
||||||
Error *local_err = NULL;
|
* x-data-plane option compatibility. If x-data-plane is removed we
|
||||||
|
* can drop this.
|
||||||
s->internal_iothread = true;
|
*/
|
||||||
object_add(TYPE_IOTHREAD, vdev->name, NULL, NULL, &local_err);
|
object_initialize(&s->internal_iothread_obj,
|
||||||
if (error_is_set(&local_err)) {
|
sizeof(s->internal_iothread_obj),
|
||||||
error_propagate(errp, local_err);
|
TYPE_IOTHREAD);
|
||||||
g_free(s);
|
user_creatable_complete(OBJECT(&s->internal_iothread_obj), &error_abort);
|
||||||
return;
|
s->iothread = &s->internal_iothread_obj;
|
||||||
}
|
|
||||||
s->iothread = iothread_find(vdev->name);
|
|
||||||
assert(s->iothread);
|
|
||||||
}
|
}
|
||||||
object_ref(OBJECT(s->iothread));
|
|
||||||
s->ctx = iothread_get_aio_context(s->iothread);
|
s->ctx = iothread_get_aio_context(s->iothread);
|
||||||
|
|
||||||
/* Prevent block operations that conflict with data plane thread */
|
/* Prevent block operations that conflict with data plane thread */
|
||||||
@@ -426,9 +422,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
|||||||
virtio_blk_data_plane_stop(s);
|
virtio_blk_data_plane_stop(s);
|
||||||
bdrv_set_in_use(s->blk->conf.bs, 0);
|
bdrv_set_in_use(s->blk->conf.bs, 0);
|
||||||
object_unref(OBJECT(s->iothread));
|
object_unref(OBJECT(s->iothread));
|
||||||
if (s->internal_iothread) {
|
|
||||||
object_unparent(OBJECT(s->iothread));
|
|
||||||
}
|
|
||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -817,11 +817,14 @@ static int blk_connect(struct XenDevice *xendev)
|
|||||||
index = (blkdev->xendev.dev - 202 * 256) / 16;
|
index = (blkdev->xendev.dev - 202 * 256) / 16;
|
||||||
blkdev->dinfo = drive_get(IF_XEN, 0, index);
|
blkdev->dinfo = drive_get(IF_XEN, 0, index);
|
||||||
if (!blkdev->dinfo) {
|
if (!blkdev->dinfo) {
|
||||||
|
Error *local_err = NULL;
|
||||||
/* setup via xenbus -> create new block driver instance */
|
/* setup via xenbus -> create new block driver instance */
|
||||||
xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
|
xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
|
||||||
blkdev->bs = bdrv_new(blkdev->dev);
|
blkdev->bs = bdrv_new(blkdev->dev, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
blkdev->bs = NULL;
|
||||||
|
}
|
||||||
if (blkdev->bs) {
|
if (blkdev->bs) {
|
||||||
Error *local_err = NULL;
|
|
||||||
BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
|
BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
|
||||||
readonly);
|
readonly);
|
||||||
if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
|
if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
|
||||||
|
|||||||
@@ -225,8 +225,10 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
|
|||||||
|
|
||||||
if (s->tsr_retry <= 0) {
|
if (s->tsr_retry <= 0) {
|
||||||
if (s->fcr & UART_FCR_FE) {
|
if (s->fcr & UART_FCR_FE) {
|
||||||
s->tsr = fifo8_is_empty(&s->xmit_fifo) ?
|
if (fifo8_is_empty(&s->xmit_fifo)) {
|
||||||
0 : fifo8_pop(&s->xmit_fifo);
|
return FALSE;
|
||||||
|
}
|
||||||
|
s->tsr = fifo8_pop(&s->xmit_fifo);
|
||||||
if (!s->xmit_fifo.num) {
|
if (!s->xmit_fifo.num) {
|
||||||
s->lsr |= UART_LSR_THRE;
|
s->lsr |= UART_LSR_THRE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; under version 2 of the License.
|
* the Free Software Foundation; either version 2 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
@@ -2913,7 +2913,7 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
|
|||||||
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
|
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
|
||||||
VGACommonState *s = &d->cirrus_vga.vga;
|
VGACommonState *s = &d->cirrus_vga.vga;
|
||||||
|
|
||||||
vga_common_init(s, OBJECT(dev));
|
vga_common_init(s, OBJECT(dev), true);
|
||||||
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
|
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
|
||||||
isa_address_space(isadev),
|
isa_address_space(isadev),
|
||||||
isa_address_space_io(isadev));
|
isa_address_space_io(isadev));
|
||||||
@@ -2960,7 +2960,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
|
|||||||
int16_t device_id = pc->device_id;
|
int16_t device_id = pc->device_id;
|
||||||
|
|
||||||
/* setup VGA */
|
/* setup VGA */
|
||||||
vga_common_init(&s->vga, OBJECT(dev));
|
vga_common_init(&s->vga, OBJECT(dev), true);
|
||||||
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
|
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
|
||||||
pci_address_space_io(dev));
|
pci_address_space_io(dev));
|
||||||
s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
|
s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
|
||||||
|
|||||||
@@ -2061,7 +2061,7 @@ static int qxl_init_primary(PCIDevice *dev)
|
|||||||
qxl->id = 0;
|
qxl->id = 0;
|
||||||
qxl_init_ramsize(qxl);
|
qxl_init_ramsize(qxl);
|
||||||
vga->vram_size_mb = qxl->vga.vram_size >> 20;
|
vga->vram_size_mb = qxl->vga.vram_size >> 20;
|
||||||
vga_common_init(vga, OBJECT(dev));
|
vga_common_init(vga, OBJECT(dev), true);
|
||||||
vga_init(vga, OBJECT(dev),
|
vga_init(vga, OBJECT(dev),
|
||||||
pci_address_space(dev), pci_address_space_io(dev), false);
|
pci_address_space(dev), pci_address_space_io(dev), false);
|
||||||
portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,
|
portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ int isa_vga_mm_init(hwaddr vram_base,
|
|||||||
s = g_malloc0(sizeof(*s));
|
s = g_malloc0(sizeof(*s));
|
||||||
|
|
||||||
s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
|
s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
|
||||||
vga_common_init(&s->vga, NULL);
|
vga_common_init(&s->vga, NULL, true);
|
||||||
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
|
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
|
||||||
|
|
||||||
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
|
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
|
|||||||
MemoryRegion *vga_io_memory;
|
MemoryRegion *vga_io_memory;
|
||||||
const MemoryRegionPortio *vga_ports, *vbe_ports;
|
const MemoryRegionPortio *vga_ports, *vbe_ports;
|
||||||
|
|
||||||
vga_common_init(s, OBJECT(dev));
|
vga_common_init(s, OBJECT(dev), true);
|
||||||
s->legacy_address_space = isa_address_space(isadev);
|
s->legacy_address_space = isa_address_space(isadev);
|
||||||
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
|
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
|
||||||
isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");
|
isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
|
|||||||
VGACommonState *s = &d->vga;
|
VGACommonState *s = &d->vga;
|
||||||
|
|
||||||
/* vga + console init */
|
/* vga + console init */
|
||||||
vga_common_init(s, OBJECT(dev));
|
vga_common_init(s, OBJECT(dev), true);
|
||||||
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
|
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
@@ -179,12 +179,51 @@ static int pci_std_vga_initfn(PCIDevice *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pci_secondary_vga_initfn(PCIDevice *dev)
|
||||||
|
{
|
||||||
|
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
|
||||||
|
VGACommonState *s = &d->vga;
|
||||||
|
|
||||||
|
/* vga + console init */
|
||||||
|
vga_common_init(s, OBJECT(dev), false);
|
||||||
|
s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
|
||||||
|
|
||||||
|
/* mmio bar */
|
||||||
|
memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096);
|
||||||
|
memory_region_init_io(&d->ioport, OBJECT(dev), &pci_vga_ioport_ops, d,
|
||||||
|
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
|
||||||
|
memory_region_init_io(&d->bochs, OBJECT(dev), &pci_vga_bochs_ops, d,
|
||||||
|
"bochs dispi interface", PCI_VGA_BOCHS_SIZE);
|
||||||
|
|
||||||
|
memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
|
||||||
|
&d->ioport);
|
||||||
|
memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET,
|
||||||
|
&d->bochs);
|
||||||
|
|
||||||
|
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
|
||||||
|
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pci_secondary_vga_reset(DeviceState *dev)
|
||||||
|
{
|
||||||
|
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev.qdev, dev);
|
||||||
|
|
||||||
|
vga_common_reset(&d->vga);
|
||||||
|
}
|
||||||
|
|
||||||
static Property vga_pci_properties[] = {
|
static Property vga_pci_properties[] = {
|
||||||
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
||||||
DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true),
|
DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property secondary_pci_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void vga_class_init(ObjectClass *klass, void *data)
|
static void vga_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
@@ -201,6 +240,20 @@ static void vga_class_init(ObjectClass *klass, void *data)
|
|||||||
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void secondary_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
k->init = pci_secondary_vga_initfn;
|
||||||
|
k->vendor_id = PCI_VENDOR_ID_QEMU;
|
||||||
|
k->device_id = PCI_DEVICE_ID_QEMU_VGA;
|
||||||
|
k->class_id = PCI_CLASS_DISPLAY_OTHER;
|
||||||
|
dc->vmsd = &vmstate_vga_pci;
|
||||||
|
dc->props = secondary_pci_properties;
|
||||||
|
dc->reset = pci_secondary_vga_reset;
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo vga_info = {
|
static const TypeInfo vga_info = {
|
||||||
.name = "VGA",
|
.name = "VGA",
|
||||||
.parent = TYPE_PCI_DEVICE,
|
.parent = TYPE_PCI_DEVICE,
|
||||||
@@ -208,9 +261,17 @@ static const TypeInfo vga_info = {
|
|||||||
.class_init = vga_class_init,
|
.class_init = vga_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TypeInfo secondary_info = {
|
||||||
|
.name = "secondary-vga",
|
||||||
|
.parent = TYPE_PCI_DEVICE,
|
||||||
|
.instance_size = sizeof(PCIVGAState),
|
||||||
|
.class_init = secondary_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
static void vga_register_types(void)
|
static void vga_register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&vga_info);
|
type_register_static(&vga_info);
|
||||||
|
type_register_static(&secondary_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(vga_register_types)
|
type_init(vga_register_types)
|
||||||
|
|||||||
@@ -171,6 +171,10 @@ static void vga_update_memory_access(VGACommonState *s)
|
|||||||
MemoryRegion *region, *old_region = s->chain4_alias;
|
MemoryRegion *region, *old_region = s->chain4_alias;
|
||||||
hwaddr base, offset, size;
|
hwaddr base, offset, size;
|
||||||
|
|
||||||
|
if (s->legacy_address_space == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
s->chain4_alias = NULL;
|
s->chain4_alias = NULL;
|
||||||
|
|
||||||
if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
|
if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
|
||||||
@@ -2252,7 +2256,7 @@ static const GraphicHwOps vga_ops = {
|
|||||||
.text_update = vga_update_text,
|
.text_update = vga_update_text,
|
||||||
};
|
};
|
||||||
|
|
||||||
void vga_common_init(VGACommonState *s, Object *obj)
|
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
|
||||||
{
|
{
|
||||||
int i, j, v, b;
|
int i, j, v, b;
|
||||||
|
|
||||||
@@ -2289,7 +2293,7 @@ void vga_common_init(VGACommonState *s, Object *obj)
|
|||||||
|
|
||||||
s->is_vbe_vmstate = 1;
|
s->is_vbe_vmstate = 1;
|
||||||
memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
|
memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
|
||||||
vmstate_register_ram_global(&s->vram);
|
vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
|
||||||
xen_register_framebuffer(&s->vram);
|
xen_register_framebuffer(&s->vram);
|
||||||
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
|
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
|
||||||
s->get_bpp = vga_get_bpp;
|
s->get_bpp = vga_get_bpp;
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ static inline int c6_to_8(int v)
|
|||||||
return (v << 2) | (b << 1) | b;
|
return (v << 2) | (b << 1) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vga_common_init(VGACommonState *s, Object *obj);
|
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate);
|
||||||
void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
|
void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
|
||||||
MemoryRegion *address_space_io, bool init_vga_ports);
|
MemoryRegion *address_space_io, bool init_vga_ports);
|
||||||
MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
|
MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
|
||||||
|
|||||||
@@ -1207,7 +1207,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
|
|||||||
vmstate_register_ram_global(&s->fifo_ram);
|
vmstate_register_ram_global(&s->fifo_ram);
|
||||||
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
|
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
|
||||||
|
|
||||||
vga_common_init(&s->vga, OBJECT(dev));
|
vga_common_init(&s->vga, OBJECT(dev), true);
|
||||||
vga_init(&s->vga, OBJECT(dev), address_space, io, true);
|
vga_init(&s->vga, OBJECT(dev), address_space, io, true);
|
||||||
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
|
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
|
||||||
s->new_depth = 32;
|
s->new_depth = 32;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ static void eeprom_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int l
|
|||||||
printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
|
printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
|
||||||
dev->i2c.address, cmd, buf[0]);
|
dev->i2c.address, cmd, buf[0]);
|
||||||
#endif
|
#endif
|
||||||
/* An page write operation is not a valid SMBus command.
|
/* A page write operation is not a valid SMBus command.
|
||||||
It is a block write without a length byte. Fortunately we
|
It is a block write without a length byte. Fortunately we
|
||||||
get the full block anyway. */
|
get the full block anyway. */
|
||||||
/* TODO: Should this set the current location? */
|
/* TODO: Should this set the current location? */
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ static void build_append_int(GArray *table, uint32_t value)
|
|||||||
build_append_byte(table, 0x01); /* OneOp */
|
build_append_byte(table, 0x01); /* OneOp */
|
||||||
} else if (value <= 0xFF) {
|
} else if (value <= 0xFF) {
|
||||||
build_append_value(table, value, 1);
|
build_append_value(table, value, 1);
|
||||||
} else if (value <= 0xFFFFF) {
|
} else if (value <= 0xFFFF) {
|
||||||
build_append_value(table, value, 2);
|
build_append_value(table, value, 2);
|
||||||
} else {
|
} else {
|
||||||
build_append_value(table, value, 4);
|
build_append_value(table, value, 4);
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ Scope(\_SB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Device(CPU_HOTPLUG_RESOURCE_DEVICE) {
|
Device(CPU_HOTPLUG_RESOURCE_DEVICE) {
|
||||||
Name(_HID, "ACPI0004")
|
Name(_HID, EisaId("PNP0A06"))
|
||||||
|
|
||||||
Name(_CRS, ResourceTemplate() {
|
Name(_CRS, ResourceTemplate() {
|
||||||
IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN)
|
IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN)
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x44,
|
0x44,
|
||||||
0x54,
|
0x54,
|
||||||
0x85,
|
0x80,
|
||||||
0x11,
|
0x11,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x1,
|
0x1,
|
||||||
0x8b,
|
0x60,
|
||||||
0x42,
|
0x42,
|
||||||
0x58,
|
0x58,
|
||||||
0x50,
|
0x50,
|
||||||
@@ -31,8 +31,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x4e,
|
0x4e,
|
||||||
0x54,
|
0x54,
|
||||||
0x4c,
|
0x4c,
|
||||||
0x23,
|
0x15,
|
||||||
0x8,
|
0x11,
|
||||||
0x13,
|
0x13,
|
||||||
0x20,
|
0x20,
|
||||||
0x10,
|
0x10,
|
||||||
@@ -4010,7 +4010,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x1,
|
0x1,
|
||||||
0x10,
|
0x10,
|
||||||
0x47,
|
0x42,
|
||||||
0x11,
|
0x11,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x53,
|
0x53,
|
||||||
@@ -4243,7 +4243,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x60,
|
0x60,
|
||||||
0x5b,
|
0x5b,
|
||||||
0x82,
|
0x82,
|
||||||
0x2e,
|
0x29,
|
||||||
0x50,
|
0x50,
|
||||||
0x52,
|
0x52,
|
||||||
0x45,
|
0x45,
|
||||||
@@ -4253,16 +4253,11 @@ static unsigned char AcpiDsdtAmlCode[] = {
|
|||||||
0x48,
|
0x48,
|
||||||
0x49,
|
0x49,
|
||||||
0x44,
|
0x44,
|
||||||
0xd,
|
0xc,
|
||||||
0x41,
|
0x41,
|
||||||
0x43,
|
0xd0,
|
||||||
0x50,
|
0xa,
|
||||||
0x49,
|
0x6,
|
||||||
0x30,
|
|
||||||
0x30,
|
|
||||||
0x30,
|
|
||||||
0x34,
|
|
||||||
0x0,
|
|
||||||
0x8,
|
0x8,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x43,
|
0x43,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x44,
|
0x44,
|
||||||
0x54,
|
0x54,
|
||||||
0xd7,
|
0xd2,
|
||||||
0x1c,
|
0x1c,
|
||||||
0x0,
|
0x0,
|
||||||
0x0,
|
0x0,
|
||||||
0x1,
|
0x1,
|
||||||
0x3e,
|
0x13,
|
||||||
0x42,
|
0x42,
|
||||||
0x58,
|
0x58,
|
||||||
0x50,
|
0x50,
|
||||||
@@ -31,8 +31,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x4e,
|
0x4e,
|
||||||
0x54,
|
0x54,
|
||||||
0x4c,
|
0x4c,
|
||||||
0x23,
|
0x15,
|
||||||
0x8,
|
0x11,
|
||||||
0x13,
|
0x13,
|
||||||
0x20,
|
0x20,
|
||||||
0x10,
|
0x10,
|
||||||
@@ -6959,7 +6959,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x53,
|
0x53,
|
||||||
0x1,
|
0x1,
|
||||||
0x10,
|
0x10,
|
||||||
0x47,
|
0x42,
|
||||||
0x11,
|
0x11,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x53,
|
0x53,
|
||||||
@@ -7192,7 +7192,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x60,
|
0x60,
|
||||||
0x5b,
|
0x5b,
|
||||||
0x82,
|
0x82,
|
||||||
0x2e,
|
0x29,
|
||||||
0x50,
|
0x50,
|
||||||
0x52,
|
0x52,
|
||||||
0x45,
|
0x45,
|
||||||
@@ -7202,16 +7202,11 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
|
|||||||
0x48,
|
0x48,
|
||||||
0x49,
|
0x49,
|
||||||
0x44,
|
0x44,
|
||||||
0xd,
|
0xc,
|
||||||
0x41,
|
0x41,
|
||||||
0x43,
|
0xd0,
|
||||||
0x50,
|
0xa,
|
||||||
0x49,
|
0x6,
|
||||||
0x30,
|
|
||||||
0x30,
|
|
||||||
0x30,
|
|
||||||
0x34,
|
|
||||||
0x0,
|
|
||||||
0x8,
|
0x8,
|
||||||
0x5f,
|
0x5f,
|
||||||
0x43,
|
0x43,
|
||||||
|
|||||||
@@ -438,9 +438,9 @@ static void check_cmd(AHCIState *s, int port)
|
|||||||
|
|
||||||
if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {
|
if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {
|
||||||
for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {
|
for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {
|
||||||
if ((pr->cmd_issue & (1 << slot)) &&
|
if ((pr->cmd_issue & (1U << slot)) &&
|
||||||
!handle_cmd(s, port, slot)) {
|
!handle_cmd(s, port, slot)) {
|
||||||
pr->cmd_issue &= ~(1 << slot);
|
pr->cmd_issue &= ~(1U << slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1602,7 +1602,7 @@ static bool cmd_smart(IDEState *s, uint8_t cmd)
|
|||||||
case 2: /* extended self test */
|
case 2: /* extended self test */
|
||||||
s->smart_selftest_count++;
|
s->smart_selftest_count++;
|
||||||
if (s->smart_selftest_count > 21) {
|
if (s->smart_selftest_count > 21) {
|
||||||
s->smart_selftest_count = 0;
|
s->smart_selftest_count = 1;
|
||||||
}
|
}
|
||||||
n = 2 + (s->smart_selftest_count - 1) * 24;
|
n = 2 + (s->smart_selftest_count - 1) * 24;
|
||||||
s->smart_selftest_data[n] = s->sector;
|
s->smart_selftest_data[n] = s->sector;
|
||||||
|
|||||||
@@ -23,11 +23,20 @@
|
|||||||
static void aw_a10_pic_update(AwA10PICState *s)
|
static void aw_a10_pic_update(AwA10PICState *s)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
int irq = 0, fiq = 0;
|
int irq = 0, fiq = 0, pending;
|
||||||
|
|
||||||
|
s->vector = 0;
|
||||||
|
|
||||||
for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
|
for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
|
||||||
irq |= s->irq_pending[i] & ~s->mask[i];
|
irq |= s->irq_pending[i] & ~s->mask[i];
|
||||||
fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
|
fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
|
||||||
|
|
||||||
|
if (!s->vector) {
|
||||||
|
pending = ffs(s->irq_pending[i] & ~s->mask[i]);
|
||||||
|
if (pending) {
|
||||||
|
s->vector = (i * 32 + pending - 1) * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_set_irq(s->parent_irq, !!irq);
|
qemu_set_irq(s->parent_irq, !!irq);
|
||||||
@@ -40,6 +49,8 @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
|
|||||||
|
|
||||||
if (level) {
|
if (level) {
|
||||||
set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
||||||
|
} else {
|
||||||
|
clear_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
|
||||||
}
|
}
|
||||||
aw_a10_pic_update(s);
|
aw_a10_pic_update(s);
|
||||||
}
|
}
|
||||||
@@ -84,9 +95,6 @@ static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
uint8_t index = (offset & 0xc) / 4;
|
uint8_t index = (offset & 0xc) / 4;
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case AW_A10_PIC_VECTOR:
|
|
||||||
s->vector = value & ~0x3;
|
|
||||||
break;
|
|
||||||
case AW_A10_PIC_BASE_ADDR:
|
case AW_A10_PIC_BASE_ADDR:
|
||||||
s->base_addr = value & ~0x3;
|
s->base_addr = value & ~0x3;
|
||||||
case AW_A10_PIC_PROTECT:
|
case AW_A10_PIC_PROTECT:
|
||||||
@@ -96,7 +104,11 @@ static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
s->nmi = value;
|
s->nmi = value;
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
|
case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
|
||||||
s->irq_pending[index] &= ~value;
|
/*
|
||||||
|
* The register is read-only; nevertheless, Linux (including
|
||||||
|
* the version originally shipped by Allwinner) pretends to
|
||||||
|
* write to the register. Just ignore it.
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
|
case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
|
||||||
s->fiq_pending[index] &= ~value;
|
s->fiq_pending[index] &= ~value;
|
||||||
|
|||||||
@@ -19,102 +19,155 @@
|
|||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
#ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
|
#ifndef ZYNQ_SLCR_ERR_DEBUG
|
||||||
#define DB_PRINT(...) do { \
|
#define ZYNQ_SLCR_ERR_DEBUG 0
|
||||||
fprintf(stderr, ": %s: ", __func__); \
|
|
||||||
fprintf(stderr, ## __VA_ARGS__); \
|
|
||||||
} while (0);
|
|
||||||
#else
|
|
||||||
#define DB_PRINT(...)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DB_PRINT(...) do { \
|
||||||
|
if (ZYNQ_SLCR_ERR_DEBUG) { \
|
||||||
|
fprintf(stderr, ": %s: ", __func__); \
|
||||||
|
fprintf(stderr, ## __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
#define XILINX_LOCK_KEY 0x767b
|
#define XILINX_LOCK_KEY 0x767b
|
||||||
#define XILINX_UNLOCK_KEY 0xdf0d
|
#define XILINX_UNLOCK_KEY 0xdf0d
|
||||||
|
|
||||||
#define R_PSS_RST_CTRL_SOFT_RST 0x1
|
#define R_PSS_RST_CTRL_SOFT_RST 0x1
|
||||||
|
|
||||||
typedef enum {
|
enum {
|
||||||
ARM_PLL_CTRL,
|
SCL = 0x000 / 4,
|
||||||
DDR_PLL_CTRL,
|
LOCK,
|
||||||
IO_PLL_CTRL,
|
UNLOCK,
|
||||||
PLL_STATUS,
|
LOCKSTA,
|
||||||
ARM_PPL_CFG,
|
|
||||||
DDR_PLL_CFG,
|
|
||||||
IO_PLL_CFG,
|
|
||||||
PLL_BG_CTRL,
|
|
||||||
PLL_MAX
|
|
||||||
} PLLValues;
|
|
||||||
|
|
||||||
typedef enum {
|
ARM_PLL_CTRL = 0x100 / 4,
|
||||||
ARM_CLK_CTRL,
|
DDR_PLL_CTRL,
|
||||||
DDR_CLK_CTRL,
|
IO_PLL_CTRL,
|
||||||
DCI_CLK_CTRL,
|
PLL_STATUS,
|
||||||
APER_CLK_CTRL,
|
ARM_PLL_CFG,
|
||||||
USB0_CLK_CTRL,
|
DDR_PLL_CFG,
|
||||||
USB1_CLK_CTRL,
|
IO_PLL_CFG,
|
||||||
GEM0_RCLK_CTRL,
|
|
||||||
GEM1_RCLK_CTRL,
|
|
||||||
GEM0_CLK_CTRL,
|
|
||||||
GEM1_CLK_CTRL,
|
|
||||||
SMC_CLK_CTRL,
|
|
||||||
LQSPI_CLK_CTRL,
|
|
||||||
SDIO_CLK_CTRL,
|
|
||||||
UART_CLK_CTRL,
|
|
||||||
SPI_CLK_CTRL,
|
|
||||||
CAN_CLK_CTRL,
|
|
||||||
CAN_MIOCLK_CTRL,
|
|
||||||
DBG_CLK_CTRL,
|
|
||||||
PCAP_CLK_CTRL,
|
|
||||||
TOPSW_CLK_CTRL,
|
|
||||||
CLK_MAX
|
|
||||||
} ClkValues;
|
|
||||||
|
|
||||||
typedef enum {
|
ARM_CLK_CTRL = 0x120 / 4,
|
||||||
CLK_CTRL,
|
DDR_CLK_CTRL,
|
||||||
THR_CTRL,
|
DCI_CLK_CTRL,
|
||||||
THR_CNT,
|
APER_CLK_CTRL,
|
||||||
THR_STA,
|
USB0_CLK_CTRL,
|
||||||
FPGA_MAX
|
USB1_CLK_CTRL,
|
||||||
} FPGAValues;
|
GEM0_RCLK_CTRL,
|
||||||
|
GEM1_RCLK_CTRL,
|
||||||
|
GEM0_CLK_CTRL,
|
||||||
|
GEM1_CLK_CTRL,
|
||||||
|
SMC_CLK_CTRL,
|
||||||
|
LQSPI_CLK_CTRL,
|
||||||
|
SDIO_CLK_CTRL,
|
||||||
|
UART_CLK_CTRL,
|
||||||
|
SPI_CLK_CTRL,
|
||||||
|
CAN_CLK_CTRL,
|
||||||
|
CAN_MIOCLK_CTRL,
|
||||||
|
DBG_CLK_CTRL,
|
||||||
|
PCAP_CLK_CTRL,
|
||||||
|
TOPSW_CLK_CTRL,
|
||||||
|
|
||||||
typedef enum {
|
#define FPGA_CTRL_REGS(n, start) \
|
||||||
SYNC_CTRL,
|
FPGA ## n ## _CLK_CTRL = (start) / 4, \
|
||||||
SYNC_STATUS,
|
FPGA ## n ## _THR_CTRL, \
|
||||||
BANDGAP_TRIP,
|
FPGA ## n ## _THR_CNT, \
|
||||||
CC_TEST,
|
FPGA ## n ## _THR_STA,
|
||||||
PLL_PREDIVISOR,
|
FPGA_CTRL_REGS(0, 0x170)
|
||||||
CLK_621_TRUE,
|
FPGA_CTRL_REGS(1, 0x180)
|
||||||
PICTURE_DBG,
|
FPGA_CTRL_REGS(2, 0x190)
|
||||||
PICTURE_DBG_UCNT,
|
FPGA_CTRL_REGS(3, 0x1a0)
|
||||||
PICTURE_DBG_LCNT,
|
|
||||||
MISC_MAX
|
|
||||||
} MiscValues;
|
|
||||||
|
|
||||||
typedef enum {
|
BANDGAP_TRIP = 0x1b8 / 4,
|
||||||
PSS,
|
PLL_PREDIVISOR = 0x1c0 / 4,
|
||||||
DDDR,
|
CLK_621_TRUE,
|
||||||
DMAC = 3,
|
|
||||||
USB,
|
PSS_RST_CTRL = 0x200 / 4,
|
||||||
GEM,
|
DDR_RST_CTRL,
|
||||||
SDIO,
|
TOPSW_RESET_CTRL,
|
||||||
SPI,
|
DMAC_RST_CTRL,
|
||||||
CAN,
|
USB_RST_CTRL,
|
||||||
I2C,
|
GEM_RST_CTRL,
|
||||||
UART,
|
SDIO_RST_CTRL,
|
||||||
GPIO,
|
SPI_RST_CTRL,
|
||||||
LQSPI,
|
CAN_RST_CTRL,
|
||||||
SMC,
|
I2C_RST_CTRL,
|
||||||
OCM,
|
UART_RST_CTRL,
|
||||||
DEVCI,
|
GPIO_RST_CTRL,
|
||||||
FPGA,
|
LQSPI_RST_CTRL,
|
||||||
A9_CPU,
|
SMC_RST_CTRL,
|
||||||
RS_AWDT,
|
OCM_RST_CTRL,
|
||||||
RST_REASON,
|
FPGA_RST_CTRL = 0x240 / 4,
|
||||||
RST_REASON_CLR,
|
A9_CPU_RST_CTRL,
|
||||||
REBOOT_STATUS,
|
|
||||||
BOOT_MODE,
|
RS_AWDT_CTRL = 0x24c / 4,
|
||||||
RESET_MAX
|
RST_REASON,
|
||||||
} ResetValues;
|
|
||||||
|
REBOOT_STATUS = 0x258 / 4,
|
||||||
|
BOOT_MODE,
|
||||||
|
|
||||||
|
APU_CTRL = 0x300 / 4,
|
||||||
|
WDT_CLK_SEL,
|
||||||
|
|
||||||
|
TZ_DMA_NS = 0x440 / 4,
|
||||||
|
TZ_DMA_IRQ_NS,
|
||||||
|
TZ_DMA_PERIPH_NS,
|
||||||
|
|
||||||
|
PSS_IDCODE = 0x530 / 4,
|
||||||
|
|
||||||
|
DDR_URGENT = 0x600 / 4,
|
||||||
|
DDR_CAL_START = 0x60c / 4,
|
||||||
|
DDR_REF_START = 0x614 / 4,
|
||||||
|
DDR_CMD_STA,
|
||||||
|
DDR_URGENT_SEL,
|
||||||
|
DDR_DFI_STATUS,
|
||||||
|
|
||||||
|
MIO = 0x700 / 4,
|
||||||
|
#define MIO_LENGTH 54
|
||||||
|
|
||||||
|
MIO_LOOPBACK = 0x804 / 4,
|
||||||
|
MIO_MST_TRI0,
|
||||||
|
MIO_MST_TRI1,
|
||||||
|
|
||||||
|
SD0_WP_CD_SEL = 0x830 / 4,
|
||||||
|
SD1_WP_CD_SEL,
|
||||||
|
|
||||||
|
LVL_SHFTR_EN = 0x900 / 4,
|
||||||
|
OCM_CFG = 0x910 / 4,
|
||||||
|
|
||||||
|
CPU_RAM = 0xa00 / 4,
|
||||||
|
|
||||||
|
IOU = 0xa30 / 4,
|
||||||
|
|
||||||
|
DMAC_RAM = 0xa50 / 4,
|
||||||
|
|
||||||
|
AFI0 = 0xa60 / 4,
|
||||||
|
AFI1 = AFI0 + 3,
|
||||||
|
AFI2 = AFI1 + 3,
|
||||||
|
AFI3 = AFI2 + 3,
|
||||||
|
#define AFI_LENGTH 3
|
||||||
|
|
||||||
|
OCM = 0xa90 / 4,
|
||||||
|
|
||||||
|
DEVCI_RAM = 0xaa0 / 4,
|
||||||
|
|
||||||
|
CSG_RAM = 0xab0 / 4,
|
||||||
|
|
||||||
|
GPIOB_CTRL = 0xb00 / 4,
|
||||||
|
GPIOB_CFG_CMOS18,
|
||||||
|
GPIOB_CFG_CMOS25,
|
||||||
|
GPIOB_CFG_CMOS33,
|
||||||
|
GPIOB_CFG_HSTL = 0xb14 / 4,
|
||||||
|
GPIOB_DRVR_BIAS_CTRL,
|
||||||
|
|
||||||
|
DDRIOB = 0xb40 / 4,
|
||||||
|
#define DDRIOB_LENGTH 14
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ZYNQ_SLCR_MMIO_SIZE 0x1000
|
||||||
|
#define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4)
|
||||||
|
|
||||||
#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
|
#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
|
||||||
#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
|
#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
|
||||||
@@ -124,42 +177,7 @@ typedef struct ZynqSLCRState {
|
|||||||
|
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
|
||||||
union {
|
uint32_t regs[ZYNQ_SLCR_NUM_REGS];
|
||||||
struct {
|
|
||||||
uint16_t scl;
|
|
||||||
uint16_t lockval;
|
|
||||||
uint32_t pll[PLL_MAX]; /* 0x100 - 0x11C */
|
|
||||||
uint32_t clk[CLK_MAX]; /* 0x120 - 0x16C */
|
|
||||||
uint32_t fpga[4][FPGA_MAX]; /* 0x170 - 0x1AC */
|
|
||||||
uint32_t misc[MISC_MAX]; /* 0x1B0 - 0x1D8 */
|
|
||||||
uint32_t reset[RESET_MAX]; /* 0x200 - 0x25C */
|
|
||||||
uint32_t apu_ctrl; /* 0x300 */
|
|
||||||
uint32_t wdt_clk_sel; /* 0x304 */
|
|
||||||
uint32_t tz_ocm[3]; /* 0x400 - 0x408 */
|
|
||||||
uint32_t tz_ddr; /* 0x430 */
|
|
||||||
uint32_t tz_dma[3]; /* 0x440 - 0x448 */
|
|
||||||
uint32_t tz_misc[3]; /* 0x450 - 0x458 */
|
|
||||||
uint32_t tz_fpga[2]; /* 0x484 - 0x488 */
|
|
||||||
uint32_t dbg_ctrl; /* 0x500 */
|
|
||||||
uint32_t pss_idcode; /* 0x530 */
|
|
||||||
uint32_t ddr[8]; /* 0x600 - 0x620 - 0x604-missing */
|
|
||||||
uint32_t mio[54]; /* 0x700 - 0x7D4 */
|
|
||||||
uint32_t mio_func[4]; /* 0x800 - 0x810 */
|
|
||||||
uint32_t sd[2]; /* 0x830 - 0x834 */
|
|
||||||
uint32_t lvl_shftr_en; /* 0x900 */
|
|
||||||
uint32_t ocm_cfg; /* 0x910 */
|
|
||||||
uint32_t cpu_ram[8]; /* 0xA00 - 0xA1C */
|
|
||||||
uint32_t iou[7]; /* 0xA30 - 0xA48 */
|
|
||||||
uint32_t dmac_ram; /* 0xA50 */
|
|
||||||
uint32_t afi[4][3]; /* 0xA60 - 0xA8C */
|
|
||||||
uint32_t ocm[3]; /* 0xA90 - 0xA98 */
|
|
||||||
uint32_t devci_ram; /* 0xAA0 */
|
|
||||||
uint32_t csg_ram; /* 0xAB0 */
|
|
||||||
uint32_t gpiob[12]; /* 0xB00 - 0xB2C */
|
|
||||||
uint32_t ddriob[14]; /* 0xB40 - 0xB74 */
|
|
||||||
};
|
|
||||||
uint8_t data[0x1000];
|
|
||||||
};
|
|
||||||
} ZynqSLCRState;
|
} ZynqSLCRState;
|
||||||
|
|
||||||
static void zynq_slcr_reset(DeviceState *d)
|
static void zynq_slcr_reset(DeviceState *d)
|
||||||
@@ -169,177 +187,169 @@ static void zynq_slcr_reset(DeviceState *d)
|
|||||||
|
|
||||||
DB_PRINT("RESET\n");
|
DB_PRINT("RESET\n");
|
||||||
|
|
||||||
s->lockval = 1;
|
s->regs[LOCKSTA] = 1;
|
||||||
/* 0x100 - 0x11C */
|
/* 0x100 - 0x11C */
|
||||||
s->pll[ARM_PLL_CTRL] = 0x0001A008;
|
s->regs[ARM_PLL_CTRL] = 0x0001A008;
|
||||||
s->pll[DDR_PLL_CTRL] = 0x0001A008;
|
s->regs[DDR_PLL_CTRL] = 0x0001A008;
|
||||||
s->pll[IO_PLL_CTRL] = 0x0001A008;
|
s->regs[IO_PLL_CTRL] = 0x0001A008;
|
||||||
s->pll[PLL_STATUS] = 0x0000003F;
|
s->regs[PLL_STATUS] = 0x0000003F;
|
||||||
s->pll[ARM_PPL_CFG] = 0x00014000;
|
s->regs[ARM_PLL_CFG] = 0x00014000;
|
||||||
s->pll[DDR_PLL_CFG] = 0x00014000;
|
s->regs[DDR_PLL_CFG] = 0x00014000;
|
||||||
s->pll[IO_PLL_CFG] = 0x00014000;
|
s->regs[IO_PLL_CFG] = 0x00014000;
|
||||||
|
|
||||||
/* 0x120 - 0x16C */
|
/* 0x120 - 0x16C */
|
||||||
s->clk[ARM_CLK_CTRL] = 0x1F000400;
|
s->regs[ARM_CLK_CTRL] = 0x1F000400;
|
||||||
s->clk[DDR_CLK_CTRL] = 0x18400003;
|
s->regs[DDR_CLK_CTRL] = 0x18400003;
|
||||||
s->clk[DCI_CLK_CTRL] = 0x01E03201;
|
s->regs[DCI_CLK_CTRL] = 0x01E03201;
|
||||||
s->clk[APER_CLK_CTRL] = 0x01FFCCCD;
|
s->regs[APER_CLK_CTRL] = 0x01FFCCCD;
|
||||||
s->clk[USB0_CLK_CTRL] = s->clk[USB1_CLK_CTRL] = 0x00101941;
|
s->regs[USB0_CLK_CTRL] = s->regs[USB1_CLK_CTRL] = 0x00101941;
|
||||||
s->clk[GEM0_RCLK_CTRL] = s->clk[GEM1_RCLK_CTRL] = 0x00000001;
|
s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL] = 0x00000001;
|
||||||
s->clk[GEM0_CLK_CTRL] = s->clk[GEM1_CLK_CTRL] = 0x00003C01;
|
s->regs[GEM0_CLK_CTRL] = s->regs[GEM1_CLK_CTRL] = 0x00003C01;
|
||||||
s->clk[SMC_CLK_CTRL] = 0x00003C01;
|
s->regs[SMC_CLK_CTRL] = 0x00003C01;
|
||||||
s->clk[LQSPI_CLK_CTRL] = 0x00002821;
|
s->regs[LQSPI_CLK_CTRL] = 0x00002821;
|
||||||
s->clk[SDIO_CLK_CTRL] = 0x00001E03;
|
s->regs[SDIO_CLK_CTRL] = 0x00001E03;
|
||||||
s->clk[UART_CLK_CTRL] = 0x00003F03;
|
s->regs[UART_CLK_CTRL] = 0x00003F03;
|
||||||
s->clk[SPI_CLK_CTRL] = 0x00003F03;
|
s->regs[SPI_CLK_CTRL] = 0x00003F03;
|
||||||
s->clk[CAN_CLK_CTRL] = 0x00501903;
|
s->regs[CAN_CLK_CTRL] = 0x00501903;
|
||||||
s->clk[DBG_CLK_CTRL] = 0x00000F03;
|
s->regs[DBG_CLK_CTRL] = 0x00000F03;
|
||||||
s->clk[PCAP_CLK_CTRL] = 0x00000F01;
|
s->regs[PCAP_CLK_CTRL] = 0x00000F01;
|
||||||
|
|
||||||
/* 0x170 - 0x1AC */
|
/* 0x170 - 0x1AC */
|
||||||
s->fpga[0][CLK_CTRL] = s->fpga[1][CLK_CTRL] = s->fpga[2][CLK_CTRL] =
|
s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL]
|
||||||
s->fpga[3][CLK_CTRL] = 0x00101800;
|
= s->regs[FPGA3_CLK_CTRL] = 0x00101800;
|
||||||
s->fpga[0][THR_STA] = s->fpga[1][THR_STA] = s->fpga[2][THR_STA] =
|
s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA]
|
||||||
s->fpga[3][THR_STA] = 0x00010000;
|
= s->regs[FPGA3_THR_STA] = 0x00010000;
|
||||||
|
|
||||||
/* 0x1B0 - 0x1D8 */
|
/* 0x1B0 - 0x1D8 */
|
||||||
s->misc[BANDGAP_TRIP] = 0x0000001F;
|
s->regs[BANDGAP_TRIP] = 0x0000001F;
|
||||||
s->misc[PLL_PREDIVISOR] = 0x00000001;
|
s->regs[PLL_PREDIVISOR] = 0x00000001;
|
||||||
s->misc[CLK_621_TRUE] = 0x00000001;
|
s->regs[CLK_621_TRUE] = 0x00000001;
|
||||||
|
|
||||||
/* 0x200 - 0x25C */
|
/* 0x200 - 0x25C */
|
||||||
s->reset[FPGA] = 0x01F33F0F;
|
s->regs[FPGA_RST_CTRL] = 0x01F33F0F;
|
||||||
s->reset[RST_REASON] = 0x00000040;
|
s->regs[RST_REASON] = 0x00000040;
|
||||||
|
|
||||||
|
s->regs[BOOT_MODE] = 0x00000001;
|
||||||
|
|
||||||
/* 0x700 - 0x7D4 */
|
/* 0x700 - 0x7D4 */
|
||||||
for (i = 0; i < 54; i++) {
|
for (i = 0; i < 54; i++) {
|
||||||
s->mio[i] = 0x00001601;
|
s->regs[MIO + i] = 0x00001601;
|
||||||
}
|
}
|
||||||
for (i = 2; i <= 8; i++) {
|
for (i = 2; i <= 8; i++) {
|
||||||
s->mio[i] = 0x00000601;
|
s->regs[MIO + i] = 0x00000601;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MIO_MST_TRI0, MIO_MST_TRI1 */
|
s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF;
|
||||||
s->mio_func[2] = s->mio_func[3] = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
s->cpu_ram[0] = s->cpu_ram[1] = s->cpu_ram[3] =
|
s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3]
|
||||||
s->cpu_ram[4] = s->cpu_ram[7] = 0x00010101;
|
= s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7]
|
||||||
s->cpu_ram[2] = s->cpu_ram[5] = 0x01010101;
|
= 0x00010101;
|
||||||
s->cpu_ram[6] = 0x00000001;
|
s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101;
|
||||||
|
s->regs[CPU_RAM + 6] = 0x00000001;
|
||||||
|
|
||||||
s->iou[0] = s->iou[1] = s->iou[2] = s->iou[3] = 0x09090909;
|
s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3]
|
||||||
s->iou[4] = s->iou[5] = 0x00090909;
|
= 0x09090909;
|
||||||
s->iou[6] = 0x00000909;
|
s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909;
|
||||||
|
s->regs[IOU + 6] = 0x00000909;
|
||||||
|
|
||||||
s->dmac_ram = 0x00000009;
|
s->regs[DMAC_RAM] = 0x00000009;
|
||||||
|
|
||||||
s->afi[0][0] = s->afi[0][1] = 0x09090909;
|
s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909;
|
||||||
s->afi[1][0] = s->afi[1][1] = 0x09090909;
|
s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909;
|
||||||
s->afi[2][0] = s->afi[2][1] = 0x09090909;
|
s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909;
|
||||||
s->afi[3][0] = s->afi[3][1] = 0x09090909;
|
s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909;
|
||||||
s->afi[0][2] = s->afi[1][2] = s->afi[2][2] = s->afi[3][2] = 0x00000909;
|
s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2]
|
||||||
|
= s->regs[AFI3 + 2] = 0x00000909;
|
||||||
|
|
||||||
s->ocm[0] = 0x01010101;
|
s->regs[OCM + 0] = 0x01010101;
|
||||||
s->ocm[1] = s->ocm[2] = 0x09090909;
|
s->regs[OCM + 1] = s->regs[OCM + 2] = 0x09090909;
|
||||||
|
|
||||||
s->devci_ram = 0x00000909;
|
s->regs[DEVCI_RAM] = 0x00000909;
|
||||||
s->csg_ram = 0x00000001;
|
s->regs[CSG_RAM] = 0x00000001;
|
||||||
|
|
||||||
s->ddriob[0] = s->ddriob[1] = s->ddriob[2] = s->ddriob[3] = 0x00000e00;
|
s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2]
|
||||||
s->ddriob[4] = s->ddriob[5] = s->ddriob[6] = 0x00000e00;
|
= s->regs[DDRIOB + 3] = 0x00000e00;
|
||||||
s->ddriob[12] = 0x00000021;
|
s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6]
|
||||||
|
= 0x00000e00;
|
||||||
|
s->regs[DDRIOB + 12] = 0x00000021;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t zynq_slcr_read_imp(void *opaque,
|
|
||||||
hwaddr offset)
|
|
||||||
{
|
|
||||||
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
|
|
||||||
|
|
||||||
|
static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
|
||||||
|
{
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case 0x0: /* SCL */
|
case LOCK:
|
||||||
return s->scl;
|
case UNLOCK:
|
||||||
case 0x4: /* LOCK */
|
case DDR_CAL_START:
|
||||||
case 0x8: /* UNLOCK */
|
case DDR_REF_START:
|
||||||
DB_PRINT("Reading SCLR_LOCK/UNLOCK is not enabled\n");
|
return !rnw; /* Write only */
|
||||||
return 0;
|
case LOCKSTA:
|
||||||
case 0x0C: /* LOCKSTA */
|
case FPGA0_THR_STA:
|
||||||
return s->lockval;
|
case FPGA1_THR_STA:
|
||||||
case 0x100 ... 0x11C:
|
case FPGA2_THR_STA:
|
||||||
return s->pll[(offset - 0x100) / 4];
|
case FPGA3_THR_STA:
|
||||||
case 0x120 ... 0x16C:
|
case BOOT_MODE:
|
||||||
return s->clk[(offset - 0x120) / 4];
|
case PSS_IDCODE:
|
||||||
case 0x170 ... 0x1AC:
|
case DDR_CMD_STA:
|
||||||
return s->fpga[0][(offset - 0x170) / 4];
|
case DDR_DFI_STATUS:
|
||||||
case 0x1B0 ... 0x1D8:
|
case PLL_STATUS:
|
||||||
return s->misc[(offset - 0x1B0) / 4];
|
return rnw;/* read only */
|
||||||
case 0x200 ... 0x258:
|
case SCL:
|
||||||
return s->reset[(offset - 0x200) / 4];
|
case ARM_PLL_CTRL ... IO_PLL_CTRL:
|
||||||
case 0x25c:
|
case ARM_PLL_CFG ... IO_PLL_CFG:
|
||||||
return 1;
|
case ARM_CLK_CTRL ... TOPSW_CLK_CTRL:
|
||||||
case 0x300:
|
case FPGA0_CLK_CTRL ... FPGA0_THR_CNT:
|
||||||
return s->apu_ctrl;
|
case FPGA1_CLK_CTRL ... FPGA1_THR_CNT:
|
||||||
case 0x304:
|
case FPGA2_CLK_CTRL ... FPGA2_THR_CNT:
|
||||||
return s->wdt_clk_sel;
|
case FPGA3_CLK_CTRL ... FPGA3_THR_CNT:
|
||||||
case 0x400 ... 0x408:
|
case BANDGAP_TRIP:
|
||||||
return s->tz_ocm[(offset - 0x400) / 4];
|
case PLL_PREDIVISOR:
|
||||||
case 0x430:
|
case CLK_621_TRUE:
|
||||||
return s->tz_ddr;
|
case PSS_RST_CTRL ... A9_CPU_RST_CTRL:
|
||||||
case 0x440 ... 0x448:
|
case RS_AWDT_CTRL:
|
||||||
return s->tz_dma[(offset - 0x440) / 4];
|
case RST_REASON:
|
||||||
case 0x450 ... 0x458:
|
case REBOOT_STATUS:
|
||||||
return s->tz_misc[(offset - 0x450) / 4];
|
case APU_CTRL:
|
||||||
case 0x484 ... 0x488:
|
case WDT_CLK_SEL:
|
||||||
return s->tz_fpga[(offset - 0x484) / 4];
|
case TZ_DMA_NS ... TZ_DMA_PERIPH_NS:
|
||||||
case 0x500:
|
case DDR_URGENT:
|
||||||
return s->dbg_ctrl;
|
case DDR_URGENT_SEL:
|
||||||
case 0x530:
|
case MIO ... MIO + MIO_LENGTH - 1:
|
||||||
return s->pss_idcode;
|
case MIO_LOOPBACK ... MIO_MST_TRI1:
|
||||||
case 0x600 ... 0x620:
|
case SD0_WP_CD_SEL:
|
||||||
if (offset == 0x604) {
|
case SD1_WP_CD_SEL:
|
||||||
goto bad_reg;
|
case LVL_SHFTR_EN:
|
||||||
}
|
case OCM_CFG:
|
||||||
return s->ddr[(offset - 0x600) / 4];
|
case CPU_RAM:
|
||||||
case 0x700 ... 0x7D4:
|
case IOU:
|
||||||
return s->mio[(offset - 0x700) / 4];
|
case DMAC_RAM:
|
||||||
case 0x800 ... 0x810:
|
case AFI0 ... AFI3 + AFI_LENGTH - 1:
|
||||||
return s->mio_func[(offset - 0x800) / 4];
|
case OCM:
|
||||||
case 0x830 ... 0x834:
|
case DEVCI_RAM:
|
||||||
return s->sd[(offset - 0x830) / 4];
|
case CSG_RAM:
|
||||||
case 0x900:
|
case GPIOB_CTRL ... GPIOB_CFG_CMOS33:
|
||||||
return s->lvl_shftr_en;
|
case GPIOB_CFG_HSTL:
|
||||||
case 0x910:
|
case GPIOB_DRVR_BIAS_CTRL:
|
||||||
return s->ocm_cfg;
|
case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1:
|
||||||
case 0xA00 ... 0xA1C:
|
return true;
|
||||||
return s->cpu_ram[(offset - 0xA00) / 4];
|
|
||||||
case 0xA30 ... 0xA48:
|
|
||||||
return s->iou[(offset - 0xA30) / 4];
|
|
||||||
case 0xA50:
|
|
||||||
return s->dmac_ram;
|
|
||||||
case 0xA60 ... 0xA8C:
|
|
||||||
return s->afi[0][(offset - 0xA60) / 4];
|
|
||||||
case 0xA90 ... 0xA98:
|
|
||||||
return s->ocm[(offset - 0xA90) / 4];
|
|
||||||
case 0xAA0:
|
|
||||||
return s->devci_ram;
|
|
||||||
case 0xAB0:
|
|
||||||
return s->csg_ram;
|
|
||||||
case 0xB00 ... 0xB2C:
|
|
||||||
return s->gpiob[(offset - 0xB00) / 4];
|
|
||||||
case 0xB40 ... 0xB74:
|
|
||||||
return s->ddriob[(offset - 0xB40) / 4];
|
|
||||||
default:
|
default:
|
||||||
bad_reg:
|
return false;
|
||||||
DB_PRINT("Bad register offset 0x%x\n", (int)offset);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
|
static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
uint32_t ret = zynq_slcr_read_imp(opaque, offset);
|
ZynqSLCRState *s = opaque;
|
||||||
|
offset /= 4;
|
||||||
|
uint32_t ret = s->regs[offset];
|
||||||
|
|
||||||
DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)ret);
|
if (!zynq_slcr_check_offset(offset, true)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to "
|
||||||
|
" addr %" HWADDR_PRIx "\n", offset * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset * 4, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,148 +357,55 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
|
|||||||
uint64_t val, unsigned size)
|
uint64_t val, unsigned size)
|
||||||
{
|
{
|
||||||
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
|
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
|
||||||
|
offset /= 4;
|
||||||
|
|
||||||
DB_PRINT("offset: %08x data: %08x\n", (unsigned)offset, (unsigned)val);
|
DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n", offset * 4, val);
|
||||||
|
|
||||||
|
if (!zynq_slcr_check_offset(offset, false)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid write access to "
|
||||||
|
"addr %" HWADDR_PRIx "\n", offset * 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case 0x00: /* SCL */
|
case SCL:
|
||||||
s->scl = val & 0x1;
|
s->regs[SCL] = val & 0x1;
|
||||||
return;
|
return;
|
||||||
case 0x4: /* SLCR_LOCK */
|
case LOCK:
|
||||||
if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
|
if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
|
||||||
DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
||||||
(unsigned)val & 0xFFFF);
|
(unsigned)val & 0xFFFF);
|
||||||
s->lockval = 1;
|
s->regs[LOCKSTA] = 1;
|
||||||
} else {
|
} else {
|
||||||
DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
||||||
(int)offset, (unsigned)val & 0xFFFF);
|
(int)offset, (unsigned)val & 0xFFFF);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0x8: /* SLCR_UNLOCK */
|
case UNLOCK:
|
||||||
if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
|
if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
|
||||||
DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
|
||||||
(unsigned)val & 0xFFFF);
|
(unsigned)val & 0xFFFF);
|
||||||
s->lockval = 0;
|
s->regs[LOCKSTA] = 0;
|
||||||
} else {
|
} else {
|
||||||
DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
|
||||||
(int)offset, (unsigned)val & 0xFFFF);
|
(int)offset, (unsigned)val & 0xFFFF);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0xc: /* LOCKSTA */
|
}
|
||||||
DB_PRINT("Writing SCLR_LOCKSTA is not enabled\n");
|
|
||||||
|
if (!s->regs[LOCKSTA]) {
|
||||||
|
s->regs[offset / 4] = val;
|
||||||
|
} else {
|
||||||
|
DB_PRINT("SCLR registers are locked. Unlock them first\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->lockval) {
|
switch (offset) {
|
||||||
switch (offset) {
|
case PSS_RST_CTRL:
|
||||||
case 0x100 ... 0x11C:
|
if (val & R_PSS_RST_CTRL_SOFT_RST) {
|
||||||
if (offset == 0x10C) {
|
qemu_system_reset_request();
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->pll[(offset - 0x100) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x120 ... 0x16C:
|
|
||||||
s->clk[(offset - 0x120) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x170 ... 0x1AC:
|
|
||||||
s->fpga[0][(offset - 0x170) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x1B0 ... 0x1D8:
|
|
||||||
s->misc[(offset - 0x1B0) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x200 ... 0x25C:
|
|
||||||
if (offset == 0x250) {
|
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->reset[(offset - 0x200) / 4] = val;
|
|
||||||
if (offset == 0x200 && (val & R_PSS_RST_CTRL_SOFT_RST)) {
|
|
||||||
qemu_system_reset_request();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x300:
|
|
||||||
s->apu_ctrl = val;
|
|
||||||
break;
|
|
||||||
case 0x304:
|
|
||||||
s->wdt_clk_sel = val;
|
|
||||||
break;
|
|
||||||
case 0x400 ... 0x408:
|
|
||||||
s->tz_ocm[(offset - 0x400) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x430:
|
|
||||||
s->tz_ddr = val;
|
|
||||||
break;
|
|
||||||
case 0x440 ... 0x448:
|
|
||||||
s->tz_dma[(offset - 0x440) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x450 ... 0x458:
|
|
||||||
s->tz_misc[(offset - 0x450) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x484 ... 0x488:
|
|
||||||
s->tz_fpga[(offset - 0x484) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x500:
|
|
||||||
s->dbg_ctrl = val;
|
|
||||||
break;
|
|
||||||
case 0x530:
|
|
||||||
s->pss_idcode = val;
|
|
||||||
break;
|
|
||||||
case 0x600 ... 0x620:
|
|
||||||
if (offset == 0x604) {
|
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->ddr[(offset - 0x600) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x700 ... 0x7D4:
|
|
||||||
s->mio[(offset - 0x700) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x800 ... 0x810:
|
|
||||||
s->mio_func[(offset - 0x800) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x830 ... 0x834:
|
|
||||||
s->sd[(offset - 0x830) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0x900:
|
|
||||||
s->lvl_shftr_en = val;
|
|
||||||
break;
|
|
||||||
case 0x910:
|
|
||||||
break;
|
|
||||||
case 0xA00 ... 0xA1C:
|
|
||||||
s->cpu_ram[(offset - 0xA00) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xA30 ... 0xA48:
|
|
||||||
s->iou[(offset - 0xA30) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xA50:
|
|
||||||
s->dmac_ram = val;
|
|
||||||
break;
|
|
||||||
case 0xA60 ... 0xA8C:
|
|
||||||
s->afi[0][(offset - 0xA60) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xA90:
|
|
||||||
s->ocm[0] = val;
|
|
||||||
break;
|
|
||||||
case 0xAA0:
|
|
||||||
s->devci_ram = val;
|
|
||||||
break;
|
|
||||||
case 0xAB0:
|
|
||||||
s->csg_ram = val;
|
|
||||||
break;
|
|
||||||
case 0xB00 ... 0xB2C:
|
|
||||||
if (offset == 0xB20 || offset == 0xB2C) {
|
|
||||||
goto bad_reg;
|
|
||||||
}
|
|
||||||
s->gpiob[(offset - 0xB00) / 4] = val;
|
|
||||||
break;
|
|
||||||
case 0xB40 ... 0xB74:
|
|
||||||
s->ddriob[(offset - 0xB40) / 4] = val;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
bad_reg:
|
|
||||||
DB_PRINT("Bad register write %x <= %08x\n", (int)offset,
|
|
||||||
(unsigned)val);
|
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
DB_PRINT("SCLR registers are locked. Unlock them first\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,23 +415,22 @@ static const MemoryRegionOps slcr_ops = {
|
|||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int zynq_slcr_init(SysBusDevice *dev)
|
static void zynq_slcr_init(Object *obj)
|
||||||
{
|
{
|
||||||
ZynqSLCRState *s = ZYNQ_SLCR(dev);
|
ZynqSLCRState *s = ZYNQ_SLCR(obj);
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, OBJECT(s), &slcr_ops, s, "slcr", 0x1000);
|
memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr",
|
||||||
sysbus_init_mmio(dev, &s->iomem);
|
ZYNQ_SLCR_MMIO_SIZE);
|
||||||
|
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_zynq_slcr = {
|
static const VMStateDescription vmstate_zynq_slcr = {
|
||||||
.name = "zynq_slcr",
|
.name = "zynq_slcr",
|
||||||
.version_id = 1,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 2,
|
||||||
.minimum_version_id_old = 1,
|
.minimum_version_id_old = 2,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8_ARRAY(data, ZynqSLCRState, 0x1000),
|
VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -522,9 +438,7 @@ static const VMStateDescription vmstate_zynq_slcr = {
|
|||||||
static void zynq_slcr_class_init(ObjectClass *klass, void *data)
|
static void zynq_slcr_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
sdc->init = zynq_slcr_init;
|
|
||||||
dc->vmsd = &vmstate_zynq_slcr;
|
dc->vmsd = &vmstate_zynq_slcr;
|
||||||
dc->reset = zynq_slcr_reset;
|
dc->reset = zynq_slcr_reset;
|
||||||
}
|
}
|
||||||
@@ -534,6 +448,7 @@ static const TypeInfo zynq_slcr_info = {
|
|||||||
.name = TYPE_ZYNQ_SLCR,
|
.name = TYPE_ZYNQ_SLCR,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(ZynqSLCRState),
|
.instance_size = sizeof(ZynqSLCRState),
|
||||||
|
.instance_init = zynq_slcr_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void zynq_slcr_register_types(void)
|
static void zynq_slcr_register_types(void)
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ static uint8_t padding[60];
|
|||||||
static void mii_set_link(RTL8201CPState *mii, bool link_ok)
|
static void mii_set_link(RTL8201CPState *mii, bool link_ok)
|
||||||
{
|
{
|
||||||
if (link_ok) {
|
if (link_ok) {
|
||||||
mii->bmsr |= MII_BMSR_LINK_ST;
|
mii->bmsr |= MII_BMSR_LINK_ST | MII_BMSR_AN_COMP;
|
||||||
mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 |
|
mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 |
|
||||||
MII_ANAR_CSMACD;
|
MII_ANAR_CSMACD;
|
||||||
} else {
|
} else {
|
||||||
mii->bmsr &= ~MII_BMSR_LINK_ST;
|
mii->bmsr &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
|
||||||
mii->anlpar = MII_ANAR_TX;
|
mii->anlpar = MII_ANAR_TX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -391,9 +391,11 @@ static void aw_emac_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
break;
|
break;
|
||||||
case EMAC_INT_CTL_REG:
|
case EMAC_INT_CTL_REG:
|
||||||
s->int_ctl = value;
|
s->int_ctl = value;
|
||||||
|
aw_emac_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case EMAC_INT_STA_REG:
|
case EMAC_INT_STA_REG:
|
||||||
s->int_sta &= ~value;
|
s->int_sta &= ~value;
|
||||||
|
aw_emac_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case EMAC_MAC_MADR_REG:
|
case EMAC_MAC_MADR_REG:
|
||||||
s->phy_target = value;
|
s->phy_target = value;
|
||||||
|
|||||||
@@ -1093,7 +1093,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
|
|||||||
uint32_t phy_addr, reg_num;
|
uint32_t phy_addr, reg_num;
|
||||||
|
|
||||||
phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
||||||
if (phy_addr == BOARD_PHY_ADDRESS) {
|
if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
|
||||||
reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
||||||
retval &= 0xFFFF0000;
|
retval &= 0xFFFF0000;
|
||||||
retval |= gem_phy_read(s, reg_num);
|
retval |= gem_phy_read(s, reg_num);
|
||||||
@@ -1193,7 +1193,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
|
|||||||
uint32_t phy_addr, reg_num;
|
uint32_t phy_addr, reg_num;
|
||||||
|
|
||||||
phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
|
||||||
if (phy_addr == BOARD_PHY_ADDRESS) {
|
if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {
|
||||||
reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
|
||||||
gem_phy_write(s, reg_num, val);
|
gem_phy_write(s, reg_num, val);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -677,7 +677,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
|
if (mac_data.entries <= MAC_TABLE_ENTRIES - in_use) {
|
||||||
s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],
|
s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],
|
||||||
mac_data.entries * ETH_ALEN);
|
mac_data.entries * ETH_ALEN);
|
||||||
if (s != mac_data.entries * ETH_ALEN) {
|
if (s != mac_data.entries * ETH_ALEN) {
|
||||||
|
|||||||
@@ -52,6 +52,9 @@
|
|||||||
#define VMXNET3_DEVICE_VERSION 0x1
|
#define VMXNET3_DEVICE_VERSION 0x1
|
||||||
#define VMXNET3_DEVICE_REVISION 0x1
|
#define VMXNET3_DEVICE_REVISION 0x1
|
||||||
|
|
||||||
|
/* Number of interrupt vectors for non-MSIx modes */
|
||||||
|
#define VMXNET3_MAX_NMSIX_INTRS (1)
|
||||||
|
|
||||||
/* Macros for rings descriptors access */
|
/* Macros for rings descriptors access */
|
||||||
#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
|
#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
|
||||||
(vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
|
(vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
|
||||||
@@ -1305,6 +1308,51 @@ static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
|
|||||||
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
|
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
|
||||||
|
{
|
||||||
|
int max_ints = is_msix ? VMXNET3_MAX_INTRS : VMXNET3_MAX_NMSIX_INTRS;
|
||||||
|
if (idx >= max_ints) {
|
||||||
|
hw_error("Bad interrupt index: %d\n", idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vmxnet3_validate_interrupts(VMXNET3State *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
VMW_CFPRN("Verifying event interrupt index (%d)", s->event_int_idx);
|
||||||
|
vmxnet3_validate_interrupt_idx(s->msix_used, s->event_int_idx);
|
||||||
|
|
||||||
|
for (i = 0; i < s->txq_num; i++) {
|
||||||
|
int idx = s->txq_descr[i].intr_idx;
|
||||||
|
VMW_CFPRN("Verifying TX queue %d interrupt index (%d)", i, idx);
|
||||||
|
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < s->rxq_num; i++) {
|
||||||
|
int idx = s->rxq_descr[i].intr_idx;
|
||||||
|
VMW_CFPRN("Verifying RX queue %d interrupt index (%d)", i, idx);
|
||||||
|
vmxnet3_validate_interrupt_idx(s->msix_used, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vmxnet3_validate_queues(VMXNET3State *s)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* txq_num and rxq_num are total number of queues
|
||||||
|
* configured by guest. These numbers must not
|
||||||
|
* exceed corresponding maximal values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (s->txq_num > VMXNET3_DEVICE_MAX_TX_QUEUES) {
|
||||||
|
hw_error("Bad TX queues number: %d\n", s->txq_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->rxq_num > VMXNET3_DEVICE_MAX_RX_QUEUES) {
|
||||||
|
hw_error("Bad RX queues number: %d\n", s->rxq_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void vmxnet3_activate_device(VMXNET3State *s)
|
static void vmxnet3_activate_device(VMXNET3State *s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -1351,7 +1399,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
|||||||
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
|
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
|
||||||
|
|
||||||
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
|
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
|
||||||
assert(s->txq_num <= VMXNET3_DEVICE_MAX_TX_QUEUES);
|
vmxnet3_validate_queues(s);
|
||||||
|
|
||||||
qdescr_table_pa =
|
qdescr_table_pa =
|
||||||
VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
|
VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
|
||||||
@@ -1447,6 +1495,8 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
|||||||
sizeof(s->rxq_descr[i].rxq_stats));
|
sizeof(s->rxq_descr[i].rxq_stats));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vmxnet3_validate_interrupts(s);
|
||||||
|
|
||||||
/* Make sure everything is in place before device activation */
|
/* Make sure everything is in place before device activation */
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
||||||
@@ -2005,7 +2055,6 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VMXNET3_MSI_NUM_VECTORS (1)
|
|
||||||
#define VMXNET3_MSI_OFFSET (0x50)
|
#define VMXNET3_MSI_OFFSET (0x50)
|
||||||
#define VMXNET3_USE_64BIT (true)
|
#define VMXNET3_USE_64BIT (true)
|
||||||
#define VMXNET3_PER_VECTOR_MASK (false)
|
#define VMXNET3_PER_VECTOR_MASK (false)
|
||||||
@@ -2016,7 +2065,7 @@ vmxnet3_init_msi(VMXNET3State *s)
|
|||||||
PCIDevice *d = PCI_DEVICE(s);
|
PCIDevice *d = PCI_DEVICE(s);
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MSI_NUM_VECTORS,
|
res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MAX_NMSIX_INTRS,
|
||||||
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
|
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
|
||||||
if (0 > res) {
|
if (0 > res) {
|
||||||
VMW_WRPRN("Failed to initialize MSI, error %d", res);
|
VMW_WRPRN("Failed to initialize MSI, error %d", res);
|
||||||
@@ -2342,6 +2391,9 @@ static int vmxnet3_post_load(void *opaque, int version_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vmxnet3_validate_queues(s);
|
||||||
|
vmxnet3_validate_interrupts(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,9 +145,9 @@ static uint64_t raven_io_read(void *opaque, hwaddr addr,
|
|||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
return buf[0];
|
return buf[0];
|
||||||
} else if (size == 2) {
|
} else if (size == 2) {
|
||||||
return lduw_p(buf);
|
return lduw_le_p(buf);
|
||||||
} else if (size == 4) {
|
} else if (size == 4) {
|
||||||
return ldl_p(buf);
|
return ldl_le_p(buf);
|
||||||
} else {
|
} else {
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
@@ -164,9 +164,9 @@ static void raven_io_write(void *opaque, hwaddr addr,
|
|||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
buf[0] = val;
|
buf[0] = val;
|
||||||
} else if (size == 2) {
|
} else if (size == 2) {
|
||||||
stw_p(buf, val);
|
stw_le_p(buf, val);
|
||||||
} else if (size == 4) {
|
} else if (size == 4) {
|
||||||
stl_p(buf, val);
|
stl_le_p(buf, val);
|
||||||
} else {
|
} else {
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -649,7 +649,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params)
|
|||||||
input = (qemu_irq *)env->irq_inputs;
|
input = (qemu_irq *)env->irq_inputs;
|
||||||
irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
|
irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
|
||||||
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
|
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
|
||||||
env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
|
env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
|
||||||
env->mpic_iack = MPC8544_CCSRBAR_BASE +
|
env->mpic_iack = MPC8544_CCSRBAR_BASE +
|
||||||
MPC8544_MPIC_REGS_OFFSET + 0xa0;
|
MPC8544_MPIC_REGS_OFFSET + 0xa0;
|
||||||
|
|
||||||
|
|||||||
92
hw/ppc/ppc.c
92
hw/ppc/ppc.c
@@ -620,6 +620,13 @@ static void cpu_ppc_tb_start (CPUPPCState *env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ppc_decr_clear_on_delivery(CPUPPCState *env)
|
||||||
|
{
|
||||||
|
ppc_tb_t *tb_env = env->tb_env;
|
||||||
|
int flags = PPC_DECR_UNDERFLOW_TRIGGERED | PPC_DECR_UNDERFLOW_LEVEL;
|
||||||
|
return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
|
static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
|
||||||
{
|
{
|
||||||
ppc_tb_t *tb_env = env->tb_env;
|
ppc_tb_t *tb_env = env->tb_env;
|
||||||
@@ -677,6 +684,11 @@ static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
|
|||||||
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
|
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
|
||||||
|
{
|
||||||
|
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
|
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
|
||||||
{
|
{
|
||||||
/* Raise it */
|
/* Raise it */
|
||||||
@@ -684,11 +696,16 @@ static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
|
|||||||
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
|
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
|
||||||
|
{
|
||||||
|
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
||||||
QEMUTimer *timer,
|
QEMUTimer *timer,
|
||||||
void (*raise_excp)(PowerPCCPU *),
|
void (*raise_excp)(void *),
|
||||||
uint32_t decr, uint32_t value,
|
void (*lower_excp)(PowerPCCPU *),
|
||||||
int is_excp)
|
uint32_t decr, uint32_t value)
|
||||||
{
|
{
|
||||||
CPUPPCState *env = &cpu->env;
|
CPUPPCState *env = &cpu->env;
|
||||||
ppc_tb_t *tb_env = env->tb_env;
|
ppc_tb_t *tb_env = env->tb_env;
|
||||||
@@ -702,59 +719,74 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Going from 2 -> 1, 1 -> 0 or 0 -> -1 is the event to generate a DEC
|
||||||
|
* interrupt.
|
||||||
|
*
|
||||||
|
* If we get a really small DEC value, we can assume that by the time we
|
||||||
|
* handled it we should inject an interrupt already.
|
||||||
|
*
|
||||||
|
* On MSB level based DEC implementations the MSB always means the interrupt
|
||||||
|
* is pending, so raise it on those.
|
||||||
|
*
|
||||||
|
* On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers
|
||||||
|
* an edge interrupt, so raise it here too.
|
||||||
|
*/
|
||||||
|
if ((value < 3) ||
|
||||||
|
((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x80000000)) ||
|
||||||
|
((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000)
|
||||||
|
&& !(decr & 0x80000000))) {
|
||||||
|
(*raise_excp)(cpu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On MSB level based systems a 0 for the MSB stops interrupt delivery */
|
||||||
|
if (!(value & 0x80000000) && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
|
||||||
|
(*lower_excp)(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the next timer event */
|
||||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
|
next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
|
||||||
if (is_excp) {
|
|
||||||
next += *nextp - now;
|
|
||||||
}
|
|
||||||
if (next == now) {
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
*nextp = next;
|
*nextp = next;
|
||||||
|
|
||||||
/* Adjust timer */
|
/* Adjust timer */
|
||||||
timer_mod(timer, next);
|
timer_mod(timer, next);
|
||||||
|
|
||||||
/* If we set a negative value and the decrementer was positive, raise an
|
|
||||||
* exception.
|
|
||||||
*/
|
|
||||||
if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
|
|
||||||
&& (value & 0x80000000)
|
|
||||||
&& !(decr & 0x80000000)) {
|
|
||||||
(*raise_excp)(cpu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
|
static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
|
||||||
uint32_t value, int is_excp)
|
uint32_t value)
|
||||||
{
|
{
|
||||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||||
|
|
||||||
__cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
|
__cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
|
||||||
&cpu_ppc_decr_excp, decr, value, is_excp);
|
tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr,
|
||||||
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
|
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
|
||||||
{
|
{
|
||||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||||
|
|
||||||
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
|
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_ppc_decr_cb(void *opaque)
|
static void cpu_ppc_decr_cb(void *opaque)
|
||||||
{
|
{
|
||||||
PowerPCCPU *cpu = opaque;
|
PowerPCCPU *cpu = opaque;
|
||||||
|
|
||||||
_cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
cpu_ppc_decr_excp(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
|
static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
|
||||||
uint32_t value, int is_excp)
|
uint32_t value)
|
||||||
{
|
{
|
||||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||||
|
|
||||||
if (tb_env->hdecr_timer != NULL) {
|
if (tb_env->hdecr_timer != NULL) {
|
||||||
__cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
|
__cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
|
||||||
&cpu_ppc_hdecr_excp, hdecr, value, is_excp);
|
tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower,
|
||||||
|
hdecr, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,14 +794,14 @@ void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
|
|||||||
{
|
{
|
||||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||||
|
|
||||||
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
|
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_ppc_hdecr_cb(void *opaque)
|
static void cpu_ppc_hdecr_cb(void *opaque)
|
||||||
{
|
{
|
||||||
PowerPCCPU *cpu = opaque;
|
PowerPCCPU *cpu = opaque;
|
||||||
|
|
||||||
_cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
cpu_ppc_hdecr_excp(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
|
static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
|
||||||
@@ -792,8 +824,8 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
|||||||
* if a decrementer exception is pending when it enables msr_ee at startup,
|
* if a decrementer exception is pending when it enables msr_ee at startup,
|
||||||
* it's not ready to handle it...
|
* it's not ready to handle it...
|
||||||
*/
|
*/
|
||||||
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||||
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||||
cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
|
cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,6 +838,10 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
|
|||||||
tb_env = g_malloc0(sizeof(ppc_tb_t));
|
tb_env = g_malloc0(sizeof(ppc_tb_t));
|
||||||
env->tb_env = tb_env;
|
env->tb_env = tb_env;
|
||||||
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
|
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
|
||||||
|
if (env->insns_flags & PPC_SEGMENT_64B) {
|
||||||
|
/* All Book3S 64bit CPUs implement level based DEC logic */
|
||||||
|
tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL;
|
||||||
|
}
|
||||||
/* Create new timer */
|
/* Create new timer */
|
||||||
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
|
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
|
||||||
if (0) {
|
if (0) {
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ static void spin_reset(void *opaque)
|
|||||||
for (i = 0; i < MAX_CPUS; i++) {
|
for (i = 0; i < MAX_CPUS; i++) {
|
||||||
SpinInfo *info = &s->spin[i];
|
SpinInfo *info = &s->spin[i];
|
||||||
|
|
||||||
info->pir = i;
|
stl_p(&info->pir, i);
|
||||||
info->r3 = i;
|
stq_p(&info->r3, i);
|
||||||
info->addr = 1;
|
stq_p(&info->addr, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,15 @@
|
|||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "hw/timer/allwinner-a10-pit.h"
|
#include "hw/timer/allwinner-a10-pit.h"
|
||||||
|
|
||||||
|
static void a10_pit_update_irq(AwA10PITState *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
||||||
|
qemu_set_irq(s->irq[i], !!(s->irq_status & s->irq_enable & (1 << i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
{
|
{
|
||||||
AwA10PITState *s = AW_A10_PIT(opaque);
|
AwA10PITState *s = AW_A10_PIT(opaque);
|
||||||
@@ -65,6 +74,22 @@ static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void a10_pit_set_freq(AwA10PITState *s, int index)
|
||||||
|
{
|
||||||
|
uint32_t prescaler, source, source_freq;
|
||||||
|
|
||||||
|
prescaler = 1 << extract32(s->control[index], 4, 3);
|
||||||
|
source = extract32(s->control[index], 2, 2);
|
||||||
|
source_freq = s->clk_freq[source];
|
||||||
|
|
||||||
|
if (source_freq) {
|
||||||
|
ptimer_set_freq(s->timer[index], source_freq / prescaler);
|
||||||
|
} else {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid clock source %u\n",
|
||||||
|
__func__, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
@@ -74,9 +99,11 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
switch (offset) {
|
switch (offset) {
|
||||||
case AW_A10_PIT_TIMER_IRQ_EN:
|
case AW_A10_PIT_TIMER_IRQ_EN:
|
||||||
s->irq_enable = value;
|
s->irq_enable = value;
|
||||||
|
a10_pit_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIT_TIMER_IRQ_ST:
|
case AW_A10_PIT_TIMER_IRQ_ST:
|
||||||
s->irq_status &= ~value;
|
s->irq_status &= ~value;
|
||||||
|
a10_pit_update_irq(s);
|
||||||
break;
|
break;
|
||||||
case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
|
case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
|
||||||
index = offset & 0xf0;
|
index = offset & 0xf0;
|
||||||
@@ -85,6 +112,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
switch (offset & 0x0f) {
|
switch (offset & 0x0f) {
|
||||||
case AW_A10_PIT_TIMER_CONTROL:
|
case AW_A10_PIT_TIMER_CONTROL:
|
||||||
s->control[index] = value;
|
s->control[index] = value;
|
||||||
|
a10_pit_set_freq(s, index);
|
||||||
if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
|
if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
|
||||||
ptimer_set_count(s->timer[index], s->interval[index]);
|
ptimer_set_count(s->timer[index], s->interval[index]);
|
||||||
}
|
}
|
||||||
@@ -150,6 +178,14 @@ static const MemoryRegionOps a10_pit_ops = {
|
|||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property a10_pit_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("clk0-freq", AwA10PITState, clk_freq[0], 0),
|
||||||
|
DEFINE_PROP_UINT32("clk1-freq", AwA10PITState, clk_freq[1], 0),
|
||||||
|
DEFINE_PROP_UINT32("clk2-freq", AwA10PITState, clk_freq[2], 0),
|
||||||
|
DEFINE_PROP_UINT32("clk3-freq", AwA10PITState, clk_freq[3], 0),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_a10_pit = {
|
static const VMStateDescription vmstate_a10_pit = {
|
||||||
.name = "a10.pit",
|
.name = "a10.pit",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
@@ -178,11 +214,14 @@ static void a10_pit_reset(DeviceState *dev)
|
|||||||
|
|
||||||
s->irq_enable = 0;
|
s->irq_enable = 0;
|
||||||
s->irq_status = 0;
|
s->irq_status = 0;
|
||||||
|
a10_pit_update_irq(s);
|
||||||
|
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
|
s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
|
||||||
s->interval[i] = 0;
|
s->interval[i] = 0;
|
||||||
s->count[i] = 0;
|
s->count[i] = 0;
|
||||||
ptimer_stop(s->timer[i]);
|
ptimer_stop(s->timer[i]);
|
||||||
|
a10_pit_set_freq(s, i);
|
||||||
}
|
}
|
||||||
s->watch_dog_mode = 0;
|
s->watch_dog_mode = 0;
|
||||||
s->watch_dog_control = 0;
|
s->watch_dog_control = 0;
|
||||||
@@ -193,18 +232,17 @@ static void a10_pit_reset(DeviceState *dev)
|
|||||||
|
|
||||||
static void a10_pit_timer_cb(void *opaque)
|
static void a10_pit_timer_cb(void *opaque)
|
||||||
{
|
{
|
||||||
AwA10PITState *s = AW_A10_PIT(opaque);
|
AwA10TimerContext *tc = opaque;
|
||||||
uint8_t i;
|
AwA10PITState *s = tc->container;
|
||||||
|
uint8_t i = tc->index;
|
||||||
|
|
||||||
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
if (s->control[i] & AW_A10_PIT_TIMER_EN) {
|
||||||
if (s->control[i] & AW_A10_PIT_TIMER_EN) {
|
s->irq_status |= 1 << i;
|
||||||
s->irq_status |= 1 << i;
|
if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
|
||||||
if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
|
ptimer_stop(s->timer[i]);
|
||||||
ptimer_stop(s->timer[i]);
|
s->control[i] &= ~AW_A10_PIT_TIMER_EN;
|
||||||
s->control[i] &= ~AW_A10_PIT_TIMER_EN;
|
|
||||||
}
|
|
||||||
qemu_irq_pulse(s->irq[i]);
|
|
||||||
}
|
}
|
||||||
|
a10_pit_update_irq(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,9 +261,12 @@ static void a10_pit_init(Object *obj)
|
|||||||
sysbus_init_mmio(sbd, &s->iomem);
|
sysbus_init_mmio(sbd, &s->iomem);
|
||||||
|
|
||||||
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
||||||
bh[i] = qemu_bh_new(a10_pit_timer_cb, s);
|
AwA10TimerContext *tc = &s->timer_context[i];
|
||||||
|
|
||||||
|
tc->container = s;
|
||||||
|
tc->index = i;
|
||||||
|
bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
|
||||||
s->timer[i] = ptimer_init(bh[i]);
|
s->timer[i] = ptimer_init(bh[i]);
|
||||||
ptimer_set_freq(s->timer[i], 240000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +275,7 @@ static void a10_pit_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->reset = a10_pit_reset;
|
dc->reset = a10_pit_reset;
|
||||||
|
dc->props = a10_pit_properties;
|
||||||
dc->desc = "allwinner a10 timer";
|
dc->desc = "allwinner a10 timer";
|
||||||
dc->vmsd = &vmstate_a10_pit;
|
dc->vmsd = &vmstate_a10_pit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -346,11 +346,13 @@ static void cadence_ttc_write(void *opaque, hwaddr offset,
|
|||||||
case 0x34:
|
case 0x34:
|
||||||
case 0x38:
|
case 0x38:
|
||||||
s->reg_match[0] = value & 0xffff;
|
s->reg_match[0] = value & 0xffff;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x3c: /* match register */
|
case 0x3c: /* match register */
|
||||||
case 0x40:
|
case 0x40:
|
||||||
case 0x44:
|
case 0x44:
|
||||||
s->reg_match[1] = value & 0xffff;
|
s->reg_match[1] = value & 0xffff;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x48: /* match register */
|
case 0x48: /* match register */
|
||||||
case 0x4c:
|
case 0x4c:
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ common-obj-y += ccid-card-passthru.o
|
|||||||
common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
|
common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_POSIX),y)
|
||||||
|
common-obj-$(CONFIG_USB_STORAGE_MTP) += dev-mtp.o
|
||||||
|
endif
|
||||||
|
|
||||||
# usb redirection
|
# usb redirection
|
||||||
common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o
|
common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ typedef struct msos_compat_hdr {
|
|||||||
typedef struct msos_compat_func {
|
typedef struct msos_compat_func {
|
||||||
uint8_t bFirstInterfaceNumber;
|
uint8_t bFirstInterfaceNumber;
|
||||||
uint8_t reserved_1;
|
uint8_t reserved_1;
|
||||||
uint8_t compatibleId[8];
|
char compatibleId[8];
|
||||||
uint8_t subCompatibleId[8];
|
uint8_t subCompatibleId[8];
|
||||||
uint8_t reserved_2[6];
|
uint8_t reserved_2[6];
|
||||||
} QEMU_PACKED msos_compat_func;
|
} QEMU_PACKED msos_compat_func;
|
||||||
@@ -59,6 +59,10 @@ static int usb_desc_msos_compat(const USBDesc *desc, uint8_t *dest)
|
|||||||
func = (void *)(dest + length);
|
func = (void *)(dest + length);
|
||||||
func->bFirstInterfaceNumber = 0;
|
func->bFirstInterfaceNumber = 0;
|
||||||
func->reserved_1 = 0x01;
|
func->reserved_1 = 0x01;
|
||||||
|
if (desc->msos->CompatibleID) {
|
||||||
|
snprintf(func->compatibleId, sizeof(func->compatibleId),
|
||||||
|
"%s", desc->msos->CompatibleID);
|
||||||
|
}
|
||||||
length += sizeof(*func);
|
length += sizeof(*func);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ struct USBDescOther {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescMSOS {
|
struct USBDescMSOS {
|
||||||
|
const char *CompatibleID;
|
||||||
const wchar_t *Label;
|
const wchar_t *Label;
|
||||||
bool SelectiveSuspendEnabled;
|
bool SelectiveSuspendEnabled;
|
||||||
};
|
};
|
||||||
|
|||||||
1103
hw/usb/dev-mtp.c
Normal file
1103
hw/usb/dev-mtp.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -180,7 +180,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
|
|||||||
QEMUOptionParameter *options, Error **errp);
|
QEMUOptionParameter *options, Error **errp);
|
||||||
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
BlockDriverState *bdrv_new(const char *device_name);
|
BlockDriverState *bdrv_new(const char *device_name, Error **errp);
|
||||||
void bdrv_make_anon(BlockDriverState *bs);
|
void bdrv_make_anon(BlockDriverState *bs);
|
||||||
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
|
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
|
||||||
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
|
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
|
||||||
@@ -190,6 +190,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
|||||||
QDict *options, const char *bdref_key, int flags,
|
QDict *options, const char *bdref_key, int flags,
|
||||||
bool allow_none, Error **errp);
|
bool allow_none, Error **errp);
|
||||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
|
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
|
||||||
|
void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp);
|
||||||
int bdrv_open(BlockDriverState **pbs, const char *filename,
|
int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||||
const char *reference, QDict *options, int flags,
|
const char *reference, QDict *options, int flags,
|
||||||
BlockDriver *drv, Error **errp);
|
BlockDriver *drv, Error **errp);
|
||||||
@@ -428,7 +429,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
|
|||||||
|
|
||||||
struct HBitmapIter;
|
struct HBitmapIter;
|
||||||
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
|
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
|
||||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity);
|
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||||
|
Error **errp);
|
||||||
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
|
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
|
||||||
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
|
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
|
||||||
int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
|
int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
|
||||||
|
|||||||
@@ -162,3 +162,55 @@
|
|||||||
#define stw(p, v) stw_data(p, v)
|
#define stw(p, v) stw_data(p, v)
|
||||||
#define stl(p, v) stl_data(p, v)
|
#define stl(p, v) stl_data(p, v)
|
||||||
#define stq(p, v) stq_data(p, v)
|
#define stq(p, v) stq_data(p, v)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tlb_vaddr_to_host:
|
||||||
|
* @env: CPUArchState
|
||||||
|
* @addr: guest virtual address to look up
|
||||||
|
* @access_type: 0 for read, 1 for write, 2 for execute
|
||||||
|
* @mmu_idx: MMU index to use for lookup
|
||||||
|
*
|
||||||
|
* Look up the specified guest virtual index in the TCG softmmu TLB.
|
||||||
|
* If the TLB contains a host virtual address suitable for direct RAM
|
||||||
|
* access, then return it. Otherwise (TLB miss, TLB entry is for an
|
||||||
|
* I/O access, etc) return NULL.
|
||||||
|
*
|
||||||
|
* This is the equivalent of the initial fast-path code used by
|
||||||
|
* TCG backends for guest load and store accesses.
|
||||||
|
*/
|
||||||
|
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
|
||||||
|
int access_type, int mmu_idx)
|
||||||
|
{
|
||||||
|
int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
|
CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
|
||||||
|
target_ulong tlb_addr;
|
||||||
|
uintptr_t haddr;
|
||||||
|
|
||||||
|
switch (access_type) {
|
||||||
|
case 0:
|
||||||
|
tlb_addr = tlbentry->addr_read;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tlb_addr = tlbentry->addr_write;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tlb_addr = tlbentry->addr_code;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((addr & TARGET_PAGE_MASK)
|
||||||
|
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||||
|
/* TLB entry is for a different page */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tlb_addr & ~TARGET_PAGE_MASK) {
|
||||||
|
/* IO access */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
haddr = addr + env->tlb_table[mmu_idx][index].addend;
|
||||||
|
return (void *)haddr;
|
||||||
|
}
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ uint32 float32_to_uint32( float32 STATUS_PARAM );
|
|||||||
uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
|
uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
|
||||||
int64 float32_to_int64( float32 STATUS_PARAM );
|
int64 float32_to_int64( float32 STATUS_PARAM );
|
||||||
uint64 float32_to_uint64(float32 STATUS_PARAM);
|
uint64 float32_to_uint64(float32 STATUS_PARAM);
|
||||||
|
uint64 float32_to_uint64_round_to_zero(float32 STATUS_PARAM);
|
||||||
int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
|
int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
|
||||||
float64 float32_to_float64( float32 STATUS_PARAM );
|
float64 float32_to_float64( float32 STATUS_PARAM );
|
||||||
floatx80 float32_to_floatx80( float32 STATUS_PARAM );
|
floatx80 float32_to_floatx80( float32 STATUS_PARAM );
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; under version 2 of the License.
|
* the Free Software Foundation; either version 2 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
@@ -144,6 +144,7 @@
|
|||||||
#define MII_BMSR_10T_FD (1 << 12)
|
#define MII_BMSR_10T_FD (1 << 12)
|
||||||
#define MII_BMSR_10T_HD (1 << 11)
|
#define MII_BMSR_10T_HD (1 << 11)
|
||||||
#define MII_BMSR_MFPS (1 << 6)
|
#define MII_BMSR_MFPS (1 << 6)
|
||||||
|
#define MII_BMSR_AN_COMP (1 << 5)
|
||||||
#define MII_BMSR_AUTONEG (1 << 3)
|
#define MII_BMSR_AUTONEG (1 << 3)
|
||||||
#define MII_BMSR_LINK_ST (1 << 2)
|
#define MII_BMSR_LINK_ST (1 << 2)
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ struct ppc_tb_t {
|
|||||||
#define PPC_DECR_ZERO_TRIGGERED (1 << 3) /* Decr interrupt triggered when
|
#define PPC_DECR_ZERO_TRIGGERED (1 << 3) /* Decr interrupt triggered when
|
||||||
* the decrementer reaches zero.
|
* the decrementer reaches zero.
|
||||||
*/
|
*/
|
||||||
|
#define PPC_DECR_UNDERFLOW_LEVEL (1 << 4) /* Decr interrupt active when
|
||||||
|
* the most significant bit is 1.
|
||||||
|
*/
|
||||||
|
|
||||||
uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
|
uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
|
||||||
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
|
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
|
||||||
|
|||||||
@@ -35,13 +35,22 @@
|
|||||||
|
|
||||||
#define AW_A10_PIT_DEFAULT_CLOCK 0x4
|
#define AW_A10_PIT_DEFAULT_CLOCK 0x4
|
||||||
|
|
||||||
typedef struct AwA10PITState {
|
typedef struct AwA10PITState AwA10PITState;
|
||||||
|
|
||||||
|
typedef struct AwA10TimerContext {
|
||||||
|
AwA10PITState *container;
|
||||||
|
int index;
|
||||||
|
} AwA10TimerContext;
|
||||||
|
|
||||||
|
struct AwA10PITState {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
qemu_irq irq[AW_A10_PIT_TIMER_NR];
|
qemu_irq irq[AW_A10_PIT_TIMER_NR];
|
||||||
ptimer_state * timer[AW_A10_PIT_TIMER_NR];
|
ptimer_state * timer[AW_A10_PIT_TIMER_NR];
|
||||||
|
AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR];
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
uint32_t clk_freq[4];
|
||||||
|
|
||||||
uint32_t irq_enable;
|
uint32_t irq_enable;
|
||||||
uint32_t irq_status;
|
uint32_t irq_status;
|
||||||
@@ -53,6 +62,6 @@ typedef struct AwA10PITState {
|
|||||||
uint32_t count_lo;
|
uint32_t count_lo;
|
||||||
uint32_t count_hi;
|
uint32_t count_hi;
|
||||||
uint32_t count_ctl;
|
uint32_t count_ctl;
|
||||||
} AwA10PITState;
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static inline Int128 int128_rshift(Int128 a, int n)
|
|||||||
if (n >= 64) {
|
if (n >= 64) {
|
||||||
return (Int128) { h, h >> 63 };
|
return (Int128) { h, h >> 63 };
|
||||||
} else {
|
} else {
|
||||||
return (Int128) { (a.lo >> n) | (a.hi << (64 - n)), h };
|
return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ static inline Int128 int128_neg(Int128 a)
|
|||||||
|
|
||||||
static inline Int128 int128_sub(Int128 a, Int128 b)
|
static inline Int128 int128_sub(Int128 a, Int128 b)
|
||||||
{
|
{
|
||||||
return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
|
return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool int128_nonneg(Int128 a)
|
static inline bool int128_nonneg(Int128 a)
|
||||||
|
|||||||
@@ -15,10 +15,20 @@
|
|||||||
#define IOTHREAD_H
|
#define IOTHREAD_H
|
||||||
|
|
||||||
#include "block/aio.h"
|
#include "block/aio.h"
|
||||||
|
#include "qemu/thread.h"
|
||||||
|
|
||||||
#define TYPE_IOTHREAD "iothread"
|
#define TYPE_IOTHREAD "iothread"
|
||||||
|
|
||||||
typedef struct IOThread IOThread;
|
typedef struct {
|
||||||
|
Object parent_obj;
|
||||||
|
|
||||||
|
QemuThread thread;
|
||||||
|
AioContext *ctx;
|
||||||
|
QemuMutex init_done_lock;
|
||||||
|
QemuCond init_done_cond; /* is thread initialization done? */
|
||||||
|
bool stopping;
|
||||||
|
int thread_id;
|
||||||
|
} IOThread;
|
||||||
|
|
||||||
#define IOTHREAD(obj) \
|
#define IOTHREAD(obj) \
|
||||||
OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD)
|
OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD)
|
||||||
|
|||||||
11
iothread.c
11
iothread.c
@@ -14,7 +14,6 @@
|
|||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/thread.h"
|
|
||||||
#include "block/aio.h"
|
#include "block/aio.h"
|
||||||
#include "sysemu/iothread.h"
|
#include "sysemu/iothread.h"
|
||||||
#include "qmp-commands.h"
|
#include "qmp-commands.h"
|
||||||
@@ -22,16 +21,6 @@
|
|||||||
#define IOTHREADS_PATH "/objects"
|
#define IOTHREADS_PATH "/objects"
|
||||||
|
|
||||||
typedef ObjectClass IOThreadClass;
|
typedef ObjectClass IOThreadClass;
|
||||||
struct IOThread {
|
|
||||||
Object parent_obj;
|
|
||||||
|
|
||||||
QemuThread thread;
|
|
||||||
AioContext *ctx;
|
|
||||||
QemuMutex init_done_lock;
|
|
||||||
QemuCond init_done_cond; /* is thread initialization done? */
|
|
||||||
bool stopping;
|
|
||||||
int thread_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define IOTHREAD_GET_CLASS(obj) \
|
#define IOTHREAD_GET_CLASS(obj) \
|
||||||
OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
|
OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ static int kvm_physical_sync_dirty_bitmap(MemoryRegionSection *section)
|
|||||||
|
|
||||||
d.slot = mem->slot;
|
d.slot = mem->slot;
|
||||||
|
|
||||||
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) < 0) {
|
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
|
||||||
DPRINTF("ioctl failed %d\n", errno);
|
DPRINTF("ioctl failed %d\n", errno);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -483,17 +483,17 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
|
|||||||
addr = env->regs[2];
|
addr = env->regs[2];
|
||||||
|
|
||||||
if (get_user_u64(oldval, env->regs[0])) {
|
if (get_user_u64(oldval, env->regs[0])) {
|
||||||
env->cp15.c6_data = env->regs[0];
|
env->exception.vaddress = env->regs[0];
|
||||||
goto segv;
|
goto segv;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (get_user_u64(newval, env->regs[1])) {
|
if (get_user_u64(newval, env->regs[1])) {
|
||||||
env->cp15.c6_data = env->regs[1];
|
env->exception.vaddress = env->regs[1];
|
||||||
goto segv;
|
goto segv;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (get_user_u64(val, addr)) {
|
if (get_user_u64(val, addr)) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto segv;
|
goto segv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,7 +501,7 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
|
|||||||
val = newval;
|
val = newval;
|
||||||
|
|
||||||
if (put_user_u64(val, addr)) {
|
if (put_user_u64(val, addr)) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto segv;
|
goto segv;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -523,7 +523,7 @@ segv:
|
|||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
/* XXX: check env->error_code */
|
/* XXX: check env->error_code */
|
||||||
info.si_code = TARGET_SEGV_MAPERR;
|
info.si_code = TARGET_SEGV_MAPERR;
|
||||||
info._sifields._sigfault._addr = env->cp15.c6_data;
|
info._sifields._sigfault._addr = env->exception.vaddress;
|
||||||
queue_signal(env, info.si_signo, &info);
|
queue_signal(env, info.si_signo, &info);
|
||||||
|
|
||||||
end_exclusive();
|
end_exclusive();
|
||||||
@@ -620,14 +620,14 @@ static int do_strex(CPUARMState *env)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (size == 3) {
|
if (size == 3) {
|
||||||
uint32_t valhi;
|
uint32_t valhi;
|
||||||
segv = get_user_u32(valhi, addr + 4);
|
segv = get_user_u32(valhi, addr + 4);
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + 4;
|
env->exception.vaddress = addr + 4;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
val = deposit64(val, 32, 32, valhi);
|
val = deposit64(val, 32, 32, valhi);
|
||||||
@@ -650,14 +650,14 @@ static int do_strex(CPUARMState *env)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (size == 3) {
|
if (size == 3) {
|
||||||
val = env->regs[(env->exclusive_info >> 12) & 0xf];
|
val = env->regs[(env->exclusive_info >> 12) & 0xf];
|
||||||
segv = put_user_u32(val, addr + 4);
|
segv = put_user_u32(val, addr + 4);
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + 4;
|
env->exception.vaddress = addr + 4;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -832,12 +832,14 @@ void cpu_loop(CPUARMState *env)
|
|||||||
case EXCP_INTERRUPT:
|
case EXCP_INTERRUPT:
|
||||||
/* just indicate that signals should be handled asap */
|
/* just indicate that signals should be handled asap */
|
||||||
break;
|
break;
|
||||||
|
case EXCP_STREX:
|
||||||
|
if (!do_strex(env)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through for segv */
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
addr = env->cp15.c6_insn;
|
|
||||||
goto do_segv;
|
|
||||||
case EXCP_DATA_ABORT:
|
case EXCP_DATA_ABORT:
|
||||||
addr = env->cp15.c6_data;
|
addr = env->exception.vaddress;
|
||||||
do_segv:
|
|
||||||
{
|
{
|
||||||
info.si_signo = SIGSEGV;
|
info.si_signo = SIGSEGV;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
@@ -865,12 +867,6 @@ void cpu_loop(CPUARMState *env)
|
|||||||
if (do_kernel_trap(env))
|
if (do_kernel_trap(env))
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
case EXCP_STREX:
|
|
||||||
if (do_strex(env)) {
|
|
||||||
addr = env->cp15.c6_data;
|
|
||||||
goto do_segv;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
error:
|
error:
|
||||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||||
@@ -933,7 +929,7 @@ static int do_strex_a64(CPUARMState *env)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr;
|
env->exception.vaddress = addr;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (val != env->exclusive_val) {
|
if (val != env->exclusive_val) {
|
||||||
@@ -946,7 +942,7 @@ static int do_strex_a64(CPUARMState *env)
|
|||||||
segv = get_user_u64(val, addr + 8);
|
segv = get_user_u64(val, addr + 8);
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
|
env->exception.vaddress = addr + (size == 2 ? 4 : 8);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (val != env->exclusive_high) {
|
if (val != env->exclusive_high) {
|
||||||
@@ -981,7 +977,7 @@ static int do_strex_a64(CPUARMState *env)
|
|||||||
segv = put_user_u64(val, addr + 8);
|
segv = put_user_u64(val, addr + 8);
|
||||||
}
|
}
|
||||||
if (segv) {
|
if (segv) {
|
||||||
env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
|
env->exception.vaddress = addr + (size == 2 ? 4 : 8);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1037,12 +1033,14 @@ void cpu_loop(CPUARMState *env)
|
|||||||
info._sifields._sigfault._addr = env->pc;
|
info._sifields._sigfault._addr = env->pc;
|
||||||
queue_signal(env, info.si_signo, &info);
|
queue_signal(env, info.si_signo, &info);
|
||||||
break;
|
break;
|
||||||
|
case EXCP_STREX:
|
||||||
|
if (!do_strex_a64(env)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through for segv */
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
addr = env->cp15.c6_insn;
|
|
||||||
goto do_segv;
|
|
||||||
case EXCP_DATA_ABORT:
|
case EXCP_DATA_ABORT:
|
||||||
addr = env->cp15.c6_data;
|
addr = env->exception.vaddress;
|
||||||
do_segv:
|
|
||||||
info.si_signo = SIGSEGV;
|
info.si_signo = SIGSEGV;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
/* XXX: check env->error_code */
|
/* XXX: check env->error_code */
|
||||||
@@ -1060,12 +1058,6 @@ void cpu_loop(CPUARMState *env)
|
|||||||
queue_signal(env, info.si_signo, &info);
|
queue_signal(env, info.si_signo, &info);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXCP_STREX:
|
|
||||||
if (do_strex_a64(env)) {
|
|
||||||
addr = env->cp15.c6_data;
|
|
||||||
goto do_segv;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||||
trapnr);
|
trapnr);
|
||||||
|
|||||||
@@ -952,10 +952,12 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
|
|||||||
|
|
||||||
nc = net_hub_find_client_by_name(vlan_id, device);
|
nc = net_hub_find_client_by_name(vlan_id, device);
|
||||||
if (!nc) {
|
if (!nc) {
|
||||||
|
error_report("Host network device '%s' on hub '%d' not found",
|
||||||
|
device, vlan_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!net_host_check_device(nc->model)) {
|
if (!net_host_check_device(nc->model)) {
|
||||||
monitor_printf(mon, "invalid host network device %s\n", device);
|
error_report("invalid host network device '%s'", device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qemu_del_net_client(nc);
|
qemu_del_net_client(nc);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
||||||
implementation for certain IBM POWER hardware. The sources are at
|
implementation for certain IBM POWER hardware. The sources are at
|
||||||
https://github.com/aik/SLOF, and the image currently in qemu is
|
https://github.com/aik/SLOF, and the image currently in qemu is
|
||||||
built from git tag qemu-slof-20140304.
|
built from git tag qemu-slof-20140404.
|
||||||
|
|
||||||
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
|
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
|
||||||
legacy x86 software to communicate with an attached serial console as
|
legacy x86 software to communicate with an attached serial console as
|
||||||
|
|||||||
BIN
pc-bios/slof.bin
BIN
pc-bios/slof.bin
Binary file not shown.
@@ -823,7 +823,7 @@ In this case, the block device must be exported using qemu-nbd:
|
|||||||
qemu-nbd --socket=/tmp/my_socket my_disk.qcow2
|
qemu-nbd --socket=/tmp/my_socket my_disk.qcow2
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
The use of qemu-nbd allows to share a disk between several guests:
|
The use of qemu-nbd allows sharing of a disk between several guests:
|
||||||
@example
|
@example
|
||||||
qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
|
qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
|
||||||
@end example
|
@end example
|
||||||
|
|||||||
116
qemu-img.c
116
qemu-img.c
@@ -57,8 +57,22 @@ static void format_print(void *opaque, const char *name)
|
|||||||
printf(" %s", name);
|
printf(" %s", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
error_printf("qemu-img: ");
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
error_vprintf(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
error_printf("\nTry 'qemu-img --help' for more information\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Please keep in synch with qemu-img.texi */
|
/* Please keep in synch with qemu-img.texi */
|
||||||
static void help(void)
|
static void QEMU_NORETURN help(void)
|
||||||
{
|
{
|
||||||
const char *help_msg =
|
const char *help_msg =
|
||||||
"qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
"qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
||||||
@@ -129,7 +143,7 @@ static void help(void)
|
|||||||
printf("%s\nSupported formats:", help_msg);
|
printf("%s\nSupported formats:", help_msg);
|
||||||
bdrv_iterate_format(format_print, NULL);
|
bdrv_iterate_format(format_print, NULL);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
exit(1);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
|
static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
|
||||||
@@ -262,7 +276,8 @@ static int print_block_option_help(const char *filename, const char *fmt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlockDriverState *bdrv_new_open(const char *filename,
|
static BlockDriverState *bdrv_new_open(const char *id,
|
||||||
|
const char *filename,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
int flags,
|
int flags,
|
||||||
bool require_io,
|
bool require_io,
|
||||||
@@ -274,7 +289,7 @@ static BlockDriverState *bdrv_new_open(const char *filename,
|
|||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bs = bdrv_new("image");
|
bs = bdrv_new(id, &error_abort);
|
||||||
|
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
drv = bdrv_find_format(fmt);
|
drv = bdrv_find_format(fmt);
|
||||||
@@ -398,7 +413,7 @@ static int img_create(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (optind >= argc) {
|
if (optind >= argc) {
|
||||||
help();
|
error_exit("Expecting image file name");
|
||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
@@ -421,7 +436,7 @@ static int img_create(int argc, char **argv)
|
|||||||
img_size = (uint64_t)sval;
|
img_size = (uint64_t)sval;
|
||||||
}
|
}
|
||||||
if (optind != argc) {
|
if (optind != argc) {
|
||||||
help();
|
error_exit("Unexpected argument: %s", argv[optind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_img_create(filename, fmt, base_filename, base_fmt,
|
bdrv_img_create(filename, fmt, base_filename, base_fmt,
|
||||||
@@ -590,7 +605,8 @@ static int img_check(int argc, char **argv)
|
|||||||
} else if (!strcmp(optarg, "all")) {
|
} else if (!strcmp(optarg, "all")) {
|
||||||
fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
|
fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
|
||||||
} else {
|
} else {
|
||||||
help();
|
error_exit("Unknown option value for -r "
|
||||||
|
"(expecting 'leaks' or 'all'): %s", optarg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPTION_OUTPUT:
|
case OPTION_OUTPUT:
|
||||||
@@ -602,7 +618,7 @@ static int img_check(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind != argc - 1) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
}
|
}
|
||||||
filename = argv[optind++];
|
filename = argv[optind++];
|
||||||
|
|
||||||
@@ -615,7 +631,7 @@ static int img_check(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_new_open(filename, fmt, flags, true, quiet);
|
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -713,7 +729,7 @@ static int img_commit(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind != argc - 1) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
}
|
}
|
||||||
filename = argv[optind++];
|
filename = argv[optind++];
|
||||||
|
|
||||||
@@ -724,7 +740,7 @@ static int img_commit(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_new_open(filename, fmt, flags, true, quiet);
|
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -959,7 +975,7 @@ static int img_compare(int argc, char **argv)
|
|||||||
|
|
||||||
|
|
||||||
if (optind != argc - 2) {
|
if (optind != argc - 2) {
|
||||||
help();
|
error_exit("Expecting two image file names");
|
||||||
}
|
}
|
||||||
filename1 = argv[optind++];
|
filename1 = argv[optind++];
|
||||||
filename2 = argv[optind++];
|
filename2 = argv[optind++];
|
||||||
@@ -967,14 +983,14 @@ static int img_compare(int argc, char **argv)
|
|||||||
/* Initialize before goto out */
|
/* Initialize before goto out */
|
||||||
qemu_progress_init(progress, 2.0);
|
qemu_progress_init(progress, 2.0);
|
||||||
|
|
||||||
bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
|
bs1 = bdrv_new_open("image 1", filename1, fmt1, BDRV_O_FLAGS, true, quiet);
|
||||||
if (!bs1) {
|
if (!bs1) {
|
||||||
error_report("Can't open file %s", filename1);
|
error_report("Can't open file %s", filename1);
|
||||||
ret = 2;
|
ret = 2;
|
||||||
goto out3;
|
goto out3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs2 = bdrv_new_open(filename2, fmt2, BDRV_O_FLAGS, true, quiet);
|
bs2 = bdrv_new_open("image 2", filename2, fmt2, BDRV_O_FLAGS, true, quiet);
|
||||||
if (!bs2) {
|
if (!bs2) {
|
||||||
error_report("Can't open file %s", filename2);
|
error_report("Can't open file %s", filename2);
|
||||||
ret = 2;
|
ret = 2;
|
||||||
@@ -1275,7 +1291,7 @@ static int img_convert(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bs_n < 1) {
|
if (bs_n < 1) {
|
||||||
help();
|
error_exit("Must specify image file name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1292,8 +1308,11 @@ static int img_convert(int argc, char **argv)
|
|||||||
|
|
||||||
total_sectors = 0;
|
total_sectors = 0;
|
||||||
for (bs_i = 0; bs_i < bs_n; bs_i++) {
|
for (bs_i = 0; bs_i < bs_n; bs_i++) {
|
||||||
bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true,
|
char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
|
||||||
quiet);
|
: g_strdup("source");
|
||||||
|
bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, BDRV_O_FLAGS,
|
||||||
|
true, quiet);
|
||||||
|
g_free(id);
|
||||||
if (!bs[bs_i]) {
|
if (!bs[bs_i]) {
|
||||||
error_report("Could not open '%s'", argv[optind + bs_i]);
|
error_report("Could not open '%s'", argv[optind + bs_i]);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@@ -1416,7 +1435,7 @@ static int img_convert(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
|
out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
|
||||||
if (!out_bs) {
|
if (!out_bs) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1799,8 +1818,8 @@ static ImageInfoList *collect_image_info_list(const char *filename,
|
|||||||
}
|
}
|
||||||
g_hash_table_insert(filenames, (gpointer)filename, NULL);
|
g_hash_table_insert(filenames, (gpointer)filename, NULL);
|
||||||
|
|
||||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
|
bs = bdrv_new_open("image", filename, fmt,
|
||||||
false, false);
|
BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1882,7 +1901,7 @@ static int img_info(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind != argc - 1) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
}
|
}
|
||||||
filename = argv[optind++];
|
filename = argv[optind++];
|
||||||
|
|
||||||
@@ -2046,10 +2065,10 @@ static int img_map(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind >= argc) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
}
|
}
|
||||||
filename = argv[optind++];
|
filename = argv[optind];
|
||||||
|
|
||||||
if (output && !strcmp(output, "json")) {
|
if (output && !strcmp(output, "json")) {
|
||||||
output_format = OFORMAT_JSON;
|
output_format = OFORMAT_JSON;
|
||||||
@@ -2060,7 +2079,7 @@ static int img_map(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS, true, false);
|
bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -2138,7 +2157,7 @@ static int img_snapshot(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
case 'l':
|
case 'l':
|
||||||
if (action) {
|
if (action) {
|
||||||
help();
|
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
action = SNAPSHOT_LIST;
|
action = SNAPSHOT_LIST;
|
||||||
@@ -2146,7 +2165,7 @@ static int img_snapshot(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
if (action) {
|
if (action) {
|
||||||
help();
|
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
action = SNAPSHOT_APPLY;
|
action = SNAPSHOT_APPLY;
|
||||||
@@ -2154,7 +2173,7 @@ static int img_snapshot(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
if (action) {
|
if (action) {
|
||||||
help();
|
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
action = SNAPSHOT_CREATE;
|
action = SNAPSHOT_CREATE;
|
||||||
@@ -2162,7 +2181,7 @@ static int img_snapshot(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (action) {
|
if (action) {
|
||||||
help();
|
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
action = SNAPSHOT_DELETE;
|
action = SNAPSHOT_DELETE;
|
||||||
@@ -2175,12 +2194,12 @@ static int img_snapshot(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (optind != argc - 1) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
}
|
}
|
||||||
filename = argv[optind++];
|
filename = argv[optind++];
|
||||||
|
|
||||||
/* Open the image */
|
/* Open the image */
|
||||||
bs = bdrv_new_open(filename, NULL, bdrv_oflags, true, quiet);
|
bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -2288,8 +2307,11 @@ static int img_rebase(int argc, char **argv)
|
|||||||
progress = 0;
|
progress = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((optind != argc - 1) || (!unsafe && !out_baseimg)) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
|
}
|
||||||
|
if (!unsafe && !out_baseimg) {
|
||||||
|
error_exit("Must specify backing file (-b) or use unsafe mode (-u)");
|
||||||
}
|
}
|
||||||
filename = argv[optind++];
|
filename = argv[optind++];
|
||||||
|
|
||||||
@@ -2309,7 +2331,7 @@ static int img_rebase(int argc, char **argv)
|
|||||||
* Ignore the old backing file for unsafe rebase in case we want to correct
|
* Ignore the old backing file for unsafe rebase in case we want to correct
|
||||||
* the reference to a renamed or moved backing file.
|
* the reference to a renamed or moved backing file.
|
||||||
*/
|
*/
|
||||||
bs = bdrv_new_open(filename, fmt, flags, true, quiet);
|
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -2344,7 +2366,7 @@ static int img_rebase(int argc, char **argv)
|
|||||||
} else {
|
} else {
|
||||||
char backing_name[1024];
|
char backing_name[1024];
|
||||||
|
|
||||||
bs_old_backing = bdrv_new("old_backing");
|
bs_old_backing = bdrv_new("old_backing", &error_abort);
|
||||||
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
|
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
|
||||||
ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, BDRV_O_FLAGS,
|
ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, BDRV_O_FLAGS,
|
||||||
old_backing_drv, &local_err);
|
old_backing_drv, &local_err);
|
||||||
@@ -2355,7 +2377,7 @@ static int img_rebase(int argc, char **argv)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (out_baseimg[0]) {
|
if (out_baseimg[0]) {
|
||||||
bs_new_backing = bdrv_new("new_backing");
|
bs_new_backing = bdrv_new("new_backing", &error_abort);
|
||||||
ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL,
|
ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL,
|
||||||
BDRV_O_FLAGS, new_backing_drv, &local_err);
|
BDRV_O_FLAGS, new_backing_drv, &local_err);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -2549,7 +2571,7 @@ static int img_resize(int argc, char **argv)
|
|||||||
/* Remove size from argv manually so that negative numbers are not treated
|
/* Remove size from argv manually so that negative numbers are not treated
|
||||||
* as options by getopt. */
|
* as options by getopt. */
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
help();
|
error_exit("Not enough arguments");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2576,7 +2598,7 @@ static int img_resize(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind != argc - 1) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
}
|
}
|
||||||
filename = argv[optind++];
|
filename = argv[optind++];
|
||||||
|
|
||||||
@@ -2606,7 +2628,8 @@ static int img_resize(int argc, char **argv)
|
|||||||
n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
|
n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
|
||||||
qemu_opts_del(param);
|
qemu_opts_del(param);
|
||||||
|
|
||||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
|
bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
|
||||||
|
true, quiet);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -2692,7 +2715,7 @@ static int img_amend(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!options) {
|
if (!options) {
|
||||||
help();
|
error_exit("Must specify options (-o)");
|
||||||
}
|
}
|
||||||
|
|
||||||
filename = (optind == argc - 1) ? argv[argc - 1] : NULL;
|
filename = (optind == argc - 1) ? argv[argc - 1] : NULL;
|
||||||
@@ -2704,10 +2727,11 @@ static int img_amend(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (optind != argc - 1) {
|
if (optind != argc - 1) {
|
||||||
help();
|
error_exit("Expecting one image file name");
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
|
bs = bdrv_new_open("image", filename, fmt,
|
||||||
|
BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
error_report("Could not open image '%s'", filename);
|
error_report("Could not open image '%s'", filename);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@@ -2775,8 +2799,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
qemu_init_main_loop();
|
qemu_init_main_loop();
|
||||||
bdrv_init();
|
bdrv_init();
|
||||||
if (argc < 2)
|
if (argc < 2) {
|
||||||
help();
|
error_exit("Not enough arguments");
|
||||||
|
}
|
||||||
cmdname = argv[1];
|
cmdname = argv[1];
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
|
|
||||||
@@ -2788,6 +2813,5 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* not found */
|
/* not found */
|
||||||
help();
|
error_exit("Command not found: %s", cmdname);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qemuio_bs = bdrv_new("hda");
|
qemuio_bs = bdrv_new("hda", &error_abort);
|
||||||
|
|
||||||
if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err)
|
if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err)
|
||||||
< 0)
|
< 0)
|
||||||
|
|||||||
@@ -657,7 +657,8 @@ int main(int argc, char **argv)
|
|||||||
drv = NULL;
|
drv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_new("hda");
|
bs = bdrv_new("hda", &error_abort);
|
||||||
|
|
||||||
srcpath = argv[optind];
|
srcpath = argv[optind];
|
||||||
ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
|
ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|||||||
@@ -444,7 +444,8 @@ This option defines the type of the media: disk or cdrom.
|
|||||||
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
|
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
|
||||||
These options have the same definition as they have in @option{-hdachs}.
|
These options have the same definition as they have in @option{-hdachs}.
|
||||||
@item snapshot=@var{snapshot}
|
@item snapshot=@var{snapshot}
|
||||||
@var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
|
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
|
||||||
|
(see @option{-snapshot}).
|
||||||
@item cache=@var{cache}
|
@item cache=@var{cache}
|
||||||
@var{cache} is "none", "writeback", "unsafe", "directsync" or "writethrough" and controls how the host cache is used to access block data.
|
@var{cache} is "none", "writeback", "unsafe", "directsync" or "writethrough" and controls how the host cache is used to access block data.
|
||||||
@item aio=@var{aio}
|
@item aio=@var{aio}
|
||||||
@@ -1242,7 +1243,7 @@ Disable adaptive encodings. Adaptive encodings are enabled by default.
|
|||||||
An adaptive encoding will try to detect frequently updated screen regions,
|
An adaptive encoding will try to detect frequently updated screen regions,
|
||||||
and send updates in these regions using a lossy encoding (like JPEG).
|
and send updates in these regions using a lossy encoding (like JPEG).
|
||||||
This can be really helpful to save bandwidth when playing videos. Disabling
|
This can be really helpful to save bandwidth when playing videos. Disabling
|
||||||
adaptive encodings allows to restore the original static behavior of encodings
|
adaptive encodings restores the original static behavior of encodings
|
||||||
like Tight.
|
like Tight.
|
||||||
|
|
||||||
@item share=[allow-exclusive|force-shared|ignore]
|
@item share=[allow-exclusive|force-shared|ignore]
|
||||||
@@ -2805,7 +2806,7 @@ UTC or local time, respectively. @code{localtime} is required for correct date i
|
|||||||
MS-DOS or Windows. To start at a specific point in time, provide @var{date} in the
|
MS-DOS or Windows. To start at a specific point in time, provide @var{date} in the
|
||||||
format @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default base is UTC.
|
format @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default base is UTC.
|
||||||
|
|
||||||
By default the RTC is driven by the host system time. This allows to use the
|
By default the RTC is driven by the host system time. This allows using of the
|
||||||
RTC as accurate reference clock inside the guest, specifically if the host
|
RTC as accurate reference clock inside the guest, specifically if the host
|
||||||
time is smoothly following an accurate external reference clock, e.g. via NTP.
|
time is smoothly following an accurate external reference clock, e.g. via NTP.
|
||||||
If you want to isolate the guest time from the host, you can set @option{clock}
|
If you want to isolate the guest time from the host, you can set @option{clock}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
|
|||||||
/* Now, if user has passed a time to set and the system time is set, we
|
/* Now, if user has passed a time to set and the system time is set, we
|
||||||
* just need to synchronize the hardware clock. However, if no time was
|
* just need to synchronize the hardware clock. However, if no time was
|
||||||
* passed, user is requesting the opposite: set the system time from the
|
* passed, user is requesting the opposite: set the system time from the
|
||||||
* hardware clock. */
|
* hardware clock (RTC). */
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
setsid();
|
setsid();
|
||||||
|
|||||||
@@ -96,8 +96,8 @@
|
|||||||
##
|
##
|
||||||
# @guest-get-time:
|
# @guest-get-time:
|
||||||
#
|
#
|
||||||
# Get the information about guest time relative to the Epoch
|
# Get the information about guest's System Time relative to
|
||||||
# of 1970-01-01 in UTC.
|
# the Epoch of 1970-01-01 in UTC.
|
||||||
#
|
#
|
||||||
# Returns: Time in nanoseconds.
|
# Returns: Time in nanoseconds.
|
||||||
#
|
#
|
||||||
@@ -117,11 +117,11 @@
|
|||||||
# gap was, NTP might not be able to resynchronize the
|
# gap was, NTP might not be able to resynchronize the
|
||||||
# guest.
|
# guest.
|
||||||
#
|
#
|
||||||
# This command tries to set guest time to the given value,
|
# This command tries to set guest's System Time to the
|
||||||
# then sets the Hardware Clock to the current System Time.
|
# given value, then sets the Hardware Clock (RTC) to the
|
||||||
# This will make it easier for a guest to resynchronize
|
# current System Time. This will make it easier for a guest
|
||||||
# without waiting for NTP. If no @time is specified, then
|
# to resynchronize without waiting for NTP. If no @time is
|
||||||
# the time to set is read from RTC.
|
# specified, then the time to set is read from RTC.
|
||||||
#
|
#
|
||||||
# @time: #optional time of nanoseconds, relative to the Epoch
|
# @time: #optional time of nanoseconds, relative to the Epoch
|
||||||
# of 1970-01-01 in UTC.
|
# of 1970-01-01 in UTC.
|
||||||
|
|||||||
@@ -75,10 +75,13 @@ static void errmsg_dialog(DWORD err, const char *text, const char *opt = "")
|
|||||||
|
|
||||||
#define chk(status) _chk(hr, status, "Failed to " #status, out)
|
#define chk(status) _chk(hr, status, "Failed to " #status, out)
|
||||||
|
|
||||||
|
#if !defined(__MINGW64_VERSION_MAJOR) || !defined(__MINGW64_VERSION_MINOR) || \
|
||||||
|
__MINGW64_VERSION_MAJOR * 100 + __MINGW64_VERSION_MINOR < 301
|
||||||
void __stdcall _com_issue_error(HRESULT hr)
|
void __stdcall _com_issue_error(HRESULT hr)
|
||||||
{
|
{
|
||||||
errmsg(hr, "Unexpected error in COM");
|
errmsg(hr, "Unexpected error in COM");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
HRESULT put_Value(ICatalogObject *pObj, LPCWSTR name, T val)
|
HRESULT put_Value(ICatalogObject *pObj, LPCWSTR name, T val)
|
||||||
|
|||||||
@@ -1225,7 +1225,8 @@ Object *object_resolve_path_component(Object *parent, const gchar *part)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (object_property_is_link(prop)) {
|
if (object_property_is_link(prop)) {
|
||||||
return *(Object **)prop->opaque;
|
LinkProperty *lprop = prop->opaque;
|
||||||
|
return *lprop->child;
|
||||||
} else if (object_property_is_child(prop)) {
|
} else if (object_property_is_child(prop)) {
|
||||||
return prop->opaque;
|
return prop->opaque;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Submodule roms/SLOF updated: af6b7bf587...c90b50b505
183
scripts/coverity-model.c
Normal file
183
scripts/coverity-model.c
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/* Coverity Scan model
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Markus Armbruster <armbru@redhat.com>
|
||||||
|
* Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or, at your
|
||||||
|
* option, any later version. See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the source code for our Coverity user model file. The
|
||||||
|
* purpose of user models is to increase scanning accuracy by explaining
|
||||||
|
* code Coverity can't see (out of tree libraries) or doesn't
|
||||||
|
* sufficiently understand. Better accuracy means both fewer false
|
||||||
|
* positives and more true defects. Memory leaks in particular.
|
||||||
|
*
|
||||||
|
* - A model file can't import any header files. Some built-in primitives are
|
||||||
|
* available but not wchar_t, NULL etc.
|
||||||
|
* - Modeling doesn't need full structs and typedefs. Rudimentary structs
|
||||||
|
* and similar types are sufficient.
|
||||||
|
* - An uninitialized local variable signifies that the variable could be
|
||||||
|
* any value.
|
||||||
|
*
|
||||||
|
* The model file must be uploaded by an admin in the analysis settings of
|
||||||
|
* http://scan.coverity.com/projects/378
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef char int8_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef long ssize_t;
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
typedef long long int64_t;
|
||||||
|
typedef _Bool bool;
|
||||||
|
|
||||||
|
/* exec.c */
|
||||||
|
|
||||||
|
typedef struct AddressSpace AddressSpace;
|
||||||
|
typedef uint64_t hwaddr;
|
||||||
|
|
||||||
|
static void __write(uint8_t *buf, ssize_t len)
|
||||||
|
{
|
||||||
|
int first, last;
|
||||||
|
__coverity_negative_sink__(len);
|
||||||
|
if (len == 0) return;
|
||||||
|
buf[0] = first;
|
||||||
|
buf[len-1] = last;
|
||||||
|
__coverity_writeall__(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __read(uint8_t *buf, ssize_t len)
|
||||||
|
{
|
||||||
|
__coverity_negative_sink__(len);
|
||||||
|
if (len == 0) return;
|
||||||
|
int first = buf[0];
|
||||||
|
int last = buf[len-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||||
|
int len, bool is_write)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
// TODO: investigate impact of treating reads as producing
|
||||||
|
// tainted data, with __coverity_tainted_data_argument__(buf).
|
||||||
|
if (is_write) __write(buf, len); else __read(buf, len);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tainting */
|
||||||
|
|
||||||
|
typedef struct {} name2keysym_t;
|
||||||
|
static int get_keysym(const name2keysym_t *table,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if (result > 0) {
|
||||||
|
__coverity_tainted_string_sanitize_content__(name);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* glib memory allocation functions.
|
||||||
|
*
|
||||||
|
* Note that we ignore the fact that g_malloc of 0 bytes returns NULL,
|
||||||
|
* and g_realloc of 0 bytes frees the pointer.
|
||||||
|
*
|
||||||
|
* Modeling this would result in Coverity flagging a lot of memory
|
||||||
|
* allocations as potentially returning NULL, and asking us to check
|
||||||
|
* whether the result of the allocation is NULL or not. However, the
|
||||||
|
* resulting pointer should never be dereferenced anyway, and in fact
|
||||||
|
* it is not in the vast majority of cases.
|
||||||
|
*
|
||||||
|
* If a dereference did happen, this would suppress a defect report
|
||||||
|
* for an actual null pointer dereference. But it's too unlikely to
|
||||||
|
* be worth wading through the false positives, and with some luck
|
||||||
|
* we'll get a buffer overflow reported anyway.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *malloc(size_t);
|
||||||
|
void *calloc(size_t, size_t);
|
||||||
|
void *realloc(void *, size_t);
|
||||||
|
void free(void *);
|
||||||
|
|
||||||
|
void *
|
||||||
|
g_malloc(size_t n_bytes)
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
__coverity_negative_sink__(n_bytes);
|
||||||
|
mem = malloc(n_bytes == 0 ? 1 : n_bytes);
|
||||||
|
if (!mem) __coverity_panic__();
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
g_malloc0(size_t n_bytes)
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
__coverity_negative_sink__(n_bytes);
|
||||||
|
mem = calloc(1, n_bytes == 0 ? 1 : n_bytes);
|
||||||
|
if (!mem) __coverity_panic__();
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_free(void *mem)
|
||||||
|
{
|
||||||
|
free(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *g_realloc(void * mem, size_t n_bytes)
|
||||||
|
{
|
||||||
|
__coverity_negative_sink__(n_bytes);
|
||||||
|
mem = realloc(mem, n_bytes == 0 ? 1 : n_bytes);
|
||||||
|
if (!mem) __coverity_panic__();
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *g_try_malloc(size_t n_bytes)
|
||||||
|
{
|
||||||
|
__coverity_negative_sink__(n_bytes);
|
||||||
|
return malloc(n_bytes == 0 ? 1 : n_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *g_try_malloc0(size_t n_bytes)
|
||||||
|
{
|
||||||
|
__coverity_negative_sink__(n_bytes);
|
||||||
|
return calloc(1, n_bytes == 0 ? 1 : n_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *g_try_realloc(void *mem, size_t n_bytes)
|
||||||
|
{
|
||||||
|
__coverity_negative_sink__(n_bytes);
|
||||||
|
return realloc(mem, n_bytes == 0 ? 1 : n_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other glib functions */
|
||||||
|
|
||||||
|
typedef struct _GIOChannel GIOChannel;
|
||||||
|
GIOChannel *g_io_channel_unix_new(int fd)
|
||||||
|
{
|
||||||
|
GIOChannel *c = g_malloc0(sizeof(GIOChannel));
|
||||||
|
__coverity_escape__(fd);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_assertion_message_expr(const char *domain,
|
||||||
|
const char *file,
|
||||||
|
int line,
|
||||||
|
const char *func,
|
||||||
|
const char *expr)
|
||||||
|
{
|
||||||
|
__coverity_panic__();
|
||||||
|
}
|
||||||
@@ -820,3 +820,10 @@ uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
|
|||||||
fr = int64_to_float64(a, &FP_STATUS);
|
fr = int64_to_float64(a, &FP_STATUS);
|
||||||
return float64_to_g(fr);
|
return float64_to_g(fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void helper_fcvtql_v_input(CPUAlphaState *env, uint64_t val)
|
||||||
|
{
|
||||||
|
if (val != (int32_t)val) {
|
||||||
|
arith_excp(env, GETPC(), EXC_M_IOV, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ DEF_HELPER_FLAGS_3(fp_exc_raise_s, TCG_CALL_NO_WG, void, env, i32, i32)
|
|||||||
|
|
||||||
DEF_HELPER_FLAGS_2(ieee_input, TCG_CALL_NO_WG, void, env, i64)
|
DEF_HELPER_FLAGS_2(ieee_input, TCG_CALL_NO_WG, void, env, i64)
|
||||||
DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
|
DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
|
||||||
|
DEF_HELPER_FLAGS_2(fcvtql_v_input, TCG_CALL_NO_WG, void, env, i64)
|
||||||
|
|
||||||
#if !defined (CONFIG_USER_ONLY)
|
#if !defined (CONFIG_USER_ONLY)
|
||||||
DEF_HELPER_2(hw_ret, void, env, i64)
|
DEF_HELPER_2(hw_ret, void, env, i64)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -116,6 +116,7 @@ typedef struct ARMCPU {
|
|||||||
uint32_t reset_fpsid;
|
uint32_t reset_fpsid;
|
||||||
uint32_t mvfr0;
|
uint32_t mvfr0;
|
||||||
uint32_t mvfr1;
|
uint32_t mvfr1;
|
||||||
|
uint32_t mvfr2;
|
||||||
uint32_t ctr;
|
uint32_t ctr;
|
||||||
uint32_t reset_sctlr;
|
uint32_t reset_sctlr;
|
||||||
uint32_t id_pfr0;
|
uint32_t id_pfr0;
|
||||||
@@ -147,9 +148,12 @@ typedef struct ARMCPU {
|
|||||||
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
|
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
|
||||||
*/
|
*/
|
||||||
uint32_t ccsidr[16];
|
uint32_t ccsidr[16];
|
||||||
uint32_t reset_cbar;
|
uint64_t reset_cbar;
|
||||||
uint32_t reset_auxcr;
|
uint32_t reset_auxcr;
|
||||||
bool reset_hivecs;
|
bool reset_hivecs;
|
||||||
|
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
|
||||||
|
uint32_t dcz_blocksize;
|
||||||
|
uint64_t rvbar;
|
||||||
} ARMCPU;
|
} ARMCPU;
|
||||||
|
|
||||||
#define TYPE_AARCH64_CPU "aarch64-cpu"
|
#define TYPE_AARCH64_CPU "aarch64-cpu"
|
||||||
@@ -196,10 +200,10 @@ void arm_gt_ptimer_cb(void *opaque);
|
|||||||
void arm_gt_vtimer_cb(void *opaque);
|
void arm_gt_vtimer_cb(void *opaque);
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
#ifdef TARGET_AARCH64
|
||||||
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
|
|
||||||
fprintf_function cpu_fprintf, int flags);
|
|
||||||
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||||
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||||
|
|
||||||
|
void aarch64_cpu_do_interrupt(CPUState *cs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "internals.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
@@ -87,6 +88,7 @@ static void arm_cpu_reset(CPUState *s)
|
|||||||
env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
|
env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
|
||||||
env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
|
env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
|
||||||
env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
|
env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
|
||||||
|
env->vfp.xregs[ARM_VFP_MVFR2] = cpu->mvfr2;
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
|
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
|
||||||
env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
|
env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
|
||||||
@@ -99,8 +101,16 @@ static void arm_cpu_reset(CPUState *s)
|
|||||||
env->pstate = PSTATE_MODE_EL0t;
|
env->pstate = PSTATE_MODE_EL0t;
|
||||||
/* Userspace expects access to CTL_EL0 and the cache ops */
|
/* Userspace expects access to CTL_EL0 and the cache ops */
|
||||||
env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
|
env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
|
||||||
|
/* and to the FP/Neon instructions */
|
||||||
|
env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3);
|
||||||
#else
|
#else
|
||||||
env->pstate = PSTATE_MODE_EL1h;
|
env->pstate = PSTATE_MODE_EL1h;
|
||||||
|
env->pc = cpu->rvbar;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
/* Userspace expects access to cp10 and cp11 for FP/Neon */
|
||||||
|
env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 4, 0xf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,16 +262,20 @@ static void arm_cpu_initfn(Object *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Property arm_cpu_reset_cbar_property =
|
static Property arm_cpu_reset_cbar_property =
|
||||||
DEFINE_PROP_UINT32("reset-cbar", ARMCPU, reset_cbar, 0);
|
DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
|
||||||
|
|
||||||
static Property arm_cpu_reset_hivecs_property =
|
static Property arm_cpu_reset_hivecs_property =
|
||||||
DEFINE_PROP_BOOL("reset-hivecs", ARMCPU, reset_hivecs, false);
|
DEFINE_PROP_BOOL("reset-hivecs", ARMCPU, reset_hivecs, false);
|
||||||
|
|
||||||
|
static Property arm_cpu_rvbar_property =
|
||||||
|
DEFINE_PROP_UINT64("rvbar", ARMCPU, rvbar, 0);
|
||||||
|
|
||||||
static void arm_cpu_post_init(Object *obj)
|
static void arm_cpu_post_init(Object *obj)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(obj);
|
ARMCPU *cpu = ARM_CPU(obj);
|
||||||
|
|
||||||
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR)) {
|
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
|
||||||
|
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
|
||||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_cbar_property,
|
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_cbar_property,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
}
|
}
|
||||||
@@ -270,6 +284,11 @@ static void arm_cpu_post_init(Object *obj)
|
|||||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_hivecs_property,
|
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_hivecs_property,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
|
||||||
|
qdev_property_add_static(DEVICE(obj), &arm_cpu_rvbar_property,
|
||||||
|
&error_abort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm_cpu_finalizefn(Object *obj)
|
static void arm_cpu_finalizefn(Object *obj)
|
||||||
@@ -331,6 +350,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||||||
set_feature(env, ARM_FEATURE_V7MP);
|
set_feature(env, ARM_FEATURE_V7MP);
|
||||||
set_feature(env, ARM_FEATURE_PXN);
|
set_feature(env, ARM_FEATURE_PXN);
|
||||||
}
|
}
|
||||||
|
if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
|
||||||
|
set_feature(env, ARM_FEATURE_CBAR);
|
||||||
|
}
|
||||||
|
|
||||||
if (cpu->reset_hivecs) {
|
if (cpu->reset_hivecs) {
|
||||||
cpu->reset_sctlr |= (1 << 13);
|
cpu->reset_sctlr |= (1 << 13);
|
||||||
@@ -417,7 +439,7 @@ static void arm1026_initfn(Object *obj)
|
|||||||
ARMCPRegInfo ifar = {
|
ARMCPRegInfo ifar = {
|
||||||
.name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
|
.name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
|
||||||
.access = PL1_RW,
|
.access = PL1_RW,
|
||||||
.fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
|
.fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1),
|
||||||
.resetvalue = 0
|
.resetvalue = 0
|
||||||
};
|
};
|
||||||
define_one_arm_cp_reg(cpu, &ifar);
|
define_one_arm_cp_reg(cpu, &ifar);
|
||||||
@@ -722,7 +744,7 @@ static void cortex_a15_initfn(Object *obj)
|
|||||||
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
|
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
|
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_CBAR);
|
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_LPAE);
|
set_feature(&cpu->env, ARM_FEATURE_LPAE);
|
||||||
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
|
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
|
||||||
cpu->midr = 0x412fc0f1;
|
cpu->midr = 0x412fc0f1;
|
||||||
|
|||||||
@@ -111,11 +111,6 @@ typedef struct ARMGenericTimer {
|
|||||||
#define GTIMER_VIRT 1
|
#define GTIMER_VIRT 1
|
||||||
#define NUM_GTIMERS 2
|
#define NUM_GTIMERS 2
|
||||||
|
|
||||||
/* Scale factor for generic timers, ie number of ns per tick.
|
|
||||||
* This gives a 62.5MHz timer.
|
|
||||||
*/
|
|
||||||
#define GTIMER_SCALE 16
|
|
||||||
|
|
||||||
typedef struct CPUARMState {
|
typedef struct CPUARMState {
|
||||||
/* Regs for current mode. */
|
/* Regs for current mode. */
|
||||||
uint32_t regs[16];
|
uint32_t regs[16];
|
||||||
@@ -148,7 +143,7 @@ typedef struct CPUARMState {
|
|||||||
uint32_t spsr;
|
uint32_t spsr;
|
||||||
|
|
||||||
/* Banked registers. */
|
/* Banked registers. */
|
||||||
uint32_t banked_spsr[6];
|
uint64_t banked_spsr[6];
|
||||||
uint32_t banked_r13[6];
|
uint32_t banked_r13[6];
|
||||||
uint32_t banked_r14[6];
|
uint32_t banked_r14[6];
|
||||||
|
|
||||||
@@ -165,7 +160,10 @@ typedef struct CPUARMState {
|
|||||||
uint32_t GE; /* cpsr[19:16] */
|
uint32_t GE; /* cpsr[19:16] */
|
||||||
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
|
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
|
||||||
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
|
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
|
||||||
uint32_t daif; /* exception masks, in the bits they are in in PSTATE */
|
uint64_t daif; /* exception masks, in the bits they are in in PSTATE */
|
||||||
|
|
||||||
|
uint64_t elr_el1; /* AArch64 ELR_EL1 */
|
||||||
|
uint64_t sp_el[2]; /* AArch64 banked stack pointers */
|
||||||
|
|
||||||
/* System control coprocessor (cp15) */
|
/* System control coprocessor (cp15) */
|
||||||
struct {
|
struct {
|
||||||
@@ -184,13 +182,13 @@ typedef struct CPUARMState {
|
|||||||
uint32_t c2_insn; /* MPU instruction cachable bits. */
|
uint32_t c2_insn; /* MPU instruction cachable bits. */
|
||||||
uint32_t c3; /* MMU domain access control register
|
uint32_t c3; /* MMU domain access control register
|
||||||
MPU write buffer control. */
|
MPU write buffer control. */
|
||||||
uint32_t c5_insn; /* Fault status registers. */
|
uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
|
||||||
uint32_t c5_data;
|
uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
|
||||||
|
uint32_t ifsr_el2; /* Fault status registers. */
|
||||||
|
uint64_t esr_el1;
|
||||||
uint32_t c6_region[8]; /* MPU base/size registers. */
|
uint32_t c6_region[8]; /* MPU base/size registers. */
|
||||||
uint32_t c6_insn; /* Fault address registers. */
|
uint64_t far_el1; /* Fault address registers. */
|
||||||
uint32_t c6_data;
|
uint64_t par_el1; /* Translation result. */
|
||||||
uint32_t c7_par; /* Translation result. */
|
|
||||||
uint32_t c7_par_hi; /* Translation result, high 32 bits */
|
|
||||||
uint32_t c9_insn; /* Cache lockdown registers. */
|
uint32_t c9_insn; /* Cache lockdown registers. */
|
||||||
uint32_t c9_data;
|
uint32_t c9_data;
|
||||||
uint32_t c9_pmcr; /* performance monitor control register */
|
uint32_t c9_pmcr; /* performance monitor control register */
|
||||||
@@ -202,7 +200,7 @@ typedef struct CPUARMState {
|
|||||||
uint64_t mair_el1;
|
uint64_t mair_el1;
|
||||||
uint64_t c12_vbar; /* vector base address register */
|
uint64_t c12_vbar; /* vector base address register */
|
||||||
uint32_t c13_fcse; /* FCSE PID. */
|
uint32_t c13_fcse; /* FCSE PID. */
|
||||||
uint32_t c13_context; /* Context ID. */
|
uint64_t contextidr_el1; /* Context ID. */
|
||||||
uint64_t tpidr_el0; /* User RW Thread register. */
|
uint64_t tpidr_el0; /* User RW Thread register. */
|
||||||
uint64_t tpidrro_el0; /* User RO Thread register. */
|
uint64_t tpidrro_el0; /* User RO Thread register. */
|
||||||
uint64_t tpidr_el1; /* Privileged Thread register. */
|
uint64_t tpidr_el1; /* Privileged Thread register. */
|
||||||
@@ -238,6 +236,21 @@ typedef struct CPUARMState {
|
|||||||
int pending_exception;
|
int pending_exception;
|
||||||
} v7m;
|
} v7m;
|
||||||
|
|
||||||
|
/* Information associated with an exception about to be taken:
|
||||||
|
* code which raises an exception must set cs->exception_index and
|
||||||
|
* the relevant parts of this structure; the cpu_do_interrupt function
|
||||||
|
* will then set the guest-visible registers as part of the exception
|
||||||
|
* entry process.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
uint32_t syndrome; /* AArch64 format syndrome register */
|
||||||
|
uint32_t fsr; /* AArch32 format fault status register info */
|
||||||
|
uint64_t vaddress; /* virtual addr associated with exception, if any */
|
||||||
|
/* If we implement EL2 we will also need to store information
|
||||||
|
* about the intermediate physical address for stage 2 faults.
|
||||||
|
*/
|
||||||
|
} exception;
|
||||||
|
|
||||||
/* Thumb-2 EE state. */
|
/* Thumb-2 EE state. */
|
||||||
uint32_t teecr;
|
uint32_t teecr;
|
||||||
uint32_t teehbr;
|
uint32_t teehbr;
|
||||||
@@ -322,11 +335,7 @@ typedef struct CPUARMState {
|
|||||||
#include "cpu-qom.h"
|
#include "cpu-qom.h"
|
||||||
|
|
||||||
ARMCPU *cpu_arm_init(const char *cpu_model);
|
ARMCPU *cpu_arm_init(const char *cpu_model);
|
||||||
void arm_translate_init(void);
|
|
||||||
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
|
|
||||||
int cpu_arm_exec(CPUARMState *s);
|
int cpu_arm_exec(CPUARMState *s);
|
||||||
int bank_number(int mode);
|
|
||||||
void switch_mode(CPUARMState *, int);
|
|
||||||
uint32_t do_arm_semihosting(CPUARMState *env);
|
uint32_t do_arm_semihosting(CPUARMState *env);
|
||||||
|
|
||||||
static inline bool is_a64(CPUARMState *env)
|
static inline bool is_a64(CPUARMState *env)
|
||||||
@@ -425,6 +434,7 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
|||||||
* Only these are valid when in AArch64 mode; in
|
* Only these are valid when in AArch64 mode; in
|
||||||
* AArch32 mode SPSRs are basically CPSR-format.
|
* AArch32 mode SPSRs are basically CPSR-format.
|
||||||
*/
|
*/
|
||||||
|
#define PSTATE_SP (1U)
|
||||||
#define PSTATE_M (0xFU)
|
#define PSTATE_M (0xFU)
|
||||||
#define PSTATE_nRW (1U << 4)
|
#define PSTATE_nRW (1U << 4)
|
||||||
#define PSTATE_F (1U << 6)
|
#define PSTATE_F (1U << 6)
|
||||||
@@ -548,17 +558,6 @@ static inline void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
|||||||
vfp_set_fpscr(env, new_fpscr);
|
vfp_set_fpscr(env, new_fpscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum arm_fprounding {
|
|
||||||
FPROUNDING_TIEEVEN,
|
|
||||||
FPROUNDING_POSINF,
|
|
||||||
FPROUNDING_NEGINF,
|
|
||||||
FPROUNDING_ZERO,
|
|
||||||
FPROUNDING_TIEAWAY,
|
|
||||||
FPROUNDING_ODD
|
|
||||||
};
|
|
||||||
|
|
||||||
int arm_rmode_to_sf(int rmode);
|
|
||||||
|
|
||||||
enum arm_cpu_mode {
|
enum arm_cpu_mode {
|
||||||
ARM_CPU_MODE_USR = 0x10,
|
ARM_CPU_MODE_USR = 0x10,
|
||||||
ARM_CPU_MODE_FIQ = 0x11,
|
ARM_CPU_MODE_FIQ = 0x11,
|
||||||
@@ -572,6 +571,7 @@ enum arm_cpu_mode {
|
|||||||
/* VFP system registers. */
|
/* VFP system registers. */
|
||||||
#define ARM_VFP_FPSID 0
|
#define ARM_VFP_FPSID 0
|
||||||
#define ARM_VFP_FPSCR 1
|
#define ARM_VFP_FPSCR 1
|
||||||
|
#define ARM_VFP_MVFR2 5
|
||||||
#define ARM_VFP_MVFR1 6
|
#define ARM_VFP_MVFR1 6
|
||||||
#define ARM_VFP_MVFR0 7
|
#define ARM_VFP_MVFR0 7
|
||||||
#define ARM_VFP_FPEXC 8
|
#define ARM_VFP_FPEXC 8
|
||||||
@@ -630,6 +630,7 @@ enum arm_features {
|
|||||||
ARM_FEATURE_V8_AES, /* implements AES part of v8 Crypto Extensions */
|
ARM_FEATURE_V8_AES, /* implements AES part of v8 Crypto Extensions */
|
||||||
ARM_FEATURE_CBAR, /* has cp15 CBAR */
|
ARM_FEATURE_CBAR, /* has cp15 CBAR */
|
||||||
ARM_FEATURE_CRC, /* ARMv8 CRC instructions */
|
ARM_FEATURE_CRC, /* ARMv8 CRC instructions */
|
||||||
|
ARM_FEATURE_CBAR_RO, /* has cp15 CBAR and it is read-only */
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int arm_feature(CPUARMState *env, int feature)
|
static inline int arm_feature(CPUARMState *env, int feature)
|
||||||
@@ -763,7 +764,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
|
|||||||
#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
|
#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
|
||||||
#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
|
#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
|
||||||
#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
|
#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
|
||||||
#define ARM_LAST_SPECIAL ARM_CP_CURRENTEL
|
#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | (5 << 8))
|
||||||
|
#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
|
||||||
/* Used only as a terminator for ARMCPRegInfo lists */
|
/* Used only as a terminator for ARMCPRegInfo lists */
|
||||||
#define ARM_CP_SENTINEL 0xffff
|
#define ARM_CP_SENTINEL 0xffff
|
||||||
/* Mask of only the flag bits in a type field */
|
/* Mask of only the flag bits in a type field */
|
||||||
@@ -1109,10 +1111,14 @@ static inline int cpu_mmu_index (CPUARMState *env)
|
|||||||
#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
|
#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||||
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
|
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
|
||||||
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
||||||
|
#define ARM_TBFLAG_CPACR_FPEN_SHIFT 17
|
||||||
|
#define ARM_TBFLAG_CPACR_FPEN_MASK (1 << ARM_TBFLAG_CPACR_FPEN_SHIFT)
|
||||||
|
|
||||||
/* Bit usage when in AArch64 state */
|
/* Bit usage when in AArch64 state */
|
||||||
#define ARM_TBFLAG_AA64_EL_SHIFT 0
|
#define ARM_TBFLAG_AA64_EL_SHIFT 0
|
||||||
#define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT)
|
#define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT)
|
||||||
|
#define ARM_TBFLAG_AA64_FPEN_SHIFT 2
|
||||||
|
#define ARM_TBFLAG_AA64_FPEN_MASK (1 << ARM_TBFLAG_AA64_FPEN_SHIFT)
|
||||||
|
|
||||||
/* some convenience accessor macros */
|
/* some convenience accessor macros */
|
||||||
#define ARM_TBFLAG_AARCH64_STATE(F) \
|
#define ARM_TBFLAG_AARCH64_STATE(F) \
|
||||||
@@ -1131,16 +1137,25 @@ static inline int cpu_mmu_index (CPUARMState *env)
|
|||||||
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
|
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||||
#define ARM_TBFLAG_BSWAP_CODE(F) \
|
#define ARM_TBFLAG_BSWAP_CODE(F) \
|
||||||
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
||||||
|
#define ARM_TBFLAG_CPACR_FPEN(F) \
|
||||||
|
(((F) & ARM_TBFLAG_CPACR_FPEN_MASK) >> ARM_TBFLAG_CPACR_FPEN_SHIFT)
|
||||||
#define ARM_TBFLAG_AA64_EL(F) \
|
#define ARM_TBFLAG_AA64_EL(F) \
|
||||||
(((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
|
(((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
|
||||||
|
#define ARM_TBFLAG_AA64_FPEN(F) \
|
||||||
|
(((F) & ARM_TBFLAG_AA64_FPEN_MASK) >> ARM_TBFLAG_AA64_FPEN_SHIFT)
|
||||||
|
|
||||||
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
||||||
target_ulong *cs_base, int *flags)
|
target_ulong *cs_base, int *flags)
|
||||||
{
|
{
|
||||||
|
int fpen = extract32(env->cp15.c1_coproc, 20, 2);
|
||||||
|
|
||||||
if (is_a64(env)) {
|
if (is_a64(env)) {
|
||||||
*pc = env->pc;
|
*pc = env->pc;
|
||||||
*flags = ARM_TBFLAG_AARCH64_STATE_MASK
|
*flags = ARM_TBFLAG_AARCH64_STATE_MASK
|
||||||
| (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
|
| (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
|
||||||
|
if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
|
||||||
|
*flags |= ARM_TBFLAG_AA64_FPEN_MASK;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int privmode;
|
int privmode;
|
||||||
*pc = env->regs[15];
|
*pc = env->regs[15];
|
||||||
@@ -1157,9 +1172,13 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||||||
if (privmode) {
|
if (privmode) {
|
||||||
*flags |= ARM_TBFLAG_PRIV_MASK;
|
*flags |= ARM_TBFLAG_PRIV_MASK;
|
||||||
}
|
}
|
||||||
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
|
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
|
||||||
|
|| arm_el_is_aa64(env, 1)) {
|
||||||
*flags |= ARM_TBFLAG_VFPEN_MASK;
|
*flags |= ARM_TBFLAG_VFPEN_MASK;
|
||||||
}
|
}
|
||||||
|
if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
|
||||||
|
*flags |= ARM_TBFLAG_CPACR_FPEN_MASK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*cs_base = 0;
|
*cs_base = 0;
|
||||||
|
|||||||
@@ -32,6 +32,104 @@ static inline void set_feature(CPUARMState *env, int feature)
|
|||||||
env->features |= 1ULL << feature;
|
env->features |= 1ULL << feature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
static uint64_t a57_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||||
|
{
|
||||||
|
/* Number of processors is in [25:24]; otherwise we RAZ */
|
||||||
|
return (smp_cpus - 1) << 24;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const ARMCPRegInfo cortexa57_cp_reginfo[] = {
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
{ .name = "L2CTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 2,
|
||||||
|
.access = PL1_RW, .readfn = a57_l2ctlr_read,
|
||||||
|
.writefn = arm_cp_write_ignore },
|
||||||
|
{ .name = "L2CTLR",
|
||||||
|
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 2,
|
||||||
|
.access = PL1_RW, .readfn = a57_l2ctlr_read,
|
||||||
|
.writefn = arm_cp_write_ignore },
|
||||||
|
#endif
|
||||||
|
{ .name = "L2ECTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 3,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
{ .name = "L2ECTLR",
|
||||||
|
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 3,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
{ .name = "L2ACTLR", .state = ARM_CP_STATE_BOTH,
|
||||||
|
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 0, .opc2 = 0,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
{ .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 0,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
{ .name = "CPUACTLR",
|
||||||
|
.cp = 15, .opc1 = 0, .crm = 15,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||||
|
{ .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 1,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
{ .name = "CPUECTLR",
|
||||||
|
.cp = 15, .opc1 = 1, .crm = 15,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||||
|
{ .name = "CPUMERRSR_EL1", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 2,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
{ .name = "CPUMERRSR",
|
||||||
|
.cp = 15, .opc1 = 2, .crm = 15,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||||
|
{ .name = "L2MERRSR_EL1", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 3,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
{ .name = "L2MERRSR",
|
||||||
|
.cp = 15, .opc1 = 3, .crm = 15,
|
||||||
|
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||||
|
REGINFO_SENTINEL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void aarch64_a57_initfn(Object *obj)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = ARM_CPU(obj);
|
||||||
|
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_VFP4);
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||||
|
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57;
|
||||||
|
cpu->midr = 0x411fd070;
|
||||||
|
cpu->reset_fpsid = 0x41034070;
|
||||||
|
cpu->mvfr0 = 0x10110222;
|
||||||
|
cpu->mvfr1 = 0x12111111;
|
||||||
|
cpu->mvfr2 = 0x00000043;
|
||||||
|
cpu->ctr = 0x8444c004;
|
||||||
|
cpu->reset_sctlr = 0x00c50838;
|
||||||
|
cpu->id_pfr0 = 0x00000131;
|
||||||
|
cpu->id_pfr1 = 0x00011011;
|
||||||
|
cpu->id_dfr0 = 0x03010066;
|
||||||
|
cpu->id_afr0 = 0x00000000;
|
||||||
|
cpu->id_mmfr0 = 0x10101105;
|
||||||
|
cpu->id_mmfr1 = 0x40000000;
|
||||||
|
cpu->id_mmfr2 = 0x01260000;
|
||||||
|
cpu->id_mmfr3 = 0x02102211;
|
||||||
|
cpu->id_isar0 = 0x02101110;
|
||||||
|
cpu->id_isar1 = 0x13112111;
|
||||||
|
cpu->id_isar2 = 0x21232042;
|
||||||
|
cpu->id_isar3 = 0x01112131;
|
||||||
|
cpu->id_isar4 = 0x00011142;
|
||||||
|
cpu->id_aa64pfr0 = 0x00002222;
|
||||||
|
cpu->id_aa64dfr0 = 0x10305106;
|
||||||
|
cpu->id_aa64isar0 = 0x00010000;
|
||||||
|
cpu->id_aa64mmfr0 = 0x00001124;
|
||||||
|
cpu->clidr = 0x0a200023;
|
||||||
|
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
|
||||||
|
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
|
||||||
|
cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
|
||||||
|
cpu->dcz_blocksize = 4; /* 64 bytes */
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
static void aarch64_any_initfn(Object *obj)
|
static void aarch64_any_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
@@ -41,11 +139,11 @@ static void aarch64_any_initfn(Object *obj)
|
|||||||
set_feature(&cpu->env, ARM_FEATURE_VFP4);
|
set_feature(&cpu->env, ARM_FEATURE_VFP4);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
|
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
|
|
||||||
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
|
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_V7MP);
|
set_feature(&cpu->env, ARM_FEATURE_V7MP);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||||
cpu->ctr = 0x80030003; /* 32 byte I and D cacheline size, VIPT icache */
|
cpu->ctr = 0x80030003; /* 32 byte I and D cacheline size, VIPT icache */
|
||||||
|
cpu->dcz_blocksize = 7; /* 512 bytes */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -56,6 +154,7 @@ typedef struct ARMCPUInfo {
|
|||||||
} ARMCPUInfo;
|
} ARMCPUInfo;
|
||||||
|
|
||||||
static const ARMCPUInfo aarch64_cpus[] = {
|
static const ARMCPUInfo aarch64_cpus[] = {
|
||||||
|
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
{ .name = "any", .initfn = aarch64_any_initfn },
|
{ .name = "any", .initfn = aarch64_any_initfn },
|
||||||
#endif
|
#endif
|
||||||
@@ -73,18 +172,22 @@ static void aarch64_cpu_finalizefn(Object *obj)
|
|||||||
static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
|
static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
/*
|
/* It's OK to look at env for the current mode here, because it's
|
||||||
* TODO: this will need updating for system emulation,
|
* never possible for an AArch64 TB to chain to an AArch32 TB.
|
||||||
* when the core may be in AArch32 mode.
|
* (Otherwise we would need to use synchronize_from_tb instead.)
|
||||||
*/
|
*/
|
||||||
cpu->env.pc = value;
|
if (is_a64(&cpu->env)) {
|
||||||
|
cpu->env.pc = value;
|
||||||
|
} else {
|
||||||
|
cpu->env.regs[15] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
|
static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_CLASS(oc);
|
CPUClass *cc = CPU_CLASS(oc);
|
||||||
|
|
||||||
cc->dump_state = aarch64_cpu_dump_state;
|
cc->do_interrupt = aarch64_cpu_do_interrupt;
|
||||||
cc->set_pc = aarch64_cpu_set_pc;
|
cc->set_pc = aarch64_cpu_set_pc;
|
||||||
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
|
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
|
||||||
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
|
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
|
||||||
|
|||||||
@@ -32,10 +32,8 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||||||
switch (n) {
|
switch (n) {
|
||||||
case 31:
|
case 31:
|
||||||
return gdb_get_reg64(mem_buf, env->xregs[31]);
|
return gdb_get_reg64(mem_buf, env->xregs[31]);
|
||||||
break;
|
|
||||||
case 32:
|
case 32:
|
||||||
return gdb_get_reg64(mem_buf, env->pc);
|
return gdb_get_reg64(mem_buf, env->pc);
|
||||||
break;
|
|
||||||
case 33:
|
case 33:
|
||||||
return gdb_get_reg32(mem_buf, pstate_read(env));
|
return gdb_get_reg32(mem_buf, pstate_read(env));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
|
#include "internals.h"
|
||||||
|
|
||||||
/* C2.4.7 Multiply and divide */
|
/* C2.4.7 Multiply and divide */
|
||||||
/* special cases for 0 and LLONG_MIN are mandated by the standard */
|
/* special cases for 0 and LLONG_MIN are mandated by the standard */
|
||||||
@@ -436,3 +437,78 @@ float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState *env)
|
|||||||
set_float_exception_flags(exflags, fpst);
|
set_float_exception_flags(exflags, fpst);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle a CPU exception. */
|
||||||
|
void aarch64_cpu_do_interrupt(CPUState *cs)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
|
CPUARMState *env = &cpu->env;
|
||||||
|
target_ulong addr = env->cp15.c12_vbar;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (arm_current_pl(env) == 0) {
|
||||||
|
if (env->aarch64) {
|
||||||
|
addr += 0x400;
|
||||||
|
} else {
|
||||||
|
addr += 0x600;
|
||||||
|
}
|
||||||
|
} else if (pstate_read(env) & PSTATE_SP) {
|
||||||
|
addr += 0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
arm_log_exception(cs->exception_index);
|
||||||
|
qemu_log_mask(CPU_LOG_INT, "...from EL%d\n", arm_current_pl(env));
|
||||||
|
if (qemu_loglevel_mask(CPU_LOG_INT)
|
||||||
|
&& !excp_is_internal(cs->exception_index)) {
|
||||||
|
qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%" PRIx32 "\n",
|
||||||
|
env->exception.syndrome);
|
||||||
|
}
|
||||||
|
|
||||||
|
env->cp15.esr_el1 = env->exception.syndrome;
|
||||||
|
env->cp15.far_el1 = env->exception.vaddress;
|
||||||
|
|
||||||
|
switch (cs->exception_index) {
|
||||||
|
case EXCP_PREFETCH_ABORT:
|
||||||
|
case EXCP_DATA_ABORT:
|
||||||
|
qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
|
||||||
|
env->cp15.far_el1);
|
||||||
|
break;
|
||||||
|
case EXCP_BKPT:
|
||||||
|
case EXCP_UDEF:
|
||||||
|
case EXCP_SWI:
|
||||||
|
break;
|
||||||
|
case EXCP_IRQ:
|
||||||
|
addr += 0x80;
|
||||||
|
break;
|
||||||
|
case EXCP_FIQ:
|
||||||
|
addr += 0x100;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_a64(env)) {
|
||||||
|
env->banked_spsr[0] = pstate_read(env);
|
||||||
|
env->sp_el[arm_current_pl(env)] = env->xregs[31];
|
||||||
|
env->xregs[31] = env->sp_el[1];
|
||||||
|
env->elr_el1 = env->pc;
|
||||||
|
} else {
|
||||||
|
env->banked_spsr[0] = cpsr_read(env);
|
||||||
|
if (!env->thumb) {
|
||||||
|
env->cp15.esr_el1 |= 1 << 25;
|
||||||
|
}
|
||||||
|
env->elr_el1 = env->regs[15];
|
||||||
|
|
||||||
|
for (i = 0; i < 15; i++) {
|
||||||
|
env->xregs[i] = env->regs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
env->condexec_bits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pstate_write(env, PSTATE_DAIF | PSTATE_MODE_EL1h);
|
||||||
|
env->aarch64 = 1;
|
||||||
|
|
||||||
|
env->pc = addr;
|
||||||
|
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,8 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
|||||||
|
|
||||||
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
|
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
|
||||||
i32, i32, i32, i32)
|
i32, i32, i32, i32)
|
||||||
DEF_HELPER_2(exception, void, env, i32)
|
DEF_HELPER_2(exception_internal, void, env, i32)
|
||||||
|
DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
|
||||||
DEF_HELPER_1(wfi, void, env)
|
DEF_HELPER_1(wfi, void, env)
|
||||||
DEF_HELPER_1(wfe, void, env)
|
DEF_HELPER_1(wfe, void, env)
|
||||||
|
|
||||||
@@ -58,13 +59,14 @@ DEF_HELPER_1(cpsr_read, i32, env)
|
|||||||
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
|
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
|
||||||
DEF_HELPER_2(v7m_mrs, i32, env, i32)
|
DEF_HELPER_2(v7m_mrs, i32, env, i32)
|
||||||
|
|
||||||
DEF_HELPER_2(access_check_cp_reg, void, env, ptr)
|
DEF_HELPER_3(access_check_cp_reg, void, env, ptr, i32)
|
||||||
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
|
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
|
||||||
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
|
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
|
||||||
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
|
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
|
||||||
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
|
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
|
||||||
|
|
||||||
DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
|
DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
|
||||||
|
DEF_HELPER_1(exception_return, void, env)
|
||||||
|
|
||||||
DEF_HELPER_2(get_r13_banked, i32, env, i32)
|
DEF_HELPER_2(get_r13_banked, i32, env, i32)
|
||||||
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
|
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
|
||||||
@@ -514,6 +516,7 @@ DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32)
|
|||||||
|
|
||||||
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
|
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
|
||||||
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
|
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
|
||||||
|
DEF_HELPER_2(dc_zva, void, env, i64)
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
#ifdef TARGET_AARCH64
|
||||||
#include "helper-a64.h"
|
#include "helper-a64.h"
|
||||||
|
|||||||
267
target-arm/internals.h
Normal file
267
target-arm/internals.h
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* QEMU ARM CPU -- internal functions and types
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Linaro Ltd
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see
|
||||||
|
* <http://www.gnu.org/licenses/gpl-2.0.html>
|
||||||
|
*
|
||||||
|
* This header defines functions, types, etc which need to be shared
|
||||||
|
* between different source files within target-arm/ but which are
|
||||||
|
* private to it and not required by the rest of QEMU.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TARGET_ARM_INTERNALS_H
|
||||||
|
#define TARGET_ARM_INTERNALS_H
|
||||||
|
|
||||||
|
static inline bool excp_is_internal(int excp)
|
||||||
|
{
|
||||||
|
/* Return true if this exception number represents a QEMU-internal
|
||||||
|
* exception that will not be passed to the guest.
|
||||||
|
*/
|
||||||
|
return excp == EXCP_INTERRUPT
|
||||||
|
|| excp == EXCP_HLT
|
||||||
|
|| excp == EXCP_DEBUG
|
||||||
|
|| excp == EXCP_HALTED
|
||||||
|
|| excp == EXCP_EXCEPTION_EXIT
|
||||||
|
|| excp == EXCP_KERNEL_TRAP
|
||||||
|
|| excp == EXCP_STREX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exception names for debug logging; note that not all of these
|
||||||
|
* precisely correspond to architectural exceptions.
|
||||||
|
*/
|
||||||
|
static const char * const excnames[] = {
|
||||||
|
[EXCP_UDEF] = "Undefined Instruction",
|
||||||
|
[EXCP_SWI] = "SVC",
|
||||||
|
[EXCP_PREFETCH_ABORT] = "Prefetch Abort",
|
||||||
|
[EXCP_DATA_ABORT] = "Data Abort",
|
||||||
|
[EXCP_IRQ] = "IRQ",
|
||||||
|
[EXCP_FIQ] = "FIQ",
|
||||||
|
[EXCP_BKPT] = "Breakpoint",
|
||||||
|
[EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
|
||||||
|
[EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
|
||||||
|
[EXCP_STREX] = "QEMU intercept of STREX",
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void arm_log_exception(int idx)
|
||||||
|
{
|
||||||
|
if (qemu_loglevel_mask(CPU_LOG_INT)) {
|
||||||
|
const char *exc = NULL;
|
||||||
|
|
||||||
|
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
|
||||||
|
exc = excnames[idx];
|
||||||
|
}
|
||||||
|
if (!exc) {
|
||||||
|
exc = "unknown";
|
||||||
|
}
|
||||||
|
qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scale factor for generic timers, ie number of ns per tick.
|
||||||
|
* This gives a 62.5MHz timer.
|
||||||
|
*/
|
||||||
|
#define GTIMER_SCALE 16
|
||||||
|
|
||||||
|
int bank_number(int mode);
|
||||||
|
void switch_mode(CPUARMState *, int);
|
||||||
|
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
|
||||||
|
void arm_translate_init(void);
|
||||||
|
|
||||||
|
enum arm_fprounding {
|
||||||
|
FPROUNDING_TIEEVEN,
|
||||||
|
FPROUNDING_POSINF,
|
||||||
|
FPROUNDING_NEGINF,
|
||||||
|
FPROUNDING_ZERO,
|
||||||
|
FPROUNDING_TIEAWAY,
|
||||||
|
FPROUNDING_ODD
|
||||||
|
};
|
||||||
|
|
||||||
|
int arm_rmode_to_sf(int rmode);
|
||||||
|
|
||||||
|
static inline void update_spsel(CPUARMState *env, uint32_t imm)
|
||||||
|
{
|
||||||
|
/* Update PSTATE SPSel bit; this requires us to update the
|
||||||
|
* working stack pointer in xregs[31].
|
||||||
|
*/
|
||||||
|
if (!((imm ^ env->pstate) & PSTATE_SP)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
env->pstate = deposit32(env->pstate, 0, 1, imm);
|
||||||
|
|
||||||
|
/* EL0 has no access rights to update SPSel, and this code
|
||||||
|
* assumes we are updating SP for EL1 while running as EL1.
|
||||||
|
*/
|
||||||
|
assert(arm_current_pl(env) == 1);
|
||||||
|
if (env->pstate & PSTATE_SP) {
|
||||||
|
/* Switch from using SP_EL0 to using SP_ELx */
|
||||||
|
env->sp_el[0] = env->xregs[31];
|
||||||
|
env->xregs[31] = env->sp_el[1];
|
||||||
|
} else {
|
||||||
|
/* Switch from SP_EL0 to SP_ELx */
|
||||||
|
env->sp_el[1] = env->xregs[31];
|
||||||
|
env->xregs[31] = env->sp_el[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Valid Syndrome Register EC field values */
|
||||||
|
enum arm_exception_class {
|
||||||
|
EC_UNCATEGORIZED = 0x00,
|
||||||
|
EC_WFX_TRAP = 0x01,
|
||||||
|
EC_CP15RTTRAP = 0x03,
|
||||||
|
EC_CP15RRTTRAP = 0x04,
|
||||||
|
EC_CP14RTTRAP = 0x05,
|
||||||
|
EC_CP14DTTRAP = 0x06,
|
||||||
|
EC_ADVSIMDFPACCESSTRAP = 0x07,
|
||||||
|
EC_FPIDTRAP = 0x08,
|
||||||
|
EC_CP14RRTTRAP = 0x0c,
|
||||||
|
EC_ILLEGALSTATE = 0x0e,
|
||||||
|
EC_AA32_SVC = 0x11,
|
||||||
|
EC_AA32_HVC = 0x12,
|
||||||
|
EC_AA32_SMC = 0x13,
|
||||||
|
EC_AA64_SVC = 0x15,
|
||||||
|
EC_AA64_HVC = 0x16,
|
||||||
|
EC_AA64_SMC = 0x17,
|
||||||
|
EC_SYSTEMREGISTERTRAP = 0x18,
|
||||||
|
EC_INSNABORT = 0x20,
|
||||||
|
EC_INSNABORT_SAME_EL = 0x21,
|
||||||
|
EC_PCALIGNMENT = 0x22,
|
||||||
|
EC_DATAABORT = 0x24,
|
||||||
|
EC_DATAABORT_SAME_EL = 0x25,
|
||||||
|
EC_SPALIGNMENT = 0x26,
|
||||||
|
EC_AA32_FPTRAP = 0x28,
|
||||||
|
EC_AA64_FPTRAP = 0x2c,
|
||||||
|
EC_SERROR = 0x2f,
|
||||||
|
EC_BREAKPOINT = 0x30,
|
||||||
|
EC_BREAKPOINT_SAME_EL = 0x31,
|
||||||
|
EC_SOFTWARESTEP = 0x32,
|
||||||
|
EC_SOFTWARESTEP_SAME_EL = 0x33,
|
||||||
|
EC_WATCHPOINT = 0x34,
|
||||||
|
EC_WATCHPOINT_SAME_EL = 0x35,
|
||||||
|
EC_AA32_BKPT = 0x38,
|
||||||
|
EC_VECTORCATCH = 0x3a,
|
||||||
|
EC_AA64_BKPT = 0x3c,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ARM_EL_EC_SHIFT 26
|
||||||
|
#define ARM_EL_IL_SHIFT 25
|
||||||
|
#define ARM_EL_IL (1 << ARM_EL_IL_SHIFT)
|
||||||
|
|
||||||
|
/* Utility functions for constructing various kinds of syndrome value.
|
||||||
|
* Note that in general we follow the AArch64 syndrome values; in a
|
||||||
|
* few cases the value in HSR for exceptions taken to AArch32 Hyp
|
||||||
|
* mode differs slightly, so if we ever implemented Hyp mode then the
|
||||||
|
* syndrome value would need some massaging on exception entry.
|
||||||
|
* (One example of this is that AArch64 defaults to IL bit set for
|
||||||
|
* exceptions which don't specifically indicate information about the
|
||||||
|
* trapping instruction, whereas AArch32 defaults to IL bit clear.)
|
||||||
|
*/
|
||||||
|
static inline uint32_t syn_uncategorized(void)
|
||||||
|
{
|
||||||
|
return (EC_UNCATEGORIZED << ARM_EL_EC_SHIFT) | ARM_EL_IL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_aa64_svc(uint32_t imm16)
|
||||||
|
{
|
||||||
|
return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
|
||||||
|
{
|
||||||
|
return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
|
||||||
|
| (is_thumb ? 0 : ARM_EL_IL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
|
||||||
|
{
|
||||||
|
return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_aa32_bkpt(uint32_t imm16, bool is_thumb)
|
||||||
|
{
|
||||||
|
return (EC_AA32_BKPT << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
|
||||||
|
| (is_thumb ? 0 : ARM_EL_IL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_aa64_sysregtrap(int op0, int op1, int op2,
|
||||||
|
int crn, int crm, int rt,
|
||||||
|
int isread)
|
||||||
|
{
|
||||||
|
return (EC_SYSTEMREGISTERTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL
|
||||||
|
| (op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (rt << 5)
|
||||||
|
| (crm << 1) | isread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_cp14_rt_trap(int cv, int cond, int opc1, int opc2,
|
||||||
|
int crn, int crm, int rt, int isread,
|
||||||
|
bool is_thumb)
|
||||||
|
{
|
||||||
|
return (EC_CP14RTTRAP << ARM_EL_EC_SHIFT)
|
||||||
|
| (is_thumb ? 0 : ARM_EL_IL)
|
||||||
|
| (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
|
||||||
|
| (crn << 10) | (rt << 5) | (crm << 1) | isread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_cp15_rt_trap(int cv, int cond, int opc1, int opc2,
|
||||||
|
int crn, int crm, int rt, int isread,
|
||||||
|
bool is_thumb)
|
||||||
|
{
|
||||||
|
return (EC_CP15RTTRAP << ARM_EL_EC_SHIFT)
|
||||||
|
| (is_thumb ? 0 : ARM_EL_IL)
|
||||||
|
| (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
|
||||||
|
| (crn << 10) | (rt << 5) | (crm << 1) | isread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_cp14_rrt_trap(int cv, int cond, int opc1, int crm,
|
||||||
|
int rt, int rt2, int isread,
|
||||||
|
bool is_thumb)
|
||||||
|
{
|
||||||
|
return (EC_CP14RRTTRAP << ARM_EL_EC_SHIFT)
|
||||||
|
| (is_thumb ? 0 : ARM_EL_IL)
|
||||||
|
| (cv << 24) | (cond << 20) | (opc1 << 16)
|
||||||
|
| (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
|
||||||
|
int rt, int rt2, int isread,
|
||||||
|
bool is_thumb)
|
||||||
|
{
|
||||||
|
return (EC_CP15RRTTRAP << ARM_EL_EC_SHIFT)
|
||||||
|
| (is_thumb ? 0 : ARM_EL_IL)
|
||||||
|
| (cv << 24) | (cond << 20) | (opc1 << 16)
|
||||||
|
| (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_thumb)
|
||||||
|
{
|
||||||
|
return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
|
||||||
|
| (is_thumb ? 0 : ARM_EL_IL)
|
||||||
|
| (cv << 24) | (cond << 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
|
||||||
|
{
|
||||||
|
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
|
||||||
|
| (ea << 9) | (s1ptw << 7) | fsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_data_abort(int same_el, int ea, int cm, int s1ptw,
|
||||||
|
int wnr, int fsc)
|
||||||
|
{
|
||||||
|
return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
|
||||||
|
| (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "kvm_arm.h"
|
#include "kvm_arm.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "internals.h"
|
||||||
#include "hw/arm/arm.h"
|
#include "hw/arm/arm.h"
|
||||||
|
|
||||||
static inline void set_feature(uint64_t *features, int feature)
|
static inline void set_feature(uint64_t *features, int feature)
|
||||||
@@ -294,6 +295,14 @@ typedef struct Reg {
|
|||||||
offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
|
offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
|
||||||
|
#define COREREG64(KERNELNAME, QEMUFIELD) \
|
||||||
|
{ \
|
||||||
|
KVM_REG_ARM | KVM_REG_SIZE_U32 | \
|
||||||
|
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
|
||||||
|
offsetoflow32(CPUARMState, QEMUFIELD) \
|
||||||
|
}
|
||||||
|
|
||||||
static const Reg regs[] = {
|
static const Reg regs[] = {
|
||||||
/* R0_usr .. R14_usr */
|
/* R0_usr .. R14_usr */
|
||||||
COREREG(usr_regs.uregs[0], regs[0]),
|
COREREG(usr_regs.uregs[0], regs[0]),
|
||||||
@@ -314,16 +323,16 @@ static const Reg regs[] = {
|
|||||||
/* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
|
/* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
|
||||||
COREREG(svc_regs[0], banked_r13[1]),
|
COREREG(svc_regs[0], banked_r13[1]),
|
||||||
COREREG(svc_regs[1], banked_r14[1]),
|
COREREG(svc_regs[1], banked_r14[1]),
|
||||||
COREREG(svc_regs[2], banked_spsr[1]),
|
COREREG64(svc_regs[2], banked_spsr[1]),
|
||||||
COREREG(abt_regs[0], banked_r13[2]),
|
COREREG(abt_regs[0], banked_r13[2]),
|
||||||
COREREG(abt_regs[1], banked_r14[2]),
|
COREREG(abt_regs[1], banked_r14[2]),
|
||||||
COREREG(abt_regs[2], banked_spsr[2]),
|
COREREG64(abt_regs[2], banked_spsr[2]),
|
||||||
COREREG(und_regs[0], banked_r13[3]),
|
COREREG(und_regs[0], banked_r13[3]),
|
||||||
COREREG(und_regs[1], banked_r14[3]),
|
COREREG(und_regs[1], banked_r14[3]),
|
||||||
COREREG(und_regs[2], banked_spsr[3]),
|
COREREG64(und_regs[2], banked_spsr[3]),
|
||||||
COREREG(irq_regs[0], banked_r13[4]),
|
COREREG(irq_regs[0], banked_r13[4]),
|
||||||
COREREG(irq_regs[1], banked_r14[4]),
|
COREREG(irq_regs[1], banked_r14[4]),
|
||||||
COREREG(irq_regs[2], banked_spsr[4]),
|
COREREG64(irq_regs[2], banked_spsr[4]),
|
||||||
/* R8_fiq .. R14_fiq and SPSR_fiq */
|
/* R8_fiq .. R14_fiq and SPSR_fiq */
|
||||||
COREREG(fiq_regs[0], fiq_regs[0]),
|
COREREG(fiq_regs[0], fiq_regs[0]),
|
||||||
COREREG(fiq_regs[1], fiq_regs[1]),
|
COREREG(fiq_regs[1], fiq_regs[1]),
|
||||||
@@ -332,7 +341,7 @@ static const Reg regs[] = {
|
|||||||
COREREG(fiq_regs[4], fiq_regs[4]),
|
COREREG(fiq_regs[4], fiq_regs[4]),
|
||||||
COREREG(fiq_regs[5], banked_r13[5]),
|
COREREG(fiq_regs[5], banked_r13[5]),
|
||||||
COREREG(fiq_regs[6], banked_r14[5]),
|
COREREG(fiq_regs[6], banked_r14[5]),
|
||||||
COREREG(fiq_regs[7], banked_spsr[5]),
|
COREREG64(fiq_regs[7], banked_spsr[5]),
|
||||||
/* R15 */
|
/* R15 */
|
||||||
COREREG(usr_regs.uregs[15], regs[15]),
|
COREREG(usr_regs.uregs[15], regs[15]),
|
||||||
/* VFP system registers */
|
/* VFP system registers */
|
||||||
|
|||||||
@@ -121,8 +121,24 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the
|
||||||
|
* QEMU side we keep the current SP in xregs[31] as well.
|
||||||
|
*/
|
||||||
|
if (env->pstate & PSTATE_SP) {
|
||||||
|
env->sp_el[1] = env->xregs[31];
|
||||||
|
} else {
|
||||||
|
env->sp_el[0] = env->xregs[31];
|
||||||
|
}
|
||||||
|
|
||||||
reg.id = AARCH64_CORE_REG(regs.sp);
|
reg.id = AARCH64_CORE_REG(regs.sp);
|
||||||
reg.addr = (uintptr_t) &env->xregs[31];
|
reg.addr = (uintptr_t) &env->sp_el[0];
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg.id = AARCH64_CORE_REG(sp_el1);
|
||||||
|
reg.addr = (uintptr_t) &env->sp_el[1];
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -144,10 +160,23 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reg.id = AARCH64_CORE_REG(elr_el1);
|
||||||
|
reg.addr = (uintptr_t) &env->elr_el1;
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < KVM_NR_SPSR; i++) {
|
||||||
|
reg.id = AARCH64_CORE_REG(spsr[i]);
|
||||||
|
reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* SP_EL1
|
|
||||||
* ELR_EL1
|
|
||||||
* SPSR[]
|
|
||||||
* FP state
|
* FP state
|
||||||
* system registers
|
* system registers
|
||||||
*/
|
*/
|
||||||
@@ -174,7 +203,14 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reg.id = AARCH64_CORE_REG(regs.sp);
|
reg.id = AARCH64_CORE_REG(regs.sp);
|
||||||
reg.addr = (uintptr_t) &env->xregs[31];
|
reg.addr = (uintptr_t) &env->sp_el[0];
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg.id = AARCH64_CORE_REG(sp_el1);
|
||||||
|
reg.addr = (uintptr_t) &env->sp_el[1];
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -188,6 +224,15 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||||||
}
|
}
|
||||||
pstate_write(env, val);
|
pstate_write(env, val);
|
||||||
|
|
||||||
|
/* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the
|
||||||
|
* QEMU side we keep the current SP in xregs[31] as well.
|
||||||
|
*/
|
||||||
|
if (env->pstate & PSTATE_SP) {
|
||||||
|
env->xregs[31] = env->sp_el[1];
|
||||||
|
} else {
|
||||||
|
env->xregs[31] = env->sp_el[0];
|
||||||
|
}
|
||||||
|
|
||||||
reg.id = AARCH64_CORE_REG(regs.pc);
|
reg.id = AARCH64_CORE_REG(regs.pc);
|
||||||
reg.addr = (uintptr_t) &env->pc;
|
reg.addr = (uintptr_t) &env->pc;
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||||
@@ -195,6 +240,22 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reg.id = AARCH64_CORE_REG(elr_el1);
|
||||||
|
reg.addr = (uintptr_t) &env->elr_el1;
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < KVM_NR_SPSR; i++) {
|
||||||
|
reg.id = AARCH64_CORE_REG(spsr[i]);
|
||||||
|
reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: other registers */
|
/* TODO: other registers */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user