Compare commits
87
Commits
v3.1.0-rc2
...
v3.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32a1a94dd3 | ||
|
|
4f818e7b7f | ||
|
|
f2609ffdf3 | ||
|
|
80422b0019 | ||
|
|
118cafff25 | ||
|
|
432a82d727 | ||
|
|
ae4c445c6f | ||
|
|
56512e1dc1 | ||
|
|
25c01bd19d | ||
|
|
933cc4bb34 | ||
|
|
c52d46e041 | ||
|
|
6de02a1323 | ||
|
|
9225cd127d | ||
|
|
3af8c4be90 | ||
|
|
db5e8210ad | ||
|
|
d12ade5732 | ||
|
|
83ea23cd20 | ||
|
|
629457a130 | ||
|
|
c688e6ca7b | ||
|
|
47829c4079 | ||
|
|
e31d802479 | ||
|
|
4750e1a888 | ||
|
|
3f2f3b33db | ||
|
|
ea066d39ac | ||
|
|
c56606684a | ||
|
|
86100290cb | ||
|
|
039d4e3df0 | ||
|
|
549b50a31d | ||
|
|
36ea397956 | ||
|
|
15ffb43cbf | ||
|
|
9681ad3e2b | ||
|
|
e84fcd7f66 | ||
|
|
f1e35acf78 | ||
|
|
d4c7e7e7e0 | ||
|
|
8f1d22d970 | ||
|
|
353c7d58b9 | ||
|
|
03fee66fde | ||
|
|
59ed3fe8d3 | ||
|
|
5aaac46793 | ||
|
|
56333e69ee | ||
|
|
a8efa60633 | ||
|
|
d98f26073b | ||
|
|
2264faa55f | ||
|
|
6da021815e | ||
|
|
330ca111ea | ||
|
|
9e37271f50 | ||
|
|
4822f1ee9e | ||
|
|
d5d31c9a8a | ||
|
|
e1ca8f7e19 | ||
|
|
933d2d4bf2 | ||
|
|
7ec9106759 | ||
|
|
b7ee9e4970 | ||
|
|
d2e550a828 | ||
|
|
30a759b61a | ||
|
|
aec5e9c3a9 | ||
|
|
d522fba244 | ||
|
|
58102ce7fb | ||
|
|
49154ea0bf | ||
|
|
123a069ae6 | ||
|
|
72138f9bf5 | ||
|
|
b05730a876 | ||
|
|
57ac4a7a28 | ||
|
|
1d20398694 | ||
|
|
5298f4d67a | ||
|
|
895e4897e2 | ||
|
|
6bd858b311 | ||
|
|
0065c455f9 | ||
|
|
a237dea330 | ||
|
|
ad3a7e4555 | ||
|
|
71a86ddece | ||
|
|
2067d39e5e | ||
|
|
87ad860c62 | ||
|
|
6bf7463615 | ||
|
|
e4c8f2925d | ||
|
|
2a3d4331fa | ||
|
|
1c7f618f68 | ||
|
|
ebfd6216ec | ||
|
|
59b5e9bbea | ||
|
|
3ecd5a4f19 | ||
|
|
f0998879e0 | ||
|
|
155af09d44 | ||
|
|
7e934f5b27 | ||
|
|
3ebb9c4f52 | ||
|
|
fa1cfb4026 | ||
|
|
d8336c6b28 | ||
|
|
7da9111e77 | ||
|
|
4614f0f8bd |
No files matched your search
+43
@@ -117,6 +117,7 @@ S: Maintained
|
||||
F: cpus.c
|
||||
F: exec.c
|
||||
F: accel/tcg/
|
||||
F: accel/stubs/tcg-stub.c
|
||||
F: include/exec/cpu*.h
|
||||
F: include/exec/exec-all.h
|
||||
F: include/exec/helper*.h
|
||||
@@ -151,6 +152,13 @@ F: disas/arm.c
|
||||
F: disas/arm-a64.cc
|
||||
F: disas/libvixl/
|
||||
|
||||
ARM SMMU
|
||||
M: Eric Auger <eric.auger@redhat.com>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/smmu*
|
||||
F: include/hw/arm/smmu*
|
||||
|
||||
CRIS
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
@@ -311,6 +319,8 @@ F: target/xtensa/
|
||||
F: hw/xtensa/
|
||||
F: tests/tcg/xtensa/
|
||||
F: disas/xtensa.c
|
||||
F: include/hw/xtensa/xtensa-isa.h
|
||||
F: default-configs/xtensa*.mak
|
||||
|
||||
TriCore
|
||||
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
||||
@@ -332,7 +342,10 @@ L: kvm@vger.kernel.org
|
||||
S: Supported
|
||||
F: */kvm.*
|
||||
F: accel/kvm/
|
||||
F: accel/stubs/kvm-stub.c
|
||||
F: include/hw/kvm/
|
||||
F: include/sysemu/kvm*.h
|
||||
F: scripts/kvm/kvm_flightrecorder
|
||||
|
||||
ARM
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
@@ -375,6 +388,7 @@ M: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
L: kvm@vger.kernel.org
|
||||
S: Supported
|
||||
F: target/i386/kvm.c
|
||||
F: scripts/kvm/vmxcap
|
||||
|
||||
Guest CPU Cores (Xen):
|
||||
----------------------
|
||||
@@ -533,6 +547,17 @@ L: qemu-arm@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/arm/gumstix.c
|
||||
|
||||
i.MX25 PDK
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
R: Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/arm/fsl-imx25.c
|
||||
F: hw/arm/imx25_pdk.c
|
||||
F: hw/misc/imx25_ccm.c
|
||||
F: include/hw/arm/fsl-imx25.h
|
||||
F: include/hw/misc/imx25_ccm.h
|
||||
|
||||
i.MX31 (kzm)
|
||||
M: Peter Chubb <peter.chubb@nicta.com.au>
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
@@ -615,6 +640,7 @@ R: Andrew Baumann <Andrew.Baumann@microsoft.com>
|
||||
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/arm/raspi.c
|
||||
F: hw/arm/raspi_platform.h
|
||||
F: hw/*/bcm283*
|
||||
F: include/hw/arm/raspi*
|
||||
@@ -639,8 +665,12 @@ F: hw/arm/spitz.c
|
||||
F: hw/arm/tosa.c
|
||||
F: hw/arm/z2.c
|
||||
F: hw/*/pxa2xx*
|
||||
F: hw/display/tc6393xb.c
|
||||
F: hw/gpio/max7310.c
|
||||
F: hw/gpio/zaurus.c
|
||||
F: hw/misc/mst_fpga.c
|
||||
F: include/hw/arm/pxa.h
|
||||
F: include/hw/arm/sharpsl.h
|
||||
|
||||
SABRELITE / i.MX6
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
@@ -1534,6 +1564,19 @@ F: hw/display/edid*
|
||||
F: include/hw/display/edid.h
|
||||
F: qemu-edid.c
|
||||
|
||||
Firmware configuration (fw_cfg)
|
||||
M: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
R: Laszlo Ersek <lersek@redhat.com>
|
||||
R: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Supported
|
||||
F: docs/specs/fw_cfg.txt
|
||||
F: hw/nvram/fw_cfg.c
|
||||
F: include/hw/nvram/fw_cfg.h
|
||||
F: include/standard-headers/linux/qemu_fw_cfg.h
|
||||
F: tests/libqos/fw_cfg.c
|
||||
F: tests/fw_cfg-test.c
|
||||
T: git https://github.com/philmd/qemu.git fw_cfg-next
|
||||
|
||||
Subsystems
|
||||
----------
|
||||
Audio
|
||||
|
||||
+12
-12
@@ -42,6 +42,9 @@ static void
|
||||
file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
{
|
||||
HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
|
||||
#ifdef CONFIG_POSIX
|
||||
gchar *path;
|
||||
#endif
|
||||
|
||||
if (!backend->size) {
|
||||
error_setg(errp, "can't create backend with size 0");
|
||||
@@ -54,18 +57,15 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
#ifndef CONFIG_POSIX
|
||||
error_setg(errp, "-mem-path not supported on this host");
|
||||
#else
|
||||
if (!host_memory_backend_mr_inited(backend)) {
|
||||
gchar *path;
|
||||
backend->force_prealloc = mem_prealloc;
|
||||
path = object_get_canonical_path(OBJECT(backend));
|
||||
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
|
||||
path,
|
||||
backend->size, fb->align,
|
||||
(backend->share ? RAM_SHARED : 0) |
|
||||
(fb->is_pmem ? RAM_PMEM : 0),
|
||||
fb->mem_path, errp);
|
||||
g_free(path);
|
||||
}
|
||||
backend->force_prealloc = mem_prealloc;
|
||||
path = object_get_canonical_path(OBJECT(backend));
|
||||
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
|
||||
path,
|
||||
backend->size, fb->align,
|
||||
(backend->share ? RAM_SHARED : 0) |
|
||||
(fb->is_pmem ? RAM_PMEM : 0),
|
||||
fb->mem_path, errp);
|
||||
g_free(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -44,10 +44,6 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (host_memory_backend_mr_inited(backend)) {
|
||||
return;
|
||||
}
|
||||
|
||||
backend->force_prealloc = mem_prealloc;
|
||||
fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
|
||||
m->hugetlb, m->hugetlbsize, m->seal ?
|
||||
@@ -59,7 +55,8 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
|
||||
name = object_get_canonical_path(OBJECT(backend));
|
||||
memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
|
||||
name, backend->size, true, fd, errp);
|
||||
name, backend->size,
|
||||
backend->share, fd, errp);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
@@ -131,6 +128,7 @@ memfd_backend_instance_init(Object *obj)
|
||||
|
||||
/* default to sealed file */
|
||||
m->seal = true;
|
||||
MEMORY_BACKEND(m)->share = true;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -1137,7 +1137,7 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||
|
||||
static void update_flags_from_options(int *flags, QemuOpts *opts)
|
||||
{
|
||||
*flags &= ~BDRV_O_CACHE_MASK;
|
||||
*flags &= ~(BDRV_O_CACHE_MASK | BDRV_O_RDWR | BDRV_O_AUTO_RDONLY);
|
||||
|
||||
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
|
||||
if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
|
||||
@@ -1149,8 +1149,6 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
|
||||
*flags |= BDRV_O_NOCACHE;
|
||||
}
|
||||
|
||||
*flags &= ~BDRV_O_RDWR;
|
||||
|
||||
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
|
||||
if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
|
||||
*flags |= BDRV_O_RDWR;
|
||||
@@ -2262,6 +2260,18 @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if you can reach parent going through child->inherits_from
|
||||
* recursively. If parent or child are NULL, return false */
|
||||
static bool bdrv_inherits_from_recursive(BlockDriverState *child,
|
||||
BlockDriverState *parent)
|
||||
{
|
||||
while (child && child != parent) {
|
||||
child = child->inherits_from;
|
||||
}
|
||||
|
||||
return child != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the backing file link of a BDS. A new reference is created; callers
|
||||
* which don't need their own reference any more must call bdrv_unref().
|
||||
@@ -2269,6 +2279,9 @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
|
||||
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
Error **errp)
|
||||
{
|
||||
bool update_inherits_from = bdrv_chain_contains(bs, backing_hd) &&
|
||||
bdrv_inherits_from_recursive(backing_hd, bs);
|
||||
|
||||
if (backing_hd) {
|
||||
bdrv_ref(backing_hd);
|
||||
}
|
||||
@@ -2284,6 +2297,12 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
|
||||
bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
|
||||
errp);
|
||||
/* If backing_hd was already part of bs's backing chain, and
|
||||
* inherits_from pointed recursively to bs then let's update it to
|
||||
* point directly to bs (else it will become NULL). */
|
||||
if (update_inherits_from) {
|
||||
backing_hd->inherits_from = bs;
|
||||
}
|
||||
if (!bs->backing) {
|
||||
bdrv_unref(backing_hd);
|
||||
}
|
||||
@@ -3836,6 +3855,8 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs)
|
||||
int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||
const char *backing_file_str)
|
||||
{
|
||||
BlockDriverState *explicit_top = top;
|
||||
bool update_inherits_from;
|
||||
BdrvChild *c, *next;
|
||||
Error *local_err = NULL;
|
||||
int ret = -EIO;
|
||||
@@ -3851,6 +3872,16 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* If 'base' recursively inherits from 'top' then we should set
|
||||
* base->inherits_from to top->inherits_from after 'top' and all
|
||||
* other intermediate nodes have been dropped.
|
||||
* If 'top' is an implicit node (e.g. "commit_top") we should skip
|
||||
* it because no one inherits from it. We use explicit_top for that. */
|
||||
while (explicit_top && explicit_top->implicit) {
|
||||
explicit_top = backing_bs(explicit_top);
|
||||
}
|
||||
update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
|
||||
|
||||
/* success - we can delete the intermediate states, and link top->base */
|
||||
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
|
||||
* we've figured out how they should work. */
|
||||
@@ -3886,6 +3917,10 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||
bdrv_unref(top);
|
||||
}
|
||||
|
||||
if (update_inherits_from) {
|
||||
base->inherits_from = explicit_top->inherits_from;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
exit:
|
||||
bdrv_unref(top);
|
||||
@@ -4577,45 +4612,68 @@ void bdrv_invalidate_cache_all(Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static int bdrv_inactivate_recurse(BlockDriverState *bs,
|
||||
bool setting_flag)
|
||||
static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
|
||||
{
|
||||
BdrvChild *parent;
|
||||
|
||||
QLIST_FOREACH(parent, &bs->parents, next_parent) {
|
||||
if (parent->role->parent_is_bds) {
|
||||
BlockDriverState *parent_bs = parent->opaque;
|
||||
if (!only_active || !(parent_bs->open_flags & BDRV_O_INACTIVE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int bdrv_inactivate_recurse(BlockDriverState *bs)
|
||||
{
|
||||
BdrvChild *child, *parent;
|
||||
uint64_t perm, shared_perm;
|
||||
int ret;
|
||||
|
||||
if (!bs->drv) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
if (!setting_flag && bs->drv->bdrv_inactivate) {
|
||||
/* Make sure that we don't inactivate a child before its parent.
|
||||
* It will be covered by recursion from the yet active parent. */
|
||||
if (bdrv_has_bds_parent(bs, true)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(!(bs->open_flags & BDRV_O_INACTIVE));
|
||||
|
||||
/* Inactivate this node */
|
||||
if (bs->drv->bdrv_inactivate) {
|
||||
ret = bs->drv->bdrv_inactivate(bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (setting_flag && !(bs->open_flags & BDRV_O_INACTIVE)) {
|
||||
uint64_t perm, shared_perm;
|
||||
|
||||
QLIST_FOREACH(parent, &bs->parents, next_parent) {
|
||||
if (parent->role->inactivate) {
|
||||
ret = parent->role->inactivate(parent);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
QLIST_FOREACH(parent, &bs->parents, next_parent) {
|
||||
if (parent->role->inactivate) {
|
||||
ret = parent->role->inactivate(parent);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bs->open_flags |= BDRV_O_INACTIVE;
|
||||
|
||||
/* Update permissions, they may differ for inactive nodes */
|
||||
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
|
||||
bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &error_abort);
|
||||
bdrv_set_perm(bs, perm, shared_perm);
|
||||
}
|
||||
|
||||
bs->open_flags |= BDRV_O_INACTIVE;
|
||||
|
||||
/* Update permissions, they may differ for inactive nodes */
|
||||
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
|
||||
bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &error_abort);
|
||||
bdrv_set_perm(bs, perm, shared_perm);
|
||||
|
||||
|
||||
/* Recursively inactivate children */
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
ret = bdrv_inactivate_recurse(child->bs, setting_flag);
|
||||
ret = bdrv_inactivate_recurse(child->bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -4629,7 +4687,6 @@ int bdrv_inactivate_all(void)
|
||||
BlockDriverState *bs = NULL;
|
||||
BdrvNextIterator it;
|
||||
int ret = 0;
|
||||
int pass;
|
||||
GSList *aio_ctxs = NULL, *ctx;
|
||||
|
||||
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
@@ -4641,17 +4698,17 @@ int bdrv_inactivate_all(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* We do two passes of inactivation. The first pass calls to drivers'
|
||||
* .bdrv_inactivate callbacks recursively so all cache is flushed to disk;
|
||||
* the second pass sets the BDRV_O_INACTIVE flag so that no further write
|
||||
* is allowed. */
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
ret = bdrv_inactivate_recurse(bs, pass);
|
||||
if (ret < 0) {
|
||||
bdrv_next_cleanup(&it);
|
||||
goto out;
|
||||
}
|
||||
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
/* Nodes with BDS parents are covered by recursion from the last
|
||||
* parent that gets inactivated. Don't inactivate them a second
|
||||
* time if that has already happened. */
|
||||
if (bdrv_has_bds_parent(bs, false)) {
|
||||
continue;
|
||||
}
|
||||
ret = bdrv_inactivate_recurse(bs);
|
||||
if (ret < 0) {
|
||||
bdrv_next_cleanup(&it);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-8
@@ -199,7 +199,6 @@ static void coroutine_fn mirror_write_complete(MirrorOp *op, int ret)
|
||||
{
|
||||
MirrorBlockJob *s = op->s;
|
||||
|
||||
aio_context_acquire(blk_get_aio_context(s->common.blk));
|
||||
if (ret < 0) {
|
||||
BlockErrorAction action;
|
||||
|
||||
@@ -209,15 +208,14 @@ static void coroutine_fn mirror_write_complete(MirrorOp *op, int ret)
|
||||
s->ret = ret;
|
||||
}
|
||||
}
|
||||
|
||||
mirror_iteration_done(op, ret);
|
||||
aio_context_release(blk_get_aio_context(s->common.blk));
|
||||
}
|
||||
|
||||
static void coroutine_fn mirror_read_complete(MirrorOp *op, int ret)
|
||||
{
|
||||
MirrorBlockJob *s = op->s;
|
||||
|
||||
aio_context_acquire(blk_get_aio_context(s->common.blk));
|
||||
if (ret < 0) {
|
||||
BlockErrorAction action;
|
||||
|
||||
@@ -228,12 +226,11 @@ static void coroutine_fn mirror_read_complete(MirrorOp *op, int ret)
|
||||
}
|
||||
|
||||
mirror_iteration_done(op, ret);
|
||||
} else {
|
||||
ret = blk_co_pwritev(s->target, op->offset,
|
||||
op->qiov.size, &op->qiov, 0);
|
||||
mirror_write_complete(op, ret);
|
||||
return;
|
||||
}
|
||||
aio_context_release(blk_get_aio_context(s->common.blk));
|
||||
|
||||
ret = blk_co_pwritev(s->target, op->offset, op->qiov.size, &op->qiov, 0);
|
||||
mirror_write_complete(op, ret);
|
||||
}
|
||||
|
||||
/* Clip bytes relative to offset to not exceed end-of-file */
|
||||
|
||||
+20
-1
@@ -992,10 +992,16 @@ int nbd_client_init(BlockDriverState *bs,
|
||||
logout("Failed to negotiate with the NBD server\n");
|
||||
return ret;
|
||||
}
|
||||
if (x_dirty_bitmap && !client->info.base_allocation) {
|
||||
error_setg(errp, "requested x-dirty-bitmap %s not found",
|
||||
x_dirty_bitmap);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
if (client->info.flags & NBD_FLAG_READ_ONLY) {
|
||||
ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (client->info.flags & NBD_FLAG_SEND_FUA) {
|
||||
@@ -1024,4 +1030,17 @@ int nbd_client_init(BlockDriverState *bs,
|
||||
|
||||
logout("Established connection with NBD server\n");
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/*
|
||||
* We have connected, but must fail for other reasons. The
|
||||
* connection is still blocking; send NBD_CMD_DISC as a courtesy
|
||||
* to the server.
|
||||
*/
|
||||
{
|
||||
NBDRequest request = { .type = NBD_CMD_DISC };
|
||||
|
||||
nbd_send_request(client->ioc ?: QIO_CHANNEL(sioc), &request);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1220,16 +1220,20 @@ static void qemu_wait_io_event_common(CPUState *cpu)
|
||||
process_queued_cpu_work(cpu);
|
||||
}
|
||||
|
||||
static void qemu_tcg_rr_wait_io_event(CPUState *cpu)
|
||||
static void qemu_tcg_rr_wait_io_event(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
while (all_cpu_threads_idle()) {
|
||||
stop_tcg_kick_timer();
|
||||
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
||||
qemu_cond_wait(first_cpu->halt_cond, &qemu_global_mutex);
|
||||
}
|
||||
|
||||
start_tcg_kick_timer();
|
||||
|
||||
qemu_wait_io_event_common(cpu);
|
||||
CPU_FOREACH(cpu) {
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_wait_io_event(CPUState *cpu)
|
||||
@@ -1562,7 +1566,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
|
||||
qemu_notify_event();
|
||||
}
|
||||
|
||||
qemu_tcg_rr_wait_io_event(cpu ? cpu : first_cpu);
|
||||
qemu_tcg_rr_wait_io_event();
|
||||
deal_with_unplugged_cpus();
|
||||
}
|
||||
|
||||
|
||||
@@ -2855,6 +2855,7 @@ static void coroutine_fn v9fs_wstat(void *opaque)
|
||||
struct stat stbuf;
|
||||
V9fsFidState *fidp;
|
||||
V9fsPDU *pdu = opaque;
|
||||
V9fsState *s = pdu->s;
|
||||
|
||||
v9fs_stat_init(&v9stat);
|
||||
err = pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
|
||||
@@ -2920,7 +2921,9 @@ static void coroutine_fn v9fs_wstat(void *opaque)
|
||||
}
|
||||
}
|
||||
if (v9stat.name.size != 0) {
|
||||
v9fs_path_write_lock(s);
|
||||
err = v9fs_complete_rename(pdu, fidp, -1, &v9stat.name);
|
||||
v9fs_path_unlock(s);
|
||||
if (err < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
+2
-2
@@ -29,11 +29,11 @@ static struct arm_boot_info aspeed_board_binfo = {
|
||||
.nb_cpus = 1,
|
||||
};
|
||||
|
||||
typedef struct AspeedBoardState {
|
||||
struct AspeedBoardState {
|
||||
AspeedSoCState soc;
|
||||
MemoryRegion ram;
|
||||
MemoryRegion max_ram;
|
||||
} AspeedBoardState;
|
||||
};
|
||||
|
||||
/* Palmetto hardware value: 0x120CE416 */
|
||||
#define PALMETTO_BMC_HW_STRAP1 ( \
|
||||
|
||||
@@ -174,6 +174,7 @@ static const char *valid_cpus[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-a15"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a53"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a57"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a72"),
|
||||
ARM_CPU_TYPE_NAME("host"),
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
|
||||
+2
-2
@@ -72,8 +72,8 @@ typedef struct fm_opl_f {
|
||||
/* Rhythm sention */
|
||||
uint8_t rhythm; /* Rhythm mode , key flag */
|
||||
/* time tables */
|
||||
int32_t AR_TABLE[75]; /* atttack rate tables */
|
||||
int32_t DR_TABLE[75]; /* decay rate tables */
|
||||
int32_t AR_TABLE[76]; /* attack rate tables */
|
||||
int32_t DR_TABLE[76]; /* decay rate tables */
|
||||
uint32_t FN_TABLE[1024]; /* fnumber -> increment counter */
|
||||
/* LFO */
|
||||
int32_t *ams_table;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/audio/soundhw.h"
|
||||
#include "intel-hda.h"
|
||||
#include "intel-hda-defs.h"
|
||||
@@ -929,6 +930,11 @@ static void intel_hda_reg_write(IntelHDAState *d, const IntelHDAReg *reg, uint32
|
||||
if (!reg) {
|
||||
return;
|
||||
}
|
||||
if (!reg->wmask) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "intel-hda: write to r/o reg %s\n",
|
||||
reg->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->debug) {
|
||||
time_t now = time(NULL);
|
||||
|
||||
+9
-14
@@ -272,7 +272,9 @@ static void nvme_post_cqes(void *opaque)
|
||||
sizeof(req->cqe));
|
||||
QTAILQ_INSERT_TAIL(&sq->req_list, req, entry);
|
||||
}
|
||||
nvme_irq_assert(n, cq);
|
||||
if (cq->tail != cq->head) {
|
||||
nvme_irq_assert(n, cq);
|
||||
}
|
||||
}
|
||||
|
||||
static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req)
|
||||
@@ -554,6 +556,7 @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeCmd *cmd)
|
||||
trace_nvme_err_invalid_del_cq_notempty(qid);
|
||||
return NVME_INVALID_QUEUE_DEL;
|
||||
}
|
||||
nvme_irq_deassert(n, cq);
|
||||
trace_nvme_del_cq(qid);
|
||||
nvme_free_cq(cq, n);
|
||||
return NVME_SUCCESS;
|
||||
@@ -797,6 +800,8 @@ static void nvme_clear_ctrl(NvmeCtrl *n)
|
||||
{
|
||||
int i;
|
||||
|
||||
blk_drain(n->conf.blk);
|
||||
|
||||
for (i = 0; i < n->num_queues; i++) {
|
||||
if (n->sq[i] != NULL) {
|
||||
nvme_free_sq(n->sq[i], n);
|
||||
@@ -1175,23 +1180,13 @@ static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned size)
|
||||
{
|
||||
NvmeCtrl *n = (NvmeCtrl *)opaque;
|
||||
|
||||
if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) {
|
||||
return;
|
||||
}
|
||||
memcpy(&n->cmbuf[addr], &data, size);
|
||||
stn_le_p(&n->cmbuf[addr], size, data);
|
||||
}
|
||||
|
||||
static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
uint64_t val;
|
||||
NvmeCtrl *n = (NvmeCtrl *)opaque;
|
||||
|
||||
if (addr + size > NVME_CMBSZ_GETSIZE(n->bar.cmbsz)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(&val, &n->cmbuf[addr], size);
|
||||
return val;
|
||||
return ldn_le_p(&n->cmbuf[addr], size);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps nvme_cmb_ops = {
|
||||
@@ -1199,7 +1194,7 @@ static const MemoryRegionOps nvme_cmb_ops = {
|
||||
.write = nvme_cmb_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.impl = {
|
||||
.min_access_size = 2,
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2746,11 +2746,12 @@ static int cirrus_post_load(void *opaque, int version_id)
|
||||
s->vga.gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
|
||||
s->vga.gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
|
||||
|
||||
cirrus_update_bank_ptr(s, 0);
|
||||
cirrus_update_bank_ptr(s, 1);
|
||||
cirrus_update_memory_access(s);
|
||||
/* force refresh */
|
||||
s->vga.graphic_mode = -1;
|
||||
cirrus_update_bank_ptr(s, 0);
|
||||
cirrus_update_bank_ptr(s, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1073,7 +1073,7 @@ static const VMStateDescription vmstate_virtio_gpu_scanouts = {
|
||||
};
|
||||
|
||||
static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
VirtIOGPU *g = opaque;
|
||||
struct virtio_gpu_simple_resource *res;
|
||||
@@ -1101,7 +1101,7 @@ static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size,
|
||||
}
|
||||
|
||||
static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
VirtIOGPU *g = opaque;
|
||||
struct virtio_gpu_simple_resource *res;
|
||||
|
||||
+5
-1
@@ -136,7 +136,11 @@ void hyperv_synic_add(CPUState *cs)
|
||||
|
||||
void hyperv_synic_reset(CPUState *cs)
|
||||
{
|
||||
device_reset(DEVICE(get_synic(cs)));
|
||||
SynICState *synic = get_synic(cs);
|
||||
|
||||
if (synic) {
|
||||
device_reset(DEVICE(synic));
|
||||
}
|
||||
}
|
||||
|
||||
static const TypeInfo synic_type_info = {
|
||||
|
||||
@@ -240,6 +240,9 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
|
||||
uint8_t read = s->smb_addr & 0x01;
|
||||
|
||||
s->smb_index++;
|
||||
if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
|
||||
s->smb_index = 0;
|
||||
}
|
||||
if (!read && s->smb_index == s->smb_data0) {
|
||||
uint8_t prot = (s->smb_ctl >> 2) & 0x07;
|
||||
uint8_t cmd = s->smb_cmd;
|
||||
|
||||
+5
-1
@@ -193,7 +193,11 @@ static int smbus_i2c_send(I2CSlave *s, uint8_t data)
|
||||
switch (dev->mode) {
|
||||
case SMBUS_WRITE_DATA:
|
||||
DPRINTF("Write data %02x\n", data);
|
||||
dev->data_buf[dev->data_len++] = data;
|
||||
if (dev->data_len >= sizeof(dev->data_buf)) {
|
||||
BADF("Too many bytes sent\n");
|
||||
} else {
|
||||
dev->data_buf[dev->data_len++] = data;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BADF("Unexpected write in state %d\n", dev->mode);
|
||||
|
||||
+1
-1
@@ -942,7 +942,7 @@ static void ps2_kbd_reset(void *opaque)
|
||||
|
||||
trace_ps2_kbd_reset(opaque);
|
||||
ps2_common_reset(&s->common);
|
||||
s->scan_enabled = 0;
|
||||
s->scan_enabled = 1;
|
||||
s->translate = 0;
|
||||
s->scancode_set = 2;
|
||||
s->modifiers = 0;
|
||||
|
||||
@@ -376,7 +376,7 @@ static void kvm_s390_release_adapter_routes(S390FLICState *fs,
|
||||
* reached
|
||||
*/
|
||||
static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
KVMS390FLICState *flic = opaque;
|
||||
int len = FLIC_SAVE_INITIAL_SIZE;
|
||||
@@ -426,7 +426,7 @@ static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
|
||||
* in QEMUFile
|
||||
*/
|
||||
static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint64_t len = 0;
|
||||
uint64_t count = 0;
|
||||
|
||||
@@ -979,7 +979,6 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
|
||||
|
||||
/* Do nothing if receive is not enabled. */
|
||||
if (!gem_can_receive(nc)) {
|
||||
assert(!first_desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,15 +95,15 @@ struct _eeprom_t {
|
||||
*/
|
||||
|
||||
static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint16_t *v = pv;
|
||||
*v = qemu_get_ubyte(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_unused(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n");
|
||||
fprintf(stderr, "Never should be used to write a new state.\n");
|
||||
|
||||
+3
-3
@@ -520,15 +520,15 @@ static void fw_cfg_reset(DeviceState *d)
|
||||
*/
|
||||
|
||||
static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint32_t *v = pv;
|
||||
*v = qemu_get_be16(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_unused(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
|
||||
fprintf(stderr, "This functions shouldn't be called.\n");
|
||||
|
||||
+2
-2
@@ -625,7 +625,7 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
|
||||
}
|
||||
|
||||
static int put_msix_state(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
msix_save(pv, f);
|
||||
|
||||
@@ -633,7 +633,7 @@ static int put_msix_state(QEMUFile *f, void *pv, size_t size,
|
||||
}
|
||||
|
||||
static int get_msix_state(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
msix_load(pv, f);
|
||||
return 0;
|
||||
|
||||
+4
-4
@@ -450,7 +450,7 @@ int pci_bus_numa_node(PCIBus *bus)
|
||||
}
|
||||
|
||||
static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
PCIDevice *s = container_of(pv, PCIDevice, config);
|
||||
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s);
|
||||
@@ -490,7 +490,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
|
||||
|
||||
/* just put buffer */
|
||||
static int put_pci_config_device(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
const uint8_t **v = pv;
|
||||
assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
|
||||
@@ -506,7 +506,7 @@ static VMStateInfo vmstate_info_pci_config = {
|
||||
};
|
||||
|
||||
static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
PCIDevice *s = container_of(pv, PCIDevice, irq_state);
|
||||
uint32_t irq_state[PCI_NUM_PINS];
|
||||
@@ -528,7 +528,7 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size,
|
||||
}
|
||||
|
||||
static int put_pci_irq_state(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
int i;
|
||||
PCIDevice *s = container_of(pv, PCIDevice, irq_state);
|
||||
|
||||
+4
-3
@@ -688,8 +688,8 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
|
||||
shpc_cap_update_dword(d);
|
||||
}
|
||||
|
||||
static int shpc_save(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int shpc_save(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
PCIDevice *d = container_of(pv, PCIDevice, shpc);
|
||||
qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
|
||||
@@ -697,7 +697,8 @@ static int shpc_save(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shpc_load(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int shpc_load(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
PCIDevice *d = container_of(pv, PCIDevice, shpc);
|
||||
int ret = qemu_get_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
|
||||
|
||||
+36
-12
@@ -298,6 +298,18 @@ static inline int lsi_irq_on_rsl(LSIState *s)
|
||||
return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE);
|
||||
}
|
||||
|
||||
static lsi_request *get_pending_req(LSIState *s)
|
||||
{
|
||||
lsi_request *p;
|
||||
|
||||
QTAILQ_FOREACH(p, &s->queue, next) {
|
||||
if (p->pending) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void lsi_soft_reset(LSIState *s)
|
||||
{
|
||||
trace_lsi_reset();
|
||||
@@ -446,7 +458,6 @@ static void lsi_update_irq(LSIState *s)
|
||||
{
|
||||
int level;
|
||||
static int last_level;
|
||||
lsi_request *p;
|
||||
|
||||
/* It's unclear whether the DIP/SIP bits should be cleared when the
|
||||
Interrupt Status Registers are cleared or when istat0 is read.
|
||||
@@ -476,13 +487,13 @@ static void lsi_update_irq(LSIState *s)
|
||||
}
|
||||
lsi_set_irq(s, level);
|
||||
|
||||
if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
|
||||
if (!s->current && !level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
|
||||
lsi_request *p;
|
||||
|
||||
trace_lsi_update_irq_disconnected();
|
||||
QTAILQ_FOREACH(p, &s->queue, next) {
|
||||
if (p->pending) {
|
||||
lsi_reselect(s, p);
|
||||
break;
|
||||
}
|
||||
p = get_pending_req(s);
|
||||
if (p) {
|
||||
lsi_reselect(s, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1065,11 +1076,12 @@ static void lsi_wait_reselect(LSIState *s)
|
||||
|
||||
trace_lsi_wait_reselect();
|
||||
|
||||
QTAILQ_FOREACH(p, &s->queue, next) {
|
||||
if (p->pending) {
|
||||
lsi_reselect(s, p);
|
||||
break;
|
||||
}
|
||||
if (s->current) {
|
||||
return;
|
||||
}
|
||||
p = get_pending_req(s);
|
||||
if (p) {
|
||||
lsi_reselect(s, p);
|
||||
}
|
||||
if (s->current == NULL) {
|
||||
s->waiting = 1;
|
||||
@@ -1259,6 +1271,18 @@ again:
|
||||
case 1: /* Disconnect */
|
||||
trace_lsi_execute_script_io_disconnect();
|
||||
s->scntl1 &= ~LSI_SCNTL1_CON;
|
||||
/* FIXME: this is not entirely correct; the target need not ask
|
||||
* for reselection until it has to send data, while here we force a
|
||||
* reselection as soon as the bus is free. The correct flow would
|
||||
* reselect before lsi_transfer_data and disconnect as soon as
|
||||
* DMA ends.
|
||||
*/
|
||||
if (!s->current) {
|
||||
lsi_request *p = get_pending_req(s);
|
||||
if (p) {
|
||||
lsi_reselect(s, p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: /* Wait Reselect */
|
||||
if (!lsi_irq_on_rsl(s)) {
|
||||
|
||||
+2
-2
@@ -1571,7 +1571,7 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
|
||||
/* SCSI request list. For simplicity, pv points to the whole device */
|
||||
|
||||
static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
SCSIDevice *s = pv;
|
||||
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
|
||||
@@ -1599,7 +1599,7 @@ static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
|
||||
}
|
||||
|
||||
static int get_scsi_requests(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
SCSIDevice *s = pv;
|
||||
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
|
||||
|
||||
+1
-1
@@ -482,7 +482,7 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||||
if (action == BLOCK_ERROR_ACTION_STOP) {
|
||||
scsi_req_retry(&r->req);
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void scsi_write_complete_noio(SCSIDiskReq *r, int ret)
|
||||
|
||||
+2
-2
@@ -750,7 +750,7 @@ static int menelaus_rx(I2CSlave *i2c)
|
||||
*/
|
||||
|
||||
static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
int *v = pv;
|
||||
*v = qemu_get_be16(f);
|
||||
@@ -758,7 +758,7 @@ static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
|
||||
}
|
||||
|
||||
static int put_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
int *v = pv;
|
||||
qemu_put_be16(f, *v);
|
||||
|
||||
+18
-6
@@ -1593,17 +1593,23 @@ static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)
|
||||
fprintf(stderr, "%s\n", __func__);
|
||||
}
|
||||
|
||||
static void utf16_to_str(uint8_t len, uint16_t *arr, char *name)
|
||||
static char *utf16_to_str(uint8_t len, uint16_t *arr)
|
||||
{
|
||||
int count;
|
||||
wchar_t *wstr = g_new0(wchar_t, len);
|
||||
wchar_t *wstr = g_new0(wchar_t, len + 1);
|
||||
int count, dlen;
|
||||
char *dest;
|
||||
|
||||
for (count = 0; count < len; count++) {
|
||||
/* FIXME: not working for surrogate pairs */
|
||||
wstr[count] = (wchar_t)arr[count];
|
||||
}
|
||||
wstr[count] = 0;
|
||||
|
||||
wcstombs(name, wstr, len);
|
||||
dlen = wcstombs(NULL, wstr, 0) + 1;
|
||||
dest = g_malloc(dlen);
|
||||
wcstombs(dest, wstr, dlen);
|
||||
g_free(wstr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Wrapper around write, returns 0 on failure */
|
||||
@@ -1703,7 +1709,7 @@ static void usb_mtp_write_metadata(MTPState *s)
|
||||
{
|
||||
MTPData *d = s->data_out;
|
||||
ObjectInfo *dataset = (ObjectInfo *)d->data;
|
||||
char *filename = g_new0(char, dataset->length);
|
||||
char *filename;
|
||||
MTPObject *o;
|
||||
MTPObject *p = usb_mtp_object_lookup(s, s->dataset.parent_handle);
|
||||
uint32_t next_handle = s->next_handle;
|
||||
@@ -1711,7 +1717,13 @@ static void usb_mtp_write_metadata(MTPState *s)
|
||||
assert(!s->write_pending);
|
||||
assert(p != NULL);
|
||||
|
||||
utf16_to_str(dataset->length, dataset->filename, filename);
|
||||
filename = utf16_to_str(dataset->length, dataset->filename);
|
||||
|
||||
if (strchr(filename, '/')) {
|
||||
usb_mtp_queue_result(s, RES_PARAMETER_NOT_SUPPORTED, d->trans,
|
||||
0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
o = usb_mtp_object_lookup_name(p, filename, dataset->length);
|
||||
if (o != NULL) {
|
||||
|
||||
@@ -1120,6 +1120,9 @@ static void usb_host_detach_kernel(USBHostDevice *s)
|
||||
rc = libusb_kernel_driver_active(s->dh, i);
|
||||
usb_host_libusb_error("libusb_kernel_driver_active", rc);
|
||||
if (rc != 1) {
|
||||
if (rc == 0) {
|
||||
s->ifs[i].detached = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
trace_usb_host_detach_kernel(s->bus_num, s->addr, i);
|
||||
|
||||
+6
-6
@@ -2155,7 +2155,7 @@ static int usbredir_post_load(void *priv, int version_id)
|
||||
|
||||
/* For usbredirparser migration */
|
||||
static int usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
uint8_t *data;
|
||||
@@ -2178,7 +2178,7 @@ static int usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
|
||||
}
|
||||
|
||||
static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
uint8_t *data;
|
||||
@@ -2222,7 +2222,7 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
|
||||
|
||||
/* For buffered packets (iso/irq) queue migration */
|
||||
static int usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
struct endp_data *endp = priv;
|
||||
USBRedirDevice *dev = endp->dev;
|
||||
@@ -2245,7 +2245,7 @@ static int usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
|
||||
}
|
||||
|
||||
static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
struct endp_data *endp = priv;
|
||||
USBRedirDevice *dev = endp->dev;
|
||||
@@ -2349,7 +2349,7 @@ static const VMStateDescription usbredir_ep_vmstate = {
|
||||
|
||||
/* For PacketIdQueue migration */
|
||||
static int usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
struct PacketIdQueue *q = priv;
|
||||
USBRedirDevice *dev = q->dev;
|
||||
@@ -2368,7 +2368,7 @@ static int usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
|
||||
}
|
||||
|
||||
static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
struct PacketIdQueue *q = priv;
|
||||
USBRedirDevice *dev = q->dev;
|
||||
|
||||
+4
-4
@@ -1816,7 +1816,7 @@ static const VMStateDescription vmstate_virtio_ringsize = {
|
||||
};
|
||||
|
||||
static int get_extra_state(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
VirtIODevice *vdev = pv;
|
||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||
@@ -1830,7 +1830,7 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size,
|
||||
}
|
||||
|
||||
static int put_extra_state(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
VirtIODevice *vdev = pv;
|
||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||
@@ -1979,14 +1979,14 @@ int virtio_save(VirtIODevice *vdev, QEMUFile *f)
|
||||
|
||||
/* A wrapper for use as a VMState .put function */
|
||||
static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
return virtio_save(VIRTIO_DEVICE(opaque), f);
|
||||
}
|
||||
|
||||
/* A wrapper for use as a VMState .get function */
|
||||
static int virtio_device_get(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
|
||||
DeviceClass *dc = DEVICE_CLASS(VIRTIO_DEVICE_GET_CLASS(vdev));
|
||||
|
||||
@@ -446,6 +446,8 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
#define XTFPGA_MMU_RESERVED_MEMORY_SIZE (128 * MiB)
|
||||
|
||||
static const hwaddr xtfpga_mmu_io[2] = {
|
||||
0xf0000000,
|
||||
};
|
||||
@@ -568,6 +570,7 @@ static void xtfpga_lx60_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_lx60_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
|
||||
mc->default_ram_size = 64 * MiB;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_lx60_type = {
|
||||
@@ -584,6 +587,7 @@ static void xtfpga_lx60_nommu_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_lx60_nommu_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
|
||||
mc->default_ram_size = 64 * MiB;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_lx60_nommu_type = {
|
||||
@@ -600,6 +604,7 @@ static void xtfpga_lx200_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_lx200_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
|
||||
mc->default_ram_size = 96 * MiB;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_lx200_type = {
|
||||
@@ -616,6 +621,7 @@ static void xtfpga_lx200_nommu_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_lx200_nommu_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
|
||||
mc->default_ram_size = 96 * MiB;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_lx200_nommu_type = {
|
||||
@@ -632,6 +638,7 @@ static void xtfpga_ml605_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_ml605_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
|
||||
mc->default_ram_size = 512 * MiB - XTFPGA_MMU_RESERVED_MEMORY_SIZE;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_ml605_type = {
|
||||
@@ -648,6 +655,7 @@ static void xtfpga_ml605_nommu_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_ml605_nommu_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
|
||||
mc->default_ram_size = 256 * MiB;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_ml605_nommu_type = {
|
||||
@@ -664,6 +672,7 @@ static void xtfpga_kc705_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_kc705_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
|
||||
mc->default_ram_size = 1 * GiB - XTFPGA_MMU_RESERVED_MEMORY_SIZE;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_kc705_type = {
|
||||
@@ -680,6 +689,7 @@ static void xtfpga_kc705_nommu_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = xtfpga_kc705_nommu_init;
|
||||
mc->max_cpus = 4;
|
||||
mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
|
||||
mc->default_ram_size = 256 * MiB;
|
||||
}
|
||||
|
||||
static const TypeInfo xtfpga_kc705_nommu_type = {
|
||||
|
||||
@@ -40,8 +40,8 @@ typedef struct VMStateField VMStateField;
|
||||
*/
|
||||
struct VMStateInfo {
|
||||
const char *name;
|
||||
int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field);
|
||||
int (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
int (*get)(QEMUFile *f, void *pv, size_t size, const VMStateField *field);
|
||||
int (*put)(QEMUFile *f, void *pv, size_t size, const VMStateField *field,
|
||||
QJSON *vmdesc);
|
||||
};
|
||||
|
||||
@@ -186,7 +186,7 @@ struct VMStateDescription {
|
||||
int (*post_load)(void *opaque, int version_id);
|
||||
int (*pre_save)(void *opaque);
|
||||
bool (*needed)(void *opaque);
|
||||
VMStateField *fields;
|
||||
const VMStateField *fields;
|
||||
const VMStateDescription **subsections;
|
||||
};
|
||||
|
||||
|
||||
@@ -169,12 +169,6 @@ void qemu_check_nic_model(NICInfo *nd, const char *model);
|
||||
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
|
||||
const char *default_model);
|
||||
|
||||
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
||||
unsigned flags,
|
||||
const struct iovec *iov,
|
||||
int iovcnt,
|
||||
void *opaque);
|
||||
|
||||
void print_net_client(Monitor *mon, NetClientState *nc);
|
||||
void hmp_info_network(Monitor *mon, const QDict *qdict);
|
||||
void net_socket_rs_init(SocketReadState *rs,
|
||||
|
||||
+27
-1
@@ -59,6 +59,8 @@ static bool colo_runstate_is_stopped(void)
|
||||
|
||||
static void secondary_vm_do_failover(void)
|
||||
{
|
||||
/* COLO needs enable block-replication */
|
||||
#ifdef CONFIG_REPLICATION
|
||||
int old_state;
|
||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||
Error *local_err = NULL;
|
||||
@@ -121,10 +123,14 @@ static void secondary_vm_do_failover(void)
|
||||
if (mis->migration_incoming_co) {
|
||||
qemu_coroutine_enter(mis->migration_incoming_co);
|
||||
}
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void primary_vm_do_failover(void)
|
||||
{
|
||||
#ifdef CONFIG_REPLICATION
|
||||
MigrationState *s = migrate_get_current();
|
||||
int old_state;
|
||||
Error *local_err = NULL;
|
||||
@@ -165,6 +171,9 @@ static void primary_vm_do_failover(void)
|
||||
|
||||
/* Notify COLO thread that failover work is finished */
|
||||
qemu_sem_post(&s->colo_exit_sem);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
COLOMode get_colo_mode(void)
|
||||
@@ -415,11 +424,16 @@ static int colo_do_checkpoint_transaction(MigrationState *s,
|
||||
/* Disable block migration */
|
||||
migrate_set_block_enabled(false, &local_err);
|
||||
qemu_mutex_lock_iothread();
|
||||
|
||||
#ifdef CONFIG_REPLICATION
|
||||
replication_do_checkpoint_all(&local_err);
|
||||
if (local_err) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
|
||||
colo_send_message(s->to_dst_file, COLO_MESSAGE_VMSTATE_SEND, &local_err);
|
||||
if (local_err) {
|
||||
@@ -523,11 +537,15 @@ static void colo_process_checkpoint(MigrationState *s)
|
||||
object_unref(OBJECT(bioc));
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
#ifdef CONFIG_REPLICATION
|
||||
replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
|
||||
if (local_err) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
|
||||
vm_start();
|
||||
qemu_mutex_unlock_iothread();
|
||||
@@ -690,11 +708,15 @@ void *colo_process_incoming_thread(void *opaque)
|
||||
object_unref(OBJECT(bioc));
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
#ifdef CONFIG_REPLICATION
|
||||
replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
|
||||
if (local_err) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
vm_start();
|
||||
trace_colo_vm_state_change("stop", "run");
|
||||
qemu_mutex_unlock_iothread();
|
||||
@@ -785,18 +807,22 @@ void *colo_process_incoming_thread(void *opaque)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REPLICATION
|
||||
replication_get_error_all(&local_err);
|
||||
if (local_err) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* discard colo disk buffer */
|
||||
replication_do_checkpoint_all(&local_err);
|
||||
if (local_err) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
goto out;
|
||||
}
|
||||
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
/* Notify all filters of all NIC to do checkpoint */
|
||||
colo_notify_filters_event(COLO_EVENT_CHECKPOINT, &local_err);
|
||||
|
||||
|
||||
@@ -918,6 +918,15 @@ static bool migrate_caps_check(bool *cap_list,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_REPLICATION
|
||||
if (cap_list[MIGRATION_CAPABILITY_X_COLO]) {
|
||||
error_setg(errp, "QEMU compiled without replication module"
|
||||
" can't enable COLO");
|
||||
error_append_hint(errp, "Please enable replication before COLO.\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cap_list[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
|
||||
if (cap_list[MIGRATION_CAPABILITY_COMPRESS]) {
|
||||
/* The decompression threads asynchronously write into RAM
|
||||
|
||||
+8
-3
@@ -263,15 +263,16 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
|
||||
* Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
|
||||
*/
|
||||
|
||||
static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_timer(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
QEMUTimer *v = pv;
|
||||
timer_get(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_timer(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
QEMUTimer *v = pv;
|
||||
timer_put(f, v);
|
||||
@@ -2455,6 +2456,10 @@ int save_snapshot(const char *name, Error **errp)
|
||||
struct tm tm;
|
||||
AioContext *aio_context;
|
||||
|
||||
if (migration_is_blocked(errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!replay_can_snapshot()) {
|
||||
error_setg(errp, "Record/replay does not allow making snapshot "
|
||||
"right now. Try once more later.");
|
||||
|
||||
+66
-53
@@ -22,15 +22,16 @@
|
||||
|
||||
/* bool */
|
||||
|
||||
static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_bool(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
bool *v = pv;
|
||||
*v = qemu_get_byte(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_bool(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
bool *v = pv;
|
||||
qemu_put_byte(f, *v);
|
||||
@@ -45,15 +46,16 @@ const VMStateInfo vmstate_info_bool = {
|
||||
|
||||
/* 8 bit int */
|
||||
|
||||
static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_int8(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
int8_t *v = pv;
|
||||
qemu_get_s8s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_int8(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
int8_t *v = pv;
|
||||
qemu_put_s8s(f, v);
|
||||
@@ -68,15 +70,16 @@ const VMStateInfo vmstate_info_int8 = {
|
||||
|
||||
/* 16 bit int */
|
||||
|
||||
static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_int16(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
int16_t *v = pv;
|
||||
qemu_get_sbe16s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_int16(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
int16_t *v = pv;
|
||||
qemu_put_sbe16s(f, v);
|
||||
@@ -91,15 +94,16 @@ const VMStateInfo vmstate_info_int16 = {
|
||||
|
||||
/* 32 bit int */
|
||||
|
||||
static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_int32(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
int32_t *v = pv;
|
||||
qemu_get_sbe32s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_int32(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
int32_t *v = pv;
|
||||
qemu_put_sbe32s(f, v);
|
||||
@@ -116,7 +120,7 @@ const VMStateInfo vmstate_info_int32 = {
|
||||
in the field */
|
||||
|
||||
static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
int32_t *v = pv;
|
||||
int32_t v2;
|
||||
@@ -142,7 +146,8 @@ const VMStateInfo vmstate_info_int32_equal = {
|
||||
* and less than or equal to the one in the field.
|
||||
*/
|
||||
|
||||
static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_int32_le(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
int32_t *cur = pv;
|
||||
int32_t loaded;
|
||||
@@ -166,15 +171,16 @@ const VMStateInfo vmstate_info_int32_le = {
|
||||
|
||||
/* 64 bit int */
|
||||
|
||||
static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_int64(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
int64_t *v = pv;
|
||||
qemu_get_sbe64s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_int64(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
int64_t *v = pv;
|
||||
qemu_put_sbe64s(f, v);
|
||||
@@ -189,15 +195,16 @@ const VMStateInfo vmstate_info_int64 = {
|
||||
|
||||
/* 8 bit unsigned int */
|
||||
|
||||
static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_uint8(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint8_t *v = pv;
|
||||
qemu_get_8s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_uint8(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
uint8_t *v = pv;
|
||||
qemu_put_8s(f, v);
|
||||
@@ -212,15 +219,16 @@ const VMStateInfo vmstate_info_uint8 = {
|
||||
|
||||
/* 16 bit unsigned int */
|
||||
|
||||
static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_uint16(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint16_t *v = pv;
|
||||
qemu_get_be16s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_uint16(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
uint16_t *v = pv;
|
||||
qemu_put_be16s(f, v);
|
||||
@@ -235,15 +243,16 @@ const VMStateInfo vmstate_info_uint16 = {
|
||||
|
||||
/* 32 bit unsigned int */
|
||||
|
||||
static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_uint32(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint32_t *v = pv;
|
||||
qemu_get_be32s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_uint32(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
uint32_t *v = pv;
|
||||
qemu_put_be32s(f, v);
|
||||
@@ -260,7 +269,7 @@ const VMStateInfo vmstate_info_uint32 = {
|
||||
in the field */
|
||||
|
||||
static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint32_t *v = pv;
|
||||
uint32_t v2;
|
||||
@@ -284,15 +293,16 @@ const VMStateInfo vmstate_info_uint32_equal = {
|
||||
|
||||
/* 64 bit unsigned int */
|
||||
|
||||
static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_uint64(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint64_t *v = pv;
|
||||
qemu_get_be64s(f, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_uint64(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
uint64_t *v = pv;
|
||||
qemu_put_be64s(f, v);
|
||||
@@ -305,7 +315,8 @@ const VMStateInfo vmstate_info_uint64 = {
|
||||
.put = put_uint64,
|
||||
};
|
||||
|
||||
static int get_nullptr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_nullptr(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
|
||||
{
|
||||
if (qemu_get_byte(f) == VMS_NULLPTR_MARKER) {
|
||||
@@ -316,7 +327,7 @@ static int get_nullptr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
}
|
||||
|
||||
static int put_nullptr(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
|
||||
{
|
||||
if (pv == NULL) {
|
||||
@@ -337,7 +348,7 @@ const VMStateInfo vmstate_info_nullptr = {
|
||||
in the field */
|
||||
|
||||
static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint64_t *v = pv;
|
||||
uint64_t v2;
|
||||
@@ -363,7 +374,7 @@ const VMStateInfo vmstate_info_uint64_equal = {
|
||||
in the field */
|
||||
|
||||
static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint8_t *v = pv;
|
||||
uint8_t v2;
|
||||
@@ -389,7 +400,7 @@ const VMStateInfo vmstate_info_uint8_equal = {
|
||||
in the field */
|
||||
|
||||
static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint16_t *v = pv;
|
||||
uint16_t v2;
|
||||
@@ -414,7 +425,7 @@ const VMStateInfo vmstate_info_uint16_equal = {
|
||||
/* floating point */
|
||||
|
||||
static int get_float64(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
float64 *v = pv;
|
||||
|
||||
@@ -422,8 +433,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_float64(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
uint64_t *v = pv;
|
||||
|
||||
@@ -440,7 +451,7 @@ const VMStateInfo vmstate_info_float64 = {
|
||||
/* CPU_DoubleU type */
|
||||
|
||||
static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
CPU_DoubleU *v = pv;
|
||||
qemu_get_be32s(f, &v->l.upper);
|
||||
@@ -449,7 +460,7 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
|
||||
}
|
||||
|
||||
static int put_cpudouble(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
CPU_DoubleU *v = pv;
|
||||
qemu_put_be32s(f, &v->l.upper);
|
||||
@@ -466,15 +477,15 @@ const VMStateInfo vmstate_info_cpudouble = {
|
||||
/* uint8_t buffers */
|
||||
|
||||
static int get_buffer(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint8_t *v = pv;
|
||||
qemu_get_buffer(f, v, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_buffer(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
uint8_t *v = pv;
|
||||
qemu_put_buffer(f, v, size);
|
||||
@@ -491,7 +502,7 @@ const VMStateInfo vmstate_info_buffer = {
|
||||
not useful anymore */
|
||||
|
||||
static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
int block_len;
|
||||
@@ -505,7 +516,7 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
|
||||
}
|
||||
|
||||
static int put_unused_buffer(QEMUFile *f, void *pv, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
static const uint8_t buf[1024];
|
||||
int block_len;
|
||||
@@ -531,7 +542,8 @@ const VMStateInfo vmstate_info_unused_buffer = {
|
||||
* in fields that don't really exist in the parent but need to be in the
|
||||
* stream.
|
||||
*/
|
||||
static int get_tmp(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_tmp(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
int ret;
|
||||
const VMStateDescription *vmsd = field->vmsd;
|
||||
@@ -545,8 +557,8 @@ static int get_tmp(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int put_tmp(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_tmp(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
const VMStateDescription *vmsd = field->vmsd;
|
||||
void *tmp = g_malloc(size);
|
||||
@@ -573,7 +585,8 @@ const VMStateInfo vmstate_info_tmp = {
|
||||
*/
|
||||
/* This is the number of 64 bit words sent over the wire */
|
||||
#define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
|
||||
static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_bitmap(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
unsigned long *bmp = pv;
|
||||
int i, idx = 0;
|
||||
@@ -587,8 +600,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_bitmap(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
unsigned long *bmp = pv;
|
||||
int i, idx = 0;
|
||||
@@ -613,7 +626,7 @@ const VMStateInfo vmstate_info_bitmap = {
|
||||
* meta data about the QTAILQ is encoded in a VMStateField structure
|
||||
*/
|
||||
static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
int ret = 0;
|
||||
const VMStateDescription *vmsd = field->vmsd;
|
||||
@@ -652,7 +665,7 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
|
||||
|
||||
/* put for QTAILQ */
|
||||
static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
const VMStateDescription *vmsd = field->vmsd;
|
||||
/* offset of the QTAILQ entry in a QTAILQ element*/
|
||||
|
||||
+17
-14
@@ -26,7 +26,7 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
void *opaque);
|
||||
|
||||
static int vmstate_n_elems(void *opaque, VMStateField *field)
|
||||
static int vmstate_n_elems(void *opaque, const VMStateField *field)
|
||||
{
|
||||
int n_elems = 1;
|
||||
|
||||
@@ -50,7 +50,7 @@ static int vmstate_n_elems(void *opaque, VMStateField *field)
|
||||
return n_elems;
|
||||
}
|
||||
|
||||
static int vmstate_size(void *opaque, VMStateField *field)
|
||||
static int vmstate_size(void *opaque, const VMStateField *field)
|
||||
{
|
||||
int size = field->size;
|
||||
|
||||
@@ -64,7 +64,8 @@ static int vmstate_size(void *opaque, VMStateField *field)
|
||||
return size;
|
||||
}
|
||||
|
||||
static void vmstate_handle_alloc(void *ptr, VMStateField *field, void *opaque)
|
||||
static void vmstate_handle_alloc(void *ptr, const VMStateField *field,
|
||||
void *opaque)
|
||||
{
|
||||
if (field->flags & VMS_POINTER && field->flags & VMS_ALLOC) {
|
||||
gsize size = vmstate_size(opaque, field);
|
||||
@@ -78,7 +79,7 @@ static void vmstate_handle_alloc(void *ptr, VMStateField *field, void *opaque)
|
||||
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
void *opaque, int version_id)
|
||||
{
|
||||
VMStateField *field = vmsd->fields;
|
||||
const VMStateField *field = vmsd->fields;
|
||||
int ret = 0;
|
||||
|
||||
trace_vmstate_load_state(vmsd->name, version_id);
|
||||
@@ -171,9 +172,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vmfield_name_num(VMStateField *start, VMStateField *search)
|
||||
static int vmfield_name_num(const VMStateField *start,
|
||||
const VMStateField *search)
|
||||
{
|
||||
VMStateField *field;
|
||||
const VMStateField *field;
|
||||
int found = 0;
|
||||
|
||||
for (field = start; field->name; field++) {
|
||||
@@ -188,9 +190,10 @@ static int vmfield_name_num(VMStateField *start, VMStateField *search)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool vmfield_name_is_unique(VMStateField *start, VMStateField *search)
|
||||
static bool vmfield_name_is_unique(const VMStateField *start,
|
||||
const VMStateField *search)
|
||||
{
|
||||
VMStateField *field;
|
||||
const VMStateField *field;
|
||||
int found = 0;
|
||||
|
||||
for (field = start; field->name; field++) {
|
||||
@@ -206,7 +209,7 @@ static bool vmfield_name_is_unique(VMStateField *start, VMStateField *search)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *vmfield_get_type_name(VMStateField *field)
|
||||
static const char *vmfield_get_type_name(const VMStateField *field)
|
||||
{
|
||||
const char *type = "unknown";
|
||||
|
||||
@@ -221,7 +224,7 @@ static const char *vmfield_get_type_name(VMStateField *field)
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool vmsd_can_compress(VMStateField *field)
|
||||
static bool vmsd_can_compress(const VMStateField *field)
|
||||
{
|
||||
if (field->field_exists) {
|
||||
/* Dynamically existing fields mess up compression */
|
||||
@@ -229,7 +232,7 @@ static bool vmsd_can_compress(VMStateField *field)
|
||||
}
|
||||
|
||||
if (field->flags & VMS_STRUCT) {
|
||||
VMStateField *sfield = field->vmsd->fields;
|
||||
const VMStateField *sfield = field->vmsd->fields;
|
||||
while (sfield->name) {
|
||||
if (!vmsd_can_compress(sfield)) {
|
||||
/* Child elements can't compress, so can't we */
|
||||
@@ -248,7 +251,7 @@ static bool vmsd_can_compress(VMStateField *field)
|
||||
}
|
||||
|
||||
static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
|
||||
VMStateField *field, int i, int max)
|
||||
const VMStateField *field, int i, int max)
|
||||
{
|
||||
char *name, *old_name;
|
||||
bool is_array = max > 1;
|
||||
@@ -287,7 +290,7 @@ static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
|
||||
}
|
||||
|
||||
static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
|
||||
VMStateField *field, size_t size, int i)
|
||||
const VMStateField *field, size_t size, int i)
|
||||
{
|
||||
if (!vmdesc) {
|
||||
return;
|
||||
@@ -323,7 +326,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
void *opaque, QJSON *vmdesc, int version_id)
|
||||
{
|
||||
int ret = 0;
|
||||
VMStateField *field = vmsd->fields;
|
||||
const VMStateField *field = vmsd->fields;
|
||||
|
||||
trace_vmstate_save_state_top(vmsd->name);
|
||||
|
||||
|
||||
@@ -978,6 +978,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client,
|
||||
if (client->opt == NBD_OPT_LIST_META_CONTEXT && !nb_queries) {
|
||||
/* enable all known contexts */
|
||||
meta->base_allocation = true;
|
||||
meta->bitmap = !!meta->exp->export_bitmap;
|
||||
} else {
|
||||
for (i = 0; i < nb_queries; ++i) {
|
||||
ret = nbd_negotiate_meta_query(client, meta, errp);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "hub.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
/*
|
||||
* A hub broadcasts incoming packets to all its ports except the source port.
|
||||
@@ -346,7 +347,7 @@ void net_hub_check_clients(void)
|
||||
if (has_host_dev && !has_nic) {
|
||||
warn_report("hub %d with no nics", hub->id);
|
||||
}
|
||||
if (has_nic && !has_host_dev) {
|
||||
if (has_nic && !has_host_dev && !qtest_enabled()) {
|
||||
warn_report("hub %d is not connected to host network", hub->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +231,11 @@ static void qemu_net_client_destructor(NetClientState *nc)
|
||||
{
|
||||
g_free(nc);
|
||||
}
|
||||
static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
||||
unsigned flags,
|
||||
const struct iovec *iov,
|
||||
int iovcnt,
|
||||
void *opaque);
|
||||
|
||||
static void qemu_net_client_setup(NetClientState *nc,
|
||||
NetClientInfo *info,
|
||||
@@ -705,22 +710,18 @@ static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
||||
unsigned flags,
|
||||
const struct iovec *iov,
|
||||
int iovcnt,
|
||||
void *opaque)
|
||||
static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
||||
unsigned flags,
|
||||
const struct iovec *iov,
|
||||
int iovcnt,
|
||||
void *opaque)
|
||||
{
|
||||
NetClientState *nc = opaque;
|
||||
size_t size = iov_size(iov, iovcnt);
|
||||
int ret;
|
||||
|
||||
if (size > INT_MAX) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (nc->link_down) {
|
||||
return size;
|
||||
return iov_size(iov, iovcnt);
|
||||
}
|
||||
|
||||
if (nc->receive_disabled) {
|
||||
@@ -745,10 +746,15 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
|
||||
NetPacketSent *sent_cb)
|
||||
{
|
||||
NetQueue *queue;
|
||||
size_t size = iov_size(iov, iovcnt);
|
||||
int ret;
|
||||
|
||||
if (size > NET_BUFSIZE) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (sender->link_down || !sender->peer) {
|
||||
return iov_size(iov, iovcnt);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Let filters handle the packet first */
|
||||
|
||||
@@ -1102,3 +1102,16 @@
|
||||
'discriminator' : 'type',
|
||||
'data' : { 'gtk' : 'DisplayGTK',
|
||||
'egl-headless' : 'DisplayEGLHeadless'} }
|
||||
|
||||
##
|
||||
# @query-display-options:
|
||||
#
|
||||
# Returns information about display configuration
|
||||
#
|
||||
# Returns: @DisplayOptions
|
||||
#
|
||||
# Since: 3.1
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-display-options',
|
||||
'returns': 'DisplayOptions' }
|
||||
+2
-1
@@ -261,8 +261,9 @@ static int print_block_option_help(const char *filename, const char *fmt)
|
||||
return 1;
|
||||
}
|
||||
if (!proto_drv->create_opts) {
|
||||
error_report("Protocal driver '%s' does not support image creation",
|
||||
error_report("Protocol driver '%s' does not support image creation",
|
||||
proto_drv->format_name);
|
||||
qemu_opts_free(create_opts);
|
||||
return 1;
|
||||
}
|
||||
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
|
||||
|
||||
+3
-1
@@ -4025,7 +4025,7 @@ Memory backend objects offer more control than the @option{-m} option that is
|
||||
traditionally used to define guest RAM. Please refer to
|
||||
@option{memory-backend-file} for a description of the options.
|
||||
|
||||
@item -object memory-backend-memfd,id=@var{id},merge=@var{on|off},dump=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave},seal=@var{on|off},hugetlb=@var{on|off},hugetlbsize=@var{size}
|
||||
@item -object memory-backend-memfd,id=@var{id},merge=@var{on|off},dump=@var{on|off},share=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave},seal=@var{on|off},hugetlb=@var{on|off},hugetlbsize=@var{size}
|
||||
|
||||
Creates an anonymous memory file backend object, which allows QEMU to
|
||||
share the memory with an external process (e.g. when using
|
||||
@@ -4047,6 +4047,8 @@ with the @option{seal} option (requires at least Linux 4.16).
|
||||
Please refer to @option{memory-backend-file} for a description of the
|
||||
other options.
|
||||
|
||||
The @option{share} boolean option is @var{on} by default with memfd.
|
||||
|
||||
@item -object rng-random,id=@var{id},filename=@var{/dev/random}
|
||||
|
||||
Creates a random number generator backend which obtains entropy from
|
||||
|
||||
@@ -2752,7 +2752,8 @@ sub process {
|
||||
info_vreport|
|
||||
error_report|
|
||||
warn_report|
|
||||
info_report}x;
|
||||
info_report|
|
||||
g_test_message}x;
|
||||
|
||||
if ($rawline =~ /\b(?:$qemu_error_funcs)\s*\(.*\".*\\n/) {
|
||||
ERROR("Error messages should not contain newlines\n" . $herecurr);
|
||||
|
||||
@@ -236,7 +236,7 @@ static void dm_init(void)
|
||||
perror("Cannot open " CONTROL_PATH);
|
||||
exit(1);
|
||||
}
|
||||
struct dm_ioctl dm = { 0 };
|
||||
struct dm_ioctl dm = { };
|
||||
if (!dm_ioctl(DM_VERSION, &dm)) {
|
||||
perror("ioctl");
|
||||
exit(1);
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
#include "hw/boards.h"
|
||||
#include "migration/cpu.h"
|
||||
|
||||
static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
static int get_fpcr(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
CPUAlphaState *env = opaque;
|
||||
cpu_alpha_store_fpcr(env, qemu_get_be64(f));
|
||||
@@ -13,7 +14,7 @@ static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
}
|
||||
|
||||
static int put_fpcr(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
CPUAlphaState *env = opaque;
|
||||
qemu_put_be64(f, cpu_alpha_load_fpcr(env));
|
||||
|
||||
@@ -18,7 +18,7 @@ static bool vfp_needed(void *opaque)
|
||||
}
|
||||
|
||||
static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
CPUARMState *env = &cpu->env;
|
||||
@@ -29,7 +29,7 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
|
||||
}
|
||||
|
||||
static int put_fpscr(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
CPUARMState *env = &cpu->env;
|
||||
@@ -503,7 +503,7 @@ static const VMStateDescription vmstate_m_security = {
|
||||
};
|
||||
|
||||
static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
CPUARMState *env = &cpu->env;
|
||||
@@ -559,7 +559,7 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
|
||||
}
|
||||
|
||||
static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
CPUARMState *env = &cpu->env;
|
||||
@@ -585,7 +585,7 @@ static const VMStateInfo vmstate_cpsr = {
|
||||
};
|
||||
|
||||
static int get_power(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field)
|
||||
const VMStateField *field)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
bool powered_off = qemu_get_byte(f);
|
||||
@@ -594,7 +594,7 @@ static int get_power(QEMUFile *f, void *opaque, size_t size,
|
||||
}
|
||||
|
||||
static int put_power(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
|
||||
|
||||
+10
-10
@@ -4382,20 +4382,20 @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr,
|
||||
}
|
||||
|
||||
#define DO_LDN_1(N) \
|
||||
void __attribute__((flatten)) HELPER(sve_ld##N##bb_r) \
|
||||
void QEMU_FLATTEN HELPER(sve_ld##N##bb_r) \
|
||||
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
|
||||
{ \
|
||||
sve_ld##N##_r(env, vg, addr, desc, 1, GETPC(), sve_ld1bb_tlb); \
|
||||
}
|
||||
|
||||
#define DO_LDN_2(N, SUFF, SIZE) \
|
||||
void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_le_r) \
|
||||
void QEMU_FLATTEN HELPER(sve_ld##N##SUFF##_le_r) \
|
||||
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
|
||||
{ \
|
||||
sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
|
||||
sve_ld1##SUFF##_le_tlb); \
|
||||
} \
|
||||
void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_be_r) \
|
||||
void QEMU_FLATTEN HELPER(sve_ld##N##SUFF##_be_r) \
|
||||
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
|
||||
{ \
|
||||
sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
|
||||
@@ -4832,7 +4832,7 @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr,
|
||||
}
|
||||
|
||||
#define DO_STN_1(N, NAME, ESIZE) \
|
||||
void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
|
||||
void QEMU_FLATTEN HELPER(sve_st##N##NAME##_r) \
|
||||
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
|
||||
{ \
|
||||
sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, 1, \
|
||||
@@ -4840,13 +4840,13 @@ void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
|
||||
}
|
||||
|
||||
#define DO_STN_2(N, NAME, ESIZE, MSIZE) \
|
||||
void __attribute__((flatten)) HELPER(sve_st##N##NAME##_le_r) \
|
||||
void QEMU_FLATTEN HELPER(sve_st##N##NAME##_le_r) \
|
||||
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
|
||||
{ \
|
||||
sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
|
||||
sve_st1##NAME##_le_tlb); \
|
||||
} \
|
||||
void __attribute__((flatten)) HELPER(sve_st##N##NAME##_be_r) \
|
||||
void QEMU_FLATTEN HELPER(sve_st##N##NAME##_be_r) \
|
||||
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
|
||||
{ \
|
||||
sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
|
||||
@@ -4966,7 +4966,7 @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
|
||||
}
|
||||
|
||||
#define DO_LD1_ZPZ_S(MEM, OFS) \
|
||||
void __attribute__((flatten)) HELPER(sve_ld##MEM##_##OFS) \
|
||||
void QEMU_FLATTEN HELPER(sve_ld##MEM##_##OFS) \
|
||||
(CPUARMState *env, void *vd, void *vg, void *vm, \
|
||||
target_ulong base, uint32_t desc) \
|
||||
{ \
|
||||
@@ -4975,7 +4975,7 @@ void __attribute__((flatten)) HELPER(sve_ld##MEM##_##OFS) \
|
||||
}
|
||||
|
||||
#define DO_LD1_ZPZ_D(MEM, OFS) \
|
||||
void __attribute__((flatten)) HELPER(sve_ld##MEM##_##OFS) \
|
||||
void QEMU_FLATTEN HELPER(sve_ld##MEM##_##OFS) \
|
||||
(CPUARMState *env, void *vd, void *vg, void *vm, \
|
||||
target_ulong base, uint32_t desc) \
|
||||
{ \
|
||||
@@ -5326,7 +5326,7 @@ static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
|
||||
}
|
||||
|
||||
#define DO_ST1_ZPZ_S(MEM, OFS) \
|
||||
void __attribute__((flatten)) HELPER(sve_st##MEM##_##OFS) \
|
||||
void QEMU_FLATTEN HELPER(sve_st##MEM##_##OFS) \
|
||||
(CPUARMState *env, void *vd, void *vg, void *vm, \
|
||||
target_ulong base, uint32_t desc) \
|
||||
{ \
|
||||
@@ -5335,7 +5335,7 @@ void __attribute__((flatten)) HELPER(sve_st##MEM##_##OFS) \
|
||||
}
|
||||
|
||||
#define DO_ST1_ZPZ_D(MEM, OFS) \
|
||||
void __attribute__((flatten)) HELPER(sve_st##MEM##_##OFS) \
|
||||
void QEMU_FLATTEN HELPER(sve_st##MEM##_##OFS) \
|
||||
(CPUARMState *env, void *vd, void *vg, void *vm, \
|
||||
target_ulong base, uint32_t desc) \
|
||||
{ \
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
VMSTATE_UINTTR_ARRAY_V(_f, _s, _n, 0)
|
||||
|
||||
|
||||
static int get_psw(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
static int get_psw(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
CPUHPPAState *env = opaque;
|
||||
cpu_hppa_put_psw(env, qemu_get_betr(f));
|
||||
@@ -54,7 +55,7 @@ static int get_psw(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
}
|
||||
|
||||
static int put_psw(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
CPUHPPAState *env = opaque;
|
||||
qemu_put_betr(f, cpu_hppa_get_psw(env));
|
||||
@@ -68,7 +69,8 @@ static const VMStateInfo vmstate_psw = {
|
||||
};
|
||||
|
||||
/* FIXME: Use the PA2.0 format, which is a superset of the PA1.1 format. */
|
||||
static int get_tlb(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
static int get_tlb(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
hppa_tlb_entry *ent = opaque;
|
||||
uint32_t val;
|
||||
@@ -94,7 +96,7 @@ static int get_tlb(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
}
|
||||
|
||||
static int put_tlb(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
hppa_tlb_entry *ent = opaque;
|
||||
uint32_t val = 0;
|
||||
|
||||
@@ -454,9 +454,9 @@ struct decode_x87_tbl {
|
||||
struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL,
|
||||
decode_invalid};
|
||||
|
||||
struct decode_tbl _decode_tbl1[255];
|
||||
struct decode_tbl _decode_tbl2[255];
|
||||
struct decode_x87_tbl _decode_tbl3[255];
|
||||
struct decode_tbl _decode_tbl1[256];
|
||||
struct decode_tbl _decode_tbl2[256];
|
||||
struct decode_x87_tbl _decode_tbl3[256];
|
||||
|
||||
static void decode_x87_ins(CPUX86State *env, struct x86_decode *decode)
|
||||
{
|
||||
|
||||
+19
-11
@@ -95,6 +95,7 @@ static bool has_msr_xss;
|
||||
static bool has_msr_spec_ctrl;
|
||||
static bool has_msr_virt_ssbd;
|
||||
static bool has_msr_smi_count;
|
||||
static bool has_msr_arch_capabs;
|
||||
|
||||
static uint32_t has_architectural_pmu_version;
|
||||
static uint32_t num_architectural_pmu_gp_counters;
|
||||
@@ -854,6 +855,7 @@ static int hyperv_init_vcpu(X86CPU *cpu)
|
||||
}
|
||||
|
||||
static Error *invtsc_mig_blocker;
|
||||
static Error *vmx_mig_blocker;
|
||||
|
||||
#define KVM_MAX_CPUID_ENTRIES 100
|
||||
|
||||
@@ -1246,6 +1248,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
!!(c->ecx & CPUID_EXT_SMX);
|
||||
}
|
||||
|
||||
if ((env->features[FEAT_1_ECX] & CPUID_EXT_VMX) && !vmx_mig_blocker) {
|
||||
error_setg(&vmx_mig_blocker,
|
||||
"Nested VMX virtualization does not support live migration yet");
|
||||
r = migrate_add_blocker(vmx_mig_blocker, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
error_free(vmx_mig_blocker);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (env->mcg_cap & MCG_LMCE_P) {
|
||||
has_msr_mcg_ext_ctl = has_msr_feature_control = true;
|
||||
}
|
||||
@@ -1253,7 +1266,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
if (!env->user_tsc_khz) {
|
||||
if ((env->features[FEAT_8000_0007_EDX] & CPUID_APM_INVTSC) &&
|
||||
invtsc_mig_blocker == NULL) {
|
||||
/* for migration */
|
||||
error_setg(&invtsc_mig_blocker,
|
||||
"State blocked by non-migratable CPU device"
|
||||
" (invtsc flag)");
|
||||
@@ -1263,8 +1275,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
error_free(invtsc_mig_blocker);
|
||||
return r;
|
||||
}
|
||||
/* for savevm */
|
||||
vmstate_x86_cpu.unmigratable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1481,6 +1491,9 @@ static int kvm_get_supported_msrs(KVMState *s)
|
||||
case MSR_VIRT_SSBD:
|
||||
has_msr_virt_ssbd = true;
|
||||
break;
|
||||
case MSR_IA32_ARCH_CAPABILITIES:
|
||||
has_msr_arch_capabs = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2002,14 +2015,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
#endif
|
||||
|
||||
/* If host supports feature MSR, write down. */
|
||||
if (kvm_feature_msrs) {
|
||||
int i;
|
||||
for (i = 0; i < kvm_feature_msrs->nmsrs; i++)
|
||||
if (kvm_feature_msrs->indices[i] == MSR_IA32_ARCH_CAPABILITIES) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES,
|
||||
env->features[FEAT_ARCH_CAPABILITIES]);
|
||||
break;
|
||||
}
|
||||
if (has_msr_arch_capabs) {
|
||||
kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES,
|
||||
env->features[FEAT_ARCH_CAPABILITIES]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+20
-15
@@ -1268,10 +1268,30 @@ static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
|
||||
{
|
||||
gen_update_cc_op(s);
|
||||
gen_jmp_im(s, cur_eip);
|
||||
gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
|
||||
s->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
/* Generate #UD for the current instruction. The assumption here is that
|
||||
the instruction is known, but it isn't allowed in the current cpu mode. */
|
||||
static void gen_illegal_opcode(DisasContext *s)
|
||||
{
|
||||
gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
|
||||
}
|
||||
|
||||
/* if d == OR_TMP0, it means memory operand (address in A0) */
|
||||
static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
|
||||
{
|
||||
if (d != OR_TMP0) {
|
||||
if (s1->prefix & PREFIX_LOCK) {
|
||||
/* Lock prefix when destination is not memory. */
|
||||
gen_illegal_opcode(s1);
|
||||
return;
|
||||
}
|
||||
gen_op_mov_v_reg(s1, ot, s1->T0, d);
|
||||
} else if (!(s1->prefix & PREFIX_LOCK)) {
|
||||
gen_op_ld_v(s1, ot, s1->T0, s1->A0);
|
||||
@@ -2469,21 +2489,6 @@ static void gen_leave(DisasContext *s)
|
||||
gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1);
|
||||
}
|
||||
|
||||
static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
|
||||
{
|
||||
gen_update_cc_op(s);
|
||||
gen_jmp_im(s, cur_eip);
|
||||
gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
|
||||
s->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
/* Generate #UD for the current instruction. The assumption here is that
|
||||
the instruction is known, but it isn't allowed in the current cpu mode. */
|
||||
static void gen_illegal_opcode(DisasContext *s)
|
||||
{
|
||||
gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
|
||||
}
|
||||
|
||||
/* Similarly, except that the assumption here is that we don't decode
|
||||
the instruction at all -- either a missing opcode, an unimplemented
|
||||
feature, or just a bogus instruction stream. */
|
||||
|
||||
@@ -20,7 +20,8 @@ static int cpu_post_load(void *opaque, int version_id)
|
||||
|
||||
/* FPU state */
|
||||
|
||||
static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_fpr(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
int i;
|
||||
fpr_t *v = pv;
|
||||
@@ -31,8 +32,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_fpr(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
int i;
|
||||
fpr_t *v = pv;
|
||||
@@ -128,7 +129,8 @@ const VMStateDescription vmstate_mvp = {
|
||||
|
||||
/* TLB state */
|
||||
|
||||
static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_tlb(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
r4k_tlb_t *v = pv;
|
||||
uint16_t flags;
|
||||
@@ -155,8 +157,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_tlb(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
r4k_tlb_t *v = pv;
|
||||
|
||||
|
||||
@@ -49,7 +49,8 @@ static const VMStateDescription vmstate_cpu_tlb = {
|
||||
}
|
||||
};
|
||||
|
||||
static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
static int get_sr(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
CPUOpenRISCState *env = opaque;
|
||||
cpu_set_sr(env, qemu_get_be32(f));
|
||||
@@ -57,7 +58,7 @@ static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
}
|
||||
|
||||
static int put_sr(QEMUFile *f, void *opaque, size_t size,
|
||||
VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
CPUOpenRISCState *env = opaque;
|
||||
qemu_put_be32(f, cpu_get_sr(env));
|
||||
|
||||
@@ -110,7 +110,8 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_avr(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
ppc_avr_t *v = pv;
|
||||
|
||||
@@ -120,8 +121,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_avr(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
ppc_avr_t *v = pv;
|
||||
|
||||
@@ -452,7 +453,8 @@ static const VMStateDescription vmstate_sr = {
|
||||
};
|
||||
|
||||
#ifdef TARGET_PPC64
|
||||
static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
static int get_slbe(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
ppc_slb_t *v = pv;
|
||||
|
||||
@@ -462,8 +464,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_slbe(QEMUFile *f, void *pv, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
ppc_slb_t *v = pv;
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ static const VMStateDescription vmstate_tlb_entry = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
static int get_psr(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field)
|
||||
{
|
||||
SPARCCPU *cpu = opaque;
|
||||
CPUSPARCState *env = &cpu->env;
|
||||
@@ -69,8 +70,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field,
|
||||
QJSON *vmdesc)
|
||||
static int put_psr(QEMUFile *f, void *opaque, size_t size,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
{
|
||||
SPARCCPU *cpu = opaque;
|
||||
CPUSPARCState *env = &cpu->env;
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
static XtensaConfig dc232b __attribute__((unused)) = {
|
||||
.name = "dc232b",
|
||||
.gdb_regmap = {
|
||||
.num_regs = 120,
|
||||
.num_core_regs = 52,
|
||||
.reg = {
|
||||
#include "core-dc232b/gdb-config.inc.c"
|
||||
}
|
||||
|
||||
@@ -259,3 +259,4 @@
|
||||
0, 0, 0, 0, 0, 0)
|
||||
XTREG(119, 476, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15,
|
||||
0, 0, 0, 0, 0, 0)
|
||||
XTREG_END
|
||||
@@ -40,8 +40,6 @@
|
||||
static XtensaConfig dc233c __attribute__((unused)) = {
|
||||
.name = "dc233c",
|
||||
.gdb_regmap = {
|
||||
.num_regs = 121,
|
||||
.num_core_regs = 52,
|
||||
.reg = {
|
||||
#include "core-dc233c/gdb-config.inc.c"
|
||||
}
|
||||
|
||||
@@ -143,3 +143,4 @@ XTREG(117, 468, 32, 4, 4, 0x000c, 0x0006, -2, 8, 0x0100, a12, 0, 0, 0, 0
|
||||
XTREG(118, 472, 32, 4, 4, 0x000d, 0x0006, -2, 8, 0x0100, a13, 0, 0, 0, 0, 0, 0)
|
||||
XTREG(119, 476, 32, 4, 4, 0x000e, 0x0006, -2, 8, 0x0100, a14, 0, 0, 0, 0, 0, 0)
|
||||
XTREG(120, 480, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15, 0, 0, 0, 0, 0, 0)
|
||||
XTREG_END
|
||||
@@ -45,15 +45,20 @@ void xtensa_count_regs(const XtensaConfig *config,
|
||||
unsigned *n_regs, unsigned *n_core_regs)
|
||||
{
|
||||
unsigned i;
|
||||
bool count_core_regs = true;
|
||||
|
||||
for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) {
|
||||
if (config->gdb_regmap.reg[i].type != xtRegisterTypeTieState &&
|
||||
config->gdb_regmap.reg[i].type != xtRegisterTypeMapped &&
|
||||
config->gdb_regmap.reg[i].type != xtRegisterTypeUnmapped) {
|
||||
++*n_regs;
|
||||
if ((config->gdb_regmap.reg[i].flags &
|
||||
XTENSA_REGISTER_FLAGS_PRIVILEGED) == 0) {
|
||||
++*n_core_regs;
|
||||
if (count_core_regs) {
|
||||
if ((config->gdb_regmap.reg[i].flags &
|
||||
XTENSA_REGISTER_FLAGS_PRIVILEGED) == 0) {
|
||||
++*n_core_regs;
|
||||
} else {
|
||||
count_core_regs = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,7 +730,7 @@ tests/test-hmp$(EXESUF): tests/test-hmp.o
|
||||
tests/machine-none-test$(EXESUF): tests/machine-none-test.o
|
||||
tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y)
|
||||
tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
|
||||
tests/nvme-test$(EXESUF): tests/nvme-test.o
|
||||
tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y)
|
||||
tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
|
||||
tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o
|
||||
tests/ac97-test$(EXESUF): tests/ac97-test.o
|
||||
|
||||
+58
-10
@@ -8,25 +8,73 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "libqtest.h"
|
||||
#include "libqos/libqos-pc.h"
|
||||
|
||||
static QOSState *qnvme_start(const char *extra_opts)
|
||||
{
|
||||
QOSState *qs;
|
||||
const char *arch = qtest_get_arch();
|
||||
const char *cmd = "-drive id=drv0,if=none,file=null-co://,format=raw "
|
||||
"-device nvme,addr=0x4.0,serial=foo,drive=drv0 %s";
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
qs = qtest_pc_boot(cmd, extra_opts ? : "");
|
||||
global_qtest = qs->qts;
|
||||
return qs;
|
||||
}
|
||||
|
||||
g_printerr("nvme tests are only available on x86\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void qnvme_stop(QOSState *qs)
|
||||
{
|
||||
qtest_shutdown(qs);
|
||||
}
|
||||
|
||||
/* Tests only initialization so far. TODO: Replace with functional tests */
|
||||
static void nop(void)
|
||||
{
|
||||
QOSState *qs;
|
||||
|
||||
qs = qnvme_start(NULL);
|
||||
qnvme_stop(qs);
|
||||
}
|
||||
|
||||
static void nvmetest_cmb_test(void)
|
||||
{
|
||||
const int cmb_bar_size = 2 * MiB;
|
||||
QOSState *qs;
|
||||
QPCIDevice *pdev;
|
||||
QPCIBar bar;
|
||||
|
||||
qs = qnvme_start("-global nvme.cmb_size_mb=2");
|
||||
pdev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4,0));
|
||||
g_assert(pdev != NULL);
|
||||
|
||||
qpci_device_enable(pdev);
|
||||
bar = qpci_iomap(pdev, 2, NULL);
|
||||
|
||||
qpci_io_writel(pdev, bar, 0, 0xccbbaa99);
|
||||
g_assert_cmpint(qpci_io_readb(pdev, bar, 0), ==, 0x99);
|
||||
g_assert_cmpint(qpci_io_readw(pdev, bar, 0), ==, 0xaa99);
|
||||
|
||||
/* Test partially out-of-bounds accesses. */
|
||||
qpci_io_writel(pdev, bar, cmb_bar_size - 1, 0x44332211);
|
||||
g_assert_cmpint(qpci_io_readb(pdev, bar, cmb_bar_size - 1), ==, 0x11);
|
||||
g_assert_cmpint(qpci_io_readw(pdev, bar, cmb_bar_size - 1), !=, 0x2211);
|
||||
g_assert_cmpint(qpci_io_readl(pdev, bar, cmb_bar_size - 1), !=, 0x44332211);
|
||||
g_free(pdev);
|
||||
|
||||
qnvme_stop(qs);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
qtest_add_func("/nvme/nop", nop);
|
||||
qtest_add_func("/nvme/cmb_test", nvmetest_cmb_test);
|
||||
|
||||
qtest_start("-drive id=drv0,if=none,file=null-co://,format=raw "
|
||||
"-device nvme,drive=drv0,serial=foo");
|
||||
ret = g_test_run();
|
||||
|
||||
qtest_end();
|
||||
|
||||
return ret;
|
||||
return g_test_run();
|
||||
}
|
||||
@@ -469,7 +469,7 @@ new_state = "1"
|
||||
self.assert_qmp(event, 'data/id', 'drive0')
|
||||
event = self.vm.get_qmp_event(wait=True)
|
||||
|
||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assertEqual(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'read')
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
@@ -494,7 +494,7 @@ new_state = "1"
|
||||
self.assert_qmp(event, 'data/id', 'drive0')
|
||||
event = self.vm.get_qmp_event(wait=True)
|
||||
|
||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assertEqual(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'read')
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
@@ -625,7 +625,7 @@ new_state = "1"
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
event = self.vm.event_wait(name='BLOCK_JOB_ERROR')
|
||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assertEqual(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'write')
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
|
||||
+8
-12
@@ -53,21 +53,17 @@ class ChangeBaseClass(iotests.QMPTestCase):
|
||||
if not self.has_real_tray:
|
||||
return
|
||||
|
||||
timeout = time.clock() + 3
|
||||
while not self.has_opened and time.clock() < timeout:
|
||||
self.process_events()
|
||||
if not self.has_opened:
|
||||
self.fail('Timeout while waiting for the tray to open')
|
||||
with iotests.Timeout(3, 'Timeout while waiting for the tray to open'):
|
||||
while not self.has_opened:
|
||||
self.process_events()
|
||||
|
||||
def wait_for_close(self):
|
||||
if not self.has_real_tray:
|
||||
return
|
||||
|
||||
timeout = time.clock() + 3
|
||||
while not self.has_closed and time.clock() < timeout:
|
||||
self.process_events()
|
||||
if not self.has_opened:
|
||||
self.fail('Timeout while waiting for the tray to close')
|
||||
with iotests.Timeout(3, 'Timeout while waiting for the tray to close'):
|
||||
while not self.has_closed:
|
||||
self.process_events()
|
||||
|
||||
class GeneralChangeTestsBaseClass(ChangeBaseClass):
|
||||
|
||||
@@ -265,7 +261,7 @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
|
||||
result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
|
||||
# Should be a no-op
|
||||
self.assert_qmp(result, 'return', {})
|
||||
self.assertEquals(self.vm.get_qmp_events(wait=False), [])
|
||||
self.assertEqual(self.vm.get_qmp_events(wait=False), [])
|
||||
|
||||
def test_remove_on_closed(self):
|
||||
if not self.has_real_tray:
|
||||
@@ -452,7 +448,7 @@ class TestChangeReadOnly(ChangeBaseClass):
|
||||
read_only_mode='retain')
|
||||
self.assert_qmp(result, 'error/class', 'GenericError')
|
||||
|
||||
self.assertEquals(self.vm.get_qmp_events(wait=False), [])
|
||||
self.assertEqual(self.vm.get_qmp_events(wait=False), [])
|
||||
|
||||
result = self.vm.qmp('query-block')
|
||||
self.assert_qmp(result, 'return[0]/inserted/ro', False)
|
||||
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test reopening a backing image after block-stream and block-commit
|
||||
#
|
||||
# Copyright (C) 2018 Igalia, S.L.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=berto@igalia.com
|
||||
|
||||
seq=`basename $0`
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here=`pwd`
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
rm -f "$TEST_IMG.base"
|
||||
rm -f "$TEST_IMG.int"
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
. ./common.qemu
|
||||
|
||||
# Any format implementing BlockDriver.bdrv_change_backing_file
|
||||
_supported_fmt qcow2 qed
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
IMG_SIZE=1M
|
||||
|
||||
# Create the images
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE | _filter_imgfmt
|
||||
TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" | _filter_imgfmt
|
||||
_make_test_img -b "$TEST_IMG.int" | _filter_imgfmt
|
||||
|
||||
# First test: reopen $TEST.IMG changing the detect-zeroes option on
|
||||
# its backing file ($TEST_IMG.int).
|
||||
echo
|
||||
echo "*** Change an option on the backing file"
|
||||
echo
|
||||
_launch_qemu -drive if=none,file="${TEST_IMG}"
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'qmp_capabilities' }" \
|
||||
'return'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'human-monitor-command',
|
||||
'arguments': { 'command-line':
|
||||
'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
|
||||
"return"
|
||||
|
||||
_cleanup_qemu
|
||||
|
||||
# Second test: stream $TEST_IMG.base into $TEST_IMG.int and then
|
||||
# reopen $TEST.IMG changing the detect-zeroes option on its new
|
||||
# backing file ($TEST_IMG.base).
|
||||
echo
|
||||
echo "*** Stream and then change an option on the backing file"
|
||||
echo
|
||||
_launch_qemu -drive if=none,file="${TEST_IMG}"
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'qmp_capabilities' }" \
|
||||
'return'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'block-stream', \
|
||||
'arguments': { 'device': 'none0',
|
||||
'base': '${TEST_IMG}.base' } }" \
|
||||
'return'
|
||||
|
||||
# Wait for block-stream to finish
|
||||
sleep 0.5
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'human-monitor-command',
|
||||
'arguments': { 'command-line':
|
||||
'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
|
||||
"return"
|
||||
|
||||
_cleanup_qemu
|
||||
|
||||
# Third test: commit $TEST_IMG.int into $TEST_IMG.base and then reopen
|
||||
# $TEST.IMG changing the detect-zeroes option on its new backing file
|
||||
# ($TEST_IMG.base).
|
||||
echo
|
||||
echo "*** Commit and then change an option on the backing file"
|
||||
echo
|
||||
# Create the images again
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE | _filter_imgfmt
|
||||
TEST_IMG="$TEST_IMG.int" _make_test_img -b "$TEST_IMG.base" | _filter_imgfmt
|
||||
_make_test_img -b "$TEST_IMG.int" | _filter_imgfmt
|
||||
|
||||
_launch_qemu -drive if=none,file="${TEST_IMG}"
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'qmp_capabilities' }" \
|
||||
'return'
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'block-commit', \
|
||||
'arguments': { 'device': 'none0',
|
||||
'top': '${TEST_IMG}.int' } }" \
|
||||
'return'
|
||||
|
||||
# Wait for block-commit to finish
|
||||
sleep 0.5
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE \
|
||||
"{ 'execute': 'human-monitor-command',
|
||||
'arguments': { 'command-line':
|
||||
'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
|
||||
"return"
|
||||
|
||||
_cleanup_qemu
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
||||
@@ -0,0 +1,39 @@
|
||||
QA output created by 161
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
|
||||
Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int
|
||||
|
||||
*** Change an option on the backing file
|
||||
|
||||
{"return": {}}
|
||||
{"return": ""}
|
||||
|
||||
*** Stream and then change an option on the backing file
|
||||
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "stream"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
|
||||
{"return": ""}
|
||||
|
||||
*** Commit and then change an option on the backing file
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
|
||||
Formatting 'TEST_DIR/t.IMGFMT.int', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.int
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
|
||||
{"return": ""}
|
||||
*** done
|
||||
+35
-8
@@ -57,10 +57,11 @@ run_qemu()
|
||||
}
|
||||
|
||||
echo
|
||||
echo "=== Create partially sparse image, then add dirty bitmap ==="
|
||||
echo "=== Create partially sparse image, then add dirty bitmaps ==="
|
||||
echo
|
||||
|
||||
_make_test_img 4M
|
||||
# Two bitmaps, to contrast granularity issues
|
||||
_make_test_img -o cluster_size=4k 4M
|
||||
$QEMU_IO -c 'w -P 0x11 1M 2M' "$TEST_IMG" | _filter_qemu_io
|
||||
run_qemu <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
@@ -78,7 +79,16 @@ run_qemu <<EOF
|
||||
"arguments": {
|
||||
"node": "n",
|
||||
"name": "b",
|
||||
"persistent": true
|
||||
"persistent": true,
|
||||
"granularity": 65536
|
||||
}
|
||||
}
|
||||
{ "execute": "block-dirty-bitmap-add",
|
||||
"arguments": {
|
||||
"node": "n",
|
||||
"name": "b2",
|
||||
"persistent": true,
|
||||
"granularity": 512
|
||||
}
|
||||
}
|
||||
{ "execute": "quit" }
|
||||
@@ -88,10 +98,11 @@ echo
|
||||
echo "=== Write part of the file under active bitmap ==="
|
||||
echo
|
||||
|
||||
$QEMU_IO -c 'w -P 0x22 2M 2M' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c 'w -P 0x22 512 512' -c 'w -P 0x33 2M 2M' "$TEST_IMG" \
|
||||
| _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "=== End dirty bitmap, and start serving image over NBD ==="
|
||||
echo "=== End dirty bitmaps, and start serving image over NBD ==="
|
||||
echo
|
||||
|
||||
_launch_qemu 2> >(_filter_nbd)
|
||||
@@ -103,6 +114,8 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"blockdev-add",
|
||||
"file":{"driver":"file", "filename":"'"$TEST_IMG"'"}}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable",
|
||||
"arguments":{"node":"n", "name":"b"}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable",
|
||||
"arguments":{"node":"n", "name":"b2"}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start",
|
||||
"arguments":{"addr":{"type":"unix",
|
||||
"data":{"path":"'"$TEST_DIR/nbd"'"}}}}' "return"
|
||||
@@ -110,26 +123,40 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
||||
"arguments":{"device":"n"}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
|
||||
"arguments":{"name":"n", "bitmap":"b"}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
|
||||
"arguments":{"device":"n", "name":"n2"}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
|
||||
"arguments":{"name":"n2", "bitmap":"b2"}}' "return"
|
||||
|
||||
echo
|
||||
echo "=== Contrast normal status with dirty-bitmap status ==="
|
||||
echo "=== Contrast normal status to large granularity dirty-bitmap ==="
|
||||
echo
|
||||
|
||||
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
|
||||
IMG="driver=nbd,export=n,server.type=unix,server.path=$TEST_DIR/nbd"
|
||||
$QEMU_IO -r -c 'r -P 0 0 1m' -c 'r -P 0x11 1m 1m' \
|
||||
-c 'r -P 0x22 2m 2m' --image-opts "$IMG" | _filter_qemu_io
|
||||
$QEMU_IO -r -c 'r -P 0x22 512 512' -c 'r -P 0 512k 512k' -c 'r -P 0x11 1m 1m' \
|
||||
-c 'r -P 0x33 2m 2m' --image-opts "$IMG" | _filter_qemu_io
|
||||
$QEMU_IMG map --output=json --image-opts \
|
||||
"$IMG" | _filter_qemu_img_map
|
||||
$QEMU_IMG map --output=json --image-opts \
|
||||
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b" | _filter_qemu_img_map
|
||||
|
||||
echo
|
||||
echo "=== Contrast to small granularity dirty-bitmap ==="
|
||||
echo
|
||||
|
||||
IMG="driver=nbd,export=n2,server.type=unix,server.path=$TEST_DIR/nbd"
|
||||
$QEMU_IMG map --output=json --image-opts \
|
||||
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
|
||||
|
||||
echo
|
||||
echo "=== End NBD server ==="
|
||||
echo
|
||||
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n"}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
|
||||
"arguments":{"name":"n2"}}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-stop"}' "return"
|
||||
_send_qemu_cmd $QEMU_HANDLE '{"execute":"quit"}' "return"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
QA output created by 223
|
||||
|
||||
=== Create partially sparse image, then add dirty bitmap ===
|
||||
=== Create partially sparse image, then add dirty bitmaps ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
|
||||
wrote 2097152/2097152 bytes at offset 1048576
|
||||
@@ -11,15 +11,18 @@ QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
|
||||
|
||||
|
||||
=== Write part of the file under active bitmap ===
|
||||
|
||||
wrote 512/512 bytes at offset 512
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 2097152/2097152 bytes at offset 2097152
|
||||
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== End dirty bitmap, and start serving image over NBD ===
|
||||
=== End dirty bitmaps, and start serving image over NBD ===
|
||||
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
@@ -27,18 +30,32 @@ wrote 2097152/2097152 bytes at offset 2097152
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
|
||||
=== Contrast normal status with dirty-bitmap status ===
|
||||
=== Contrast normal status to large granularity dirty-bitmap ===
|
||||
|
||||
read 1048576/1048576 bytes at offset 0
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 512
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 524288/524288 bytes at offset 524288
|
||||
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 1048576/1048576 bytes at offset 1048576
|
||||
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 2097152/2097152 bytes at offset 2097152
|
||||
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false},
|
||||
[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true},
|
||||
{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false},
|
||||
{ "start": 1048576, "length": 3145728, "depth": 0, "zero": false, "data": true}]
|
||||
[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true},
|
||||
[{ "start": 0, "length": 65536, "depth": 0, "zero": false, "data": false},
|
||||
{ "start": 65536, "length": 2031616, "depth": 0, "zero": false, "data": true},
|
||||
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
||||
|
||||
=== Contrast to small granularity dirty-bitmap ===
|
||||
|
||||
[{ "start": 0, "length": 512, "depth": 0, "zero": false, "data": true},
|
||||
{ "start": 512, "length": 512, "depth": 0, "zero": false, "data": false},
|
||||
{ "start": 1024, "length": 2096128, "depth": 0, "zero": false, "data": true},
|
||||
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
||||
|
||||
=== End NBD server ===
|
||||
@@ -46,4 +63,5 @@ read 2097152/2097152 bytes at offset 2097152
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
*** done
|
||||
@@ -66,7 +66,7 @@ $QEMU_IO -c 'w -P 0x11 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== check TLS client to plain server fails =="
|
||||
nbd_server_start_tcp_socket "$TEST_IMG"
|
||||
nbd_server_start_tcp_socket -f $IMGFMT "$TEST_IMG"
|
||||
|
||||
$QEMU_IMG info --image-opts \
|
||||
--object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \
|
||||
@@ -78,7 +78,10 @@ nbd_server_stop
|
||||
echo
|
||||
echo "== check plain client to TLS server fails =="
|
||||
|
||||
nbd_server_start_tcp_socket --object tls-creds-x509,dir=${tls_dir}/server1,endpoint=server,id=tls0,verify-peer=yes --tls-creds tls0 "$TEST_IMG"
|
||||
nbd_server_start_tcp_socket \
|
||||
--object tls-creds-x509,dir=${tls_dir}/server1,endpoint=server,id=tls0,verify-peer=yes \
|
||||
--tls-creds tls0 \
|
||||
-f $IMGFMT "$TEST_IMG"
|
||||
|
||||
$QEMU_IMG info nbd://localhost:$nbd_tcp_port 2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
|
||||
@@ -104,7 +107,7 @@ $QEMU_IO -c 'r -P 0x11 1m 1m' -c 'w -P 0x22 1m 1m' --image-opts \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | _filter_qemu_io
|
||||
|
||||
$QEMU_IO -f qcow2 -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -f $IMGFMT -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2018 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
|
||||
#
|
||||
# Check that block node activation and inactivation works with a block graph
|
||||
# that is built with individually created nodes
|
||||
|
||||
import iotests
|
||||
import os
|
||||
|
||||
iotests.verify_image_format(supported_fmts=['qcow2'])
|
||||
iotests.verify_platform(['linux'])
|
||||
|
||||
with iotests.FilePath('img') as img_path, \
|
||||
iotests.FilePath('backing') as backing_path, \
|
||||
iotests.FilePath('mig_fifo_a') as fifo_a, \
|
||||
iotests.FilePath('mig_fifo_b') as fifo_b, \
|
||||
iotests.VM(path_suffix='a') as vm_a, \
|
||||
iotests.VM(path_suffix='b') as vm_b:
|
||||
|
||||
iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, backing_path, '64M')
|
||||
iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, img_path, '64M')
|
||||
|
||||
os.mkfifo(fifo_a)
|
||||
os.mkfifo(fifo_b)
|
||||
|
||||
iotests.log('Launching source VM...')
|
||||
(vm_a.add_blockdev('file,filename=%s,node-name=drive0-file' % (img_path))
|
||||
.add_blockdev('%s,file=drive0-file,node-name=drive0' % (iotests.imgfmt))
|
||||
.add_blockdev('file,filename=%s,node-name=drive0-backing-file' % (backing_path))
|
||||
.add_blockdev('%s,file=drive0-backing-file,node-name=drive0-backing' % (iotests.imgfmt))
|
||||
.launch())
|
||||
|
||||
iotests.log('Launching destination VM...')
|
||||
(vm_b.add_blockdev('file,filename=%s,node-name=drive0-file' % (img_path))
|
||||
.add_blockdev('%s,file=drive0-file,node-name=drive0' % (iotests.imgfmt))
|
||||
.add_blockdev('file,filename=%s,node-name=drive0-backing-file' % (backing_path))
|
||||
.add_blockdev('%s,file=drive0-backing-file,node-name=drive0-backing' % (iotests.imgfmt))
|
||||
.add_incoming("exec: cat '%s'" % (fifo_a))
|
||||
.launch())
|
||||
|
||||
# Add a child node that was created after the parent node. The reverse case
|
||||
# is covered by the -blockdev options above.
|
||||
iotests.log(vm_a.qmp('blockdev-snapshot', node='drive0-backing',
|
||||
overlay='drive0'))
|
||||
iotests.log(vm_b.qmp('blockdev-snapshot', node='drive0-backing',
|
||||
overlay='drive0'))
|
||||
|
||||
iotests.log('Enabling migration QMP events on A...')
|
||||
iotests.log(vm_a.qmp('migrate-set-capabilities', capabilities=[
|
||||
{
|
||||
'capability': 'events',
|
||||
'state': True
|
||||
}
|
||||
]))
|
||||
|
||||
iotests.log('Starting migration to B...')
|
||||
iotests.log(vm_a.qmp('migrate', uri='exec:cat >%s' % (fifo_a)))
|
||||
with iotests.Timeout(3, 'Migration does not complete'):
|
||||
while True:
|
||||
event = vm_a.event_wait('MIGRATION')
|
||||
iotests.log(event, filters=[iotests.filter_qmp_event])
|
||||
if event['data']['status'] == 'completed':
|
||||
break
|
||||
|
||||
iotests.log(vm_a.qmp('query-migrate')['return']['status'])
|
||||
iotests.log(vm_b.qmp('query-migrate')['return']['status'])
|
||||
|
||||
iotests.log(vm_a.qmp('query-status'))
|
||||
iotests.log(vm_b.qmp('query-status'))
|
||||
|
||||
iotests.log('Add a second parent to drive0-file...')
|
||||
iotests.log(vm_b.qmp('blockdev-add', driver='raw', file='drive0-file',
|
||||
node_name='drive0-raw'))
|
||||
|
||||
iotests.log('Restart A with -incoming and second parent...')
|
||||
vm_a.shutdown()
|
||||
(vm_a.add_blockdev('raw,file=drive0-file,node-name=drive0-raw')
|
||||
.add_incoming("exec: cat '%s'" % (fifo_b))
|
||||
.launch())
|
||||
|
||||
iotests.log(vm_a.qmp('blockdev-snapshot', node='drive0-backing',
|
||||
overlay='drive0'))
|
||||
|
||||
iotests.log('Enabling migration QMP events on B...')
|
||||
iotests.log(vm_b.qmp('migrate-set-capabilities', capabilities=[
|
||||
{
|
||||
'capability': 'events',
|
||||
'state': True
|
||||
}
|
||||
]))
|
||||
|
||||
iotests.log('Starting migration back to A...')
|
||||
iotests.log(vm_b.qmp('migrate', uri='exec:cat >%s' % (fifo_b)))
|
||||
with iotests.Timeout(3, 'Migration does not complete'):
|
||||
while True:
|
||||
event = vm_b.event_wait('MIGRATION')
|
||||
iotests.log(event, filters=[iotests.filter_qmp_event])
|
||||
if event['data']['status'] == 'completed':
|
||||
break
|
||||
|
||||
iotests.log(vm_a.qmp('query-migrate')['return']['status'])
|
||||
iotests.log(vm_b.qmp('query-migrate')['return']['status'])
|
||||
|
||||
iotests.log(vm_a.qmp('query-status'))
|
||||
iotests.log(vm_b.qmp('query-status'))
|
||||
@@ -0,0 +1,30 @@
|
||||
Launching source VM...
|
||||
Launching destination VM...
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
Enabling migration QMP events on A...
|
||||
{"return": {}}
|
||||
Starting migration to B...
|
||||
{"return": {}}
|
||||
{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
completed
|
||||
completed
|
||||
{"return": {"running": false, "singlestep": false, "status": "postmigrate"}}
|
||||
{"return": {"running": true, "singlestep": false, "status": "running"}}
|
||||
Add a second parent to drive0-file...
|
||||
{"return": {}}
|
||||
Restart A with -incoming and second parent...
|
||||
{"return": {}}
|
||||
Enabling migration QMP events on B...
|
||||
{"return": {}}
|
||||
Starting migration back to A...
|
||||
{"return": {}}
|
||||
{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
completed
|
||||
completed
|
||||
{"return": {"running": true, "singlestep": false, "status": "running"}}
|
||||
{"return": {"running": false, "singlestep": false, "status": "postmigrate"}}
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Simple mirror test
|
||||
#
|
||||
# Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
import iotests
|
||||
from iotests import qemu_img_create, qemu_io, file_path, log
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
|
||||
|
||||
from qemu import QEMUMachine
|
||||
|
||||
# Note:
|
||||
# This test was added to check that mirror dead-lock was fixed (see previous
|
||||
# commit before this test addition).
|
||||
# And it didn't reproduce if at least one of the following:
|
||||
# 1. use small image size
|
||||
# 2. use raw format (not qcow2)
|
||||
# 3. drop kvm and use iotests.VM() (maybe, because of qtest) (however, it still
|
||||
# reproduces, if just drop kvm, but gdb failed to produce full backtraces
|
||||
# for me)
|
||||
# 4. add iothread
|
||||
|
||||
size = 1 * 1024 * 1024 * 1024
|
||||
|
||||
iotests.verify_image_format(supported_fmts=['qcow2'])
|
||||
|
||||
disk = file_path('disk')
|
||||
|
||||
# prepare source image
|
||||
qemu_img_create('-f', iotests.imgfmt, '-o', 'preallocation=metadata', disk,
|
||||
str(size))
|
||||
|
||||
vm = QEMUMachine(iotests.qemu_prog)
|
||||
vm.add_args('-machine', 'pc,accel=kvm')
|
||||
vm.add_args('-drive', 'id=src,file=' + disk)
|
||||
vm.launch()
|
||||
|
||||
log(vm.qmp('object-add', qom_type='throttle-group', id='tg0',
|
||||
props={ 'x-bps-total': size }))
|
||||
|
||||
log(vm.qmp('blockdev-add',
|
||||
**{ 'node-name': 'target',
|
||||
'driver': 'throttle',
|
||||
'throttle-group': 'tg0',
|
||||
'file': {
|
||||
'driver': 'null-co',
|
||||
'size': size
|
||||
} }))
|
||||
|
||||
log(vm.qmp('blockdev-mirror', device='src', target='target', sync='full'))
|
||||
|
||||
try:
|
||||
vm.event_wait('BLOCK_JOB_READY', timeout=10.0)
|
||||
except:
|
||||
vm.shutdown()
|
||||
raise
|
||||
|
||||
vm.shutdown()
|
||||
@@ -0,0 +1,3 @@
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
@@ -31,6 +31,9 @@ tls_x509_cleanup()
|
||||
|
||||
tls_x509_init()
|
||||
{
|
||||
(certtool --help) >/dev/null 2>&1 || \
|
||||
_notrun "certtool utility not found, skipping test"
|
||||
|
||||
mkdir -p "${tls_dir}"
|
||||
|
||||
# use a fixed key so we don't waste system entropy on
|
||||
|
||||
@@ -167,6 +167,7 @@
|
||||
158 rw auto quick
|
||||
159 rw auto quick
|
||||
160 rw auto quick
|
||||
161 rw auto quick
|
||||
162 auto quick
|
||||
163 rw auto
|
||||
165 rw auto quick
|
||||
@@ -230,3 +231,5 @@
|
||||
231 auto quick
|
||||
232 auto quick
|
||||
233 auto quick
|
||||
234 auto quick migration
|
||||
235 auto quick
|
||||
@@ -581,7 +581,7 @@ class QMPTestCase(unittest.TestCase):
|
||||
def wait_ready_and_cancel(self, drive='drive0'):
|
||||
self.wait_ready(drive=drive)
|
||||
event = self.cancel_and_wait(drive=drive)
|
||||
self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED')
|
||||
self.assertEqual(event['event'], 'BLOCK_JOB_COMPLETED')
|
||||
self.assert_qmp(event, 'data/type', 'mirror')
|
||||
self.assert_qmp(event, 'data/offset', event['data']['len'])
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ vubr_backend_recv_cb(int sock, void *ctx)
|
||||
.msg_name = (struct sockaddr *) &vubr->backend_udp_dest,
|
||||
.msg_namelen = sizeof(struct sockaddr_in),
|
||||
.msg_iov = sg,
|
||||
.msg_iovlen = elem->in_num,
|
||||
.msg_iovlen = num,
|
||||
.msg_flags = MSG_DONTWAIT,
|
||||
};
|
||||
do {
|
||||
|
||||
+57
-7
@@ -24,7 +24,6 @@
|
||||
|
||||
#define PCI_SLOT_HP 0x06
|
||||
#define PCI_SLOT 0x04
|
||||
#define PCI_FN 0x00
|
||||
|
||||
#define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
|
||||
#define VNET_HDR_SIZE sizeof(struct virtio_net_hdr_mrg_rxbuf)
|
||||
@@ -52,17 +51,21 @@ static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot)
|
||||
return dev;
|
||||
}
|
||||
|
||||
static QOSState *pci_test_start(int socket)
|
||||
GCC_FMT_ATTR(1, 2)
|
||||
static QOSState *pci_test_start(const char *cmd, ...)
|
||||
{
|
||||
QOSState *qs;
|
||||
va_list ap;
|
||||
const char *arch = qtest_get_arch();
|
||||
const char *cmd = "-netdev socket,fd=%d,id=hs0 -device "
|
||||
"virtio-net-pci,netdev=hs0";
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
qs = qtest_pc_boot(cmd, socket);
|
||||
va_start(ap, cmd);
|
||||
qs = qtest_pc_vboot(cmd, ap);
|
||||
va_end(ap);
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
qs = qtest_spapr_boot(cmd, socket);
|
||||
va_start(ap, cmd);
|
||||
qs = qtest_spapr_vboot(cmd, ap);
|
||||
va_end(ap);
|
||||
} else {
|
||||
g_printerr("virtio-net tests are only available on x86 or ppc64\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -223,7 +226,8 @@ static void pci_basic(gconstpointer data)
|
||||
ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
|
||||
g_assert_cmpint(ret, !=, -1);
|
||||
|
||||
qs = pci_test_start(sv[1]);
|
||||
qs = pci_test_start("-netdev socket,fd=%d,id=hs0 -device "
|
||||
"virtio-net-pci,netdev=hs0", sv[1]);
|
||||
dev = virtio_net_pci_init(qs->pcibus, PCI_SLOT);
|
||||
|
||||
rx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
|
||||
@@ -241,6 +245,48 @@ static void pci_basic(gconstpointer data)
|
||||
g_free(dev);
|
||||
qtest_shutdown(qs);
|
||||
}
|
||||
|
||||
static void large_tx(gconstpointer data)
|
||||
{
|
||||
QVirtioPCIDevice *dev;
|
||||
QOSState *qs;
|
||||
QVirtQueuePCI *tx, *rx;
|
||||
QVirtQueue *vq;
|
||||
uint64_t req_addr;
|
||||
uint32_t free_head;
|
||||
size_t alloc_size = (size_t)data / 64;
|
||||
int i;
|
||||
|
||||
qs = pci_test_start("-netdev hubport,id=hp0,hubid=0 "
|
||||
"-device virtio-net-pci,netdev=hp0");
|
||||
dev = virtio_net_pci_init(qs->pcibus, PCI_SLOT);
|
||||
|
||||
rx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
|
||||
tx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 1);
|
||||
|
||||
driver_init(&dev->vdev);
|
||||
vq = &tx->vq;
|
||||
|
||||
/* Bypass the limitation by pointing several descriptors to a single
|
||||
* smaller area */
|
||||
req_addr = guest_alloc(qs->alloc, alloc_size);
|
||||
free_head = qvirtqueue_add(vq, req_addr, alloc_size, false, true);
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
qvirtqueue_add(vq, req_addr, alloc_size, false, i != 63);
|
||||
}
|
||||
qvirtqueue_kick(&dev->vdev, vq, free_head);
|
||||
|
||||
qvirtio_wait_used_elem(&dev->vdev, vq, free_head, NULL,
|
||||
QVIRTIO_NET_TIMEOUT_US);
|
||||
|
||||
qvirtqueue_cleanup(dev->vdev.bus, &tx->vq, qs->alloc);
|
||||
qvirtqueue_cleanup(dev->vdev.bus, &rx->vq, qs->alloc);
|
||||
qvirtio_pci_device_disable(dev);
|
||||
g_free(dev->pdev);
|
||||
g_free(dev);
|
||||
qtest_shutdown(qs);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void hotplug(void)
|
||||
@@ -266,6 +312,10 @@ int main(int argc, char **argv)
|
||||
qtest_add_data_func("/virtio/net/pci/basic", send_recv_test, pci_basic);
|
||||
qtest_add_data_func("/virtio/net/pci/rx_stop_cont",
|
||||
stop_cont_test, pci_basic);
|
||||
qtest_add_data_func("/virtio/net/pci/large_tx_uint_max",
|
||||
(gconstpointer)UINT_MAX, large_tx);
|
||||
qtest_add_data_func("/virtio/net/pci/large_tx_net_bufsize",
|
||||
(gconstpointer)NET_BUFSIZE, large_tx);
|
||||
#endif
|
||||
qtest_add_func("/virtio/net/pci/hotplug", hotplug);
|
||||
|
||||
|
||||
+1
-1
@@ -411,13 +411,13 @@ static int qemu_vfio_init_ramblock(const char *block_name, void *host_addr,
|
||||
|
||||
static void qemu_vfio_open_common(QEMUVFIOState *s)
|
||||
{
|
||||
qemu_mutex_init(&s->lock);
|
||||
s->ram_notifier.ram_block_added = qemu_vfio_ram_block_added;
|
||||
s->ram_notifier.ram_block_removed = qemu_vfio_ram_block_removed;
|
||||
ram_block_notifier_add(&s->ram_notifier);
|
||||
s->low_water_mark = QEMU_VFIO_IOVA_MIN;
|
||||
s->high_water_mark = QEMU_VFIO_IOVA_MAX;
|
||||
qemu_ram_foreach_block(qemu_vfio_init_ramblock, s);
|
||||
qemu_mutex_init(&s->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -128,6 +128,7 @@ int main(int argc, char **argv)
|
||||
#include "qapi/qapi-commands-block-core.h"
|
||||
#include "qapi/qapi-commands-misc.h"
|
||||
#include "qapi/qapi-commands-run-state.h"
|
||||
#include "qapi/qapi-commands-ui.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "sysemu/iothread.h"
|
||||
|
||||
@@ -1522,9 +1523,6 @@ static int machine_help_func(QemuOpts *opts, MachineState *machine)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
/* main execution loop */
|
||||
|
||||
struct vm_change_state_entry {
|
||||
VMChangeStateHandler *cb;
|
||||
void *opaque;
|
||||
@@ -2055,6 +2053,11 @@ static void parse_display_qapi(const char *optarg)
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
DisplayOptions *qmp_query_display_options(Error **errp)
|
||||
{
|
||||
return QAPI_CLONE(DisplayOptions, &dpy);
|
||||
}
|
||||
|
||||
static void parse_display(const char *p)
|
||||
{
|
||||
const char *opts;
|
||||
@@ -2244,8 +2247,10 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp)
|
||||
size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */
|
||||
buf = g_memdup(str, size);
|
||||
} else {
|
||||
if (!g_file_get_contents(file, &buf, &size, NULL)) {
|
||||
error_setg(errp, "can't load %s", file);
|
||||
GError *err = NULL;
|
||||
if (!g_file_get_contents(file, &buf, &size, &err)) {
|
||||
error_setg(errp, "can't load %s: %s", file, err->message);
|
||||
g_error_free(err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user