Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1b725ee12 | ||
|
|
96bae145e2 | ||
|
|
7124ccf8b3 | ||
|
|
08c48c731a | ||
|
|
12110bf70e | ||
|
|
07672ab003 | ||
|
|
877e2b016e | ||
|
|
2f8ab9b1dd | ||
|
|
c15c6d2594 | ||
|
|
dd39c544f4 | ||
|
|
879b6454be | ||
|
|
ce37df91f4 | ||
|
|
dc35a13747 | ||
|
|
a290442234 | ||
|
|
031700e452 | ||
|
|
2f51fd1f73 | ||
|
|
63fdb09491 | ||
|
|
3328c14e63 | ||
|
|
a99fd943c4 | ||
|
|
670ddcc0aa | ||
|
|
8db38049c6 | ||
|
|
205a619563 | ||
|
|
5d26f91c89 | ||
|
|
1a184c3af3 | ||
|
|
7f515a96ab | ||
|
|
d437262fa8 | ||
|
|
74b13f92c2 | ||
|
|
4bcb497c7e | ||
|
|
8029d55a93 | ||
|
|
a3aeb9f09d | ||
|
|
34e9c09d03 | ||
|
|
9e9483dea9 | ||
|
|
ba9c51d225 | ||
|
|
495756ef9d | ||
|
|
9ad26963bf | ||
|
|
15ad066065 | ||
|
|
7cfd9c114b | ||
|
|
bddf2232fc | ||
|
|
fc8e94c3e5 | ||
|
|
5e4641777c | ||
|
|
d5506b3128 | ||
|
|
823fb688eb | ||
|
|
270a46ea0d | ||
|
|
f61f76cb3f | ||
|
|
8ac427cdd0 | ||
|
|
1d1d9226d8 | ||
|
|
adf2c47aa2 | ||
|
|
1a156ae5d1 | ||
|
|
3b8f27fe0b | ||
|
|
44d24c7b4a | ||
|
|
5f4b9013e6 | ||
|
|
5e40f283e5 | ||
|
|
d2b9063eb8 | ||
|
|
d8dea6fbcb | ||
|
|
f054cead44 | ||
|
|
5fb07a7b6c | ||
|
|
3fb4b3c371 | ||
|
|
a626117f6a | ||
|
|
3b33cba69c | ||
|
|
50b468d421 | ||
|
|
028fbea477 | ||
|
|
6e8052f967 | ||
|
|
5c60c6ef61 | ||
|
|
2ab8276a1c | ||
|
|
662a97d74f | ||
|
|
d6f119475d | ||
|
|
f47bf0823b | ||
|
|
8a6562592f | ||
|
|
9f6cb916f2 | ||
|
|
dc659e3aea | ||
|
|
87ede19db3 | ||
|
|
da95bfe06b | ||
|
|
7830be742a | ||
|
|
620a65dc44 | ||
|
|
9d14f0cd65 | ||
|
|
04cde530be | ||
|
|
a15785cfbd | ||
|
|
3731a25a62 | ||
|
|
7e9a1c4914 | ||
|
|
059f751ec2 | ||
|
|
bb07a379b5 | ||
|
|
719e6dd171 | ||
|
|
05a92c2005 | ||
|
|
9c5cb58970 | ||
|
|
c8c9aab173 | ||
|
|
5b24a96cd2 | ||
|
|
9f4ba82b06 | ||
|
|
62d1dbbfce | ||
|
|
ea9e59bdf6 | ||
|
|
e314b1b1fb | ||
|
|
d7322e13c6 | ||
|
|
d93d06a2fc | ||
|
|
0f3490faa8 | ||
|
|
cfe40e1485 | ||
|
|
3439290f9e | ||
|
|
ec10eada04 | ||
|
|
d3c54bf9e7 | ||
|
|
91225c670a | ||
|
|
4286f58bfc | ||
|
|
0bb99557e1 | ||
|
|
a9f46b8b65 | ||
|
|
ed6083afc2 | ||
|
|
d10142c11b | ||
|
|
6c1e3a16bc | ||
|
|
acf22d2264 | ||
|
|
54f951d634 | ||
|
|
984bd0a1b8 | ||
|
|
52d43ff72e | ||
|
|
e103f9e7b4 | ||
|
|
2c4f0f6c11 |
No files matched your search
+6
-2
@@ -498,14 +498,18 @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
|
|||||||
if (allocated) {
|
if (allocated) {
|
||||||
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
|
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
|
||||||
} else {
|
} else {
|
||||||
bitmap_clear(iscsilun->allocmap, cl_num_shrunk, nb_cls_shrunk);
|
if (nb_cls_shrunk > 0) {
|
||||||
|
bitmap_clear(iscsilun->allocmap, cl_num_shrunk, nb_cls_shrunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iscsilun->allocmap_valid == NULL) {
|
if (iscsilun->allocmap_valid == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (valid) {
|
if (valid) {
|
||||||
bitmap_set(iscsilun->allocmap_valid, cl_num_shrunk, nb_cls_shrunk);
|
if (nb_cls_shrunk > 0) {
|
||||||
|
bitmap_set(iscsilun->allocmap_valid, cl_num_shrunk, nb_cls_shrunk);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bitmap_clear(iscsilun->allocmap_valid, cl_num_expanded,
|
bitmap_clear(iscsilun->allocmap_valid, cl_num_expanded,
|
||||||
nb_cls_expanded);
|
nb_cls_expanded);
|
||||||
|
|||||||
+25
-24
@@ -108,12 +108,13 @@ static int nfs_parse_uri(const char *filename, QDict *options, Error **errp)
|
|||||||
qdict_put(options, "path", qstring_from_str(uri->path));
|
qdict_put(options, "path", qstring_from_str(uri->path));
|
||||||
|
|
||||||
for (i = 0; i < qp->n; i++) {
|
for (i = 0; i < qp->n; i++) {
|
||||||
|
unsigned long long val;
|
||||||
if (!qp->p[i].value) {
|
if (!qp->p[i].value) {
|
||||||
error_setg(errp, "Value for NFS parameter expected: %s",
|
error_setg(errp, "Value for NFS parameter expected: %s",
|
||||||
qp->p[i].name);
|
qp->p[i].name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (parse_uint_full(qp->p[i].value, NULL, 0)) {
|
if (parse_uint_full(qp->p[i].value, &val, 0)) {
|
||||||
error_setg(errp, "Illegal value for NFS parameter: %s",
|
error_setg(errp, "Illegal value for NFS parameter: %s",
|
||||||
qp->p[i].name);
|
qp->p[i].name);
|
||||||
goto out;
|
goto out;
|
||||||
@@ -357,27 +358,27 @@ static QemuOptsList runtime_opts = {
|
|||||||
.help = "Path of the image on the host",
|
.help = "Path of the image on the host",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "uid",
|
.name = "user",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
.help = "UID value to use when talking to the server",
|
.help = "UID value to use when talking to the server",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "gid",
|
.name = "group",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
.help = "GID value to use when talking to the server",
|
.help = "GID value to use when talking to the server",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "tcp-syncnt",
|
.name = "tcp-syn-count",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
.help = "Number of SYNs to send during the session establish",
|
.help = "Number of SYNs to send during the session establish",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "readahead",
|
.name = "readahead-size",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
.help = "Set the readahead size in bytes",
|
.help = "Set the readahead size in bytes",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "pagecache",
|
.name = "page-cache-size",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
.help = "Set the pagecache size in bytes",
|
.help = "Set the pagecache size in bytes",
|
||||||
},
|
},
|
||||||
@@ -506,29 +507,29 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemu_opt_get(opts, "uid")) {
|
if (qemu_opt_get(opts, "user")) {
|
||||||
client->uid = qemu_opt_get_number(opts, "uid", 0);
|
client->uid = qemu_opt_get_number(opts, "user", 0);
|
||||||
nfs_set_uid(client->context, client->uid);
|
nfs_set_uid(client->context, client->uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemu_opt_get(opts, "gid")) {
|
if (qemu_opt_get(opts, "group")) {
|
||||||
client->gid = qemu_opt_get_number(opts, "gid", 0);
|
client->gid = qemu_opt_get_number(opts, "group", 0);
|
||||||
nfs_set_gid(client->context, client->gid);
|
nfs_set_gid(client->context, client->gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemu_opt_get(opts, "tcp-syncnt")) {
|
if (qemu_opt_get(opts, "tcp-syn-count")) {
|
||||||
client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syncnt", 0);
|
client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syn-count", 0);
|
||||||
nfs_set_tcp_syncnt(client->context, client->tcp_syncnt);
|
nfs_set_tcp_syncnt(client->context, client->tcp_syncnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LIBNFS_FEATURE_READAHEAD
|
#ifdef LIBNFS_FEATURE_READAHEAD
|
||||||
if (qemu_opt_get(opts, "readahead")) {
|
if (qemu_opt_get(opts, "readahead-size")) {
|
||||||
if (open_flags & BDRV_O_NOCACHE) {
|
if (open_flags & BDRV_O_NOCACHE) {
|
||||||
error_setg(errp, "Cannot enable NFS readahead "
|
error_setg(errp, "Cannot enable NFS readahead "
|
||||||
"if cache.direct = on");
|
"if cache.direct = on");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
client->readahead = qemu_opt_get_number(opts, "readahead", 0);
|
client->readahead = qemu_opt_get_number(opts, "readahead-size", 0);
|
||||||
if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) {
|
if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) {
|
||||||
error_report("NFS Warning: Truncating NFS readahead "
|
error_report("NFS Warning: Truncating NFS readahead "
|
||||||
"size to %d", QEMU_NFS_MAX_READAHEAD_SIZE);
|
"size to %d", QEMU_NFS_MAX_READAHEAD_SIZE);
|
||||||
@@ -543,13 +544,13 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LIBNFS_FEATURE_PAGECACHE
|
#ifdef LIBNFS_FEATURE_PAGECACHE
|
||||||
if (qemu_opt_get(opts, "pagecache")) {
|
if (qemu_opt_get(opts, "page-cache-size")) {
|
||||||
if (open_flags & BDRV_O_NOCACHE) {
|
if (open_flags & BDRV_O_NOCACHE) {
|
||||||
error_setg(errp, "Cannot enable NFS pagecache "
|
error_setg(errp, "Cannot enable NFS pagecache "
|
||||||
"if cache.direct = on");
|
"if cache.direct = on");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
client->pagecache = qemu_opt_get_number(opts, "pagecache", 0);
|
client->pagecache = qemu_opt_get_number(opts, "page-cache-size", 0);
|
||||||
if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) {
|
if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) {
|
||||||
error_report("NFS Warning: Truncating NFS pagecache "
|
error_report("NFS Warning: Truncating NFS pagecache "
|
||||||
"size to %d pages", QEMU_NFS_MAX_PAGECACHE_SIZE);
|
"size to %d pages", QEMU_NFS_MAX_PAGECACHE_SIZE);
|
||||||
@@ -802,22 +803,22 @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
|
|||||||
qdict_put(opts, "path", qstring_from_str(client->path));
|
qdict_put(opts, "path", qstring_from_str(client->path));
|
||||||
|
|
||||||
if (client->uid) {
|
if (client->uid) {
|
||||||
qdict_put(opts, "uid", qint_from_int(client->uid));
|
qdict_put(opts, "user", qint_from_int(client->uid));
|
||||||
}
|
}
|
||||||
if (client->gid) {
|
if (client->gid) {
|
||||||
qdict_put(opts, "gid", qint_from_int(client->gid));
|
qdict_put(opts, "group", qint_from_int(client->gid));
|
||||||
}
|
}
|
||||||
if (client->tcp_syncnt) {
|
if (client->tcp_syncnt) {
|
||||||
qdict_put(opts, "tcp-syncnt",
|
qdict_put(opts, "tcp-syn-cnt",
|
||||||
qint_from_int(client->tcp_syncnt));
|
qint_from_int(client->tcp_syncnt));
|
||||||
}
|
}
|
||||||
if (client->readahead) {
|
if (client->readahead) {
|
||||||
qdict_put(opts, "readahead",
|
qdict_put(opts, "readahead-size",
|
||||||
qint_from_int(client->readahead));
|
qint_from_int(client->readahead));
|
||||||
}
|
}
|
||||||
if (client->pagecache) {
|
if (client->pagecache) {
|
||||||
qdict_put(opts, "pagecache",
|
qdict_put(opts, "page-cache-size",
|
||||||
qint_from_int(client->pagecache));
|
qint_from_int(client->pagecache));
|
||||||
}
|
}
|
||||||
if (client->debug) {
|
if (client->debug) {
|
||||||
qdict_put(opts, "debug", qint_from_int(client->debug));
|
qdict_put(opts, "debug", qint_from_int(client->debug));
|
||||||
|
|||||||
+2
-2
@@ -1354,8 +1354,8 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->lba = offset >> BDRV_SECTOR_BITS;
|
data->lba = cpu_to_le64(offset >> BDRV_SECTOR_BITS);
|
||||||
data->size = buf_len;
|
data->size = cpu_to_le32(buf_len);
|
||||||
|
|
||||||
n_bytes = buf_len + sizeof(VmdkGrainMarker);
|
n_bytes = buf_len + sizeof(VmdkGrainMarker);
|
||||||
iov = (struct iovec) {
|
iov = (struct iovec) {
|
||||||
|
|||||||
+5
-4
@@ -491,7 +491,7 @@ static inline void cpu_handle_interrupt(CPUState *cpu,
|
|||||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||||
CPUArchState *env = &x86_cpu->env;
|
CPUArchState *env = &x86_cpu->env;
|
||||||
replay_interrupt();
|
replay_interrupt();
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0, 0);
|
||||||
do_cpu_init(x86_cpu);
|
do_cpu_init(x86_cpu);
|
||||||
cpu->exception_index = EXCP_HALTED;
|
cpu->exception_index = EXCP_HALTED;
|
||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
@@ -542,7 +542,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
|||||||
|
|
||||||
trace_exec_tb(tb, tb->pc);
|
trace_exec_tb(tb, tb->pc);
|
||||||
ret = cpu_tb_exec(cpu, tb);
|
ret = cpu_tb_exec(cpu, tb);
|
||||||
*last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
|
tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
|
||||||
*tb_exit = ret & TB_EXIT_MASK;
|
*tb_exit = ret & TB_EXIT_MASK;
|
||||||
switch (*tb_exit) {
|
switch (*tb_exit) {
|
||||||
case TB_EXIT_REQUESTED:
|
case TB_EXIT_REQUESTED:
|
||||||
@@ -566,6 +566,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
|||||||
abort();
|
abort();
|
||||||
#else
|
#else
|
||||||
int insns_left = cpu->icount_decr.u32;
|
int insns_left = cpu->icount_decr.u32;
|
||||||
|
*last_tb = NULL;
|
||||||
if (cpu->icount_extra && insns_left >= 0) {
|
if (cpu->icount_extra && insns_left >= 0) {
|
||||||
/* Refill decrementer and continue execution. */
|
/* Refill decrementer and continue execution. */
|
||||||
cpu->icount_extra += insns_left;
|
cpu->icount_extra += insns_left;
|
||||||
@@ -575,17 +576,17 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
|||||||
} else {
|
} else {
|
||||||
if (insns_left > 0) {
|
if (insns_left > 0) {
|
||||||
/* Execute remaining instructions. */
|
/* Execute remaining instructions. */
|
||||||
cpu_exec_nocache(cpu, insns_left, *last_tb, false);
|
cpu_exec_nocache(cpu, insns_left, tb, false);
|
||||||
align_clocks(sc, cpu);
|
align_clocks(sc, cpu);
|
||||||
}
|
}
|
||||||
cpu->exception_index = EXCP_INTERRUPT;
|
cpu->exception_index = EXCP_INTERRUPT;
|
||||||
*last_tb = NULL;
|
|
||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
*last_tb = tb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2927,6 +2927,7 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_
|
|||||||
if (!memory_access_is_direct(mr, is_write)) {
|
if (!memory_access_is_direct(mr, is_write)) {
|
||||||
l = memory_access_size(mr, l, addr);
|
l = memory_access_size(mr, l, addr);
|
||||||
if (!memory_region_access_valid(mr, xlat, l, is_write)) {
|
if (!memory_region_access_valid(mr, xlat, l, is_write)) {
|
||||||
|
rcu_read_unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1551,6 +1551,7 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
|
|||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
BlockIOThrottle throttle = {
|
BlockIOThrottle throttle = {
|
||||||
|
.has_device = true,
|
||||||
.device = (char *) qdict_get_str(qdict, "device"),
|
.device = (char *) qdict_get_str(qdict, "device"),
|
||||||
.bps = qdict_get_int(qdict, "bps"),
|
.bps = qdict_get_int(qdict, "bps"),
|
||||||
.bps_rd = qdict_get_int(qdict, "bps_rd"),
|
.bps_rd = qdict_get_int(qdict, "bps_rd"),
|
||||||
@@ -1808,7 +1809,6 @@ void hmp_object_add(Monitor *mon, const QDict *qdict)
|
|||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
Visitor *v;
|
|
||||||
Object *obj = NULL;
|
Object *obj = NULL;
|
||||||
|
|
||||||
opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err);
|
opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err);
|
||||||
@@ -1817,9 +1817,7 @@ void hmp_object_add(Monitor *mon, const QDict *qdict)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = opts_visitor_new(opts);
|
obj = user_creatable_add_opts(opts, &err);
|
||||||
obj = user_creatable_add(qdict, v, &err);
|
|
||||||
visit_free(v);
|
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
+570
-470
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 9p local backend utilities
|
||||||
|
*
|
||||||
|
* Copyright IBM, Corp. 2017
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Greg Kurz <groug@kaod.org>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QEMU_9P_LOCAL_H
|
||||||
|
#define QEMU_9P_LOCAL_H
|
||||||
|
|
||||||
|
int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags,
|
||||||
|
mode_t mode);
|
||||||
|
int local_opendir_nofollow(FsContext *fs_ctx, const char *path);
|
||||||
|
|
||||||
|
#endif
|
||||||
+8
-36
@@ -25,13 +25,7 @@
|
|||||||
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value, size_t size)
|
const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
char *buffer;
|
return local_getxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size);
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
|
||||||
ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
|
||||||
@@ -56,23 +50,16 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
|
|||||||
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
void *value, size_t size, int flags)
|
void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
char *buffer;
|
return local_setxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size,
|
||||||
int ret;
|
flags);
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
|
||||||
ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_pacl_removexattr(FsContext *ctx,
|
static int mp_pacl_removexattr(FsContext *ctx,
|
||||||
const char *path, const char *name)
|
const char *path, const char *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char *buffer;
|
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
ret = local_removexattr_nofollow(ctx, path, MAP_ACL_ACCESS);
|
||||||
ret = lremovexattr(buffer, MAP_ACL_ACCESS);
|
|
||||||
if (ret == -1 && errno == ENODATA) {
|
if (ret == -1 && errno == ENODATA) {
|
||||||
/*
|
/*
|
||||||
* We don't get ENODATA error when trying to remove a
|
* We don't get ENODATA error when trying to remove a
|
||||||
@@ -82,20 +69,13 @@ static int mp_pacl_removexattr(FsContext *ctx,
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value, size_t size)
|
const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
char *buffer;
|
return local_getxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size);
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
|
||||||
ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
|
||||||
@@ -120,23 +100,16 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
|
|||||||
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
void *value, size_t size, int flags)
|
void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
char *buffer;
|
return local_setxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size,
|
||||||
int ret;
|
flags);
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
|
||||||
ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_dacl_removexattr(FsContext *ctx,
|
static int mp_dacl_removexattr(FsContext *ctx,
|
||||||
const char *path, const char *name)
|
const char *path, const char *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char *buffer;
|
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
ret = local_removexattr_nofollow(ctx, path, MAP_ACL_DEFAULT);
|
||||||
ret = lremovexattr(buffer, MAP_ACL_DEFAULT);
|
|
||||||
if (ret == -1 && errno == ENODATA) {
|
if (ret == -1 && errno == ENODATA) {
|
||||||
/*
|
/*
|
||||||
* We don't get ENODATA error when trying to remove a
|
* We don't get ENODATA error when trying to remove a
|
||||||
@@ -146,7 +119,6 @@ static int mp_dacl_removexattr(FsContext *ctx,
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 9p utilities
|
||||||
|
*
|
||||||
|
* Copyright IBM, Corp. 2017
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Greg Kurz <groug@kaod.org>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/xattr.h"
|
||||||
|
#include "9p-util.h"
|
||||||
|
|
||||||
|
int relative_openat_nofollow(int dirfd, const char *path, int flags,
|
||||||
|
mode_t mode)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = dup(dirfd);
|
||||||
|
if (fd == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*path) {
|
||||||
|
const char *c;
|
||||||
|
int next_fd;
|
||||||
|
char *head;
|
||||||
|
|
||||||
|
/* Only relative paths without consecutive slashes */
|
||||||
|
assert(path[0] != '/');
|
||||||
|
|
||||||
|
head = g_strdup(path);
|
||||||
|
c = strchr(path, '/');
|
||||||
|
if (c) {
|
||||||
|
head[c - path] = 0;
|
||||||
|
next_fd = openat_dir(fd, head);
|
||||||
|
} else {
|
||||||
|
next_fd = openat_file(fd, head, flags, mode);
|
||||||
|
}
|
||||||
|
g_free(head);
|
||||||
|
if (next_fd == -1) {
|
||||||
|
close_preserve_errno(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
fd = next_fd;
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path = c + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
|
||||||
|
void *value, size_t size)
|
||||||
|
{
|
||||||
|
char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = lgetxattr(proc_path, name, value, size);
|
||||||
|
g_free(proc_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 9p utilities
|
||||||
|
*
|
||||||
|
* Copyright IBM, Corp. 2017
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Greg Kurz <groug@kaod.org>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QEMU_9P_UTIL_H
|
||||||
|
#define QEMU_9P_UTIL_H
|
||||||
|
|
||||||
|
static inline void close_preserve_errno(int fd)
|
||||||
|
{
|
||||||
|
int serrno = errno;
|
||||||
|
close(fd);
|
||||||
|
errno = serrno;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int openat_dir(int dirfd, const char *name)
|
||||||
|
{
|
||||||
|
#ifdef O_PATH
|
||||||
|
#define OPENAT_DIR_O_PATH O_PATH
|
||||||
|
#else
|
||||||
|
#define OPENAT_DIR_O_PATH 0
|
||||||
|
#endif
|
||||||
|
return openat(dirfd, name,
|
||||||
|
O_DIRECTORY | O_RDONLY | O_NOFOLLOW | OPENAT_DIR_O_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int openat_file(int dirfd, const char *name, int flags,
|
||||||
|
mode_t mode)
|
||||||
|
{
|
||||||
|
int fd, serrno, ret;
|
||||||
|
|
||||||
|
fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK,
|
||||||
|
mode);
|
||||||
|
if (fd == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
serrno = errno;
|
||||||
|
/* O_NONBLOCK was only needed to open the file. Let's drop it. */
|
||||||
|
ret = fcntl(fd, F_SETFL, flags);
|
||||||
|
assert(!ret);
|
||||||
|
errno = serrno;
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int relative_openat_nofollow(int dirfd, const char *path, int flags,
|
||||||
|
mode_t mode);
|
||||||
|
ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name,
|
||||||
|
void *value, size_t size);
|
||||||
|
int fsetxattrat_nofollow(int dirfd, const char *path, const char *name,
|
||||||
|
void *value, size_t size, int flags);
|
||||||
|
|
||||||
|
#endif
|
||||||
+3
-21
@@ -20,9 +20,6 @@
|
|||||||
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
|
||||||
const char *name, void *value, size_t size)
|
const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
char *buffer;
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
||||||
/*
|
/*
|
||||||
* Don't allow fetch of user.virtfs namesapce
|
* Don't allow fetch of user.virtfs namesapce
|
||||||
@@ -31,10 +28,7 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
|
|||||||
errno = ENOATTR;
|
errno = ENOATTR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
buffer = rpath(ctx, path);
|
return local_getxattr_nofollow(ctx, path, name, value, size);
|
||||||
ret = lgetxattr(buffer, name, value, size);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
|
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
|
||||||
@@ -73,9 +67,6 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
|
|||||||
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
|
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
void *value, size_t size, int flags)
|
void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
char *buffer;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
||||||
/*
|
/*
|
||||||
* Don't allow fetch of user.virtfs namesapce
|
* Don't allow fetch of user.virtfs namesapce
|
||||||
@@ -84,18 +75,12 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
|
|||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
buffer = rpath(ctx, path);
|
return local_setxattr_nofollow(ctx, path, name, value, size, flags);
|
||||||
ret = lsetxattr(buffer, name, value, size, flags);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_user_removexattr(FsContext *ctx,
|
static int mp_user_removexattr(FsContext *ctx,
|
||||||
const char *path, const char *name)
|
const char *path, const char *name)
|
||||||
{
|
{
|
||||||
char *buffer;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
if (strncmp(name, "user.virtfs.", 12) == 0) {
|
||||||
/*
|
/*
|
||||||
* Don't allow fetch of user.virtfs namesapce
|
* Don't allow fetch of user.virtfs namesapce
|
||||||
@@ -104,10 +89,7 @@ static int mp_user_removexattr(FsContext *ctx,
|
|||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
buffer = rpath(ctx, path);
|
return local_removexattr_nofollow(ctx, path, name);
|
||||||
ret = lremovexattr(buffer, name);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XattrOperations mapped_user_xattr = {
|
XattrOperations mapped_user_xattr = {
|
||||||
|
|||||||
+160
-6
@@ -15,6 +15,8 @@
|
|||||||
#include "9p.h"
|
#include "9p.h"
|
||||||
#include "fsdev/file-op-9p.h"
|
#include "fsdev/file-op-9p.h"
|
||||||
#include "9p-xattr.h"
|
#include "9p-xattr.h"
|
||||||
|
#include "9p-util.h"
|
||||||
|
#include "9p-local.h"
|
||||||
|
|
||||||
|
|
||||||
static XattrOperations *get_xattr_operations(XattrOperations **h,
|
static XattrOperations *get_xattr_operations(XattrOperations **h,
|
||||||
@@ -58,6 +60,16 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path,
|
|||||||
return name_size;
|
return name_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
|
||||||
|
char *list, size_t size)
|
||||||
|
{
|
||||||
|
char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = llistxattr(proc_path, list, size);
|
||||||
|
g_free(proc_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the list and pass to each layer to find out whether
|
* Get the list and pass to each layer to find out whether
|
||||||
@@ -67,24 +79,37 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
|
|||||||
void *value, size_t vsize)
|
void *value, size_t vsize)
|
||||||
{
|
{
|
||||||
ssize_t size = 0;
|
ssize_t size = 0;
|
||||||
char *buffer;
|
|
||||||
void *ovalue = value;
|
void *ovalue = value;
|
||||||
XattrOperations *xops;
|
XattrOperations *xops;
|
||||||
char *orig_value, *orig_value_start;
|
char *orig_value, *orig_value_start;
|
||||||
ssize_t xattr_len, parsed_len = 0, attr_len;
|
ssize_t xattr_len, parsed_len = 0, attr_len;
|
||||||
|
char *dirpath, *name;
|
||||||
|
int dirfd;
|
||||||
|
|
||||||
/* Get the actual len */
|
/* Get the actual len */
|
||||||
buffer = rpath(ctx, path);
|
dirpath = g_path_get_dirname(path);
|
||||||
xattr_len = llistxattr(buffer, value, 0);
|
dirfd = local_opendir_nofollow(ctx, dirpath);
|
||||||
|
g_free(dirpath);
|
||||||
|
if (dirfd == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = g_path_get_basename(path);
|
||||||
|
xattr_len = flistxattrat_nofollow(dirfd, name, value, 0);
|
||||||
if (xattr_len <= 0) {
|
if (xattr_len <= 0) {
|
||||||
g_free(buffer);
|
g_free(name);
|
||||||
|
close_preserve_errno(dirfd);
|
||||||
return xattr_len;
|
return xattr_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now fetch the xattr and find the actual size */
|
/* Now fetch the xattr and find the actual size */
|
||||||
orig_value = g_malloc(xattr_len);
|
orig_value = g_malloc(xattr_len);
|
||||||
xattr_len = llistxattr(buffer, orig_value, xattr_len);
|
xattr_len = flistxattrat_nofollow(dirfd, name, orig_value, xattr_len);
|
||||||
g_free(buffer);
|
g_free(name);
|
||||||
|
close_preserve_errno(dirfd);
|
||||||
|
if (xattr_len < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* store the orig pointer */
|
/* store the orig pointer */
|
||||||
orig_value_start = orig_value;
|
orig_value_start = orig_value;
|
||||||
@@ -143,6 +168,135 @@ int v9fs_remove_xattr(FsContext *ctx,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
|
||||||
|
const char *name, void *value, size_t size)
|
||||||
|
{
|
||||||
|
char *dirpath = g_path_get_dirname(path);
|
||||||
|
char *filename = g_path_get_basename(path);
|
||||||
|
int dirfd;
|
||||||
|
ssize_t ret = -1;
|
||||||
|
|
||||||
|
dirfd = local_opendir_nofollow(ctx, dirpath);
|
||||||
|
if (dirfd == -1) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fgetxattrat_nofollow(dirfd, filename, name, value, size);
|
||||||
|
close_preserve_errno(dirfd);
|
||||||
|
out:
|
||||||
|
g_free(dirpath);
|
||||||
|
g_free(filename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
|
void *value, size_t size)
|
||||||
|
{
|
||||||
|
return local_getxattr_nofollow(ctx, path, name, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
|
||||||
|
void *value, size_t size, int flags)
|
||||||
|
{
|
||||||
|
char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = lsetxattr(proc_path, name, value, size, flags);
|
||||||
|
g_free(proc_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path,
|
||||||
|
const char *name, void *value, size_t size,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
char *dirpath = g_path_get_dirname(path);
|
||||||
|
char *filename = g_path_get_basename(path);
|
||||||
|
int dirfd;
|
||||||
|
ssize_t ret = -1;
|
||||||
|
|
||||||
|
dirfd = local_opendir_nofollow(ctx, dirpath);
|
||||||
|
if (dirfd == -1) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fsetxattrat_nofollow(dirfd, filename, name, value, size, flags);
|
||||||
|
close_preserve_errno(dirfd);
|
||||||
|
out:
|
||||||
|
g_free(dirpath);
|
||||||
|
g_free(filename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
|
||||||
|
size_t size, int flags)
|
||||||
|
{
|
||||||
|
return local_setxattr_nofollow(ctx, path, name, value, size, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = lremovexattr(proc_path, name);
|
||||||
|
g_free(proc_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
char *dirpath = g_path_get_dirname(path);
|
||||||
|
char *filename = g_path_get_basename(path);
|
||||||
|
int dirfd;
|
||||||
|
ssize_t ret = -1;
|
||||||
|
|
||||||
|
dirfd = local_opendir_nofollow(ctx, dirpath);
|
||||||
|
if (dirfd == -1) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fremovexattrat_nofollow(dirfd, filename, name);
|
||||||
|
close_preserve_errno(dirfd);
|
||||||
|
out:
|
||||||
|
g_free(dirpath);
|
||||||
|
g_free(filename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pt_removexattr(FsContext *ctx, const char *path, const char *name)
|
||||||
|
{
|
||||||
|
return local_removexattr_nofollow(ctx, path, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
|
void *value, size_t size)
|
||||||
|
{
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
|
void *value, size_t size, int flags)
|
||||||
|
{
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
|
||||||
|
void *value, size_t size)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int notsup_removexattr(FsContext *ctx, const char *path, const char *name)
|
||||||
|
{
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
XattrOperations *mapped_xattr_ops[] = {
|
XattrOperations *mapped_xattr_ops[] = {
|
||||||
&mapped_user_xattr,
|
&mapped_user_xattr,
|
||||||
&mapped_pacl_xattr,
|
&mapped_pacl_xattr,
|
||||||
|
|||||||
+20
-65
@@ -29,6 +29,13 @@ typedef struct xattr_operations
|
|||||||
const char *path, const char *name);
|
const char *path, const char *name);
|
||||||
} XattrOperations;
|
} XattrOperations;
|
||||||
|
|
||||||
|
ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
|
||||||
|
const char *name, void *value, size_t size);
|
||||||
|
ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path,
|
||||||
|
const char *name, void *value, size_t size,
|
||||||
|
int flags);
|
||||||
|
ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
extern XattrOperations mapped_user_xattr;
|
extern XattrOperations mapped_user_xattr;
|
||||||
extern XattrOperations passthrough_user_xattr;
|
extern XattrOperations passthrough_user_xattr;
|
||||||
@@ -49,73 +56,21 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, void *value,
|
|||||||
int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
|
int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
|
||||||
void *value, size_t size, int flags);
|
void *value, size_t size, int flags);
|
||||||
int v9fs_remove_xattr(FsContext *ctx, const char *path, const char *name);
|
int v9fs_remove_xattr(FsContext *ctx, const char *path, const char *name);
|
||||||
|
|
||||||
ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
|
ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
|
void *value, size_t size);
|
||||||
|
int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
|
||||||
|
size_t size, int flags);
|
||||||
|
int pt_removexattr(FsContext *ctx, const char *path, const char *name);
|
||||||
|
|
||||||
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
|
ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
const char *name, void *value, size_t size)
|
void *value, size_t size);
|
||||||
{
|
int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
|
||||||
char *buffer;
|
void *value, size_t size, int flags);
|
||||||
ssize_t ret;
|
ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
|
||||||
|
void *value, size_t size);
|
||||||
buffer = rpath(ctx, path);
|
int notsup_removexattr(FsContext *ctx, const char *path, const char *name);
|
||||||
ret = lgetxattr(buffer, name, value, size);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int pt_setxattr(FsContext *ctx, const char *path,
|
|
||||||
const char *name, void *value,
|
|
||||||
size_t size, int flags)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
|
||||||
ret = lsetxattr(buffer, name, value, size, flags);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int pt_removexattr(FsContext *ctx,
|
|
||||||
const char *path, const char *name)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
|
||||||
ret = lremovexattr(path, name);
|
|
||||||
g_free(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
|
|
||||||
const char *name, void *value,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
errno = ENOTSUP;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int notsup_setxattr(FsContext *ctx, const char *path,
|
|
||||||
const char *name, void *value,
|
|
||||||
size_t size, int flags)
|
|
||||||
{
|
|
||||||
errno = ENOTSUP;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline ssize_t notsup_listxattr(FsContext *ctx, const char *path,
|
|
||||||
char *name, void *value, size_t size)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int notsup_removexattr(FsContext *ctx,
|
|
||||||
const char *path, const char *name)
|
|
||||||
{
|
|
||||||
errno = ENOTSUP;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+10
-6
@@ -2337,7 +2337,7 @@ static void v9fs_flush(void *opaque)
|
|||||||
ssize_t err;
|
ssize_t err;
|
||||||
int16_t tag;
|
int16_t tag;
|
||||||
size_t offset = 7;
|
size_t offset = 7;
|
||||||
V9fsPDU *cancel_pdu;
|
V9fsPDU *cancel_pdu = NULL;
|
||||||
V9fsPDU *pdu = opaque;
|
V9fsPDU *pdu = opaque;
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
|
|
||||||
@@ -2348,9 +2348,13 @@ static void v9fs_flush(void *opaque)
|
|||||||
}
|
}
|
||||||
trace_v9fs_flush(pdu->tag, pdu->id, tag);
|
trace_v9fs_flush(pdu->tag, pdu->id, tag);
|
||||||
|
|
||||||
QLIST_FOREACH(cancel_pdu, &s->active_list, next) {
|
if (pdu->tag == tag) {
|
||||||
if (cancel_pdu->tag == tag) {
|
error_report("Warning: the guest sent a self-referencing 9P flush request");
|
||||||
break;
|
} else {
|
||||||
|
QLIST_FOREACH(cancel_pdu, &s->active_list, next) {
|
||||||
|
if (cancel_pdu->tag == tag) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cancel_pdu) {
|
if (cancel_pdu) {
|
||||||
@@ -3450,7 +3454,7 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
|
|||||||
/* initialize pdu allocator */
|
/* initialize pdu allocator */
|
||||||
QLIST_INIT(&s->free_list);
|
QLIST_INIT(&s->free_list);
|
||||||
QLIST_INIT(&s->active_list);
|
QLIST_INIT(&s->active_list);
|
||||||
for (i = 0; i < (MAX_REQ - 1); i++) {
|
for (i = 0; i < MAX_REQ; i++) {
|
||||||
QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next);
|
QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next);
|
||||||
v->pdus[i].s = s;
|
v->pdus[i].s = s;
|
||||||
v->pdus[i].idx = i;
|
v->pdus[i].idx = i;
|
||||||
@@ -3521,7 +3525,7 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (s->ops->cleanup && s->ctx.private) {
|
if (s->ops && s->ops->cleanup && s->ctx.private) {
|
||||||
s->ops->cleanup(&s->ctx);
|
s->ops->cleanup(&s->ctx);
|
||||||
}
|
}
|
||||||
g_free(s->tag);
|
g_free(s->tag);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
common-obj-y = 9p.o
|
common-obj-y = 9p.o 9p-util.o
|
||||||
common-obj-y += 9p-local.o 9p-xattr.o
|
common-obj-y += 9p-local.o 9p-xattr.o
|
||||||
common-obj-y += 9p-xattr-user.o 9p-posix-acl.o
|
common-obj-y += 9p-xattr-user.o 9p-posix-acl.o
|
||||||
common-obj-y += coth.o cofs.o codir.o cofile.o
|
common-obj-y += coth.o cofs.o codir.o cofile.o
|
||||||
|
|||||||
+36
-3
@@ -554,11 +554,31 @@ static void machine_class_finalize(ObjectClass *klass, void *data)
|
|||||||
g_free(mc->name);
|
g_free(mc->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void register_compat_prop(const char *driver,
|
||||||
|
const char *property,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
GlobalProperty *p = g_new0(GlobalProperty, 1);
|
||||||
|
/* Machine compat_props must never cause errors: */
|
||||||
|
p->errp = &error_abort;
|
||||||
|
p->driver = driver;
|
||||||
|
p->property = property;
|
||||||
|
p->value = value;
|
||||||
|
qdev_prop_register_global(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void machine_register_compat_for_subclass(ObjectClass *oc, void *opaque)
|
||||||
|
{
|
||||||
|
GlobalProperty *p = opaque;
|
||||||
|
register_compat_prop(object_class_get_name(oc), p->property, p->value);
|
||||||
|
}
|
||||||
|
|
||||||
void machine_register_compat_props(MachineState *machine)
|
void machine_register_compat_props(MachineState *machine)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
int i;
|
int i;
|
||||||
GlobalProperty *p;
|
GlobalProperty *p;
|
||||||
|
ObjectClass *oc;
|
||||||
|
|
||||||
if (!mc->compat_props) {
|
if (!mc->compat_props) {
|
||||||
return;
|
return;
|
||||||
@@ -566,9 +586,22 @@ void machine_register_compat_props(MachineState *machine)
|
|||||||
|
|
||||||
for (i = 0; i < mc->compat_props->len; i++) {
|
for (i = 0; i < mc->compat_props->len; i++) {
|
||||||
p = g_array_index(mc->compat_props, GlobalProperty *, i);
|
p = g_array_index(mc->compat_props, GlobalProperty *, i);
|
||||||
/* Machine compat_props must never cause errors: */
|
oc = object_class_by_name(p->driver);
|
||||||
p->errp = &error_abort;
|
if (oc && object_class_is_abstract(oc)) {
|
||||||
qdev_prop_register_global(p);
|
/* temporary hack to make sure we do not override
|
||||||
|
* globals set explicitly on -global: if an abstract class
|
||||||
|
* is on compat_props, register globals for all its
|
||||||
|
* non-abstract subtypes instead.
|
||||||
|
*
|
||||||
|
* This doesn't solve the problem for cases where
|
||||||
|
* a non-abstract typename mentioned on compat_props
|
||||||
|
* has subclasses, like spapr-pci-host-bridge.
|
||||||
|
*/
|
||||||
|
object_class_foreach(machine_register_compat_for_subclass,
|
||||||
|
p->driver, false, p);
|
||||||
|
} else {
|
||||||
|
register_compat_prop(p->driver, p->property, p->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+111
-43
@@ -177,11 +177,12 @@
|
|||||||
|
|
||||||
struct CirrusVGAState;
|
struct CirrusVGAState;
|
||||||
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
|
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
|
||||||
uint8_t * dst, const uint8_t * src,
|
uint32_t dstaddr, uint32_t srcaddr,
|
||||||
int dstpitch, int srcpitch,
|
int dstpitch, int srcpitch,
|
||||||
int bltwidth, int bltheight);
|
int bltwidth, int bltheight);
|
||||||
typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
|
typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
|
||||||
uint8_t *dst, int dst_pitch, int width, int height);
|
uint32_t dstaddr, int dst_pitch,
|
||||||
|
int width, int height);
|
||||||
|
|
||||||
typedef struct CirrusVGAState {
|
typedef struct CirrusVGAState {
|
||||||
VGACommonState vga;
|
VGACommonState vga;
|
||||||
@@ -277,10 +278,9 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
|
|||||||
}
|
}
|
||||||
if (pitch < 0) {
|
if (pitch < 0) {
|
||||||
int64_t min = addr
|
int64_t min = addr
|
||||||
+ ((int64_t)s->cirrus_blt_height-1) * pitch;
|
+ ((int64_t)s->cirrus_blt_height - 1) * pitch
|
||||||
int32_t max = addr
|
- s->cirrus_blt_width;
|
||||||
+ s->cirrus_blt_width;
|
if (min < -1 || addr >= s->vga.vram_size) {
|
||||||
if (min < 0 || max > s->vga.vram_size) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -294,7 +294,7 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool blit_is_unsafe(struct CirrusVGAState *s)
|
static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
|
||||||
{
|
{
|
||||||
/* should be the case, see cirrus_bitblt_start */
|
/* should be the case, see cirrus_bitblt_start */
|
||||||
assert(s->cirrus_blt_width > 0);
|
assert(s->cirrus_blt_width > 0);
|
||||||
@@ -305,11 +305,14 @@ static bool blit_is_unsafe(struct CirrusVGAState *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
|
if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
|
||||||
s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
|
s->cirrus_blt_dstaddr)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (dst_only) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
|
if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
|
||||||
s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {
|
s->cirrus_blt_srcaddr)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,18 +320,57 @@ static bool blit_is_unsafe(struct CirrusVGAState *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
|
static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
|
||||||
uint8_t *dst,const uint8_t *src,
|
uint32_t dstaddr, uint32_t srcaddr,
|
||||||
int dstpitch,int srcpitch,
|
int dstpitch,int srcpitch,
|
||||||
int bltwidth,int bltheight)
|
int bltwidth,int bltheight)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
|
static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
|
||||||
uint8_t *dst,
|
uint32_t dstaddr,
|
||||||
int dstpitch, int bltwidth,int bltheight)
|
int dstpitch, int bltwidth,int bltheight)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr)
|
||||||
|
{
|
||||||
|
if (s->cirrus_srccounter) {
|
||||||
|
/* cputovideo */
|
||||||
|
return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)];
|
||||||
|
} else {
|
||||||
|
/* videotovideo */
|
||||||
|
return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr)
|
||||||
|
{
|
||||||
|
uint16_t *src;
|
||||||
|
|
||||||
|
if (s->cirrus_srccounter) {
|
||||||
|
/* cputovideo */
|
||||||
|
src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1];
|
||||||
|
} else {
|
||||||
|
/* videotovideo */
|
||||||
|
src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1];
|
||||||
|
}
|
||||||
|
return *src;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr)
|
||||||
|
{
|
||||||
|
uint32_t *src;
|
||||||
|
|
||||||
|
if (s->cirrus_srccounter) {
|
||||||
|
/* cputovideo */
|
||||||
|
src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3];
|
||||||
|
} else {
|
||||||
|
/* videotovideo */
|
||||||
|
src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3];
|
||||||
|
}
|
||||||
|
return *src;
|
||||||
|
}
|
||||||
|
|
||||||
#define ROP_NAME 0
|
#define ROP_NAME 0
|
||||||
#define ROP_FN(d, s) 0
|
#define ROP_FN(d, s) 0
|
||||||
#include "cirrus_vga_rop.h"
|
#include "cirrus_vga_rop.h"
|
||||||
@@ -658,25 +700,51 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
|
|||||||
int off_cur;
|
int off_cur;
|
||||||
int off_cur_end;
|
int off_cur_end;
|
||||||
|
|
||||||
|
if (off_pitch < 0) {
|
||||||
|
off_begin -= bytesperline - 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (y = 0; y < lines; y++) {
|
for (y = 0; y < lines; y++) {
|
||||||
off_cur = off_begin;
|
off_cur = off_begin;
|
||||||
off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
|
off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1;
|
||||||
|
assert(off_cur_end >= off_cur);
|
||||||
memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
|
memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
|
||||||
off_begin += off_pitch;
|
off_begin += off_pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
|
static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s)
|
||||||
const uint8_t * src)
|
|
||||||
{
|
{
|
||||||
uint8_t *dst;
|
uint32_t patternsize;
|
||||||
|
bool videosrc = !s->cirrus_srccounter;
|
||||||
|
|
||||||
dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
|
if (videosrc) {
|
||||||
|
switch (s->vga.get_bpp(&s->vga)) {
|
||||||
|
case 8:
|
||||||
|
patternsize = 64;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
case 16:
|
||||||
|
patternsize = 128;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
case 32:
|
||||||
|
default:
|
||||||
|
patternsize = 256;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s->cirrus_blt_srcaddr &= ~(patternsize - 1);
|
||||||
|
if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (blit_is_unsafe(s))
|
if (blit_is_unsafe(s, true)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
(*s->cirrus_rop) (s, dst, src,
|
(*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
|
||||||
|
videosrc ? s->cirrus_blt_srcaddr : 0,
|
||||||
s->cirrus_blt_dstpitch, 0,
|
s->cirrus_blt_dstpitch, 0,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
||||||
@@ -691,11 +759,11 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
|
|||||||
{
|
{
|
||||||
cirrus_fill_t rop_func;
|
cirrus_fill_t rop_func;
|
||||||
|
|
||||||
if (blit_is_unsafe(s)) {
|
if (blit_is_unsafe(s, true)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
|
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
|
||||||
rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
rop_func(s, s->cirrus_blt_dstaddr,
|
||||||
s->cirrus_blt_dstpitch,
|
s->cirrus_blt_dstpitch,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
||||||
@@ -713,9 +781,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
|
|||||||
|
|
||||||
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
||||||
{
|
{
|
||||||
return cirrus_bitblt_common_patterncopy(s,
|
return cirrus_bitblt_common_patterncopy(s);
|
||||||
s->vga.vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
|
|
||||||
s->cirrus_addr_mask));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
||||||
@@ -764,23 +830,15 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have to flush all pending changes so that the copy
|
(*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
|
||||||
is generated at the appropriate moment in time */
|
s->cirrus_blt_srcaddr,
|
||||||
if (notify)
|
|
||||||
graphic_hw_update(s->vga.con);
|
|
||||||
|
|
||||||
(*s->cirrus_rop) (s, s->vga.vram_ptr +
|
|
||||||
(s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
|
||||||
s->vga.vram_ptr +
|
|
||||||
(s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
|
|
||||||
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
|
|
||||||
if (notify) {
|
if (notify) {
|
||||||
qemu_console_copy(s->vga.con,
|
dpy_gfx_update(s->vga.con, dx, dy,
|
||||||
sx, sy, dx, dy,
|
s->cirrus_blt_width / depth,
|
||||||
s->cirrus_blt_width / depth,
|
s->cirrus_blt_height);
|
||||||
s->cirrus_blt_height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we don't have to notify the display that this portion has
|
/* we don't have to notify the display that this portion has
|
||||||
@@ -795,7 +853,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
|||||||
|
|
||||||
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
|
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
|
||||||
{
|
{
|
||||||
if (blit_is_unsafe(s))
|
if (blit_is_unsafe(s, false))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
|
return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
|
||||||
@@ -816,16 +874,15 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
|
|||||||
|
|
||||||
if (s->cirrus_srccounter > 0) {
|
if (s->cirrus_srccounter > 0) {
|
||||||
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
|
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
|
||||||
cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
|
cirrus_bitblt_common_patterncopy(s);
|
||||||
the_end:
|
the_end:
|
||||||
s->cirrus_srccounter = 0;
|
s->cirrus_srccounter = 0;
|
||||||
cirrus_bitblt_reset(s);
|
cirrus_bitblt_reset(s);
|
||||||
} else {
|
} else {
|
||||||
/* at least one scan line */
|
/* at least one scan line */
|
||||||
do {
|
do {
|
||||||
(*s->cirrus_rop)(s, s->vga.vram_ptr +
|
(*s->cirrus_rop)(s, s->cirrus_blt_dstaddr,
|
||||||
(s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
0, 0, 0, s->cirrus_blt_width, 1);
|
||||||
s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
|
|
||||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
|
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
|
||||||
s->cirrus_blt_width, 1);
|
s->cirrus_blt_width, 1);
|
||||||
s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
|
s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
|
||||||
@@ -871,6 +928,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
|
|||||||
{
|
{
|
||||||
int w;
|
int w;
|
||||||
|
|
||||||
|
if (blit_is_unsafe(s, true)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
|
s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
|
||||||
s->cirrus_srcptr = &s->cirrus_bltbuf[0];
|
s->cirrus_srcptr = &s->cirrus_bltbuf[0];
|
||||||
s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
|
s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
|
||||||
@@ -896,6 +957,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
|
|||||||
}
|
}
|
||||||
s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
|
s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the blit_is_unsafe call above should catch this */
|
||||||
|
assert(s->cirrus_blt_srcpitch <= CIRRUS_BLTBUFSIZE);
|
||||||
|
|
||||||
s->cirrus_srcptr = s->cirrus_bltbuf;
|
s->cirrus_srcptr = s->cirrus_bltbuf;
|
||||||
s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
|
s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
|
||||||
cirrus_update_memory_access(s);
|
cirrus_update_memory_access(s);
|
||||||
@@ -943,6 +1008,9 @@ static void cirrus_bitblt_start(CirrusVGAState * s)
|
|||||||
s->cirrus_blt_modeext = s->vga.gr[0x33];
|
s->cirrus_blt_modeext = s->vga.gr[0x33];
|
||||||
blt_rop = s->vga.gr[0x32];
|
blt_rop = s->vga.gr[0x32];
|
||||||
|
|
||||||
|
s->cirrus_blt_dstaddr &= s->cirrus_addr_mask;
|
||||||
|
s->cirrus_blt_srcaddr &= s->cirrus_addr_mask;
|
||||||
|
|
||||||
#ifdef DEBUG_BITBLT
|
#ifdef DEBUG_BITBLT
|
||||||
printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
|
printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
|
||||||
blt_rop,
|
blt_rop,
|
||||||
|
|||||||
+115
-76
@@ -22,31 +22,65 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src)
|
static inline void glue(rop_8_, ROP_NAME)(CirrusVGAState *s,
|
||||||
|
uint32_t dstaddr, uint8_t src)
|
||||||
{
|
{
|
||||||
|
uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask];
|
||||||
*dst = ROP_FN(*dst, src);
|
*dst = ROP_FN(*dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src)
|
static inline void glue(rop_tr_8_, ROP_NAME)(CirrusVGAState *s,
|
||||||
|
uint32_t dstaddr, uint8_t src,
|
||||||
|
uint8_t transp)
|
||||||
{
|
{
|
||||||
|
uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask];
|
||||||
|
uint8_t pixel = ROP_FN(*dst, src);
|
||||||
|
if (pixel != transp) {
|
||||||
|
*dst = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void glue(rop_16_, ROP_NAME)(CirrusVGAState *s,
|
||||||
|
uint32_t dstaddr, uint16_t src)
|
||||||
|
{
|
||||||
|
uint16_t *dst = (uint16_t *)
|
||||||
|
(&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]);
|
||||||
*dst = ROP_FN(*dst, src);
|
*dst = ROP_FN(*dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src)
|
static inline void glue(rop_tr_16_, ROP_NAME)(CirrusVGAState *s,
|
||||||
|
uint32_t dstaddr, uint16_t src,
|
||||||
|
uint16_t transp)
|
||||||
{
|
{
|
||||||
|
uint16_t *dst = (uint16_t *)
|
||||||
|
(&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]);
|
||||||
|
uint16_t pixel = ROP_FN(*dst, src);
|
||||||
|
if (pixel != transp) {
|
||||||
|
*dst = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s,
|
||||||
|
uint32_t dstaddr, uint32_t src)
|
||||||
|
{
|
||||||
|
uint32_t *dst = (uint32_t *)
|
||||||
|
(&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~3]);
|
||||||
*dst = ROP_FN(*dst, src);
|
*dst = ROP_FN(*dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s)
|
#define ROP_OP(st, d, s) glue(rop_8_, ROP_NAME)(st, d, s)
|
||||||
#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s)
|
#define ROP_OP_TR(st, d, s, t) glue(rop_tr_8_, ROP_NAME)(st, d, s, t)
|
||||||
#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s)
|
#define ROP_OP_16(st, d, s) glue(rop_16_, ROP_NAME)(st, d, s)
|
||||||
|
#define ROP_OP_TR_16(st, d, s, t) glue(rop_tr_16_, ROP_NAME)(st, d, s, t)
|
||||||
|
#define ROP_OP_32(st, d, s) glue(rop_32_, ROP_NAME)(st, d, s)
|
||||||
#undef ROP_FN
|
#undef ROP_FN
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
|
glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
|
||||||
uint8_t *dst,const uint8_t *src,
|
uint32_t dstaddr,
|
||||||
int dstpitch,int srcpitch,
|
uint32_t srcaddr,
|
||||||
int bltwidth,int bltheight)
|
int dstpitch, int srcpitch,
|
||||||
|
int bltwidth, int bltheight)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
dstpitch -= bltwidth;
|
dstpitch -= bltwidth;
|
||||||
@@ -58,134 +92,139 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
|
|||||||
|
|
||||||
for (y = 0; y < bltheight; y++) {
|
for (y = 0; y < bltheight; y++) {
|
||||||
for (x = 0; x < bltwidth; x++) {
|
for (x = 0; x < bltwidth; x++) {
|
||||||
ROP_OP(dst, *src);
|
ROP_OP(s, dstaddr, cirrus_src(s, srcaddr));
|
||||||
dst++;
|
dstaddr++;
|
||||||
src++;
|
srcaddr++;
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
src += srcpitch;
|
srcaddr += srcpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
|
glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
|
||||||
uint8_t *dst,const uint8_t *src,
|
uint32_t dstaddr,
|
||||||
int dstpitch,int srcpitch,
|
uint32_t srcaddr,
|
||||||
int bltwidth,int bltheight)
|
int dstpitch, int srcpitch,
|
||||||
|
int bltwidth, int bltheight)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
dstpitch += bltwidth;
|
dstpitch += bltwidth;
|
||||||
srcpitch += bltwidth;
|
srcpitch += bltwidth;
|
||||||
for (y = 0; y < bltheight; y++) {
|
for (y = 0; y < bltheight; y++) {
|
||||||
for (x = 0; x < bltwidth; x++) {
|
for (x = 0; x < bltwidth; x++) {
|
||||||
ROP_OP(dst, *src);
|
ROP_OP(s, dstaddr, cirrus_src(s, srcaddr));
|
||||||
dst--;
|
dstaddr--;
|
||||||
src--;
|
srcaddr--;
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
src += srcpitch;
|
srcaddr += srcpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
|
glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
|
||||||
uint8_t *dst,const uint8_t *src,
|
uint32_t dstaddr,
|
||||||
int dstpitch,int srcpitch,
|
uint32_t srcaddr,
|
||||||
int bltwidth,int bltheight)
|
int dstpitch,
|
||||||
|
int srcpitch,
|
||||||
|
int bltwidth,
|
||||||
|
int bltheight)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
uint8_t p;
|
uint8_t transp = s->vga.gr[0x34];
|
||||||
dstpitch -= bltwidth;
|
dstpitch -= bltwidth;
|
||||||
srcpitch -= bltwidth;
|
srcpitch -= bltwidth;
|
||||||
|
|
||||||
|
if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (y = 0; y < bltheight; y++) {
|
for (y = 0; y < bltheight; y++) {
|
||||||
for (x = 0; x < bltwidth; x++) {
|
for (x = 0; x < bltwidth; x++) {
|
||||||
p = *dst;
|
ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp);
|
||||||
ROP_OP(&p, *src);
|
dstaddr++;
|
||||||
if (p != s->vga.gr[0x34]) *dst = p;
|
srcaddr++;
|
||||||
dst++;
|
|
||||||
src++;
|
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
src += srcpitch;
|
srcaddr += srcpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
|
glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
|
||||||
uint8_t *dst,const uint8_t *src,
|
uint32_t dstaddr,
|
||||||
int dstpitch,int srcpitch,
|
uint32_t srcaddr,
|
||||||
int bltwidth,int bltheight)
|
int dstpitch,
|
||||||
|
int srcpitch,
|
||||||
|
int bltwidth,
|
||||||
|
int bltheight)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
uint8_t p;
|
uint8_t transp = s->vga.gr[0x34];
|
||||||
dstpitch += bltwidth;
|
dstpitch += bltwidth;
|
||||||
srcpitch += bltwidth;
|
srcpitch += bltwidth;
|
||||||
for (y = 0; y < bltheight; y++) {
|
for (y = 0; y < bltheight; y++) {
|
||||||
for (x = 0; x < bltwidth; x++) {
|
for (x = 0; x < bltwidth; x++) {
|
||||||
p = *dst;
|
ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp);
|
||||||
ROP_OP(&p, *src);
|
dstaddr--;
|
||||||
if (p != s->vga.gr[0x34]) *dst = p;
|
srcaddr--;
|
||||||
dst--;
|
|
||||||
src--;
|
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
src += srcpitch;
|
srcaddr += srcpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
|
glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
|
||||||
uint8_t *dst,const uint8_t *src,
|
uint32_t dstaddr,
|
||||||
int dstpitch,int srcpitch,
|
uint32_t srcaddr,
|
||||||
int bltwidth,int bltheight)
|
int dstpitch,
|
||||||
|
int srcpitch,
|
||||||
|
int bltwidth,
|
||||||
|
int bltheight)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
uint8_t p1, p2;
|
uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8;
|
||||||
dstpitch -= bltwidth;
|
dstpitch -= bltwidth;
|
||||||
srcpitch -= bltwidth;
|
srcpitch -= bltwidth;
|
||||||
|
|
||||||
|
if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (y = 0; y < bltheight; y++) {
|
for (y = 0; y < bltheight; y++) {
|
||||||
for (x = 0; x < bltwidth; x+=2) {
|
for (x = 0; x < bltwidth; x+=2) {
|
||||||
p1 = *dst;
|
ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp);
|
||||||
p2 = *(dst+1);
|
dstaddr += 2;
|
||||||
ROP_OP(&p1, *src);
|
srcaddr += 2;
|
||||||
ROP_OP(&p2, *(src + 1));
|
|
||||||
if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) {
|
|
||||||
*dst = p1;
|
|
||||||
*(dst+1) = p2;
|
|
||||||
}
|
|
||||||
dst+=2;
|
|
||||||
src+=2;
|
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
src += srcpitch;
|
srcaddr += srcpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
|
glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
|
||||||
uint8_t *dst,const uint8_t *src,
|
uint32_t dstaddr,
|
||||||
int dstpitch,int srcpitch,
|
uint32_t srcaddr,
|
||||||
int bltwidth,int bltheight)
|
int dstpitch,
|
||||||
|
int srcpitch,
|
||||||
|
int bltwidth,
|
||||||
|
int bltheight)
|
||||||
{
|
{
|
||||||
int x,y;
|
int x,y;
|
||||||
uint8_t p1, p2;
|
uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8;
|
||||||
dstpitch += bltwidth;
|
dstpitch += bltwidth;
|
||||||
srcpitch += bltwidth;
|
srcpitch += bltwidth;
|
||||||
for (y = 0; y < bltheight; y++) {
|
for (y = 0; y < bltheight; y++) {
|
||||||
for (x = 0; x < bltwidth; x+=2) {
|
for (x = 0; x < bltwidth; x+=2) {
|
||||||
p1 = *(dst-1);
|
ROP_OP_TR_16(s, dstaddr - 1, cirrus_src16(s, srcaddr - 1), transp);
|
||||||
p2 = *dst;
|
dstaddr -= 2;
|
||||||
ROP_OP(&p1, *(src - 1));
|
srcaddr -= 2;
|
||||||
ROP_OP(&p2, *src);
|
|
||||||
if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) {
|
|
||||||
*(dst-1) = p1;
|
|
||||||
*dst = p2;
|
|
||||||
}
|
|
||||||
dst-=2;
|
|
||||||
src-=2;
|
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
src += srcpitch;
|
srcaddr += srcpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,30 +23,32 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if DEPTH == 8
|
#if DEPTH == 8
|
||||||
#define PUTPIXEL() ROP_OP(&d[0], col)
|
#define PUTPIXEL(s, a, c) ROP_OP(s, a, c)
|
||||||
#elif DEPTH == 16
|
#elif DEPTH == 16
|
||||||
#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col)
|
#define PUTPIXEL(s, a, c) ROP_OP_16(s, a, c)
|
||||||
#elif DEPTH == 24
|
#elif DEPTH == 24
|
||||||
#define PUTPIXEL() ROP_OP(&d[0], col); \
|
#define PUTPIXEL(s, a, c) do { \
|
||||||
ROP_OP(&d[1], (col >> 8)); \
|
ROP_OP(s, a, c); \
|
||||||
ROP_OP(&d[2], (col >> 16))
|
ROP_OP(s, a + 1, (col >> 8)); \
|
||||||
|
ROP_OP(s, a + 2, (col >> 16)); \
|
||||||
|
} while (0)
|
||||||
#elif DEPTH == 32
|
#elif DEPTH == 32
|
||||||
#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col)
|
#define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c)
|
||||||
#else
|
#else
|
||||||
#error unsupported DEPTH
|
#error unsupported DEPTH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
|
glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
|
||||||
(CirrusVGAState * s, uint8_t * dst,
|
(CirrusVGAState *s, uint32_t dstaddr,
|
||||||
const uint8_t * src,
|
uint32_t srcaddr,
|
||||||
int dstpitch, int srcpitch,
|
int dstpitch, int srcpitch,
|
||||||
int bltwidth, int bltheight)
|
int bltwidth, int bltheight)
|
||||||
{
|
{
|
||||||
uint8_t *d;
|
uint32_t addr;
|
||||||
int x, y, pattern_y, pattern_pitch, pattern_x;
|
int x, y, pattern_y, pattern_pitch, pattern_x;
|
||||||
unsigned int col;
|
unsigned int col;
|
||||||
const uint8_t *src1;
|
uint32_t src1addr;
|
||||||
#if DEPTH == 24
|
#if DEPTH == 24
|
||||||
int skipleft = s->vga.gr[0x2f] & 0x1f;
|
int skipleft = s->vga.gr[0x2f] & 0x1f;
|
||||||
#else
|
#else
|
||||||
@@ -63,42 +65,44 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
|
|||||||
pattern_y = s->cirrus_blt_srcaddr & 7;
|
pattern_y = s->cirrus_blt_srcaddr & 7;
|
||||||
for(y = 0; y < bltheight; y++) {
|
for(y = 0; y < bltheight; y++) {
|
||||||
pattern_x = skipleft;
|
pattern_x = skipleft;
|
||||||
d = dst + skipleft;
|
addr = dstaddr + skipleft;
|
||||||
src1 = src + pattern_y * pattern_pitch;
|
src1addr = srcaddr + pattern_y * pattern_pitch;
|
||||||
for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
|
for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
|
||||||
#if DEPTH == 8
|
#if DEPTH == 8
|
||||||
col = src1[pattern_x];
|
col = cirrus_src(s, src1addr + pattern_x);
|
||||||
pattern_x = (pattern_x + 1) & 7;
|
pattern_x = (pattern_x + 1) & 7;
|
||||||
#elif DEPTH == 16
|
#elif DEPTH == 16
|
||||||
col = ((uint16_t *)(src1 + pattern_x))[0];
|
col = cirrus_src16(s, src1addr + pattern_x);
|
||||||
pattern_x = (pattern_x + 2) & 15;
|
pattern_x = (pattern_x + 2) & 15;
|
||||||
#elif DEPTH == 24
|
#elif DEPTH == 24
|
||||||
{
|
{
|
||||||
const uint8_t *src2 = src1 + pattern_x * 3;
|
uint32_t src2addr = src1addr + pattern_x * 3;
|
||||||
col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
|
col = cirrus_src(s, src2addr) |
|
||||||
|
(cirrus_src(s, src2addr + 1) << 8) |
|
||||||
|
(cirrus_src(s, src2addr + 2) << 16);
|
||||||
pattern_x = (pattern_x + 1) & 7;
|
pattern_x = (pattern_x + 1) & 7;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
col = ((uint32_t *)(src1 + pattern_x))[0];
|
col = cirrus_src32(s, src1addr + pattern_x);
|
||||||
pattern_x = (pattern_x + 4) & 31;
|
pattern_x = (pattern_x + 4) & 31;
|
||||||
#endif
|
#endif
|
||||||
PUTPIXEL();
|
PUTPIXEL(s, addr, col);
|
||||||
d += (DEPTH / 8);
|
addr += (DEPTH / 8);
|
||||||
}
|
}
|
||||||
pattern_y = (pattern_y + 1) & 7;
|
pattern_y = (pattern_y + 1) & 7;
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: srcpitch is ignored */
|
/* NOTE: srcpitch is ignored */
|
||||||
static void
|
static void
|
||||||
glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
|
glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
|
||||||
(CirrusVGAState * s, uint8_t * dst,
|
(CirrusVGAState *s, uint32_t dstaddr,
|
||||||
const uint8_t * src,
|
uint32_t srcaddr,
|
||||||
int dstpitch, int srcpitch,
|
int dstpitch, int srcpitch,
|
||||||
int bltwidth, int bltheight)
|
int bltwidth, int bltheight)
|
||||||
{
|
{
|
||||||
uint8_t *d;
|
uint32_t addr;
|
||||||
int x, y;
|
int x, y;
|
||||||
unsigned bits, bits_xor;
|
unsigned bits, bits_xor;
|
||||||
unsigned int col;
|
unsigned int col;
|
||||||
@@ -122,33 +126,33 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
|
|||||||
|
|
||||||
for(y = 0; y < bltheight; y++) {
|
for(y = 0; y < bltheight; y++) {
|
||||||
bitmask = 0x80 >> srcskipleft;
|
bitmask = 0x80 >> srcskipleft;
|
||||||
bits = *src++ ^ bits_xor;
|
bits = cirrus_src(s, srcaddr++) ^ bits_xor;
|
||||||
d = dst + dstskipleft;
|
addr = dstaddr + dstskipleft;
|
||||||
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
||||||
if ((bitmask & 0xff) == 0) {
|
if ((bitmask & 0xff) == 0) {
|
||||||
bitmask = 0x80;
|
bitmask = 0x80;
|
||||||
bits = *src++ ^ bits_xor;
|
bits = cirrus_src(s, srcaddr++) ^ bits_xor;
|
||||||
}
|
}
|
||||||
index = (bits & bitmask);
|
index = (bits & bitmask);
|
||||||
if (index) {
|
if (index) {
|
||||||
PUTPIXEL();
|
PUTPIXEL(s, addr, col);
|
||||||
}
|
}
|
||||||
d += (DEPTH / 8);
|
addr += (DEPTH / 8);
|
||||||
bitmask >>= 1;
|
bitmask >>= 1;
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
|
glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
|
||||||
(CirrusVGAState * s, uint8_t * dst,
|
(CirrusVGAState *s, uint32_t dstaddr,
|
||||||
const uint8_t * src,
|
uint32_t srcaddr,
|
||||||
int dstpitch, int srcpitch,
|
int dstpitch, int srcpitch,
|
||||||
int bltwidth, int bltheight)
|
int bltwidth, int bltheight)
|
||||||
{
|
{
|
||||||
uint32_t colors[2];
|
uint32_t colors[2];
|
||||||
uint8_t *d;
|
uint32_t addr;
|
||||||
int x, y;
|
int x, y;
|
||||||
unsigned bits;
|
unsigned bits;
|
||||||
unsigned int col;
|
unsigned int col;
|
||||||
@@ -160,30 +164,30 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
|
|||||||
colors[1] = s->cirrus_blt_fgcol;
|
colors[1] = s->cirrus_blt_fgcol;
|
||||||
for(y = 0; y < bltheight; y++) {
|
for(y = 0; y < bltheight; y++) {
|
||||||
bitmask = 0x80 >> srcskipleft;
|
bitmask = 0x80 >> srcskipleft;
|
||||||
bits = *src++;
|
bits = cirrus_src(s, srcaddr++);
|
||||||
d = dst + dstskipleft;
|
addr = dstaddr + dstskipleft;
|
||||||
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
||||||
if ((bitmask & 0xff) == 0) {
|
if ((bitmask & 0xff) == 0) {
|
||||||
bitmask = 0x80;
|
bitmask = 0x80;
|
||||||
bits = *src++;
|
bits = cirrus_src(s, srcaddr++);
|
||||||
}
|
}
|
||||||
col = colors[!!(bits & bitmask)];
|
col = colors[!!(bits & bitmask)];
|
||||||
PUTPIXEL();
|
PUTPIXEL(s, addr, col);
|
||||||
d += (DEPTH / 8);
|
addr += (DEPTH / 8);
|
||||||
bitmask >>= 1;
|
bitmask >>= 1;
|
||||||
}
|
}
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
|
glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
|
||||||
(CirrusVGAState * s, uint8_t * dst,
|
(CirrusVGAState *s, uint32_t dstaddr,
|
||||||
const uint8_t * src,
|
uint32_t srcaddr,
|
||||||
int dstpitch, int srcpitch,
|
int dstpitch, int srcpitch,
|
||||||
int bltwidth, int bltheight)
|
int bltwidth, int bltheight)
|
||||||
{
|
{
|
||||||
uint8_t *d;
|
uint32_t addr;
|
||||||
int x, y, bitpos, pattern_y;
|
int x, y, bitpos, pattern_y;
|
||||||
unsigned int bits, bits_xor;
|
unsigned int bits, bits_xor;
|
||||||
unsigned int col;
|
unsigned int col;
|
||||||
@@ -205,30 +209,30 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
|
|||||||
pattern_y = s->cirrus_blt_srcaddr & 7;
|
pattern_y = s->cirrus_blt_srcaddr & 7;
|
||||||
|
|
||||||
for(y = 0; y < bltheight; y++) {
|
for(y = 0; y < bltheight; y++) {
|
||||||
bits = src[pattern_y] ^ bits_xor;
|
bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor;
|
||||||
bitpos = 7 - srcskipleft;
|
bitpos = 7 - srcskipleft;
|
||||||
d = dst + dstskipleft;
|
addr = dstaddr + dstskipleft;
|
||||||
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
||||||
if ((bits >> bitpos) & 1) {
|
if ((bits >> bitpos) & 1) {
|
||||||
PUTPIXEL();
|
PUTPIXEL(s, addr, col);
|
||||||
}
|
}
|
||||||
d += (DEPTH / 8);
|
addr += (DEPTH / 8);
|
||||||
bitpos = (bitpos - 1) & 7;
|
bitpos = (bitpos - 1) & 7;
|
||||||
}
|
}
|
||||||
pattern_y = (pattern_y + 1) & 7;
|
pattern_y = (pattern_y + 1) & 7;
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
|
glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
|
||||||
(CirrusVGAState * s, uint8_t * dst,
|
(CirrusVGAState *s, uint32_t dstaddr,
|
||||||
const uint8_t * src,
|
uint32_t srcaddr,
|
||||||
int dstpitch, int srcpitch,
|
int dstpitch, int srcpitch,
|
||||||
int bltwidth, int bltheight)
|
int bltwidth, int bltheight)
|
||||||
{
|
{
|
||||||
uint32_t colors[2];
|
uint32_t colors[2];
|
||||||
uint8_t *d;
|
uint32_t addr;
|
||||||
int x, y, bitpos, pattern_y;
|
int x, y, bitpos, pattern_y;
|
||||||
unsigned int bits;
|
unsigned int bits;
|
||||||
unsigned int col;
|
unsigned int col;
|
||||||
@@ -240,40 +244,39 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
|
|||||||
pattern_y = s->cirrus_blt_srcaddr & 7;
|
pattern_y = s->cirrus_blt_srcaddr & 7;
|
||||||
|
|
||||||
for(y = 0; y < bltheight; y++) {
|
for(y = 0; y < bltheight; y++) {
|
||||||
bits = src[pattern_y];
|
bits = cirrus_src(s, srcaddr + pattern_y);
|
||||||
bitpos = 7 - srcskipleft;
|
bitpos = 7 - srcskipleft;
|
||||||
d = dst + dstskipleft;
|
addr = dstaddr + dstskipleft;
|
||||||
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
|
||||||
col = colors[(bits >> bitpos) & 1];
|
col = colors[(bits >> bitpos) & 1];
|
||||||
PUTPIXEL();
|
PUTPIXEL(s, addr, col);
|
||||||
d += (DEPTH / 8);
|
addr += (DEPTH / 8);
|
||||||
bitpos = (bitpos - 1) & 7;
|
bitpos = (bitpos - 1) & 7;
|
||||||
}
|
}
|
||||||
pattern_y = (pattern_y + 1) & 7;
|
pattern_y = (pattern_y + 1) & 7;
|
||||||
dst += dstpitch;
|
dstaddr += dstpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
|
glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
|
||||||
(CirrusVGAState *s,
|
(CirrusVGAState *s,
|
||||||
uint8_t *dst, int dst_pitch,
|
uint32_t dstaddr, int dst_pitch,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
{
|
{
|
||||||
uint8_t *d, *d1;
|
uint32_t addr;
|
||||||
uint32_t col;
|
uint32_t col;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
col = s->cirrus_blt_fgcol;
|
col = s->cirrus_blt_fgcol;
|
||||||
|
|
||||||
d1 = dst;
|
|
||||||
for(y = 0; y < height; y++) {
|
for(y = 0; y < height; y++) {
|
||||||
d = d1;
|
addr = dstaddr;
|
||||||
for(x = 0; x < width; x += (DEPTH / 8)) {
|
for(x = 0; x < width; x += (DEPTH / 8)) {
|
||||||
PUTPIXEL();
|
PUTPIXEL(s, addr, col);
|
||||||
d += (DEPTH / 8);
|
addr += (DEPTH / 8);
|
||||||
}
|
}
|
||||||
d1 += dst_pitch;
|
dstaddr += dst_pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -1818,8 +1818,10 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev,
|
|||||||
|
|
||||||
/* increment the number of CPUs */
|
/* increment the number of CPUs */
|
||||||
pcms->boot_cpus++;
|
pcms->boot_cpus++;
|
||||||
if (dev->hotplugged) {
|
if (pcms->rtc) {
|
||||||
rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
|
rtc_set_cpus_count(pcms->rtc, pcms->boot_cpus);
|
||||||
|
}
|
||||||
|
if (pcms->fw_cfg) {
|
||||||
fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
|
fw_cfg_modify_i16(pcms->fw_cfg, FW_CFG_NB_CPUS, pcms->boot_cpus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -488,7 +488,7 @@ static void ahci_reg_init(AHCIState *s)
|
|||||||
s->control_regs.cap = (s->ports - 1) |
|
s->control_regs.cap = (s->ports - 1) |
|
||||||
(AHCI_NUM_COMMAND_SLOTS << 8) |
|
(AHCI_NUM_COMMAND_SLOTS << 8) |
|
||||||
(AHCI_SUPPORTED_SPEED_GEN1 << AHCI_SUPPORTED_SPEED) |
|
(AHCI_SUPPORTED_SPEED_GEN1 << AHCI_SUPPORTED_SPEED) |
|
||||||
HOST_CAP_NCQ | HOST_CAP_AHCI;
|
HOST_CAP_NCQ | HOST_CAP_AHCI | HOST_CAP_64;
|
||||||
|
|
||||||
s->control_regs.impl = (1 << s->ports) - 1;
|
s->control_regs.impl = (1 << s->ports) - 1;
|
||||||
|
|
||||||
|
|||||||
@@ -250,6 +250,8 @@ static void apic_reset_common(DeviceState *dev)
|
|||||||
s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
|
s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
|
||||||
s->id = s->initial_apic_id;
|
s->id = s->initial_apic_id;
|
||||||
|
|
||||||
|
apic_reset_irq_delivered();
|
||||||
|
|
||||||
s->vapic_paddr = 0;
|
s->vapic_paddr = 0;
|
||||||
info->vapic_base_update(s);
|
info->vapic_base_update(s);
|
||||||
|
|
||||||
|
|||||||
@@ -426,6 +426,11 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
k->realize = ioapic_realize;
|
k->realize = ioapic_realize;
|
||||||
|
/*
|
||||||
|
* If APIC is in kernel, we need to update the kernel cache after
|
||||||
|
* migration, otherwise first 24 gsi routes will be invalid.
|
||||||
|
*/
|
||||||
|
k->post_load = ioapic_update_kvm_routes;
|
||||||
dc->reset = ioapic_reset_common;
|
dc->reset = ioapic_reset_common;
|
||||||
dc->props = ioapic_properties;
|
dc->props = ioapic_properties;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -306,7 +306,7 @@ e1000e_init_msix(E1000EState *s)
|
|||||||
static void
|
static void
|
||||||
e1000e_cleanup_msix(E1000EState *s)
|
e1000e_cleanup_msix(E1000EState *s)
|
||||||
{
|
{
|
||||||
if (msix_enabled(PCI_DEVICE(s))) {
|
if (msix_present(PCI_DEVICE(s))) {
|
||||||
e1000e_unuse_msix_vectors(s, E1000E_MSIX_VEC_NUM);
|
e1000e_unuse_msix_vectors(s, E1000E_MSIX_VEC_NUM);
|
||||||
msix_uninit(PCI_DEVICE(s), &s->msix, &s->msix);
|
msix_uninit(PCI_DEVICE(s), &s->msix, &s->msix);
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-18
@@ -23,13 +23,13 @@
|
|||||||
|
|
||||||
struct NetRxPkt {
|
struct NetRxPkt {
|
||||||
struct virtio_net_hdr virt_hdr;
|
struct virtio_net_hdr virt_hdr;
|
||||||
uint8_t ehdr_buf[sizeof(struct eth_header)];
|
uint8_t ehdr_buf[sizeof(struct eth_header) + sizeof(struct vlan_header)];
|
||||||
struct iovec *vec;
|
struct iovec *vec;
|
||||||
uint16_t vec_len_total;
|
uint16_t vec_len_total;
|
||||||
uint16_t vec_len;
|
uint16_t vec_len;
|
||||||
uint32_t tot_len;
|
uint32_t tot_len;
|
||||||
uint16_t tci;
|
uint16_t tci;
|
||||||
bool vlan_stripped;
|
size_t ehdr_buf_len;
|
||||||
bool has_virt_hdr;
|
bool has_virt_hdr;
|
||||||
eth_pkt_types_e packet_type;
|
eth_pkt_types_e packet_type;
|
||||||
|
|
||||||
@@ -88,17 +88,16 @@ net_rx_pkt_pull_data(struct NetRxPkt *pkt,
|
|||||||
const struct iovec *iov, int iovcnt,
|
const struct iovec *iov, int iovcnt,
|
||||||
size_t ploff)
|
size_t ploff)
|
||||||
{
|
{
|
||||||
if (pkt->vlan_stripped) {
|
if (pkt->ehdr_buf_len) {
|
||||||
net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
|
net_rx_pkt_iovec_realloc(pkt, iovcnt + 1);
|
||||||
|
|
||||||
pkt->vec[0].iov_base = pkt->ehdr_buf;
|
pkt->vec[0].iov_base = pkt->ehdr_buf;
|
||||||
pkt->vec[0].iov_len = sizeof(pkt->ehdr_buf);
|
pkt->vec[0].iov_len = pkt->ehdr_buf_len;
|
||||||
|
|
||||||
pkt->tot_len =
|
|
||||||
iov_size(iov, iovcnt) - ploff + sizeof(struct eth_header);
|
|
||||||
|
|
||||||
|
pkt->tot_len = iov_size(iov, iovcnt) - ploff + pkt->ehdr_buf_len;
|
||||||
pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
|
pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1,
|
||||||
iov, iovcnt, ploff, pkt->tot_len);
|
iov, iovcnt, ploff,
|
||||||
|
pkt->tot_len - pkt->ehdr_buf_len) + 1;
|
||||||
} else {
|
} else {
|
||||||
net_rx_pkt_iovec_realloc(pkt, iovcnt);
|
net_rx_pkt_iovec_realloc(pkt, iovcnt);
|
||||||
|
|
||||||
@@ -123,11 +122,12 @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
|
|||||||
uint16_t tci = 0;
|
uint16_t tci = 0;
|
||||||
uint16_t ploff = iovoff;
|
uint16_t ploff = iovoff;
|
||||||
assert(pkt);
|
assert(pkt);
|
||||||
pkt->vlan_stripped = false;
|
|
||||||
|
|
||||||
if (strip_vlan) {
|
if (strip_vlan) {
|
||||||
pkt->vlan_stripped = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
|
pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf,
|
||||||
&ploff, &tci);
|
&ploff, &tci);
|
||||||
|
} else {
|
||||||
|
pkt->ehdr_buf_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->tci = tci;
|
pkt->tci = tci;
|
||||||
@@ -143,12 +143,13 @@ void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
|
|||||||
uint16_t tci = 0;
|
uint16_t tci = 0;
|
||||||
uint16_t ploff = iovoff;
|
uint16_t ploff = iovoff;
|
||||||
assert(pkt);
|
assert(pkt);
|
||||||
pkt->vlan_stripped = false;
|
|
||||||
|
|
||||||
if (strip_vlan) {
|
if (strip_vlan) {
|
||||||
pkt->vlan_stripped = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
|
pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
|
||||||
pkt->ehdr_buf,
|
pkt->ehdr_buf,
|
||||||
&ploff, &tci);
|
&ploff, &tci);
|
||||||
|
} else {
|
||||||
|
pkt->ehdr_buf_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->tci = tci;
|
pkt->tci = tci;
|
||||||
@@ -162,8 +163,8 @@ void net_rx_pkt_dump(struct NetRxPkt *pkt)
|
|||||||
NetRxPkt *pkt = (NetRxPkt *)pkt;
|
NetRxPkt *pkt = (NetRxPkt *)pkt;
|
||||||
assert(pkt);
|
assert(pkt);
|
||||||
|
|
||||||
printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
|
printf("RX PKT: tot_len: %d, ehdr_buf_len: %lu, vlan_tag: %d\n",
|
||||||
pkt->tot_len, pkt->vlan_stripped, pkt->tci);
|
pkt->tot_len, pkt->ehdr_buf_len, pkt->tci);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,7 +427,7 @@ bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt)
|
|||||||
{
|
{
|
||||||
assert(pkt);
|
assert(pkt);
|
||||||
|
|
||||||
return pkt->vlan_stripped;
|
return pkt->ehdr_buf_len ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt)
|
bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt)
|
||||||
|
|||||||
+2
-2
@@ -982,8 +982,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
|
|||||||
pci_get_function_0(pci_dev)) {
|
pci_get_function_0(pci_dev)) {
|
||||||
error_setg(errp, "PCI: slot %d function 0 already ocuppied by %s,"
|
error_setg(errp, "PCI: slot %d function 0 already ocuppied by %s,"
|
||||||
" new func %s cannot be exposed to guest.",
|
" new func %s cannot be exposed to guest.",
|
||||||
PCI_SLOT(devfn),
|
PCI_SLOT(pci_get_function_0(pci_dev)->devfn),
|
||||||
bus->devices[PCI_DEVFN(PCI_SLOT(devfn), 0)]->name,
|
pci_get_function_0(pci_dev)->name,
|
||||||
name);
|
name);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
+1
-1
@@ -250,5 +250,5 @@ int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fdt_setprop(fdt, fdt_offset, name, vec, vec_len);
|
return fdt_setprop(fdt, fdt_offset, name, vec, vec_len + 1);
|
||||||
}
|
}
|
||||||
@@ -1672,12 +1672,27 @@ void subch_device_save(SubchDev *s, QEMUFile *f)
|
|||||||
|
|
||||||
int subch_device_load(SubchDev *s, QEMUFile *f)
|
int subch_device_load(SubchDev *s, QEMUFile *f)
|
||||||
{
|
{
|
||||||
|
SubchDev *old_s;
|
||||||
|
uint16_t old_schid = s->schid;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
s->cssid = qemu_get_byte(f);
|
s->cssid = qemu_get_byte(f);
|
||||||
s->ssid = qemu_get_byte(f);
|
s->ssid = qemu_get_byte(f);
|
||||||
s->schid = qemu_get_be16(f);
|
s->schid = qemu_get_be16(f);
|
||||||
s->devno = qemu_get_be16(f);
|
s->devno = qemu_get_be16(f);
|
||||||
|
/* Re-assign subch. */
|
||||||
|
if (old_schid != s->schid) {
|
||||||
|
old_s = channel_subsys.css[s->cssid]->sch_set[s->ssid]->sch[old_schid];
|
||||||
|
/*
|
||||||
|
* (old_s != s) means that some other device has its correct
|
||||||
|
* subchannel already assigned (in load).
|
||||||
|
*/
|
||||||
|
if (old_s == s) {
|
||||||
|
css_subch_assign(s->cssid, s->ssid, old_schid, s->devno, NULL);
|
||||||
|
}
|
||||||
|
/* It's OK to re-assign without a prior de-assign. */
|
||||||
|
css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s);
|
||||||
|
}
|
||||||
s->thinint_active = qemu_get_byte(f);
|
s->thinint_active = qemu_get_byte(f);
|
||||||
/* SCHIB */
|
/* SCHIB */
|
||||||
/* PMCW */
|
/* PMCW */
|
||||||
|
|||||||
@@ -204,8 +204,8 @@ void s390_machine_reset(void)
|
|||||||
{
|
{
|
||||||
S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0));
|
S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0));
|
||||||
|
|
||||||
qemu_devices_reset();
|
|
||||||
s390_cmma_reset();
|
s390_cmma_reset();
|
||||||
|
qemu_devices_reset();
|
||||||
s390_crypto_reset();
|
s390_crypto_reset();
|
||||||
|
|
||||||
/* all cpus are stopped - configure and start the ipl cpu only */
|
/* all cpus are stopped - configure and start the ipl cpu only */
|
||||||
|
|||||||
+3
-3
@@ -756,7 +756,7 @@ static void mptsas_fetch_request(MPTSASState *s)
|
|||||||
|
|
||||||
/* Read the message header from the guest first. */
|
/* Read the message header from the guest first. */
|
||||||
addr = s->host_mfa_high_addr | MPTSAS_FIFO_GET(s, request_post);
|
addr = s->host_mfa_high_addr | MPTSAS_FIFO_GET(s, request_post);
|
||||||
pci_dma_read(pci, addr, req, sizeof(hdr));
|
pci_dma_read(pci, addr, req, sizeof(*hdr));
|
||||||
|
|
||||||
if (hdr->Function < ARRAY_SIZE(mpi_request_sizes) &&
|
if (hdr->Function < ARRAY_SIZE(mpi_request_sizes) &&
|
||||||
mpi_request_sizes[hdr->Function]) {
|
mpi_request_sizes[hdr->Function]) {
|
||||||
@@ -766,8 +766,8 @@ static void mptsas_fetch_request(MPTSASState *s)
|
|||||||
*/
|
*/
|
||||||
size = mpi_request_sizes[hdr->Function];
|
size = mpi_request_sizes[hdr->Function];
|
||||||
assert(size <= MPTSAS_MAX_REQUEST_SIZE);
|
assert(size <= MPTSAS_MAX_REQUEST_SIZE);
|
||||||
pci_dma_read(pci, addr + sizeof(hdr), &req[sizeof(hdr)],
|
pci_dma_read(pci, addr + sizeof(*hdr), &req[sizeof(*hdr)],
|
||||||
size - sizeof(hdr));
|
size - sizeof(*hdr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
|
if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
|
||||||
|
|||||||
+1
-1
@@ -2694,7 +2694,7 @@ static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf)
|
|||||||
* for the number of logical blocks specified in the length
|
* for the number of logical blocks specified in the length
|
||||||
* field). For other modes, do not use scatter/gather operation.
|
* field). For other modes, do not use scatter/gather operation.
|
||||||
*/
|
*/
|
||||||
if ((buf[1] & 6) != 2) {
|
if ((buf[1] & 6) == 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
-1
@@ -536,7 +536,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
|
|||||||
boundary_count -= block_size - begin;
|
boundary_count -= block_size - begin;
|
||||||
}
|
}
|
||||||
dma_memory_read(&address_space_memory, s->sdmasysad,
|
dma_memory_read(&address_space_memory, s->sdmasysad,
|
||||||
&s->fifo_buffer[begin], s->data_count);
|
&s->fifo_buffer[begin], s->data_count - begin);
|
||||||
s->sdmasysad += s->data_count - begin;
|
s->sdmasysad += s->data_count - begin;
|
||||||
if (s->data_count == block_size) {
|
if (s->data_count == block_size) {
|
||||||
for (n = 0; n < block_size; n++) {
|
for (n = 0; n < block_size; n++) {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ virtio_rng_pushed(void *rng, size_t len) "rng %p: %zd bytes pushed"
|
|||||||
virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left"
|
virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left"
|
||||||
|
|
||||||
# hw/virtio/virtio-balloon.c
|
# hw/virtio/virtio-balloon.c
|
||||||
|
#
|
||||||
|
virtio_balloon_bad_addr(uint64_t gpa) "%"PRIx64
|
||||||
virtio_balloon_handle_output(const char *name, uint64_t gpa) "section name: %s gpa: %"PRIx64
|
virtio_balloon_handle_output(const char *name, uint64_t gpa) "section name: %s gpa: %"PRIx64
|
||||||
virtio_balloon_get_config(uint32_t num_pages, uint32_t actual) "num_pages: %d actual: %d"
|
virtio_balloon_get_config(uint32_t num_pages, uint32_t actual) "num_pages: %d actual: %d"
|
||||||
virtio_balloon_set_config(uint32_t actual, uint32_t oldactual) "actual: %d oldactual: %d"
|
virtio_balloon_set_config(uint32_t actual, uint32_t oldactual) "actual: %d oldactual: %d"
|
||||||
|
|||||||
@@ -228,8 +228,13 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
|
|
||||||
/* FIXME: remove get_system_memory(), but how? */
|
/* FIXME: remove get_system_memory(), but how? */
|
||||||
section = memory_region_find(get_system_memory(), pa, 1);
|
section = memory_region_find(get_system_memory(), pa, 1);
|
||||||
if (!int128_nz(section.size) || !memory_region_is_ram(section.mr))
|
if (!int128_nz(section.size) ||
|
||||||
|
!memory_region_is_ram(section.mr) ||
|
||||||
|
memory_region_is_rom(section.mr) ||
|
||||||
|
memory_region_is_romd(section.mr)) {
|
||||||
|
trace_virtio_balloon_bad_addr(pa);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
trace_virtio_balloon_handle_output(memory_region_name(section.mr),
|
trace_virtio_balloon_handle_output(memory_region_name(section.mr),
|
||||||
pa);
|
pa);
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ virtio_crypto_sym_op_helper(VirtIODevice *vdev,
|
|||||||
uint32_t hash_start_src_offset = 0, len_to_hash = 0;
|
uint32_t hash_start_src_offset = 0, len_to_hash = 0;
|
||||||
uint32_t cipher_start_src_offset = 0, len_to_cipher = 0;
|
uint32_t cipher_start_src_offset = 0, len_to_cipher = 0;
|
||||||
|
|
||||||
size_t max_len, curr_size = 0;
|
uint64_t max_len, curr_size = 0;
|
||||||
size_t s;
|
size_t s;
|
||||||
|
|
||||||
/* Plain cipher */
|
/* Plain cipher */
|
||||||
@@ -441,7 +441,7 @@ virtio_crypto_sym_op_helper(VirtIODevice *vdev,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
max_len = iv_len + aad_len + src_len + dst_len + hash_result_len;
|
max_len = (uint64_t)iv_len + aad_len + src_len + dst_len + hash_result_len;
|
||||||
if (unlikely(max_len > vcrypto->conf.max_size)) {
|
if (unlikely(max_len > vcrypto->conf.max_size)) {
|
||||||
virtio_error(vdev, "virtio-crypto too big length");
|
virtio_error(vdev, "virtio-crypto too big length");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1836,6 +1836,10 @@ static void virtio_pci_reset(DeviceState *qdev)
|
|||||||
|
|
||||||
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
|
||||||
proxy->vqs[i].enabled = 0;
|
proxy->vqs[i].enabled = 0;
|
||||||
|
proxy->vqs[i].num = 0;
|
||||||
|
proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0;
|
||||||
|
proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0;
|
||||||
|
proxy->vqs[i].used[0] = proxy->vqs[i].used[1] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
-21
@@ -92,7 +92,7 @@ struct VirtQueue
|
|||||||
|
|
||||||
uint16_t queue_index;
|
uint16_t queue_index;
|
||||||
|
|
||||||
int inuse;
|
unsigned int inuse;
|
||||||
|
|
||||||
uint16_t vector;
|
uint16_t vector;
|
||||||
VirtIOHandleOutput handle_output;
|
VirtIOHandleOutput handle_output;
|
||||||
@@ -592,24 +592,12 @@ static void virtqueue_undo_map_desc(unsigned int out_num, unsigned int in_num,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void virtqueue_map_iovec(struct iovec *sg, hwaddr *addr,
|
static void virtqueue_map_iovec(struct iovec *sg, hwaddr *addr,
|
||||||
unsigned int *num_sg, unsigned int max_size,
|
unsigned int *num_sg,
|
||||||
int is_write)
|
int is_write)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
hwaddr len;
|
hwaddr len;
|
||||||
|
|
||||||
/* Note: this function MUST validate input, some callers
|
|
||||||
* are passing in num_sg values received over the network.
|
|
||||||
*/
|
|
||||||
/* TODO: teach all callers that this can fail, and return failure instead
|
|
||||||
* of asserting here.
|
|
||||||
* When we do, we might be able to re-enable NDEBUG below.
|
|
||||||
*/
|
|
||||||
#ifdef NDEBUG
|
|
||||||
#error building with NDEBUG is not supported
|
|
||||||
#endif
|
|
||||||
assert(*num_sg <= max_size);
|
|
||||||
|
|
||||||
for (i = 0; i < *num_sg; i++) {
|
for (i = 0; i < *num_sg; i++) {
|
||||||
len = sg[i].iov_len;
|
len = sg[i].iov_len;
|
||||||
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
|
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
|
||||||
@@ -626,10 +614,8 @@ static void virtqueue_map_iovec(struct iovec *sg, hwaddr *addr,
|
|||||||
|
|
||||||
void virtqueue_map(VirtQueueElement *elem)
|
void virtqueue_map(VirtQueueElement *elem)
|
||||||
{
|
{
|
||||||
virtqueue_map_iovec(elem->in_sg, elem->in_addr, &elem->in_num,
|
virtqueue_map_iovec(elem->in_sg, elem->in_addr, &elem->in_num, 1);
|
||||||
VIRTQUEUE_MAX_SIZE, 1);
|
virtqueue_map_iovec(elem->out_sg, elem->out_addr, &elem->out_num, 0);
|
||||||
virtqueue_map_iovec(elem->out_sg, elem->out_addr, &elem->out_num,
|
|
||||||
VIRTQUEUE_MAX_SIZE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num)
|
static void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num)
|
||||||
@@ -790,6 +776,16 @@ void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz)
|
|||||||
|
|
||||||
qemu_get_buffer(f, (uint8_t *)&data, sizeof(VirtQueueElementOld));
|
qemu_get_buffer(f, (uint8_t *)&data, sizeof(VirtQueueElementOld));
|
||||||
|
|
||||||
|
/* TODO: teach all callers that this can fail, and return failure instead
|
||||||
|
* of asserting here.
|
||||||
|
* When we do, we might be able to re-enable NDEBUG below.
|
||||||
|
*/
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#error building with NDEBUG is not supported
|
||||||
|
#endif
|
||||||
|
assert(ARRAY_SIZE(data.in_addr) >= data.in_num);
|
||||||
|
assert(ARRAY_SIZE(data.out_addr) >= data.out_num);
|
||||||
|
|
||||||
elem = virtqueue_alloc_element(sz, data.out_num, data.in_num);
|
elem = virtqueue_alloc_element(sz, data.out_num, data.in_num);
|
||||||
elem->index = data.index;
|
elem->index = data.index;
|
||||||
|
|
||||||
@@ -1260,7 +1256,18 @@ static void virtio_queue_notify_vq(VirtQueue *vq)
|
|||||||
|
|
||||||
void virtio_queue_notify(VirtIODevice *vdev, int n)
|
void virtio_queue_notify(VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
virtio_queue_notify_vq(&vdev->vq[n]);
|
VirtQueue *vq = &vdev->vq[n];
|
||||||
|
|
||||||
|
if (unlikely(!vq->vring.desc || vdev->broken)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
|
||||||
|
if (vq->handle_aio_output) {
|
||||||
|
event_notifier_set(&vq->host_notifier);
|
||||||
|
} else if (vq->handle_output) {
|
||||||
|
vq->handle_output(vdev, vq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
|
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
|
||||||
@@ -1855,9 +1862,11 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
|||||||
/*
|
/*
|
||||||
* Some devices migrate VirtQueueElements that have been popped
|
* Some devices migrate VirtQueueElements that have been popped
|
||||||
* from the avail ring but not yet returned to the used ring.
|
* from the avail ring but not yet returned to the used ring.
|
||||||
|
* Since max ring size < UINT16_MAX it's safe to use modulo
|
||||||
|
* UINT16_MAX + 1 subtraction.
|
||||||
*/
|
*/
|
||||||
vdev->vq[i].inuse = vdev->vq[i].last_avail_idx -
|
vdev->vq[i].inuse = (uint16_t)(vdev->vq[i].last_avail_idx -
|
||||||
vdev->vq[i].used_idx;
|
vdev->vq[i].used_idx);
|
||||||
if (vdev->vq[i].inuse > vdev->vq[i].vring.num) {
|
if (vdev->vq[i].inuse > vdev->vq[i].vring.num) {
|
||||||
error_report("VQ %d size 0x%x < last_avail_idx 0x%x - "
|
error_report("VQ %d size 0x%x < last_avail_idx 0x%x - "
|
||||||
"used_idx 0x%x",
|
"used_idx 0x%x",
|
||||||
|
|||||||
@@ -320,6 +320,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
|
|||||||
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||||
TranslationBlock *tb_next)
|
TranslationBlock *tb_next)
|
||||||
{
|
{
|
||||||
|
assert(n < ARRAY_SIZE(tb->jmp_list_next));
|
||||||
if (tb->jmp_list_next[n]) {
|
if (tb->jmp_list_next[n]) {
|
||||||
/* Another thread has already done this while we were
|
/* Another thread has already done this while we were
|
||||||
* outside of the lock; nothing to do in this case */
|
* outside of the lock; nothing to do in this case */
|
||||||
|
|||||||
+2
-2
@@ -331,12 +331,12 @@ eth_get_pkt_tci(const void *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
size_t
|
||||||
eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
|
eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
|
||||||
uint8_t *new_ehdr_buf,
|
uint8_t *new_ehdr_buf,
|
||||||
uint16_t *payload_offset, uint16_t *tci);
|
uint16_t *payload_offset, uint16_t *tci);
|
||||||
|
|
||||||
bool
|
size_t
|
||||||
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
|
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
|
||||||
uint16_t vet, uint8_t *new_ehdr_buf,
|
uint16_t vet, uint8_t *new_ehdr_buf,
|
||||||
uint16_t *payload_offset, uint16_t *tci);
|
uint16_t *payload_offset, uint16_t *tci);
|
||||||
|
|||||||
@@ -75,23 +75,6 @@ void user_creatable_complete(Object *obj, Error **errp);
|
|||||||
*/
|
*/
|
||||||
bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp);
|
bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp);
|
||||||
|
|
||||||
/**
|
|
||||||
* user_creatable_add:
|
|
||||||
* @qdict: the object definition
|
|
||||||
* @v: the visitor
|
|
||||||
* @errp: if an error occurs, a pointer to an area to store the error
|
|
||||||
*
|
|
||||||
* Create an instance of the user creatable object whose type
|
|
||||||
* is defined in @qdict by the 'qom-type' field, placing it
|
|
||||||
* in the object composition tree with name provided by the
|
|
||||||
* 'id' field. The remaining fields in @qdict are used to
|
|
||||||
* initialize the object properties.
|
|
||||||
*
|
|
||||||
* Returns: the newly created object or NULL on error
|
|
||||||
*/
|
|
||||||
Object *user_creatable_add(const QDict *qdict,
|
|
||||||
Visitor *v, Error **errp);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* user_creatable_add_type:
|
* user_creatable_add_type:
|
||||||
* @type: the object type name
|
* @type: the object type name
|
||||||
|
|||||||
@@ -189,9 +189,6 @@ typedef struct DisplayChangeListenerOps {
|
|||||||
int x, int y, int w, int h);
|
int x, int y, int w, int h);
|
||||||
void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
|
void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
|
||||||
struct DisplaySurface *new_surface);
|
struct DisplaySurface *new_surface);
|
||||||
void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
|
|
||||||
int src_x, int src_y,
|
|
||||||
int dst_x, int dst_y, int w, int h);
|
|
||||||
bool (*dpy_gfx_check_format)(DisplayChangeListener *dcl,
|
bool (*dpy_gfx_check_format)(DisplayChangeListener *dcl,
|
||||||
pixman_format_code_t format);
|
pixman_format_code_t format);
|
||||||
|
|
||||||
@@ -273,8 +270,6 @@ int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info);
|
|||||||
void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
|
void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
|
||||||
void dpy_gfx_replace_surface(QemuConsole *con,
|
void dpy_gfx_replace_surface(QemuConsole *con,
|
||||||
DisplaySurface *surface);
|
DisplaySurface *surface);
|
||||||
void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
|
|
||||||
int dst_x, int dst_y, int w, int h);
|
|
||||||
void dpy_text_cursor(QemuConsole *con, int x, int y);
|
void dpy_text_cursor(QemuConsole *con, int x, int y);
|
||||||
void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
|
void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
|
||||||
void dpy_text_resize(QemuConsole *con, int w, int h);
|
void dpy_text_resize(QemuConsole *con, int w, int h);
|
||||||
@@ -397,8 +392,6 @@ int qemu_console_get_height(QemuConsole *con, int fallback);
|
|||||||
|
|
||||||
void console_select(unsigned int index);
|
void console_select(unsigned int index);
|
||||||
void qemu_console_resize(QemuConsole *con, int width, int height);
|
void qemu_console_resize(QemuConsole *con, int width, int height);
|
||||||
void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
|
|
||||||
int dst_x, int dst_y, int w, int h);
|
|
||||||
DisplaySurface *qemu_console_surface(QemuConsole *con);
|
DisplaySurface *qemu_console_surface(QemuConsole *con);
|
||||||
|
|
||||||
/* console-gl.c */
|
/* console-gl.c */
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
#include <gdk/gdkwayland.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_OPENGL)
|
#if defined(CONFIG_OPENGL)
|
||||||
#include "ui/egl-helpers.h"
|
#include "ui/egl-helpers.h"
|
||||||
#include "ui/egl-context.h"
|
#include "ui/egl-context.h"
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ safe_syscall_base:
|
|||||||
*/
|
*/
|
||||||
safe_syscall_start:
|
safe_syscall_start:
|
||||||
/* if signal_pending is non-zero, don't do the call */
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
lt %r0,0(%r8)
|
icm %r0,15,0(%r8)
|
||||||
jne 2f
|
jne 2f
|
||||||
svc 0
|
svc 0
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
|
|||||||
+4
-1
@@ -1708,10 +1708,12 @@ void cpu_loop(CPUPPCState *env)
|
|||||||
* in syscalls.
|
* in syscalls.
|
||||||
*/
|
*/
|
||||||
env->crf[0] &= ~0x1;
|
env->crf[0] &= ~0x1;
|
||||||
|
env->nip += 4;
|
||||||
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
|
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
|
||||||
env->gpr[5], env->gpr[6], env->gpr[7],
|
env->gpr[5], env->gpr[6], env->gpr[7],
|
||||||
env->gpr[8], 0, 0);
|
env->gpr[8], 0, 0);
|
||||||
if (ret == -TARGET_ERESTARTSYS) {
|
if (ret == -TARGET_ERESTARTSYS) {
|
||||||
|
env->nip -= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
|
if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
|
||||||
@@ -1719,7 +1721,6 @@ void cpu_loop(CPUPPCState *env)
|
|||||||
Avoid corrupting register state. */
|
Avoid corrupting register state. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
env->nip += 4;
|
|
||||||
if (ret > (target_ulong)(-515)) {
|
if (ret > (target_ulong)(-515)) {
|
||||||
env->crf[0] |= 0x1;
|
env->crf[0] |= 0x1;
|
||||||
ret = -ret;
|
ret = -ret;
|
||||||
@@ -4045,6 +4046,8 @@ int main(int argc, char **argv, char **envp)
|
|||||||
# endif
|
# endif
|
||||||
#elif defined TARGET_SH4
|
#elif defined TARGET_SH4
|
||||||
cpu_model = TYPE_SH7785_CPU;
|
cpu_model = TYPE_SH7785_CPU;
|
||||||
|
#elif defined TARGET_S390X
|
||||||
|
cpu_model = "qemu";
|
||||||
#else
|
#else
|
||||||
cpu_model = "any";
|
cpu_model = "any";
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -94,7 +94,7 @@ static ssize_t drop_sync(QIOChannel *ioc, size_t size)
|
|||||||
char small[1024];
|
char small[1024];
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|
||||||
buffer = sizeof(small) < size ? small : g_malloc(MIN(65536, size));
|
buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
ssize_t count = read_sync(ioc, buffer, MIN(65536, size));
|
ssize_t count = read_sync(ioc, buffer, MIN(65536, size));
|
||||||
|
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
size_t
|
||||||
eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
|
eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
|
||||||
uint8_t *new_ehdr_buf,
|
uint8_t *new_ehdr_buf,
|
||||||
uint16_t *payload_offset, uint16_t *tci)
|
uint16_t *payload_offset, uint16_t *tci)
|
||||||
@@ -244,7 +244,7 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
|
|||||||
new_ehdr, sizeof(*new_ehdr));
|
new_ehdr, sizeof(*new_ehdr));
|
||||||
|
|
||||||
if (copied < sizeof(*new_ehdr)) {
|
if (copied < sizeof(*new_ehdr)) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (be16_to_cpu(new_ehdr->h_proto)) {
|
switch (be16_to_cpu(new_ehdr->h_proto)) {
|
||||||
@@ -254,7 +254,7 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
|
|||||||
&vlan_hdr, sizeof(vlan_hdr));
|
&vlan_hdr, sizeof(vlan_hdr));
|
||||||
|
|
||||||
if (copied < sizeof(vlan_hdr)) {
|
if (copied < sizeof(vlan_hdr)) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_ehdr->h_proto = vlan_hdr.h_proto;
|
new_ehdr->h_proto = vlan_hdr.h_proto;
|
||||||
@@ -268,18 +268,21 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
|
|||||||
PKT_GET_VLAN_HDR(new_ehdr), sizeof(vlan_hdr));
|
PKT_GET_VLAN_HDR(new_ehdr), sizeof(vlan_hdr));
|
||||||
|
|
||||||
if (copied < sizeof(vlan_hdr)) {
|
if (copied < sizeof(vlan_hdr)) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*payload_offset += sizeof(vlan_hdr);
|
*payload_offset += sizeof(vlan_hdr);
|
||||||
|
|
||||||
|
return sizeof(struct eth_header) + sizeof(struct vlan_header);
|
||||||
|
} else {
|
||||||
|
return sizeof(struct eth_header);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
size_t
|
||||||
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
|
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
|
||||||
uint16_t vet, uint8_t *new_ehdr_buf,
|
uint16_t vet, uint8_t *new_ehdr_buf,
|
||||||
uint16_t *payload_offset, uint16_t *tci)
|
uint16_t *payload_offset, uint16_t *tci)
|
||||||
@@ -291,7 +294,7 @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
|
|||||||
new_ehdr, sizeof(*new_ehdr));
|
new_ehdr, sizeof(*new_ehdr));
|
||||||
|
|
||||||
if (copied < sizeof(*new_ehdr)) {
|
if (copied < sizeof(*new_ehdr)) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (be16_to_cpu(new_ehdr->h_proto) == vet) {
|
if (be16_to_cpu(new_ehdr->h_proto) == vet) {
|
||||||
@@ -299,17 +302,17 @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
|
|||||||
&vlan_hdr, sizeof(vlan_hdr));
|
&vlan_hdr, sizeof(vlan_hdr));
|
||||||
|
|
||||||
if (copied < sizeof(vlan_hdr)) {
|
if (copied < sizeof(vlan_hdr)) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_ehdr->h_proto = vlan_hdr.h_proto;
|
new_ehdr->h_proto = vlan_hdr.h_proto;
|
||||||
|
|
||||||
*tci = be16_to_cpu(vlan_hdr.h_tci);
|
*tci = be16_to_cpu(vlan_hdr.h_tci);
|
||||||
*payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr);
|
*payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr);
|
||||||
return true;
|
return sizeof(struct eth_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -164,7 +164,7 @@ opts_check_struct(Visitor *v, Error **errp)
|
|||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
GQueue *any;
|
GQueue *any;
|
||||||
|
|
||||||
if (ov->depth > 0) {
|
if (ov->depth > 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-5
@@ -499,7 +499,7 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
|||||||
|
|
||||||
static void remove_fd_in_watch(CharDriverState *chr);
|
static void remove_fd_in_watch(CharDriverState *chr);
|
||||||
static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context);
|
static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context);
|
||||||
static void mux_set_focus(MuxDriver *d, int focus);
|
static void mux_set_focus(CharDriverState *chr, int focus);
|
||||||
|
|
||||||
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
@@ -666,7 +666,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
|
|||||||
case 'c':
|
case 'c':
|
||||||
assert(d->mux_cnt > 0); /* handler registered with first fe */
|
assert(d->mux_cnt > 0); /* handler registered with first fe */
|
||||||
/* Switch to the next registered device */
|
/* Switch to the next registered device */
|
||||||
mux_set_focus(d, (d->focus + 1) % d->mux_cnt);
|
mux_set_focus(chr, (d->focus + 1) % d->mux_cnt);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
d->timestamps = !d->timestamps;
|
d->timestamps = !d->timestamps;
|
||||||
@@ -826,8 +826,10 @@ static void mux_chr_set_handlers(CharDriverState *chr, GMainContext *context)
|
|||||||
context, true);
|
context, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mux_set_focus(MuxDriver *d, int focus)
|
static void mux_set_focus(CharDriverState *chr, int focus)
|
||||||
{
|
{
|
||||||
|
MuxDriver *d = chr->opaque;
|
||||||
|
|
||||||
assert(focus >= 0);
|
assert(focus >= 0);
|
||||||
assert(focus < d->mux_cnt);
|
assert(focus < d->mux_cnt);
|
||||||
|
|
||||||
@@ -836,6 +838,7 @@ static void mux_set_focus(MuxDriver *d, int focus)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d->focus = focus;
|
d->focus = focus;
|
||||||
|
chr->be = d->backends[focus];
|
||||||
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
|
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -935,7 +938,9 @@ void qemu_chr_fe_deinit(CharBackend *b)
|
|||||||
|
|
||||||
if (b->chr) {
|
if (b->chr) {
|
||||||
qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true);
|
qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true);
|
||||||
b->chr->be = NULL;
|
if (b->chr->be == b) {
|
||||||
|
b->chr->be = NULL;
|
||||||
|
}
|
||||||
if (b->chr->is_mux) {
|
if (b->chr->is_mux) {
|
||||||
MuxDriver *d = b->chr->opaque;
|
MuxDriver *d = b->chr->opaque;
|
||||||
d->backends[b->tag] = NULL;
|
d->backends[b->tag] = NULL;
|
||||||
@@ -999,7 +1004,7 @@ void qemu_chr_fe_take_focus(CharBackend *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (b->chr->is_mux) {
|
if (b->chr->is_mux) {
|
||||||
mux_set_focus(b->chr->opaque, b->tag);
|
mux_set_focus(b->chr, b->tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1243,6 +1243,9 @@ int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
|
|||||||
* filesystems may not implement fsfreeze for less obvious reasons.
|
* filesystems may not implement fsfreeze for less obvious reasons.
|
||||||
* these will report EOPNOTSUPP. we simply ignore these when tallying
|
* these will report EOPNOTSUPP. we simply ignore these when tallying
|
||||||
* the number of frozen filesystems.
|
* the number of frozen filesystems.
|
||||||
|
* if a filesystem is mounted more than once (aka bind mount) a
|
||||||
|
* consecutive attempt to freeze an already frozen filesystem will
|
||||||
|
* return EBUSY.
|
||||||
*
|
*
|
||||||
* any other error means a failure to freeze a filesystem we
|
* any other error means a failure to freeze a filesystem we
|
||||||
* expect to be freezable, so return an error in those cases
|
* expect to be freezable, so return an error in those cases
|
||||||
@@ -1250,7 +1253,7 @@ int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
|
|||||||
*/
|
*/
|
||||||
ret = ioctl(fd, FIFREEZE);
|
ret = ioctl(fd, FIFREEZE);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno != EOPNOTSUPP) {
|
if (errno != EOPNOTSUPP && errno != EBUSY) {
|
||||||
error_setg_errno(errp, errno, "failed to freeze %s",
|
error_setg_errno(errp, errno, "failed to freeze %s",
|
||||||
mount->dirname);
|
mount->dirname);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|||||||
+21
-54
@@ -35,57 +35,6 @@ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Object *user_creatable_add(const QDict *qdict,
|
|
||||||
Visitor *v, Error **errp)
|
|
||||||
{
|
|
||||||
char *type = NULL;
|
|
||||||
char *id = NULL;
|
|
||||||
Object *obj = NULL;
|
|
||||||
Error *local_err = NULL;
|
|
||||||
QDict *pdict;
|
|
||||||
|
|
||||||
pdict = qdict_clone_shallow(qdict);
|
|
||||||
|
|
||||||
visit_start_struct(v, NULL, NULL, 0, &local_err);
|
|
||||||
if (local_err) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdict_del(pdict, "qom-type");
|
|
||||||
visit_type_str(v, "qom-type", &type, &local_err);
|
|
||||||
if (local_err) {
|
|
||||||
goto out_visit;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdict_del(pdict, "id");
|
|
||||||
visit_type_str(v, "id", &id, &local_err);
|
|
||||||
if (local_err) {
|
|
||||||
goto out_visit;
|
|
||||||
}
|
|
||||||
visit_check_struct(v, &local_err);
|
|
||||||
if (local_err) {
|
|
||||||
goto out_visit;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj = user_creatable_add_type(type, id, pdict, v, &local_err);
|
|
||||||
|
|
||||||
out_visit:
|
|
||||||
visit_end_struct(v, NULL);
|
|
||||||
|
|
||||||
out:
|
|
||||||
QDECREF(pdict);
|
|
||||||
g_free(id);
|
|
||||||
g_free(type);
|
|
||||||
if (local_err) {
|
|
||||||
error_propagate(errp, local_err);
|
|
||||||
object_unref(obj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Object *user_creatable_add_type(const char *type, const char *id,
|
Object *user_creatable_add_type(const char *type, const char *id,
|
||||||
const QDict *qdict,
|
const QDict *qdict,
|
||||||
Visitor *v, Error **errp)
|
Visitor *v, Error **errp)
|
||||||
@@ -158,13 +107,31 @@ Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
|
|||||||
{
|
{
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
QDict *pdict;
|
QDict *pdict;
|
||||||
Object *obj = NULL;
|
Object *obj;
|
||||||
|
const char *id = qemu_opts_id(opts);
|
||||||
|
char *type = qemu_opt_get_del(opts, "qom-type");
|
||||||
|
|
||||||
v = opts_visitor_new(opts);
|
if (!type) {
|
||||||
|
error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!id) {
|
||||||
|
error_setg(errp, QERR_MISSING_PARAMETER, "id");
|
||||||
|
qemu_opt_set(opts, "qom-type", type, &error_abort);
|
||||||
|
g_free(type);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_opts_set_id(opts, NULL);
|
||||||
pdict = qemu_opts_to_qdict(opts, NULL);
|
pdict = qemu_opts_to_qdict(opts, NULL);
|
||||||
|
|
||||||
obj = user_creatable_add(pdict, v, errp);
|
v = opts_visitor_new(opts);
|
||||||
|
obj = user_creatable_add_type(type, id, pdict, v, errp);
|
||||||
visit_free(v);
|
visit_free(v);
|
||||||
|
|
||||||
|
qemu_opts_set_id(opts, (char *) id);
|
||||||
|
qemu_opt_set(opts, "qom-type", type, &error_abort);
|
||||||
|
g_free(type);
|
||||||
QDECREF(pdict);
|
QDECREF(pdict);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
Submodule roms/seabios updated: 8891697e3f...5f4c7b13cd.
@@ -527,7 +527,7 @@ static inline void assert_fp_access_checked(DisasContext *s)
|
|||||||
static inline int vec_reg_offset(DisasContext *s, int regno,
|
static inline int vec_reg_offset(DisasContext *s, int regno,
|
||||||
int element, TCGMemOp size)
|
int element, TCGMemOp size)
|
||||||
{
|
{
|
||||||
int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
|
int offs = 0;
|
||||||
#ifdef HOST_WORDS_BIGENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
/* This is complicated slightly because vfp.regs[2n] is
|
/* This is complicated slightly because vfp.regs[2n] is
|
||||||
* still the low half and vfp.regs[2n+1] the high half
|
* still the low half and vfp.regs[2n+1] the high half
|
||||||
@@ -540,6 +540,7 @@ static inline int vec_reg_offset(DisasContext *s, int regno,
|
|||||||
#else
|
#else
|
||||||
offs += element * (1 << size);
|
offs += element * (1 << size);
|
||||||
#endif
|
#endif
|
||||||
|
offs += offsetof(CPUARMState, vfp.regs[regno * 2]);
|
||||||
assert_fp_access_checked(s);
|
assert_fp_access_checked(s);
|
||||||
return offs;
|
return offs;
|
||||||
}
|
}
|
||||||
@@ -2829,9 +2830,9 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
|
|||||||
} else {
|
} else {
|
||||||
/* Load/store one element per register */
|
/* Load/store one element per register */
|
||||||
if (is_load) {
|
if (is_load) {
|
||||||
do_vec_ld(s, rt, index, tcg_addr, s->be_data + scale);
|
do_vec_ld(s, rt, index, tcg_addr, scale);
|
||||||
} else {
|
} else {
|
||||||
do_vec_st(s, rt, index, tcg_addr, s->be_data + scale);
|
do_vec_st(s, rt, index, tcg_addr, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
|
tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
|
||||||
|
|||||||
+3
-2
@@ -1610,8 +1610,9 @@ void helper_lock_init(void);
|
|||||||
|
|
||||||
/* svm_helper.c */
|
/* svm_helper.c */
|
||||||
void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
|
void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
|
||||||
uint64_t param);
|
uint64_t param, uintptr_t retaddr);
|
||||||
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1);
|
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1,
|
||||||
|
uintptr_t retaddr);
|
||||||
|
|
||||||
/* seg_helper.c */
|
/* seg_helper.c */
|
||||||
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
|
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ void helper_raise_exception(CPUX86State *env, int exception_index)
|
|||||||
* needed. It should only be called, if this is not an interrupt.
|
* needed. It should only be called, if this is not an interrupt.
|
||||||
* Returns the new exception number.
|
* Returns the new exception number.
|
||||||
*/
|
*/
|
||||||
static int check_exception(CPUX86State *env, int intno, int *error_code)
|
static int check_exception(CPUX86State *env, int intno, int *error_code,
|
||||||
|
uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
int first_contributory = env->old_exception == 0 ||
|
int first_contributory = env->old_exception == 0 ||
|
||||||
(env->old_exception >= 10 &&
|
(env->old_exception >= 10 &&
|
||||||
@@ -53,7 +54,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code)
|
|||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
if (env->old_exception == EXCP08_DBLE) {
|
if (env->old_exception == EXCP08_DBLE) {
|
||||||
if (env->hflags & HF_SVMI_MASK) {
|
if (env->hflags & HF_SVMI_MASK) {
|
||||||
cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0); /* does not return */
|
cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0, retaddr); /* does not return */
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
|
qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
|
||||||
@@ -93,10 +94,10 @@ static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno,
|
|||||||
|
|
||||||
if (!is_int) {
|
if (!is_int) {
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno,
|
cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno,
|
||||||
error_code);
|
error_code, retaddr);
|
||||||
intno = check_exception(env, intno, &error_code);
|
intno = check_exception(env, intno, &error_code, retaddr);
|
||||||
} else {
|
} else {
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0, retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
cs->exception_index = intno;
|
cs->exception_index = intno;
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ DEF_HELPER_2(inl, tl, env, i32)
|
|||||||
DEF_HELPER_FLAGS_4(bpt_io, TCG_CALL_NO_WG, void, env, i32, i32, tl)
|
DEF_HELPER_FLAGS_4(bpt_io, TCG_CALL_NO_WG, void, env, i32, i32, tl)
|
||||||
|
|
||||||
DEF_HELPER_3(svm_check_intercept_param, void, env, i32, i64)
|
DEF_HELPER_3(svm_check_intercept_param, void, env, i32, i64)
|
||||||
DEF_HELPER_3(vmexit, void, env, i32, i64)
|
|
||||||
DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32)
|
DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32)
|
||||||
DEF_HELPER_3(vmrun, void, env, int, int)
|
DEF_HELPER_3(vmrun, void, env, int, int)
|
||||||
DEF_HELPER_1(vmmcall, void, env)
|
DEF_HELPER_1(vmmcall, void, env)
|
||||||
|
|||||||
+12
-12
@@ -101,7 +101,7 @@ void helper_cpuid(CPUX86State *env)
|
|||||||
{
|
{
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
|
||||||
|
|
||||||
cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
|
cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
|
||||||
&eax, &ebx, &ecx, &edx);
|
&eax, &ebx, &ecx, &edx);
|
||||||
@@ -125,7 +125,7 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
|
|||||||
{
|
{
|
||||||
target_ulong val;
|
target_ulong val;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
default:
|
default:
|
||||||
val = env->cr[reg];
|
val = env->cr[reg];
|
||||||
@@ -143,7 +143,7 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
|
|||||||
|
|
||||||
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
|
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
|
||||||
{
|
{
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0:
|
case 0:
|
||||||
cpu_x86_update_cr0(env, t0);
|
cpu_x86_update_cr0(env, t0);
|
||||||
@@ -179,7 +179,7 @@ void helper_invlpg(CPUX86State *env, target_ulong addr)
|
|||||||
{
|
{
|
||||||
X86CPU *cpu = x86_env_get_cpu(env);
|
X86CPU *cpu = x86_env_get_cpu(env);
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
|
||||||
tlb_flush_page(CPU(cpu), addr);
|
tlb_flush_page(CPU(cpu), addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ void helper_rdtsc(CPUX86State *env)
|
|||||||
if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
|
if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
|
||||||
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
||||||
}
|
}
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
|
||||||
|
|
||||||
val = cpu_get_tsc(env) + env->tsc_offset;
|
val = cpu_get_tsc(env) + env->tsc_offset;
|
||||||
env->regs[R_EAX] = (uint32_t)(val);
|
env->regs[R_EAX] = (uint32_t)(val);
|
||||||
@@ -208,7 +208,7 @@ void helper_rdpmc(CPUX86State *env)
|
|||||||
if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
|
if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
|
||||||
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
||||||
}
|
}
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
|
||||||
|
|
||||||
/* currently unimplemented */
|
/* currently unimplemented */
|
||||||
qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
|
qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
|
||||||
@@ -228,7 +228,7 @@ void helper_wrmsr(CPUX86State *env)
|
|||||||
{
|
{
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
|
||||||
|
|
||||||
val = ((uint32_t)env->regs[R_EAX]) |
|
val = ((uint32_t)env->regs[R_EAX]) |
|
||||||
((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
|
((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
|
||||||
@@ -388,7 +388,7 @@ void helper_rdmsr(CPUX86State *env)
|
|||||||
{
|
{
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
|
||||||
|
|
||||||
switch ((uint32_t)env->regs[R_ECX]) {
|
switch ((uint32_t)env->regs[R_ECX]) {
|
||||||
case MSR_IA32_SYSENTER_CS:
|
case MSR_IA32_SYSENTER_CS:
|
||||||
@@ -557,7 +557,7 @@ void helper_hlt(CPUX86State *env, int next_eip_addend)
|
|||||||
{
|
{
|
||||||
X86CPU *cpu = x86_env_get_cpu(env);
|
X86CPU *cpu = x86_env_get_cpu(env);
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
|
||||||
env->eip += next_eip_addend;
|
env->eip += next_eip_addend;
|
||||||
|
|
||||||
do_hlt(cpu);
|
do_hlt(cpu);
|
||||||
@@ -569,7 +569,7 @@ void helper_monitor(CPUX86State *env, target_ulong ptr)
|
|||||||
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
||||||
}
|
}
|
||||||
/* XXX: store address? */
|
/* XXX: store address? */
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_mwait(CPUX86State *env, int next_eip_addend)
|
void helper_mwait(CPUX86State *env, int next_eip_addend)
|
||||||
@@ -580,7 +580,7 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
|
|||||||
if ((uint32_t)env->regs[R_ECX] != 0) {
|
if ((uint32_t)env->regs[R_ECX] != 0) {
|
||||||
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
raise_exception_ra(env, EXCP0D_GPF, GETPC());
|
||||||
}
|
}
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
|
||||||
env->eip += next_eip_addend;
|
env->eip += next_eip_addend;
|
||||||
|
|
||||||
cpu = x86_env_get_cpu(env);
|
cpu = x86_env_get_cpu(env);
|
||||||
@@ -597,7 +597,7 @@ void helper_pause(CPUX86State *env, int next_eip_addend)
|
|||||||
{
|
{
|
||||||
X86CPU *cpu = x86_env_get_cpu(env);
|
X86CPU *cpu = x86_env_get_cpu(env);
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
|
||||||
env->eip += next_eip_addend;
|
env->eip += next_eip_addend;
|
||||||
|
|
||||||
do_pause(cpu);
|
do_pause(cpu);
|
||||||
|
|||||||
@@ -1334,7 +1334,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
|||||||
} else if (env->hflags2 & HF2_GIF_MASK) {
|
} else if (env->hflags2 & HF2_GIF_MASK) {
|
||||||
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
|
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
|
||||||
!(env->hflags & HF_SMM_MASK)) {
|
!(env->hflags & HF_SMM_MASK)) {
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0, 0);
|
||||||
cs->interrupt_request &= ~CPU_INTERRUPT_SMI;
|
cs->interrupt_request &= ~CPU_INTERRUPT_SMI;
|
||||||
do_smm_enter(cpu);
|
do_smm_enter(cpu);
|
||||||
ret = true;
|
ret = true;
|
||||||
@@ -1355,7 +1355,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
|||||||
(env->eflags & IF_MASK &&
|
(env->eflags & IF_MASK &&
|
||||||
!(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
|
!(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
|
||||||
int intno;
|
int intno;
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0, 0);
|
||||||
cs->interrupt_request &= ~(CPU_INTERRUPT_HARD |
|
cs->interrupt_request &= ~(CPU_INTERRUPT_HARD |
|
||||||
CPU_INTERRUPT_VIRQ);
|
CPU_INTERRUPT_VIRQ);
|
||||||
intno = cpu_get_pic_interrupt(env);
|
intno = cpu_get_pic_interrupt(env);
|
||||||
@@ -1371,7 +1371,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
|||||||
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
|
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
|
||||||
int intno;
|
int intno;
|
||||||
/* FIXME: this should respect TPR */
|
/* FIXME: this should respect TPR */
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0, 0);
|
||||||
intno = x86_ldl_phys(cs, env->vm_vmcb
|
intno = x86_ldl_phys(cs, env->vm_vmcb
|
||||||
+ offsetof(struct vmcb, control.int_vector));
|
+ offsetof(struct vmcb, control.int_vector));
|
||||||
qemu_log_mask(CPU_LOG_TB_IN_ASM,
|
qemu_log_mask(CPU_LOG_TB_IN_ASM,
|
||||||
|
|||||||
+31
-34
@@ -60,11 +60,8 @@ void helper_invlpga(CPUX86State *env, int aflag)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
|
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1,
|
||||||
{
|
uintptr_t retaddr)
|
||||||
}
|
|
||||||
|
|
||||||
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +71,7 @@ void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
||||||
uint64_t param)
|
uint64_t param, uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +127,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
|||||||
uint32_t event_inj;
|
uint32_t event_inj;
|
||||||
uint32_t int_ctl;
|
uint32_t int_ctl;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
@@ -355,7 +352,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
|||||||
|
|
||||||
void helper_vmmcall(CPUX86State *env)
|
void helper_vmmcall(CPUX86State *env)
|
||||||
{
|
{
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMMCALL, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VMMCALL, 0, GETPC());
|
||||||
raise_exception(env, EXCP06_ILLOP);
|
raise_exception(env, EXCP06_ILLOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +361,7 @@ void helper_vmload(CPUX86State *env, int aflag)
|
|||||||
CPUState *cs = CPU(x86_env_get_cpu(env));
|
CPUState *cs = CPU(x86_env_get_cpu(env));
|
||||||
target_ulong addr;
|
target_ulong addr;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
@@ -404,7 +401,7 @@ void helper_vmsave(CPUX86State *env, int aflag)
|
|||||||
CPUState *cs = CPU(x86_env_get_cpu(env));
|
CPUState *cs = CPU(x86_env_get_cpu(env));
|
||||||
target_ulong addr;
|
target_ulong addr;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
@@ -445,19 +442,19 @@ void helper_vmsave(CPUX86State *env, int aflag)
|
|||||||
|
|
||||||
void helper_stgi(CPUX86State *env)
|
void helper_stgi(CPUX86State *env)
|
||||||
{
|
{
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_STGI, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_STGI, 0, GETPC());
|
||||||
env->hflags2 |= HF2_GIF_MASK;
|
env->hflags2 |= HF2_GIF_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_clgi(CPUX86State *env)
|
void helper_clgi(CPUX86State *env)
|
||||||
{
|
{
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_CLGI, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_CLGI, 0, GETPC());
|
||||||
env->hflags2 &= ~HF2_GIF_MASK;
|
env->hflags2 &= ~HF2_GIF_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_skinit(CPUX86State *env)
|
void helper_skinit(CPUX86State *env)
|
||||||
{
|
{
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_SKINIT, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_SKINIT, 0, GETPC());
|
||||||
/* XXX: not implemented */
|
/* XXX: not implemented */
|
||||||
raise_exception(env, EXCP06_ILLOP);
|
raise_exception(env, EXCP06_ILLOP);
|
||||||
}
|
}
|
||||||
@@ -467,7 +464,7 @@ void helper_invlpga(CPUX86State *env, int aflag)
|
|||||||
X86CPU *cpu = x86_env_get_cpu(env);
|
X86CPU *cpu = x86_env_get_cpu(env);
|
||||||
target_ulong addr;
|
target_ulong addr;
|
||||||
|
|
||||||
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPGA, 0);
|
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPGA, 0, GETPC());
|
||||||
|
|
||||||
if (aflag == 2) {
|
if (aflag == 2) {
|
||||||
addr = env->regs[R_EAX];
|
addr = env->regs[R_EAX];
|
||||||
@@ -480,8 +477,8 @@ void helper_invlpga(CPUX86State *env, int aflag)
|
|||||||
tlb_flush_page(CPU(cpu), addr);
|
tlb_flush_page(CPU(cpu), addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
||||||
uint64_t param)
|
uint64_t param, uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(x86_env_get_cpu(env));
|
CPUState *cs = CPU(x86_env_get_cpu(env));
|
||||||
|
|
||||||
@@ -491,27 +488,27 @@ void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
|
case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
|
||||||
if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
|
if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
|
case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
|
||||||
if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
|
if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
|
case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
|
||||||
if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
|
if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
|
case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
|
||||||
if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
|
if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
|
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
|
||||||
if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
|
if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SVM_EXIT_MSR:
|
case SVM_EXIT_MSR:
|
||||||
@@ -538,28 +535,28 @@ void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
|||||||
t0 %= 8;
|
t0 %= 8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
t0 = 0;
|
t0 = 0;
|
||||||
t1 = 0;
|
t1 = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (x86_ldub_phys(cs, addr + t1) & ((1 << param) << t0)) {
|
if (x86_ldub_phys(cs, addr + t1) & ((1 << param) << t0)) {
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
|
if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
|
||||||
helper_vmexit(env, type, param);
|
cpu_vmexit(env, type, param, retaddr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
|
||||||
uint64_t param)
|
uint64_t param)
|
||||||
{
|
{
|
||||||
helper_svm_check_intercept_param(env, type, param);
|
cpu_svm_check_intercept_param(env, type, param, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
|
void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
|
||||||
@@ -578,17 +575,22 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
|
|||||||
x86_stq_phys(cs,
|
x86_stq_phys(cs,
|
||||||
env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
|
env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
|
||||||
env->eip + next_eip_addend);
|
env->eip + next_eip_addend);
|
||||||
helper_vmexit(env, SVM_EXIT_IOIO, param | (port << 16));
|
cpu_vmexit(env, SVM_EXIT_IOIO, param | (port << 16), GETPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: currently only 32 bits of exit_code are used */
|
/* Note: currently only 32 bits of exit_code are used */
|
||||||
void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
|
void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
|
||||||
|
uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(x86_env_get_cpu(env));
|
CPUState *cs = CPU(x86_env_get_cpu(env));
|
||||||
uint32_t int_ctl;
|
uint32_t int_ctl;
|
||||||
|
|
||||||
|
if (retaddr) {
|
||||||
|
cpu_restore_state(cs, retaddr);
|
||||||
|
}
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
|
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
|
||||||
PRIx64 ", " TARGET_FMT_lx ")!\n",
|
PRIx64 ", " TARGET_FMT_lx ")!\n",
|
||||||
exit_code, exit_info_1,
|
exit_code, exit_info_1,
|
||||||
@@ -766,9 +768,4 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
|
|||||||
cpu_loop_exit(cs);
|
cpu_loop_exit(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
|
|
||||||
{
|
|
||||||
helper_vmexit(env, exit_code, exit_info_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -659,7 +659,6 @@ static void check_compatibility(const S390CPUModel *max_model,
|
|||||||
|
|
||||||
static S390CPUModel *get_max_cpu_model(Error **errp)
|
static S390CPUModel *get_max_cpu_model(Error **errp)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
static S390CPUModel max_model;
|
static S390CPUModel max_model;
|
||||||
static bool cached;
|
static bool cached;
|
||||||
|
|
||||||
@@ -679,7 +678,6 @@ static S390CPUModel *get_max_cpu_model(Error **errp)
|
|||||||
cached = true;
|
cached = true;
|
||||||
return &max_model;
|
return &max_model;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -197,7 +197,7 @@ void kvm_s390_cmma_reset(void)
|
|||||||
.attr = KVM_S390_VM_MEM_CLR_CMMA,
|
.attr = KVM_S390_VM_MEM_CLR_CMMA,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!mem_path || !kvm_s390_cmma_available()) {
|
if (mem_path || !kvm_s390_cmma_available()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2425,8 +2425,31 @@ static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
|
|||||||
gen_ldstub(dc, dst, addr, da.mem_idx);
|
gen_ldstub(dc, dst, addr, da.mem_idx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* ??? Should be DAE_invalid_asi. */
|
/* ??? In theory, this should be raise DAE_invalid_asi.
|
||||||
gen_exception(dc, TT_DATA_ACCESS);
|
But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */
|
||||||
|
if (parallel_cpus) {
|
||||||
|
gen_helper_exit_atomic(cpu_env);
|
||||||
|
} else {
|
||||||
|
TCGv_i32 r_asi = tcg_const_i32(da.asi);
|
||||||
|
TCGv_i32 r_mop = tcg_const_i32(MO_UB);
|
||||||
|
TCGv_i64 s64, t64;
|
||||||
|
|
||||||
|
save_state(dc);
|
||||||
|
t64 = tcg_temp_new_i64();
|
||||||
|
gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
|
||||||
|
|
||||||
|
s64 = tcg_const_i64(0xff);
|
||||||
|
gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_mop);
|
||||||
|
tcg_temp_free_i64(s64);
|
||||||
|
tcg_temp_free_i32(r_mop);
|
||||||
|
tcg_temp_free_i32(r_asi);
|
||||||
|
|
||||||
|
tcg_gen_trunc_i64_tl(dst, t64);
|
||||||
|
tcg_temp_free_i64(t64);
|
||||||
|
|
||||||
|
/* End the TB. */
|
||||||
|
dc->npc = DYNAMIC_PC;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -581,11 +581,9 @@ static void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext,
|
|||||||
static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
|
static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
|
||||||
tcg_target_long value)
|
tcg_target_long value)
|
||||||
{
|
{
|
||||||
AArch64Insn insn;
|
|
||||||
int i, wantinv, shift;
|
int i, wantinv, shift;
|
||||||
tcg_target_long svalue = value;
|
tcg_target_long svalue = value;
|
||||||
tcg_target_long ivalue = ~value;
|
tcg_target_long ivalue = ~value;
|
||||||
tcg_target_long imask;
|
|
||||||
|
|
||||||
/* For 32-bit values, discard potential garbage in value. For 64-bit
|
/* For 32-bit values, discard potential garbage in value. For 64-bit
|
||||||
values within [2**31, 2**32-1], we can create smaller sequences by
|
values within [2**31, 2**32-1], we can create smaller sequences by
|
||||||
@@ -631,42 +629,35 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
|
|||||||
|
|
||||||
/* Would it take fewer insns to begin with MOVN? For the value and its
|
/* Would it take fewer insns to begin with MOVN? For the value and its
|
||||||
inverse, count the number of 16-bit lanes that are 0. */
|
inverse, count the number of 16-bit lanes that are 0. */
|
||||||
for (i = wantinv = imask = 0; i < 64; i += 16) {
|
for (i = wantinv = 0; i < 64; i += 16) {
|
||||||
tcg_target_long mask = 0xffffull << i;
|
tcg_target_long mask = 0xffffull << i;
|
||||||
if ((value & mask) == 0) {
|
wantinv -= ((value & mask) == 0);
|
||||||
wantinv -= 1;
|
wantinv += ((ivalue & mask) == 0);
|
||||||
}
|
|
||||||
if ((ivalue & mask) == 0) {
|
|
||||||
wantinv += 1;
|
|
||||||
imask |= mask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we had more 0xffff than 0x0000, invert VALUE and use MOVN. */
|
if (wantinv <= 0) {
|
||||||
insn = I3405_MOVZ;
|
/* Find the lowest lane that is not 0x0000. */
|
||||||
if (wantinv > 0) {
|
|
||||||
value = ivalue;
|
|
||||||
insn = I3405_MOVN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the lowest lane that is not 0x0000. */
|
|
||||||
shift = ctz64(value) & (63 & -16);
|
|
||||||
tcg_out_insn_3405(s, insn, type, rd, value >> shift, shift);
|
|
||||||
|
|
||||||
if (wantinv > 0) {
|
|
||||||
/* Re-invert the value, so MOVK sees non-inverted bits. */
|
|
||||||
value = ~value;
|
|
||||||
/* Clear out all the 0xffff lanes. */
|
|
||||||
value ^= imask;
|
|
||||||
}
|
|
||||||
/* Clear out the lane that we just set. */
|
|
||||||
value &= ~(0xffffUL << shift);
|
|
||||||
|
|
||||||
/* Iterate until all lanes have been set, and thus cleared from VALUE. */
|
|
||||||
while (value) {
|
|
||||||
shift = ctz64(value) & (63 & -16);
|
shift = ctz64(value) & (63 & -16);
|
||||||
tcg_out_insn(s, 3405, MOVK, type, rd, value >> shift, shift);
|
tcg_out_insn(s, 3405, MOVZ, type, rd, value >> shift, shift);
|
||||||
|
/* Clear out the lane that we just set. */
|
||||||
value &= ~(0xffffUL << shift);
|
value &= ~(0xffffUL << shift);
|
||||||
|
/* Iterate until all non-zero lanes have been processed. */
|
||||||
|
while (value) {
|
||||||
|
shift = ctz64(value) & (63 & -16);
|
||||||
|
tcg_out_insn(s, 3405, MOVK, type, rd, value >> shift, shift);
|
||||||
|
value &= ~(0xffffUL << shift);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Like above, but with the inverted value and MOVN to start. */
|
||||||
|
shift = ctz64(ivalue) & (63 & -16);
|
||||||
|
tcg_out_insn(s, 3405, MOVN, type, rd, ivalue >> shift, shift);
|
||||||
|
ivalue &= ~(0xffffUL << shift);
|
||||||
|
while (ivalue) {
|
||||||
|
shift = ctz64(ivalue) & (63 & -16);
|
||||||
|
/* Provide MOVK with the non-inverted value. */
|
||||||
|
tcg_out_insn(s, 3405, MOVK, type, rd, ~(ivalue >> shift), shift);
|
||||||
|
ivalue &= ~(0xffffUL << shift);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,6 +956,15 @@ static inline void tcg_out_addsub2(TCGContext *s, int ext, TCGReg rl,
|
|||||||
insn = I3401_SUBSI;
|
insn = I3401_SUBSI;
|
||||||
bl = -bl;
|
bl = -bl;
|
||||||
}
|
}
|
||||||
|
if (unlikely(al == TCG_REG_XZR)) {
|
||||||
|
/* ??? We want to allow al to be zero for the benefit of
|
||||||
|
negation via subtraction. However, that leaves open the
|
||||||
|
possibility of adding 0+const in the low part, and the
|
||||||
|
immediate add instructions encode XSP not XZR. Don't try
|
||||||
|
anything more elaborate here than loading another zero. */
|
||||||
|
al = TCG_REG_TMP;
|
||||||
|
tcg_out_movi(s, ext, al, 0);
|
||||||
|
}
|
||||||
tcg_out_insn_3401(s, insn, ext, rl, al, bl);
|
tcg_out_insn_3401(s, insn, ext, rl, al, bl);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
|
tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
|
||||||
|
|||||||
@@ -172,6 +172,25 @@ expect_u64_max(OptsVisitorFixture *f, gconstpointer test_data)
|
|||||||
|
|
||||||
/* test cases */
|
/* test cases */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_opts_dict_unvisited(void)
|
||||||
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
QemuOpts *opts;
|
||||||
|
Visitor *v;
|
||||||
|
UserDefOptions *userdef;
|
||||||
|
|
||||||
|
opts = qemu_opts_parse(qemu_find_opts("userdef"), "i64x=0,bogus=1", false,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
v = opts_visitor_new(opts);
|
||||||
|
visit_type_UserDefOptions(v, NULL, &userdef, &err);
|
||||||
|
error_free_or_abort(&err);
|
||||||
|
visit_free(v);
|
||||||
|
qemu_opts_del(opts);
|
||||||
|
g_assert(!userdef);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -263,6 +282,8 @@ main(int argc, char **argv)
|
|||||||
add_test("/visitor/opts/i64/range/2big/full", &expect_fail,
|
add_test("/visitor/opts/i64/range/2big/full", &expect_fail,
|
||||||
"i64=-0x8000000000000000-0x7fffffffffffffff");
|
"i64=-0x8000000000000000-0x7fffffffffffffff");
|
||||||
|
|
||||||
|
g_test_add_func("/visitor/opts/dict/unvisited", test_opts_dict_unvisited);
|
||||||
|
|
||||||
g_test_run();
|
g_test_run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -185,6 +185,13 @@ restart:
|
|||||||
qemu_bh_schedule(pool->completion_bh);
|
qemu_bh_schedule(pool->completion_bh);
|
||||||
|
|
||||||
elem->common.cb(elem->common.opaque, elem->ret);
|
elem->common.cb(elem->common.opaque, elem->ret);
|
||||||
|
|
||||||
|
/* We can safely cancel the completion_bh here regardless of someone
|
||||||
|
* else having scheduled it meanwhile because we reenter the
|
||||||
|
* completion function anyway (goto restart).
|
||||||
|
*/
|
||||||
|
qemu_bh_cancel(pool->completion_bh);
|
||||||
|
|
||||||
qemu_aio_unref(elem);
|
qemu_aio_unref(elem);
|
||||||
goto restart;
|
goto restart;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1562,27 +1562,6 @@ static void dpy_refresh(DisplayState *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
|
|
||||||
int dst_x, int dst_y, int w, int h)
|
|
||||||
{
|
|
||||||
DisplayState *s = con->ds;
|
|
||||||
DisplayChangeListener *dcl;
|
|
||||||
|
|
||||||
if (!qemu_console_is_visible(con)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QLIST_FOREACH(dcl, &s->listeners, next) {
|
|
||||||
if (con != (dcl->con ? dcl->con : active_console)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (dcl->ops->dpy_gfx_copy) {
|
|
||||||
dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
|
|
||||||
} else { /* TODO */
|
|
||||||
dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dpy_text_cursor(QemuConsole *con, int x, int y)
|
void dpy_text_cursor(QemuConsole *con, int x, int y)
|
||||||
{
|
{
|
||||||
DisplayState *s = con->ds;
|
DisplayState *s = con->ds;
|
||||||
@@ -2120,13 +2099,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
|
|||||||
dpy_gfx_replace_surface(s, surface);
|
dpy_gfx_replace_surface(s, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
|
|
||||||
int dst_x, int dst_y, int w, int h)
|
|
||||||
{
|
|
||||||
assert(con->console_type == GRAPHIC_CONSOLE);
|
|
||||||
dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplaySurface *qemu_console_surface(QemuConsole *console)
|
DisplaySurface *qemu_console_surface(QemuConsole *console)
|
||||||
{
|
{
|
||||||
return console->surface;
|
return console->surface;
|
||||||
|
|||||||
@@ -90,6 +90,9 @@
|
|||||||
#ifndef GDK_IS_X11_DISPLAY
|
#ifndef GDK_IS_X11_DISPLAY
|
||||||
#define GDK_IS_X11_DISPLAY(dpy) (dpy == dpy)
|
#define GDK_IS_X11_DISPLAY(dpy) (dpy == dpy)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef GDK_IS_WAYLAND_DISPLAY
|
||||||
|
#define GDK_IS_WAYLAND_DISPLAY(dpy) (dpy == dpy)
|
||||||
|
#endif
|
||||||
#ifndef GDK_IS_WIN32_DISPLAY
|
#ifndef GDK_IS_WIN32_DISPLAY
|
||||||
#define GDK_IS_WIN32_DISPLAY(dpy) (dpy == dpy)
|
#define GDK_IS_WIN32_DISPLAY(dpy) (dpy == dpy)
|
||||||
#endif
|
#endif
|
||||||
@@ -1053,6 +1056,10 @@ static int gd_map_keycode(GtkDisplayState *s, GdkDisplay *dpy, int gdk_keycode)
|
|||||||
} else {
|
} else {
|
||||||
qemu_keycode = translate_xfree86_keycode(gdk_keycode - 97);
|
qemu_keycode = translate_xfree86_keycode(gdk_keycode - 97);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
} else if (GDK_IS_WAYLAND_DISPLAY(dpy) && gdk_keycode < 158) {
|
||||||
|
qemu_keycode = translate_evdev_keycode(gdk_keycode - 97);
|
||||||
#endif
|
#endif
|
||||||
} else if (gdk_keycode == 208) { /* Hiragana_Katakana */
|
} else if (gdk_keycode == 208) { /* Hiragana_Katakana */
|
||||||
qemu_keycode = 0x70;
|
qemu_keycode = 0x70;
|
||||||
@@ -2171,6 +2178,8 @@ static gboolean gtkinit;
|
|||||||
|
|
||||||
void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
|
void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
|
||||||
{
|
{
|
||||||
|
VirtualConsole *vc;
|
||||||
|
|
||||||
GtkDisplayState *s = g_malloc0(sizeof(*s));
|
GtkDisplayState *s = g_malloc0(sizeof(*s));
|
||||||
char *filename;
|
char *filename;
|
||||||
GdkDisplay *window_display;
|
GdkDisplay *window_display;
|
||||||
@@ -2249,9 +2258,11 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vc = gd_vc_find_current(s);
|
||||||
|
gtk_widget_set_sensitive(s->view_menu, vc != NULL);
|
||||||
#ifdef CONFIG_VTE
|
#ifdef CONFIG_VTE
|
||||||
gtk_widget_set_sensitive(s->copy_item,
|
gtk_widget_set_sensitive(s->copy_item,
|
||||||
gd_vc_find_current(s)->type == GD_VC_VTE);
|
vc && vc->type == GD_VC_VTE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (full_screen) {
|
if (full_screen) {
|
||||||
|
|||||||
@@ -872,105 +872,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
|
|
||||||
{
|
|
||||||
/* send bitblit op to the vnc client */
|
|
||||||
vnc_lock_output(vs);
|
|
||||||
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
|
|
||||||
vnc_write_u8(vs, 0);
|
|
||||||
vnc_write_u16(vs, 1); /* number of rects */
|
|
||||||
vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
|
|
||||||
vnc_write_u16(vs, src_x);
|
|
||||||
vnc_write_u16(vs, src_y);
|
|
||||||
vnc_unlock_output(vs);
|
|
||||||
vnc_flush(vs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vnc_dpy_copy(DisplayChangeListener *dcl,
|
|
||||||
int src_x, int src_y,
|
|
||||||
int dst_x, int dst_y, int w, int h)
|
|
||||||
{
|
|
||||||
VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
|
|
||||||
VncState *vs, *vn;
|
|
||||||
uint8_t *src_row;
|
|
||||||
uint8_t *dst_row;
|
|
||||||
int i, x, y, pitch, inc, w_lim, s;
|
|
||||||
int cmp_bytes;
|
|
||||||
|
|
||||||
if (!vd->server) {
|
|
||||||
/* no client connected */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnc_refresh_server_surface(vd);
|
|
||||||
QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
|
|
||||||
if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
|
|
||||||
vs->force_update = 1;
|
|
||||||
vnc_update_client(vs, 1, true);
|
|
||||||
/* vs might be free()ed here */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vd->server) {
|
|
||||||
/* no client connected */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* do bitblit op on the local surface too */
|
|
||||||
pitch = vnc_server_fb_stride(vd);
|
|
||||||
src_row = vnc_server_fb_ptr(vd, src_x, src_y);
|
|
||||||
dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
|
|
||||||
y = dst_y;
|
|
||||||
inc = 1;
|
|
||||||
if (dst_y > src_y) {
|
|
||||||
/* copy backwards */
|
|
||||||
src_row += pitch * (h-1);
|
|
||||||
dst_row += pitch * (h-1);
|
|
||||||
pitch = -pitch;
|
|
||||||
y = dst_y + h - 1;
|
|
||||||
inc = -1;
|
|
||||||
}
|
|
||||||
w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
|
|
||||||
if (w_lim < 0) {
|
|
||||||
w_lim = w;
|
|
||||||
} else {
|
|
||||||
w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT);
|
|
||||||
}
|
|
||||||
for (i = 0; i < h; i++) {
|
|
||||||
for (x = 0; x <= w_lim;
|
|
||||||
x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
|
|
||||||
if (x == w_lim) {
|
|
||||||
if ((s = w - w_lim) == 0)
|
|
||||||
break;
|
|
||||||
} else if (!x) {
|
|
||||||
s = (VNC_DIRTY_PIXELS_PER_BIT -
|
|
||||||
(dst_x % VNC_DIRTY_PIXELS_PER_BIT));
|
|
||||||
s = MIN(s, w_lim);
|
|
||||||
} else {
|
|
||||||
s = VNC_DIRTY_PIXELS_PER_BIT;
|
|
||||||
}
|
|
||||||
cmp_bytes = s * VNC_SERVER_FB_BYTES;
|
|
||||||
if (memcmp(src_row, dst_row, cmp_bytes) == 0)
|
|
||||||
continue;
|
|
||||||
memmove(dst_row, src_row, cmp_bytes);
|
|
||||||
QTAILQ_FOREACH(vs, &vd->clients, next) {
|
|
||||||
if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
|
|
||||||
set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT),
|
|
||||||
vs->dirty[y]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
src_row += pitch - w * VNC_SERVER_FB_BYTES;
|
|
||||||
dst_row += pitch - w * VNC_SERVER_FB_BYTES;
|
|
||||||
y += inc;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTAILQ_FOREACH(vs, &vd->clients, next) {
|
|
||||||
if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
|
|
||||||
vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vnc_mouse_set(DisplayChangeListener *dcl,
|
static void vnc_mouse_set(DisplayChangeListener *dcl,
|
||||||
int x, int y, int visible)
|
int x, int y, int visible)
|
||||||
{
|
{
|
||||||
@@ -1258,12 +1159,13 @@ ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp)
|
|||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
VNC_DEBUG("Closing down client sock: EOF\n");
|
VNC_DEBUG("Closing down client sock: EOF\n");
|
||||||
|
vnc_disconnect_start(vs);
|
||||||
} else if (ret != QIO_CHANNEL_ERR_BLOCK) {
|
} else if (ret != QIO_CHANNEL_ERR_BLOCK) {
|
||||||
VNC_DEBUG("Closing down client sock: ret %d (%s)\n",
|
VNC_DEBUG("Closing down client sock: ret %d (%s)\n",
|
||||||
ret, errp ? error_get_pretty(*errp) : "Unknown");
|
ret, errp ? error_get_pretty(*errp) : "Unknown");
|
||||||
|
vnc_disconnect_start(vs);
|
||||||
}
|
}
|
||||||
|
|
||||||
vnc_disconnect_start(vs);
|
|
||||||
if (errp) {
|
if (errp) {
|
||||||
error_free(*errp);
|
error_free(*errp);
|
||||||
*errp = NULL;
|
*errp = NULL;
|
||||||
@@ -2459,10 +2361,14 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
|
|||||||
|
|
||||||
pixel_format_message(vs);
|
pixel_format_message(vs);
|
||||||
|
|
||||||
if (qemu_name)
|
if (qemu_name) {
|
||||||
size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
|
size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
|
||||||
else
|
if (size > sizeof(buf)) {
|
||||||
|
size = sizeof(buf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
size = snprintf(buf, sizeof(buf), "QEMU");
|
size = snprintf(buf, sizeof(buf), "QEMU");
|
||||||
|
}
|
||||||
|
|
||||||
vnc_write_u32(vs, size);
|
vnc_write_u32(vs, size);
|
||||||
vnc_write(vs, buf, size);
|
vnc_write(vs, buf, size);
|
||||||
@@ -3118,7 +3024,6 @@ static gboolean vnc_listen_io(QIOChannel *ioc,
|
|||||||
static const DisplayChangeListenerOps dcl_ops = {
|
static const DisplayChangeListenerOps dcl_ops = {
|
||||||
.dpy_name = "vnc",
|
.dpy_name = "vnc",
|
||||||
.dpy_refresh = vnc_refresh,
|
.dpy_refresh = vnc_refresh,
|
||||||
.dpy_gfx_copy = vnc_dpy_copy,
|
|
||||||
.dpy_gfx_update = vnc_dpy_update,
|
.dpy_gfx_update = vnc_dpy_update,
|
||||||
.dpy_gfx_switch = vnc_dpy_switch,
|
.dpy_gfx_switch = vnc_dpy_switch,
|
||||||
.dpy_gfx_check_format = qemu_pixman_check_format,
|
.dpy_gfx_check_format = qemu_pixman_check_format,
|
||||||
|
|||||||
@@ -481,12 +481,6 @@ void qemu_thread_create(QemuThread *thread, const char *name,
|
|||||||
if (err) {
|
if (err) {
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
}
|
}
|
||||||
if (mode == QEMU_THREAD_DETACHED) {
|
|
||||||
err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
||||||
if (err) {
|
|
||||||
error_exit(err, __func__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Leave signal handling to the iothread. */
|
/* Leave signal handling to the iothread. */
|
||||||
sigfillset(&set);
|
sigfillset(&set);
|
||||||
@@ -499,6 +493,12 @@ void qemu_thread_create(QemuThread *thread, const char *name,
|
|||||||
qemu_thread_set_name(thread, name);
|
qemu_thread_set_name(thread, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode == QEMU_THREAD_DETACHED) {
|
||||||
|
err = pthread_detach(thread->thread);
|
||||||
|
if (err) {
|
||||||
|
error_exit(err, __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||||
|
|
||||||
pthread_attr_destroy(&attr);
|
pthread_attr_destroy(&attr);
|
||||||
|
|||||||
Reference in new issue
Block a user