qemu: Rebase from qemu-4.0.0 to qemu-4.0.1
Rebase to qemu-4.0.1 and drop redunt patches. Update release version info. Signed-off-by: Ying Fang <fangying1@huawei.com>
This commit is contained in:
parent
ac7cc5760b
commit
87b139ea79
@ -1,107 +0,0 @@
|
||||
From 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Wed, 17 Apr 2019 17:15:25 +0200
|
||||
Subject: [PATCH] block: Fix AioContext switch for bs->drv == NULL
|
||||
|
||||
Even for block nodes with bs->drv == NULL, we can't just ignore a
|
||||
bdrv_set_aio_context() call. Leaving the node in its old context can
|
||||
mean that it's still in an iothread context in bdrv_close_all() during
|
||||
shutdown, resulting in an attempted unlock of the AioContext lock which
|
||||
we don't hold.
|
||||
|
||||
This is an example stack trace of a related crash:
|
||||
|
||||
#0 0x00007ffff59da57f in raise () at /lib64/libc.so.6
|
||||
#1 0x00007ffff59c4895 in abort () at /lib64/libc.so.6
|
||||
#2 0x0000555555b97b1e in error_exit (err=<optimized out>, msg=msg@entry=0x555555d386d0 <__func__.19059> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36
|
||||
#3 0x0000555555b97f7f in qemu_mutex_unlock_impl (mutex=mutex@entry=0x5555568002f0, file=file@entry=0x555555d378df "util/async.c", line=line@entry=507) at util/qemu-thread-posix.c:97
|
||||
#4 0x0000555555b92f55 in aio_context_release (ctx=ctx@entry=0x555556800290) at util/async.c:507
|
||||
#5 0x0000555555b05cf8 in bdrv_prwv_co (child=child@entry=0x7fffc80012f0, offset=offset@entry=131072, qiov=qiov@entry=0x7fffffffd4f0, is_write=is_write@entry=true, flags=flags@entry=0)
|
||||
at block/io.c:833
|
||||
#6 0x0000555555b060a9 in bdrv_pwritev (qiov=0x7fffffffd4f0, offset=131072, child=0x7fffc80012f0) at block/io.c:990
|
||||
#7 0x0000555555b060a9 in bdrv_pwrite (child=0x7fffc80012f0, offset=131072, buf=<optimized out>, bytes=<optimized out>) at block/io.c:990
|
||||
#8 0x0000555555ae172b in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568cc740, i=i@entry=0) at block/qcow2-cache.c:51
|
||||
#9 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568cc740) at block/qcow2-cache.c:248
|
||||
#10 0x0000555555ae15de in qcow2_cache_flush (bs=0x555556810680, c=<optimized out>) at block/qcow2-cache.c:259
|
||||
#11 0x0000555555ae16b1 in qcow2_cache_flush_dependency (c=0x5555568a1700, c=0x5555568a1700, bs=0x555556810680) at block/qcow2-cache.c:194
|
||||
#12 0x0000555555ae16b1 in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568a1700, i=i@entry=0) at block/qcow2-cache.c:194
|
||||
#13 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568a1700) at block/qcow2-cache.c:248
|
||||
#14 0x0000555555ae15de in qcow2_cache_flush (bs=bs@entry=0x555556810680, c=<optimized out>) at block/qcow2-cache.c:259
|
||||
#15 0x0000555555ad242c in qcow2_inactivate (bs=bs@entry=0x555556810680) at block/qcow2.c:2124
|
||||
#16 0x0000555555ad2590 in qcow2_close (bs=0x555556810680) at block/qcow2.c:2153
|
||||
#17 0x0000555555ab0c62 in bdrv_close (bs=0x555556810680) at block.c:3358
|
||||
#18 0x0000555555ab0c62 in bdrv_delete (bs=0x555556810680) at block.c:3542
|
||||
#19 0x0000555555ab0c62 in bdrv_unref (bs=0x555556810680) at block.c:4598
|
||||
#20 0x0000555555af4d72 in blk_remove_bs (blk=blk@entry=0x5555568103d0) at block/block-backend.c:785
|
||||
#21 0x0000555555af4dbb in blk_remove_all_bs () at block/block-backend.c:483
|
||||
#22 0x0000555555aae02f in bdrv_close_all () at block.c:3412
|
||||
#23 0x00005555557f9796 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4776
|
||||
|
||||
The reproducer I used is a qcow2 image on gluster volume, where the
|
||||
virtual disk size (4 GB) is larger than the gluster volume size (64M),
|
||||
so we can easily trigger an ENOSPC. This backend is assigned to a
|
||||
virtio-blk device using an iothread, and then from the guest a
|
||||
'dd if=/dev/zero of=/dev/vda bs=1G count=1' causes the VM to stop
|
||||
because of an I/O error. qemu_gluster_co_flush_to_disk() sets
|
||||
bs->drv = NULL on error, so when virtio-blk stops the dataplane, the
|
||||
block nodes stay in the iothread AioContext. A 'quit' monitor command
|
||||
issued from this paused state crashes the process.
|
||||
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1631227
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
|
||||
(cherry-picked from commit 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8)
|
||||
---
|
||||
block.c | 12 ++----------
|
||||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index 16615bc876..9ae5c0ed2f 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -5672,10 +5672,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
BdrvAioNotifier *baf, *baf_tmp;
|
||||
BdrvChild *child;
|
||||
|
||||
- if (!bs->drv) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
assert(!bs->walking_aio_notifiers);
|
||||
bs->walking_aio_notifiers = true;
|
||||
QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
|
||||
@@ -5690,7 +5686,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
*/
|
||||
bs->walking_aio_notifiers = false;
|
||||
|
||||
- if (bs->drv->bdrv_detach_aio_context) {
|
||||
+ if (bs->drv && bs->drv->bdrv_detach_aio_context) {
|
||||
bs->drv->bdrv_detach_aio_context(bs);
|
||||
}
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
@@ -5709,10 +5705,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
BdrvAioNotifier *ban, *ban_tmp;
|
||||
BdrvChild *child;
|
||||
|
||||
- if (!bs->drv) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
if (bs->quiesce_counter) {
|
||||
aio_disable_external(new_context);
|
||||
}
|
||||
@@ -5722,7 +5714,7 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
bdrv_attach_aio_context(child->bs, new_context);
|
||||
}
|
||||
- if (bs->drv->bdrv_attach_aio_context) {
|
||||
+ if (bs->drv && bs->drv->bdrv_attach_aio_context) {
|
||||
bs->drv->bdrv_attach_aio_context(bs, new_context);
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
From c24d971c130d889d4d001d2ae2cb02b9a34d51b6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
|
||||
Date: Thu, 12 Sep 2019 00:08:49 +0200
|
||||
Subject: [PATCH] block/create: Do not abort if a block driver is not available
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The 'blockdev-create' QMP command was introduced as experimental
|
||||
feature in commit b0292b851b8, using the assert() debug call.
|
||||
It got promoted to 'stable' command in 3fb588a0f2c, but the
|
||||
assert call was not removed.
|
||||
|
||||
Some block drivers are optional, and bdrv_find_format() might
|
||||
return a NULL value, triggering the assertion.
|
||||
|
||||
Stable code is not expected to abort, so return an error instead.
|
||||
|
||||
This is easily reproducible when libnfs is not installed:
|
||||
|
||||
./configure
|
||||
[...]
|
||||
module support no
|
||||
Block whitelist (rw)
|
||||
Block whitelist (ro)
|
||||
libiscsi support yes
|
||||
libnfs support no
|
||||
[...]
|
||||
|
||||
Start QEMU:
|
||||
|
||||
$ qemu-system-x86_64 -S -qmp unix:/tmp/qemu.qmp,server,nowait
|
||||
|
||||
Send the 'blockdev-create' with the 'nfs' driver:
|
||||
|
||||
$ ( cat << 'EOF'
|
||||
{'execute': 'qmp_capabilities'}
|
||||
{'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'}
|
||||
EOF
|
||||
) | socat STDIO UNIX:/tmp/qemu.qmp
|
||||
{"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 4}, "package": "v4.1.0-733-g89ea03a7dc"}, "capabilities": ["oob"]}}
|
||||
{"return": {}}
|
||||
|
||||
QEMU crashes:
|
||||
|
||||
$ gdb qemu-system-x86_64 core
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
(gdb) bt
|
||||
#0 0x00007ffff510957f in raise () at /lib64/libc.so.6
|
||||
#1 0x00007ffff50f3895 in abort () at /lib64/libc.so.6
|
||||
#2 0x00007ffff50f3769 in _nl_load_domain.cold.0 () at /lib64/libc.so.6
|
||||
#3 0x00007ffff5101a26 in .annobin_assert.c_end () at /lib64/libc.so.6
|
||||
#4 0x0000555555d7e1f1 in qmp_blockdev_create (job_id=0x555556baee40 "x", options=0x555557666610, errp=0x7fffffffc770) at block/create.c:69
|
||||
#5 0x0000555555c96b52 in qmp_marshal_blockdev_create (args=0x7fffdc003830, ret=0x7fffffffc7f8, errp=0x7fffffffc7f0) at qapi/qapi-commands-block-core.c:1314
|
||||
#6 0x0000555555deb0a0 in do_qmp_dispatch (cmds=0x55555645de70 <qmp_commands>, request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131
|
||||
#7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 <qmp_commands>, request=0x7fffdc005c70, allow_oob=false) at qapi/qmp-dispatch.c:174
|
||||
|
||||
With this patch applied, QEMU returns a QMP error:
|
||||
|
||||
{'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'}
|
||||
{"id": "x", "error": {"class": "GenericError", "desc": "Block driver 'nfs' not found or not supported"}}
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reported-by: Xu Tian <xutian@redhat.com>
|
||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit d90d5cae2b10efc0e8d0b3cc91ff16201853d3ba)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
block/create.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/create.c b/block/create.c
|
||||
index 95341219ef..de5e97bb18 100644
|
||||
--- a/block/create.c
|
||||
+++ b/block/create.c
|
||||
@@ -63,9 +63,13 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
|
||||
const char *fmt = BlockdevDriver_str(options->driver);
|
||||
BlockDriver *drv = bdrv_find_format(fmt);
|
||||
|
||||
+ if (!drv) {
|
||||
+ error_setg(errp, "Block driver '%s' not found or not supported", fmt);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* If the driver is in the schema, we know that it exists. But it may not
|
||||
* be whitelisted. */
|
||||
- assert(drv);
|
||||
if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
|
||||
error_setg(errp, "Driver is not whitelisted");
|
||||
return;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,87 +0,0 @@
|
||||
From 9c3db310ff0b7473272ae8dce5e04e2f8a825390 Mon Sep 17 00:00:00 2001
|
||||
From: Max Reitz <mreitz@redhat.com>
|
||||
Date: Wed, 15 May 2019 06:15:40 +0200
|
||||
Subject: [PATCH] block/file-posix: Unaligned O_DIRECT block-status
|
||||
|
||||
Currently, qemu crashes whenever someone queries the block status of an
|
||||
unaligned image tail of an O_DIRECT image:
|
||||
$ echo > foo
|
||||
$ qemu-img map --image-opts driver=file,filename=foo,cache.direct=on
|
||||
Offset Length Mapped to File
|
||||
qemu-img: block/io.c:2093: bdrv_co_block_status: Assertion `*pnum &&
|
||||
QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset'
|
||||
failed.
|
||||
|
||||
This is because bdrv_co_block_status() checks that the result returned
|
||||
by the driver's implementation is aligned to the request_alignment, but
|
||||
file-posix can fail to do so, which is actually mentioned in a comment
|
||||
there: "[...] possibly including a partial sector at EOF".
|
||||
|
||||
Fix this by rounding up those partial sectors.
|
||||
|
||||
There are two possible alternative fixes:
|
||||
(1) We could refuse to open unaligned image files with O_DIRECT
|
||||
altogether. That sounds reasonable until you realize that qcow2
|
||||
does necessarily not fill up its metadata clusters, and that nobody
|
||||
runs qemu-img create with O_DIRECT. Therefore, unpreallocated qcow2
|
||||
files usually have an unaligned image tail.
|
||||
|
||||
(2) bdrv_co_block_status() could ignore unaligned tails. It actually
|
||||
throws away everything past the EOF already, so that sounds
|
||||
reasonable.
|
||||
Unfortunately, the block layer knows file lengths only with a
|
||||
granularity of BDRV_SECTOR_SIZE, so bdrv_co_block_status() usually
|
||||
would have to guess whether its file length information is inexact
|
||||
or whether the driver is broken.
|
||||
|
||||
Fixing what raw_co_block_status() returns is the safest thing to do.
|
||||
|
||||
There seems to be no other block driver that sets request_alignment and
|
||||
does not make sure that it always returns aligned values.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry-picked from commit 9c3db310ff0b7473272ae8dce5e04e2f8a825390)
|
||||
---
|
||||
block/file-posix.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/block/file-posix.c b/block/file-posix.c
|
||||
index e09e15bbf8..d018429672 100644
|
||||
--- a/block/file-posix.c
|
||||
+++ b/block/file-posix.c
|
||||
@@ -2488,6 +2488,8 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
|
||||
off_t data = 0, hole = 0;
|
||||
int ret;
|
||||
|
||||
+ assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
|
||||
+
|
||||
ret = fd_open(bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -2513,6 +2515,20 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
|
||||
/* On a data extent, compute bytes to the end of the extent,
|
||||
* possibly including a partial sector at EOF. */
|
||||
*pnum = MIN(bytes, hole - offset);
|
||||
+
|
||||
+ /*
|
||||
+ * We are not allowed to return partial sectors, though, so
|
||||
+ * round up if necessary.
|
||||
+ */
|
||||
+ if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
|
||||
+ int64_t file_length = raw_getlength(bs);
|
||||
+ if (file_length > 0) {
|
||||
+ /* Ignore errors, this is just a safeguard */
|
||||
+ assert(hole == file_length);
|
||||
+ }
|
||||
+ *pnum = ROUND_UP(*pnum, bs->bl.request_alignment);
|
||||
+ }
|
||||
+
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
} else {
|
||||
/* On a hole, compute bytes to the beginning of the next extent. */
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
From 6cb3e9e4f17c182c43ded773a04b1072c881aa78 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Lieven <pl@kamp.de>
|
||||
Date: Tue, 10 Sep 2019 17:41:09 +0200
|
||||
Subject: [PATCH] block/nfs: tear down aio before nfs_close
|
||||
|
||||
nfs_close is a sync call from libnfs and has its own event
|
||||
handler polling on the nfs FD. Avoid that both QEMU and libnfs
|
||||
are intefering here.
|
||||
|
||||
CC: qemu-stable@nongnu.org
|
||||
Signed-off-by: Peter Lieven <pl@kamp.de>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 601dc6559725f7a614b6f893611e17ff0908e914)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
block/nfs.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/nfs.c b/block/nfs.c
|
||||
index 531903610b..f04f675c63 100644
|
||||
--- a/block/nfs.c
|
||||
+++ b/block/nfs.c
|
||||
@@ -389,12 +389,14 @@ static void nfs_attach_aio_context(BlockDriverState *bs,
|
||||
static void nfs_client_close(NFSClient *client)
|
||||
{
|
||||
if (client->context) {
|
||||
+ qemu_mutex_lock(&client->mutex);
|
||||
+ aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
||||
+ false, NULL, NULL, NULL, NULL);
|
||||
+ qemu_mutex_unlock(&client->mutex);
|
||||
if (client->fh) {
|
||||
nfs_close(client->context, client->fh);
|
||||
client->fh = NULL;
|
||||
}
|
||||
- aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
||||
- false, NULL, NULL, NULL, NULL);
|
||||
nfs_destroy_context(client->context);
|
||||
client->context = NULL;
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
From 2429dc4eea91b381ff67a4d25ea9f6bbfe87c784 Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Thu, 23 May 2019 13:06:39 -0400
|
||||
Subject: [PATCH] blockdev-backup: don't check aio_context too early
|
||||
|
||||
in blockdev_backup_prepare, we check to make sure that the target is
|
||||
associated with a compatible aio context. However, do_blockdev_backup is
|
||||
called later and has some logic to move the target to a compatible
|
||||
aio_context. The transaction version will fail certain commands
|
||||
needlessly early as a result.
|
||||
|
||||
Allow blockdev_backup_prepare to simply call do_blockdev_backup, which
|
||||
will ultimately decide if the contexts are compatible or not.
|
||||
|
||||
Note: the transaction version has always disallowed this operation since
|
||||
its initial commit bd8baecd (2014), whereas the version of
|
||||
qmp_blockdev_backup at the time, from commit c29c1dd312f, tried to
|
||||
enforce the aio_context switch instead. It's not clear, and I can't see
|
||||
from the mailing list archives at the time, why the two functions take a
|
||||
different approach. It wasn't until later in efd7556708b (2016) that the
|
||||
standalone version tried to determine if it could set the context or
|
||||
not.
|
||||
|
||||
Reported-by: aihua liang <aliang@redhat.com>
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1683498
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Message-id: 20190523170643.20794-2-jsnow@redhat.com
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit d81e1efbea7d19c2f142d300df56538c73800590)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
blockdev.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 4775a07d93..d358169995 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -1871,10 +1871,6 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
||||
}
|
||||
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
- if (aio_context != bdrv_get_aio_context(target)) {
|
||||
- error_setg(errp, "Backup between two IO threads is not implemented");
|
||||
- return;
|
||||
- }
|
||||
aio_context_acquire(aio_context);
|
||||
state->bs = bs;
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
From b9405afb0956fe2c293a94bdc4440579e5c0efee Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Lopez <slp@redhat.com>
|
||||
Date: Wed, 11 Sep 2019 12:03:16 +0200
|
||||
Subject: [PATCH] blockjob: update nodes head while removing all bdrv
|
||||
|
||||
block_job_remove_all_bdrv() iterates through job->nodes, calling
|
||||
bdrv_root_unref_child() for each entry. The call to the latter may
|
||||
reach child_job_[can_]set_aio_ctx(), which will also attempt to
|
||||
traverse job->nodes, potentially finding entries that where freed
|
||||
on previous iterations.
|
||||
|
||||
To avoid this situation, update job->nodes head on each iteration to
|
||||
ensure that already freed entries are no longer linked to the list.
|
||||
|
||||
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631
|
||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190911100316.32282-1-mreitz@redhat.com
|
||||
Reviewed-by: Sergio Lopez <slp@redhat.com>
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit d876bf676f5e7c6aa9ac64555e48cba8734ecb2f)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
blockjob.c | 17 +++++++++++++----
|
||||
1 file changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/blockjob.c b/blockjob.c
|
||||
index 730101d282..d770144fd6 100644
|
||||
--- a/blockjob.c
|
||||
+++ b/blockjob.c
|
||||
@@ -193,14 +193,23 @@ static const BdrvChildRole child_job = {
|
||||
|
||||
void block_job_remove_all_bdrv(BlockJob *job)
|
||||
{
|
||||
- GSList *l;
|
||||
- for (l = job->nodes; l; l = l->next) {
|
||||
+ /*
|
||||
+ * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(),
|
||||
+ * which will also traverse job->nodes, so consume the list one by
|
||||
+ * one to make sure that such a concurrent access does not attempt
|
||||
+ * to process an already freed BdrvChild.
|
||||
+ */
|
||||
+ while (job->nodes) {
|
||||
+ GSList *l = job->nodes;
|
||||
BdrvChild *c = l->data;
|
||||
+
|
||||
+ job->nodes = l->next;
|
||||
+
|
||||
bdrv_op_unblock_all(c->bs, job->blocker);
|
||||
bdrv_root_unref_child(c);
|
||||
+
|
||||
+ g_slist_free_1(l);
|
||||
}
|
||||
- g_slist_free(job->nodes);
|
||||
- job->nodes = NULL;
|
||||
}
|
||||
|
||||
int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
From 754da86714d550c3f995f11a2587395081362e0a Mon Sep 17 00:00:00 2001
|
||||
From: Eric Blake <eblake@redhat.com>
|
||||
Date: Wed, 17 Apr 2019 12:11:00 -0500
|
||||
Subject: [PATCH] cutils: Fix size_to_str() on 32-bit platforms
|
||||
|
||||
When extracting a human-readable size formatter, we changed 'uint64_t
|
||||
div' pre-patch to 'unsigned long div' post-patch. Which breaks on
|
||||
32-bit platforms, resulting in 'inf' instead of intended values larger
|
||||
than 999GB.
|
||||
|
||||
Fixes: 22951aaa
|
||||
CC: qemu-stable@nongnu.org
|
||||
Reported-by: Max Reitz <mreitz@redhat.com>
|
||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry-picked from commit 754da86714d550c3f995f11a2587395081362e0a)
|
||||
---
|
||||
util/cutils.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/util/cutils.c b/util/cutils.c
|
||||
index e098debdc0..d682c90901 100644
|
||||
--- a/util/cutils.c
|
||||
+++ b/util/cutils.c
|
||||
@@ -825,7 +825,7 @@ const char *qemu_ether_ntoa(const MACAddr *mac)
|
||||
char *size_to_str(uint64_t val)
|
||||
{
|
||||
static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
|
||||
- unsigned long div;
|
||||
+ uint64_t div;
|
||||
int i;
|
||||
|
||||
/*
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,80 +0,0 @@
|
||||
From 53c641048e0a8da1d2bed76cbd17f259a35e39a0 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Mon, 29 Jul 2019 23:34:16 +0200
|
||||
Subject: [PATCH] dma-helpers: ensure AIO callback is invoked after
|
||||
cancellation
|
||||
|
||||
dma_aio_cancel unschedules the BH if there is one, which corresponds
|
||||
to the reschedule_dma case of dma_blk_cb. This can stall the DMA
|
||||
permanently, because dma_complete will never get invoked and therefore
|
||||
nobody will ever invoke the original AIO callback in dbs->common.cb.
|
||||
|
||||
Fix this by invoking the callback (which is ensured to happen after
|
||||
a bdrv_aio_cancel_async, or done manually in the dbs->bh case), and
|
||||
add assertions to check that the DMA state machine is indeed waiting
|
||||
for dma_complete or reschedule_dma, but never both.
|
||||
|
||||
Reported-by: John Snow <jsnow@redhat.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Message-id: 20190729213416.1972-1-pbonzini@redhat.com
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
(cherry picked from commit 539343c0a47e19d5dd64d846d64d084d9793681f)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
dma-helpers.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dma-helpers.c b/dma-helpers.c
|
||||
index 2d7e02d35e..d3871dc61e 100644
|
||||
--- a/dma-helpers.c
|
||||
+++ b/dma-helpers.c
|
||||
@@ -90,6 +90,7 @@ static void reschedule_dma(void *opaque)
|
||||
{
|
||||
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
|
||||
|
||||
+ assert(!dbs->acb && dbs->bh);
|
||||
qemu_bh_delete(dbs->bh);
|
||||
dbs->bh = NULL;
|
||||
dma_blk_cb(dbs, 0);
|
||||
@@ -111,15 +112,12 @@ static void dma_complete(DMAAIOCB *dbs, int ret)
|
||||
{
|
||||
trace_dma_complete(dbs, ret, dbs->common.cb);
|
||||
|
||||
+ assert(!dbs->acb && !dbs->bh);
|
||||
dma_blk_unmap(dbs);
|
||||
if (dbs->common.cb) {
|
||||
dbs->common.cb(dbs->common.opaque, ret);
|
||||
}
|
||||
qemu_iovec_destroy(&dbs->iov);
|
||||
- if (dbs->bh) {
|
||||
- qemu_bh_delete(dbs->bh);
|
||||
- dbs->bh = NULL;
|
||||
- }
|
||||
qemu_aio_unref(dbs);
|
||||
}
|
||||
|
||||
@@ -179,14 +177,21 @@ static void dma_aio_cancel(BlockAIOCB *acb)
|
||||
|
||||
trace_dma_aio_cancel(dbs);
|
||||
|
||||
+ assert(!(dbs->acb && dbs->bh));
|
||||
if (dbs->acb) {
|
||||
+ /* This will invoke dma_blk_cb. */
|
||||
blk_aio_cancel_async(dbs->acb);
|
||||
+ return;
|
||||
}
|
||||
+
|
||||
if (dbs->bh) {
|
||||
cpu_unregister_map_client(dbs->bh);
|
||||
qemu_bh_delete(dbs->bh);
|
||||
dbs->bh = NULL;
|
||||
}
|
||||
+ if (dbs->common.cb) {
|
||||
+ dbs->common.cb(dbs->common.opaque, -ECANCELED);
|
||||
+ }
|
||||
}
|
||||
|
||||
static AioContext *dma_get_aio_context(BlockAIOCB *acb)
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,124 +0,0 @@
|
||||
From 56deb8f0db72858985ba077cb0f678f2dbc13bba Mon Sep 17 00:00:00 2001
|
||||
From: Greg Kurz <groug@kaod.org>
|
||||
Date: Mon, 5 Aug 2019 15:56:58 +0800
|
||||
Subject: [PATCH] hw: Nuke hw_compat_4_0_1 and pc_compat_4_0_1
|
||||
|
||||
Commit c87759ce876a fixed a regression affecting pc-q35 machines by
|
||||
introducing a new pc-q35-4.0.1 machine version to be used instead
|
||||
of pc-q35-4.0. The only purpose was to revert the default behaviour
|
||||
of not using split irqchip, but the change also introduced the usual
|
||||
hw_compat and pc_compat bits, and wired them for pc-q35 only.
|
||||
|
||||
This raises questions when it comes to add new compat properties for
|
||||
4.0* machine versions of any architecture. Where to add them ? In
|
||||
4.0, 4.0.1 or both ? Error prone. Another possibility would be to teach
|
||||
all other architectures about 4.0.1. This solution isn't satisfying,
|
||||
especially since this is a pc-q35 specific issue.
|
||||
|
||||
It turns out that the split irqchip default is handled in the machine
|
||||
option function and doesn't involve compat lists at all.
|
||||
|
||||
Drop all the 4.0.1 compat lists and use the 4.0 ones instead in the 4.0.1
|
||||
machine option function.
|
||||
|
||||
Move the compat props that were added to the 4.0.1 since c87759ce876a to
|
||||
4.0.
|
||||
|
||||
Even if only hw_compat_4_0_1 had an impact on other architectures,
|
||||
drop pc_compat_4_0_1 as well for consistency.
|
||||
|
||||
Fixes: c87759ce876a "q35: Revert to kernel irqchip"
|
||||
Suggested-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Signed-off-by: Greg Kurz <groug@kaod.org>
|
||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Message-Id: <156051774276.244890.8660277280145466396.stgit@bahia.lan>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry-picked from commit 8e8cbed09ad9d577955691b4c061b61b602406d1)
|
||||
---
|
||||
hw/core/machine.c | 3 ---
|
||||
hw/i386/pc.c | 3 ---
|
||||
hw/i386/pc_q35.c | 9 +++++++--
|
||||
include/hw/boards.h | 3 ---
|
||||
include/hw/i386/pc.h | 3 ---
|
||||
5 files changed, 7 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index e41e6698..5d046a43 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -24,9 +24,6 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
|
||||
-GlobalProperty hw_compat_4_0_1[] = {};
|
||||
-const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1);
|
||||
-
|
||||
GlobalProperty hw_compat_4_0[] = {};
|
||||
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
|
||||
|
||||
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||
index b5311e7e..d98b737b 100644
|
||||
--- a/hw/i386/pc.c
|
||||
+++ b/hw/i386/pc.c
|
||||
@@ -115,9 +115,6 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
|
||||
/* Physical Address of PVH entry point read from kernel ELF NOTE */
|
||||
static size_t pvh_start_addr;
|
||||
|
||||
-GlobalProperty pc_compat_4_0_1[] = {};
|
||||
-const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1);
|
||||
-
|
||||
GlobalProperty pc_compat_4_0[] = {};
|
||||
const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
|
||||
|
||||
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||
index dcddc646..e3498a45 100644
|
||||
--- a/hw/i386/pc_q35.c
|
||||
+++ b/hw/i386/pc_q35.c
|
||||
@@ -378,8 +378,13 @@ static void pc_q35_4_0_1_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_q35_4_1_machine_options(m);
|
||||
m->alias = NULL;
|
||||
- compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len);
|
||||
- compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len);
|
||||
+ /*
|
||||
+ * This is the default machine for the 4.0-stable branch. It is basically
|
||||
+ * a 4.0 that doesn't use split irqchip by default. It MUST hence apply the
|
||||
+ * 4.0 compat props.
|
||||
+ */
|
||||
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
|
||||
}
|
||||
|
||||
DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL,
|
||||
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||
index ad3950d3..fe1885cb 100644
|
||||
--- a/include/hw/boards.h
|
||||
+++ b/include/hw/boards.h
|
||||
@@ -293,9 +293,6 @@ struct MachineState {
|
||||
} \
|
||||
type_init(machine_initfn##_register_types)
|
||||
|
||||
-extern GlobalProperty hw_compat_4_0_1[];
|
||||
-extern const size_t hw_compat_4_0_1_len;
|
||||
-
|
||||
extern GlobalProperty hw_compat_4_0[];
|
||||
extern const size_t hw_compat_4_0_len;
|
||||
|
||||
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||
index 5d563624..43df7230 100644
|
||||
--- a/include/hw/i386/pc.h
|
||||
+++ b/include/hw/i386/pc.h
|
||||
@@ -293,9 +293,6 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
||||
int e820_get_num_entries(void);
|
||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
-extern GlobalProperty pc_compat_4_0_1[];
|
||||
-extern const size_t pc_compat_4_0_1_len;
|
||||
-
|
||||
extern GlobalProperty pc_compat_4_0[];
|
||||
extern const size_t pc_compat_4_0_len;
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,232 +0,0 @@
|
||||
From 9bf2650bc3aab126b85c034bf86e27d564f9a1aa Mon Sep 17 00:00:00 2001
|
||||
From: Cornelia Huck <cohuck@redhat.com>
|
||||
Date: Thu, 11 Apr 2019 12:20:25 +0200
|
||||
Subject: [PATCH] hw: add compat machines for 4.1
|
||||
|
||||
Add 4.1 machine types for arm/i440fx/q35/s390x/spapr.
|
||||
|
||||
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
|
||||
Message-Id: <20190411102025.22559-1-cohuck@redhat.com>
|
||||
Acked-by: Greg Kurz <groug@kaod.org>
|
||||
Acked-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||
(cherry-picked from commit 9bf2650bc3aab126b85c034bf86e27d564f9a1aa)
|
||||
---
|
||||
hw/arm/virt.c | 9 ++++++++-
|
||||
hw/core/machine.c | 3 +++
|
||||
hw/i386/pc.c | 3 +++
|
||||
hw/i386/pc_piix.c | 14 +++++++++++++-
|
||||
hw/i386/pc_q35.c | 13 ++++++++++++-
|
||||
hw/ppc/spapr.c | 15 +++++++++++++--
|
||||
hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++-
|
||||
include/hw/boards.h | 3 +++
|
||||
include/hw/i386/pc.h | 3 +++
|
||||
9 files changed, 71 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index ce2664a30b..16ba67f7a7 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -1978,10 +1978,17 @@ static void machvirt_machine_init(void)
|
||||
}
|
||||
type_init(machvirt_machine_init);
|
||||
|
||||
+static void virt_machine_4_1_options(MachineClass *mc)
|
||||
+{
|
||||
+}
|
||||
+DEFINE_VIRT_MACHINE_AS_LATEST(4, 1)
|
||||
+
|
||||
static void virt_machine_4_0_options(MachineClass *mc)
|
||||
{
|
||||
+ virt_machine_4_1_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
}
|
||||
-DEFINE_VIRT_MACHINE_AS_LATEST(4, 0)
|
||||
+DEFINE_VIRT_MACHINE(4, 0)
|
||||
|
||||
static void virt_machine_3_1_options(MachineClass *mc)
|
||||
{
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index 743fef2898..5d046a43e3 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -24,6 +24,9 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
|
||||
+GlobalProperty hw_compat_4_0[] = {};
|
||||
+const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
|
||||
+
|
||||
GlobalProperty hw_compat_3_1[] = {
|
||||
{ "pcie-root-port", "x-speed", "2_5" },
|
||||
{ "pcie-root-port", "x-width", "1" },
|
||||
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||
index f2c15bf1f2..d98b737b8f 100644
|
||||
--- a/hw/i386/pc.c
|
||||
+++ b/hw/i386/pc.c
|
||||
@@ -115,6 +115,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
|
||||
/* Physical Address of PVH entry point read from kernel ELF NOTE */
|
||||
static size_t pvh_start_addr;
|
||||
|
||||
+GlobalProperty pc_compat_4_0[] = {};
|
||||
+const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
|
||||
+
|
||||
GlobalProperty pc_compat_3_1[] = {
|
||||
{ "intel-iommu", "dma-drain", "off" },
|
||||
{ "Opteron_G3" "-" TYPE_X86_CPU, "rdtscp", "off" },
|
||||
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||
index 8ad8e885c6..2a7700b564 100644
|
||||
--- a/hw/i386/pc_piix.c
|
||||
+++ b/hw/i386/pc_piix.c
|
||||
@@ -428,13 +428,25 @@ static void pc_i440fx_machine_options(MachineClass *m)
|
||||
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
|
||||
}
|
||||
|
||||
-static void pc_i440fx_4_0_machine_options(MachineClass *m)
|
||||
+static void pc_i440fx_4_1_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_i440fx_machine_options(m);
|
||||
m->alias = "pc";
|
||||
m->is_default = 1;
|
||||
}
|
||||
|
||||
+DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
|
||||
+ pc_i440fx_4_1_machine_options);
|
||||
+
|
||||
+static void pc_i440fx_4_0_machine_options(MachineClass *m)
|
||||
+{
|
||||
+ pc_i440fx_4_1_machine_options(m);
|
||||
+ m->alias = NULL;
|
||||
+ m->is_default = 0;
|
||||
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
|
||||
+}
|
||||
+
|
||||
DEFINE_I440FX_MACHINE(v4_0, "pc-i440fx-4.0", NULL,
|
||||
pc_i440fx_4_0_machine_options);
|
||||
|
||||
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||
index 372c6b73be..37dd350511 100644
|
||||
--- a/hw/i386/pc_q35.c
|
||||
+++ b/hw/i386/pc_q35.c
|
||||
@@ -365,12 +365,23 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||
m->max_cpus = 288;
|
||||
}
|
||||
|
||||
-static void pc_q35_4_0_machine_options(MachineClass *m)
|
||||
+static void pc_q35_4_1_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_q35_machine_options(m);
|
||||
m->alias = "q35";
|
||||
}
|
||||
|
||||
+DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
|
||||
+ pc_q35_4_1_machine_options);
|
||||
+
|
||||
+static void pc_q35_4_0_machine_options(MachineClass *m)
|
||||
+{
|
||||
+ pc_q35_4_1_machine_options(m);
|
||||
+ m->alias = NULL;
|
||||
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
|
||||
+}
|
||||
+
|
||||
DEFINE_Q35_MACHINE(v4_0, "pc-q35-4.0", NULL,
|
||||
pc_q35_4_0_machine_options);
|
||||
|
||||
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
|
||||
index b52b82d298..8438741ec2 100644
|
||||
--- a/hw/ppc/spapr.c
|
||||
+++ b/hw/ppc/spapr.c
|
||||
@@ -4344,15 +4344,26 @@ static const TypeInfo spapr_machine_info = {
|
||||
} \
|
||||
type_init(spapr_machine_register_##suffix)
|
||||
|
||||
+/*
|
||||
+ * pseries-4.1
|
||||
+ */
|
||||
+static void spapr_machine_4_1_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ /* Defaults for the latest behaviour inherited from the base class */
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE(4_1, "4.1", true);
|
||||
+
|
||||
/*
|
||||
* pseries-4.0
|
||||
*/
|
||||
static void spapr_machine_4_0_class_options(MachineClass *mc)
|
||||
{
|
||||
- /* Defaults for the latest behaviour inherited from the base class */
|
||||
+ spapr_machine_4_1_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
}
|
||||
|
||||
-DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
|
||||
+DEFINE_SPAPR_MACHINE(4_0, "4.0", false);
|
||||
|
||||
/*
|
||||
* pseries-3.1
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index d11069b860..02470e78c7 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -646,14 +646,26 @@ bool css_migration_enabled(void)
|
||||
} \
|
||||
type_init(ccw_machine_register_##suffix)
|
||||
|
||||
+static void ccw_machine_4_1_instance_options(MachineState *machine)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_4_1_class_options(MachineClass *mc)
|
||||
+{
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(4_1, "4.1", true);
|
||||
+
|
||||
static void ccw_machine_4_0_instance_options(MachineState *machine)
|
||||
{
|
||||
+ ccw_machine_4_1_instance_options(machine);
|
||||
}
|
||||
|
||||
static void ccw_machine_4_0_class_options(MachineClass *mc)
|
||||
{
|
||||
+ ccw_machine_4_1_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
}
|
||||
-DEFINE_CCW_MACHINE(4_0, "4.0", true);
|
||||
+DEFINE_CCW_MACHINE(4_0, "4.0", false);
|
||||
|
||||
static void ccw_machine_3_1_instance_options(MachineState *machine)
|
||||
{
|
||||
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||
index e231860666..fe1885cbff 100644
|
||||
--- a/include/hw/boards.h
|
||||
+++ b/include/hw/boards.h
|
||||
@@ -293,6 +293,9 @@ struct MachineState {
|
||||
} \
|
||||
type_init(machine_initfn##_register_types)
|
||||
|
||||
+extern GlobalProperty hw_compat_4_0[];
|
||||
+extern const size_t hw_compat_4_0_len;
|
||||
+
|
||||
extern GlobalProperty hw_compat_3_1[];
|
||||
extern const size_t hw_compat_3_1_len;
|
||||
|
||||
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||
index ca65ef18af..43df7230a2 100644
|
||||
--- a/include/hw/i386/pc.h
|
||||
+++ b/include/hw/i386/pc.h
|
||||
@@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
||||
int e820_get_num_entries(void);
|
||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
+extern GlobalProperty pc_compat_4_0[];
|
||||
+extern const size_t pc_compat_4_0_len;
|
||||
+
|
||||
extern GlobalProperty pc_compat_3_1[];
|
||||
extern const size_t pc_compat_3_1_len;
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
From 4f1c6cb2f9afafda05eab150fd2bd284edce6676 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Wed, 25 Sep 2019 14:16:43 +0200
|
||||
Subject: [PATCH] hw/core/loader: Fix possible crash in rom_copy()
|
||||
|
||||
Both, "rom->addr" and "addr" are derived from the binary image
|
||||
that can be loaded with the "-kernel" paramer. The code in
|
||||
rom_copy() then calculates:
|
||||
|
||||
d = dest + (rom->addr - addr);
|
||||
|
||||
and uses "d" as destination in a memcpy() some lines later. Now with
|
||||
bad kernel images, it is possible that rom->addr is smaller than addr,
|
||||
thus "rom->addr - addr" gets negative and the memcpy() then tries to
|
||||
copy contents from the image to a bad memory location. This could
|
||||
maybe be used to inject code from a kernel image into the QEMU binary,
|
||||
so we better fix it with an additional sanity check here.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reported-by: Guangming Liu
|
||||
Buglink: https://bugs.launchpad.net/qemu/+bug/1844635
|
||||
Message-Id: <20190925130331.27825-1-thuth@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit e423455c4f23a1a828901c78fe6d03b7dde79319)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/core/loader.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/core/loader.c b/hw/core/loader.c
|
||||
index fe5cb24122..4ef2095247 100644
|
||||
--- a/hw/core/loader.c
|
||||
+++ b/hw/core/loader.c
|
||||
@@ -1240,7 +1240,7 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size)
|
||||
if (rom->addr + rom->romsize < addr) {
|
||||
continue;
|
||||
}
|
||||
- if (rom->addr > end) {
|
||||
+ if (rom->addr > end || rom->addr < addr) {
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
From 21e2acd583126db94f6d881005cd58e835160582 Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Yakovlev <wrfsh@yandex-team.ru>
|
||||
Date: Thu, 18 Jul 2019 19:14:23 +0300
|
||||
Subject: [PATCH] i386/acpi: fix gint overflow in crs_range_compare
|
||||
|
||||
When very large regions (32GB sized in our case, PCI pass-through of GPUs)
|
||||
are compared substraction result does not fit into gint.
|
||||
|
||||
As a result crs_replace_with_free_ranges does not get sorted ranges and
|
||||
incorrectly computes PCI64 free space regions. Which then makes linux
|
||||
guest complain about device and PCI64 hole intersection and device
|
||||
becomes unusable.
|
||||
|
||||
Fix that by returning exactly fitting ranges.
|
||||
|
||||
Also fix indentation of an entire crs_replace_with_free_ranges to make
|
||||
checkpatch happy.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Evgeny Yakovlev <wrfsh@yandex-team.ru>
|
||||
Message-Id: <1563466463-26012-1-git-send-email-wrfsh@yandex-team.ru>
|
||||
Signed-off-by: Evgeny Yakovlev <wrfsh@yandex-team.ru>
|
||||
(cherry-picked from commit 21e2acd583126db94f6d881005cd58e835160582)
|
||||
---
|
||||
hw/i386/acpi-build.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
|
||||
index d281ffa89e..e7b756b51b 100644
|
||||
--- a/hw/i386/acpi-build.c
|
||||
+++ b/hw/i386/acpi-build.c
|
||||
@@ -755,10 +755,16 @@ static void crs_range_set_free(CrsRangeSet *range_set)
|
||||
|
||||
static gint crs_range_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
- CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
|
||||
- CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
|
||||
+ CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
|
||||
+ CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
|
||||
|
||||
- return (int64_t)entry_a->base - (int64_t)entry_b->base;
|
||||
+ if (entry_a->base < entry_b->base) {
|
||||
+ return -1;
|
||||
+ } else if (entry_a->base > entry_b->base) {
|
||||
+ return 1;
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From ee4b0c8686f781987879508d7c6dd605b5435bac Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Yakovlev <wrfsh@yandex-team.ru>
|
||||
Date: Fri, 19 Jul 2019 11:54:29 +0300
|
||||
Subject: [PATCH] i386/acpi: show PCI Express bus on pxb-pcie expanders
|
||||
|
||||
Show PCIe host bridge PNP id with PCI host bridge as a compatible id
|
||||
when expanding a pcie bus.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Evgeny Yakovlev <wrfsh@yandex-team.ru>
|
||||
Message-Id: <1563526469-15588-1-git-send-email-wrfsh@yandex-team.ru>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-picked from commit ee4b0c8686f781987879508d7c6dd605b5435bac)
|
||||
---
|
||||
hw/i386/acpi-build.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
|
||||
index e7b756b51b..f3fdfefcd5 100644
|
||||
--- a/hw/i386/acpi-build.c
|
||||
+++ b/hw/i386/acpi-build.c
|
||||
@@ -1914,10 +1914,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
scope = aml_scope("\\_SB");
|
||||
dev = aml_device("PC%.02X", bus_num);
|
||||
aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
|
||||
- aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
|
||||
aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
|
||||
if (pci_bus_is_express(bus)) {
|
||||
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
|
||||
+ aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
|
||||
aml_append(dev, build_q35_osc_method());
|
||||
+ } else {
|
||||
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
|
||||
}
|
||||
|
||||
if (numa_node != NUMA_NODE_UNASSIGNED) {
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
From be1927c97e564346cbd409cb17fe611df74b84e5 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
Date: Sun, 2 Jun 2019 13:42:13 +0200
|
||||
Subject: [PATCH] ioapic: kvm: Skip route updates for masked pins
|
||||
|
||||
Masked entries will not generate interrupt messages, thus do no need to
|
||||
be routed by KVM. This is a cosmetic cleanup, just avoiding warnings of
|
||||
the kind
|
||||
|
||||
qemu-system-x86_64: vtd_irte_get: detected non-present IRTE (index=0, high=0xff00, low=0x100)
|
||||
|
||||
if the masked entry happens to reference a non-present IRTE.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
Message-Id: <a84b7e03-f9a8-b577-be27-4d93d1caa1c9@siemens.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Reviewed-by: Peter Xu <peterx@redhat.com>
|
||||
(cherry-picked from commit be1927c97e564346cbd409cb17fe611df74b84e5)
|
||||
---
|
||||
hw/intc/ioapic.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
|
||||
index c408749876..e99c37cceb 100644
|
||||
--- a/hw/intc/ioapic.c
|
||||
+++ b/hw/intc/ioapic.c
|
||||
@@ -197,9 +197,11 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s)
|
||||
MSIMessage msg;
|
||||
struct ioapic_entry_info info;
|
||||
ioapic_entry_parse(s->ioredtbl[i], &info);
|
||||
- msg.address = info.addr;
|
||||
- msg.data = info.data;
|
||||
- kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
|
||||
+ if (!info.masked) {
|
||||
+ msg.address = info.addr;
|
||||
+ msg.data = info.data;
|
||||
+ kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
|
||||
+ }
|
||||
}
|
||||
kvm_irqchip_commit_routes(kvm_state);
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From 5fff13f245cddd3bc260dfe6ebe1b1f05b72116f Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Tue, 14 May 2019 06:24:43 +0200
|
||||
Subject: [PATCH] kbd-state: fix autorepeat handling
|
||||
|
||||
When allowing multiple down-events in a row (key autorepeat) we can't
|
||||
use change_bit() any more to update the state, because autorepeat events
|
||||
don't change the key state. We have to explicitly use set_bit() and
|
||||
clear_bit() instead.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Fixes: 35921860156e kbd-state: don't block auto-repeat events
|
||||
Buglink: https://bugs.launchpad.net/qemu/+bug/1828272
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Message-id: 20190514042443.10735-1-kraxel@redhat.com
|
||||
(cherry-picked from commit 5fff13f245cddd3bc260dfe6ebe1b1f05b72116f)
|
||||
---
|
||||
ui/kbd-state.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ui/kbd-state.c b/ui/kbd-state.c
|
||||
index f3ab2d7a66..1668d17dda 100644
|
||||
--- a/ui/kbd-state.c
|
||||
+++ b/ui/kbd-state.c
|
||||
@@ -59,7 +59,11 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
|
||||
}
|
||||
|
||||
/* update key and modifier state */
|
||||
- change_bit(qcode, kbd->keys);
|
||||
+ if (down) {
|
||||
+ set_bit(qcode, kbd->keys);
|
||||
+ } else {
|
||||
+ clear_bit(qcode, kbd->keys);
|
||||
+ }
|
||||
switch (qcode) {
|
||||
case Q_KEY_CODE_SHIFT:
|
||||
case Q_KEY_CODE_SHIFT_R:
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
From 2e56fbc87f6ec3cd56c37b01d313abd502b80d61 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Lieven <pl@kamp.de>
|
||||
Date: Thu, 4 Apr 2019 14:10:15 +0200
|
||||
Subject: [PATCH] megasas: fix mapped frame size
|
||||
|
||||
the current value of 1024 bytes (16 * MFI_FRAME_SIZE) we map is not enough to hold
|
||||
the maximum number of scatter gather elements we advertise. We actually need a
|
||||
maximum of 2048 bytes. This is 128 max sg elements * 16 bytes (sizeof (union mfi_sgl)).
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Peter Lieven <pl@kamp.de>
|
||||
Message-Id: <20190404121015.28634-1-pl@kamp.de>
|
||||
Reviewed-by: Hannes Reinecke <hare@suse.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry-picked from commit 2e56fbc87f6ec3cd56c37b01d313abd502b80d61)
|
||||
---
|
||||
hw/scsi/megasas.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
|
||||
index a56317e026..5ad762de23 100644
|
||||
--- a/hw/scsi/megasas.c
|
||||
+++ b/hw/scsi/megasas.c
|
||||
@@ -477,7 +477,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
|
||||
{
|
||||
PCIDevice *pcid = PCI_DEVICE(s);
|
||||
MegasasCmd *cmd = NULL;
|
||||
- int frame_size = MFI_FRAME_SIZE * 16;
|
||||
+ int frame_size = MEGASAS_MAX_SGE * sizeof(union mfi_sgl);
|
||||
hwaddr frame_size_p = frame_size;
|
||||
unsigned long index;
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,205 +0,0 @@
|
||||
From 35d6458d6a100b2f15a7e079558a4570742c6e5a Mon Sep 17 00:00:00 2001
|
||||
From: Yury Kotov <yury-kotov@yandex-team.ru>
|
||||
Date: Mon, 8 Apr 2019 14:33:43 +0300
|
||||
Subject: [PATCH] migration: Fix use-after-free during process exit
|
||||
|
||||
It fixes heap-use-after-free which was found by clang's ASAN.
|
||||
|
||||
Control flow of this use-after-free:
|
||||
main_thread:
|
||||
* Got SIGTERM and completes main loop
|
||||
* Calls migration_shutdown
|
||||
- migrate_fd_cancel (so, migration_thread begins to complete)
|
||||
- object_unref(OBJECT(current_migration));
|
||||
|
||||
migration_thread:
|
||||
* migration_iteration_finish -> schedule cleanup bh
|
||||
* object_unref(OBJECT(s)); (Now, current_migration is freed)
|
||||
* exits
|
||||
|
||||
main_thread:
|
||||
* Calls vm_shutdown -> drain bdrvs -> main loop
|
||||
-> cleanup_bh -> use after free
|
||||
|
||||
If you want to reproduce, these couple of sleeps will help:
|
||||
vl.c:4613:
|
||||
migration_shutdown();
|
||||
+ sleep(2);
|
||||
migration.c:3269:
|
||||
+ sleep(1);
|
||||
trace_migration_thread_after_loop();
|
||||
migration_iteration_finish(s);
|
||||
|
||||
Original output:
|
||||
qemu-system-x86_64: terminating on signal 15 from pid 31980 (<unknown process>)
|
||||
=================================================================
|
||||
==31958==ERROR: AddressSanitizer: heap-use-after-free on address 0x61900001d210
|
||||
at pc 0x555558a535ca bp 0x7fffffffb190 sp 0x7fffffffb188
|
||||
READ of size 8 at 0x61900001d210 thread T0 (qemu-vm-0)
|
||||
#0 0x555558a535c9 in migrate_fd_cleanup migration/migration.c:1502:23
|
||||
#1 0x5555594fde0a in aio_bh_call util/async.c:90:5
|
||||
#2 0x5555594fe522 in aio_bh_poll util/async.c:118:13
|
||||
#3 0x555559524783 in aio_poll util/aio-posix.c:725:17
|
||||
#4 0x555559504fb3 in aio_wait_bh_oneshot util/aio-wait.c:71:5
|
||||
#5 0x5555573bddf6 in virtio_blk_data_plane_stop
|
||||
hw/block/dataplane/virtio-blk.c:282:5
|
||||
#6 0x5555589d5c09 in virtio_bus_stop_ioeventfd hw/virtio/virtio-bus.c:246:9
|
||||
#7 0x5555589e9917 in virtio_pci_stop_ioeventfd hw/virtio/virtio-pci.c:287:5
|
||||
#8 0x5555589e22bf in virtio_pci_vmstate_change hw/virtio/virtio-pci.c:1072:9
|
||||
#9 0x555557628931 in virtio_vmstate_change hw/virtio/virtio.c:2257:9
|
||||
#10 0x555557c36713 in vm_state_notify vl.c:1605:9
|
||||
#11 0x55555716ef53 in do_vm_stop cpus.c:1074:9
|
||||
#12 0x55555716eeff in vm_shutdown cpus.c:1092:12
|
||||
#13 0x555557c4283e in main vl.c:4617:5
|
||||
#14 0x7fffdfdb482f in __libc_start_main
|
||||
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
|
||||
#15 0x555556ecb118 in _start (x86_64-softmmu/qemu-system-x86_64+0x1977118)
|
||||
|
||||
0x61900001d210 is located 144 bytes inside of 952-byte region
|
||||
[0x61900001d180,0x61900001d538)
|
||||
freed by thread T6 (live_migration) here:
|
||||
#0 0x555556f76782 in __interceptor_free
|
||||
/tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:124:3
|
||||
#1 0x555558d5fa94 in object_finalize qom/object.c:618:9
|
||||
#2 0x555558d57651 in object_unref qom/object.c:1068:9
|
||||
#3 0x555558a55588 in migration_thread migration/migration.c:3272:5
|
||||
#4 0x5555595393f2 in qemu_thread_start util/qemu-thread-posix.c:502:9
|
||||
#5 0x7fffe057f6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
|
||||
|
||||
previously allocated by thread T0 (qemu-vm-0) here:
|
||||
#0 0x555556f76b03 in __interceptor_malloc
|
||||
/tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:146:3
|
||||
#1 0x7ffff6ee37b8 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x4f7b8)
|
||||
#2 0x555558d58031 in object_new qom/object.c:640:12
|
||||
#3 0x555558a31f21 in migration_object_init migration/migration.c:139:25
|
||||
#4 0x555557c41398 in main vl.c:4320:5
|
||||
#5 0x7fffdfdb482f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
|
||||
|
||||
Thread T6 (live_migration) created by T0 (qemu-vm-0) here:
|
||||
#0 0x555556f5f0dd in pthread_create
|
||||
/tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:210:3
|
||||
#1 0x555559538cf9 in qemu_thread_create util/qemu-thread-posix.c:539:11
|
||||
#2 0x555558a53304 in migrate_fd_connect migration/migration.c:3332:5
|
||||
#3 0x555558a72bd8 in migration_channel_connect migration/channel.c:92:5
|
||||
#4 0x555558a6ef87 in exec_start_outgoing_migration migration/exec.c:42:5
|
||||
#5 0x555558a4f3c2 in qmp_migrate migration/migration.c:1922:9
|
||||
#6 0x555558bb4f6a in qmp_marshal_migrate qapi/qapi-commands-migration.c:607:5
|
||||
#7 0x555559363738 in do_qmp_dispatch qapi/qmp-dispatch.c:131:5
|
||||
#8 0x555559362a15 in qmp_dispatch qapi/qmp-dispatch.c:174:11
|
||||
#9 0x5555571bac15 in monitor_qmp_dispatch monitor.c:4124:11
|
||||
#10 0x55555719a22d in monitor_qmp_bh_dispatcher monitor.c:4207:9
|
||||
#11 0x5555594fde0a in aio_bh_call util/async.c:90:5
|
||||
#12 0x5555594fe522 in aio_bh_poll util/async.c:118:13
|
||||
#13 0x5555595201e0 in aio_dispatch util/aio-posix.c:460:5
|
||||
#14 0x555559503553 in aio_ctx_dispatch util/async.c:261:5
|
||||
#15 0x7ffff6ede196 in g_main_context_dispatch
|
||||
(/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x4a196)
|
||||
|
||||
SUMMARY: AddressSanitizer: heap-use-after-free migration/migration.c:1502:23
|
||||
in migrate_fd_cleanup
|
||||
Shadow bytes around the buggy address:
|
||||
0x0c327fffb9f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||
0x0c327fffba00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||
0x0c327fffba10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||
0x0c327fffba20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||
0x0c327fffba30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
|
||||
=>0x0c327fffba40: fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd
|
||||
0x0c327fffba50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
|
||||
0x0c327fffba60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
|
||||
0x0c327fffba70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
|
||||
0x0c327fffba80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
|
||||
0x0c327fffba90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
|
||||
Shadow byte legend (one shadow byte represents 8 application bytes):
|
||||
Addressable: 00
|
||||
Partially addressable: 01 02 03 04 05 06 07
|
||||
Heap left redzone: fa
|
||||
Freed heap region: fd
|
||||
Stack left redzone: f1
|
||||
Stack mid redzone: f2
|
||||
Stack right redzone: f3
|
||||
Stack after return: f5
|
||||
Stack use after scope: f8
|
||||
Global redzone: f9
|
||||
Global init order: f6
|
||||
Poisoned by user: f7
|
||||
Container overflow: fc
|
||||
Array cookie: ac
|
||||
Intra object redzone: bb
|
||||
ASan internal: fe
|
||||
Left alloca redzone: ca
|
||||
Right alloca redzone: cb
|
||||
Shadow gap: cc
|
||||
==31958==ABORTING
|
||||
|
||||
Signed-off-by: Yury Kotov <yury-kotov@yandex-team.ru>
|
||||
Message-Id: <20190408113343.2370-1-yury-kotov@yandex-team.ru>
|
||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Fixed up comment formatting
|
||||
(cherry picked from commit fd392cfa8e6fb0dc34bd0327fc356dfbf6edf1fd)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
migration/migration.c | 25 ++++++++++++++++++++-----
|
||||
1 file changed, 20 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/migration/migration.c b/migration/migration.c
|
||||
index 609e0df5d0..2f617b9dba 100644
|
||||
--- a/migration/migration.c
|
||||
+++ b/migration/migration.c
|
||||
@@ -1495,10 +1495,8 @@ static void block_cleanup_parameters(MigrationState *s)
|
||||
}
|
||||
}
|
||||
|
||||
-static void migrate_fd_cleanup(void *opaque)
|
||||
+static void migrate_fd_cleanup(MigrationState *s)
|
||||
{
|
||||
- MigrationState *s = opaque;
|
||||
-
|
||||
qemu_bh_delete(s->cleanup_bh);
|
||||
s->cleanup_bh = NULL;
|
||||
|
||||
@@ -1543,6 +1541,23 @@ static void migrate_fd_cleanup(void *opaque)
|
||||
block_cleanup_parameters(s);
|
||||
}
|
||||
|
||||
+static void migrate_fd_cleanup_schedule(MigrationState *s)
|
||||
+{
|
||||
+ /*
|
||||
+ * Ref the state for bh, because it may be called when
|
||||
+ * there're already no other refs
|
||||
+ */
|
||||
+ object_ref(OBJECT(s));
|
||||
+ qemu_bh_schedule(s->cleanup_bh);
|
||||
+}
|
||||
+
|
||||
+static void migrate_fd_cleanup_bh(void *opaque)
|
||||
+{
|
||||
+ MigrationState *s = opaque;
|
||||
+ migrate_fd_cleanup(s);
|
||||
+ object_unref(OBJECT(s));
|
||||
+}
|
||||
+
|
||||
void migrate_set_error(MigrationState *s, const Error *error)
|
||||
{
|
||||
qemu_mutex_lock(&s->error_mutex);
|
||||
@@ -3144,7 +3159,7 @@ static void migration_iteration_finish(MigrationState *s)
|
||||
error_report("%s: Unknown ending state %d", __func__, s->state);
|
||||
break;
|
||||
}
|
||||
- qemu_bh_schedule(s->cleanup_bh);
|
||||
+ migrate_fd_cleanup_schedule(s);
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
|
||||
@@ -3279,7 +3294,7 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
|
||||
bool resume = s->state == MIGRATION_STATUS_POSTCOPY_PAUSED;
|
||||
|
||||
s->expected_downtime = s->parameters.downtime_limit;
|
||||
- s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
|
||||
+ s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup_bh, s);
|
||||
if (error_in) {
|
||||
migrate_fd_error(s, error_in);
|
||||
migrate_fd_cleanup(s);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
From 3a87d07722d4be717a97b59cfbc7b2ba27ca30b0 Mon Sep 17 00:00:00 2001
|
||||
From: John Snow <jsnow@redhat.com>
|
||||
Date: Tue, 28 May 2019 19:33:31 -0400
|
||||
Subject: [PATCH] migration/dirty-bitmaps: change bitmap enumeration method
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Shift from looking at every root BDS to *every* BDS. This will migrate
|
||||
bitmaps that are attached to blockdev created nodes instead of just ones
|
||||
attached to emulated storage devices.
|
||||
|
||||
Note that this will not migrate anonymous or internal-use bitmaps, as
|
||||
those are defined as having no name.
|
||||
|
||||
This will also fix the Coverity issues Peter Maydell has been asking
|
||||
about for the past several releases, as well as fixing a real bug.
|
||||
|
||||
Reported-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Reported-by: Coverity 😅
|
||||
Reported-by: aihua liang <aliang@redhat.com>
|
||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
Message-id: 20190514201926.10407-1-jsnow@redhat.com
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1652490
|
||||
Fixes: Coverity CID 1390625
|
||||
CC: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
||||
(cherry picked from commit 592203e7cfbd1ad261178431fcf390adfe8b16df)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
migration/block-dirty-bitmap.c | 14 ++++----------
|
||||
1 file changed, 4 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
|
||||
index d1bb863cb6..4a896a09eb 100644
|
||||
--- a/migration/block-dirty-bitmap.c
|
||||
+++ b/migration/block-dirty-bitmap.c
|
||||
@@ -273,7 +273,6 @@ static int init_dirty_bitmap_migration(void)
|
||||
BlockDriverState *bs;
|
||||
BdrvDirtyBitmap *bitmap;
|
||||
DirtyBitmapMigBitmapState *dbms;
|
||||
- BdrvNextIterator it;
|
||||
Error *local_err = NULL;
|
||||
|
||||
dirty_bitmap_mig_state.bulk_completed = false;
|
||||
@@ -281,13 +280,8 @@ static int init_dirty_bitmap_migration(void)
|
||||
dirty_bitmap_mig_state.prev_bitmap = NULL;
|
||||
dirty_bitmap_mig_state.no_bitmaps = false;
|
||||
|
||||
- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
- const char *drive_name = bdrv_get_device_or_node_name(bs);
|
||||
-
|
||||
- /* skip automatically inserted nodes */
|
||||
- while (bs && bs->drv && bs->implicit) {
|
||||
- bs = backing_bs(bs);
|
||||
- }
|
||||
+ for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) {
|
||||
+ const char *name = bdrv_get_device_or_node_name(bs);
|
||||
|
||||
for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap;
|
||||
bitmap = bdrv_dirty_bitmap_next(bs, bitmap))
|
||||
@@ -296,7 +290,7 @@ static int init_dirty_bitmap_migration(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (drive_name == NULL) {
|
||||
+ if (!name || strcmp(name, "") == 0) {
|
||||
error_report("Found bitmap '%s' in unnamed node %p. It can't "
|
||||
"be migrated", bdrv_dirty_bitmap_name(bitmap), bs);
|
||||
goto fail;
|
||||
@@ -313,7 +307,7 @@ static int init_dirty_bitmap_migration(void)
|
||||
|
||||
dbms = g_new0(DirtyBitmapMigBitmapState, 1);
|
||||
dbms->bs = bs;
|
||||
- dbms->node_name = drive_name;
|
||||
+ dbms->node_name = name;
|
||||
dbms->bitmap = bitmap;
|
||||
dbms->total_sectors = bdrv_nb_sectors(bs);
|
||||
dbms->sectors_per_chunk = CHUNK_SIZE * 8 *
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
From d65d02614b6b0f6bcc64cd2a737b5204c0fc5304 Mon Sep 17 00:00:00 2001
|
||||
From: Max Reitz <mreitz@redhat.com>
|
||||
Date: Mon, 5 Aug 2019 17:33:08 +0200
|
||||
Subject: [PATCH] mirror: Only mirror granularity-aligned chunks
|
||||
|
||||
In write-blocking mode, all writes to the top node directly go to the
|
||||
target. We must only mirror chunks of data that are aligned to the
|
||||
job's granularity, because that is how the dirty bitmap works.
|
||||
Therefore, the request alignment for writes must be the job's
|
||||
granularity (in write-blocking mode).
|
||||
|
||||
Unfortunately, this forces all reads and writes to have the same
|
||||
granularity (we only need this alignment for writes to the target, not
|
||||
the source), but that is something to be fixed another time.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
Message-id: 20190805153308.2657-1-mreitz@redhat.com
|
||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Fixes: d06107ade0ce74dc39739bac80de84b51ec18546
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit 9adc1cb49af8d4e54f57980b1eed5c0a4b2dafa6)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
block/mirror.c | 29 +++++++++++++++++++++++++++++
|
||||
1 file changed, 29 insertions(+)
|
||||
|
||||
diff --git a/block/mirror.c b/block/mirror.c
|
||||
index ff15cfb197..062dc42867 100644
|
||||
--- a/block/mirror.c
|
||||
+++ b/block/mirror.c
|
||||
@@ -1477,6 +1477,15 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
||||
*nshared = BLK_PERM_ALL;
|
||||
}
|
||||
|
||||
+static void bdrv_mirror_top_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
+{
|
||||
+ MirrorBDSOpaque *s = bs->opaque;
|
||||
+
|
||||
+ if (s && s->job && s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING) {
|
||||
+ bs->bl.request_alignment = s->job->granularity;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Dummy node that provides consistent read to its users without requiring it
|
||||
* from its backing file and that allows writes on the backing file chain. */
|
||||
static BlockDriver bdrv_mirror_top = {
|
||||
@@ -1489,6 +1498,7 @@ static BlockDriver bdrv_mirror_top = {
|
||||
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
|
||||
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
|
||||
.bdrv_child_perm = bdrv_mirror_top_child_perm,
|
||||
+ .bdrv_refresh_limits = bdrv_mirror_top_refresh_limits,
|
||||
};
|
||||
|
||||
static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
||||
@@ -1627,6 +1637,25 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
||||
s->should_complete = true;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Must be called before we start tracking writes, but after
|
||||
+ *
|
||||
+ * ((MirrorBlockJob *)
|
||||
+ * ((MirrorBDSOpaque *)
|
||||
+ * mirror_top_bs->opaque
|
||||
+ * )->job
|
||||
+ * )->copy_mode
|
||||
+ *
|
||||
+ * has the correct value.
|
||||
+ * (We start tracking writes as of the following
|
||||
+ * bdrv_create_dirty_bitmap() call.)
|
||||
+ */
|
||||
+ bdrv_refresh_limits(mirror_top_bs, &local_err);
|
||||
+ if (local_err) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
|
||||
if (!s->dirty_bitmap) {
|
||||
goto fail;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From 83f9b84c8bcb24265e25cd7f22e971e81cacebc6 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Armbruster <armbru@redhat.com>
|
||||
Date: Thu, 22 Aug 2019 15:38:46 +0200
|
||||
Subject: [PATCH] pr-manager: Fix invalid g_free() crash bug
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
pr_manager_worker() passes its @opaque argument to g_free(). Wrong;
|
||||
it points to pr_manager_worker()'s automatic @data. Broken when
|
||||
commit 2f3a7ab39be converted @data from heap- to stack-allocated. Fix
|
||||
by deleting the g_free().
|
||||
|
||||
Fixes: 2f3a7ab39bec4ba8022dc4d42ea641165b004e3e
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 6b9d62c2a9e83bbad73fb61406f0ff69b46ff6f3)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
scsi/pr-manager.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c
|
||||
index d9f4e8c3ad..227bdfaad2 100644
|
||||
--- a/scsi/pr-manager.c
|
||||
+++ b/scsi/pr-manager.c
|
||||
@@ -38,7 +38,6 @@ static int pr_manager_worker(void *opaque)
|
||||
int fd = data->fd;
|
||||
int r;
|
||||
|
||||
- g_free(data);
|
||||
trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]);
|
||||
|
||||
/* The reference was taken in pr_manager_execute. */
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
From c87759ce876a7a0b17c2bf4f0b964bd51f0ee871 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Williamson <alex.williamson@redhat.com>
|
||||
Date: Tue, 14 May 2019 14:14:41 -0600
|
||||
Subject: [PATCH] q35: Revert to kernel irqchip
|
||||
|
||||
Commit b2fc91db8447 ("q35: set split kernel irqchip as default") changed
|
||||
the default for the pc-q35-4.0 machine type to use split irqchip, which
|
||||
turned out to have disasterous effects on vfio-pci INTx support. KVM
|
||||
resampling irqfds are registered for handling these interrupts, but
|
||||
these are non-functional in split irqchip mode. We can't simply test
|
||||
for split irqchip in QEMU as userspace handling of this interrupt is a
|
||||
significant performance regression versus KVM handling (GeForce GPUs
|
||||
assigned to Windows VMs are non-functional without forcing MSI mode or
|
||||
re-enabling kernel irqchip).
|
||||
|
||||
The resolution is to revert the change in default irqchip mode in the
|
||||
pc-q35-4.1 machine and create a pc-q35-4.0.1 machine for the 4.0-stable
|
||||
branch. The qemu-q35-4.0 machine type should not be used in vfio-pci
|
||||
configurations for devices requiring legacy INTx support without
|
||||
explicitly modifying the VM configuration to use kernel irqchip.
|
||||
|
||||
Link: https://bugs.launchpad.net/qemu/+bug/1826422
|
||||
Fixes: b2fc91db8447 ("q35: set split kernel irqchip as default")
|
||||
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
|
||||
Reviewed-by: Peter Xu <peterx@redhat.com>
|
||||
Message-Id: <155786484688.13873.6037015630912983760.stgit@gimli.home>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry-picked from commit c87759ce876a7a0b17c2bf4f0b964bd51f0ee871)
|
||||
---
|
||||
hw/core/machine.c | 3 +++
|
||||
hw/i386/pc.c | 3 +++
|
||||
hw/i386/pc_q35.c | 16 ++++++++++++++--
|
||||
include/hw/boards.h | 3 +++
|
||||
include/hw/i386/pc.h | 3 +++
|
||||
5 files changed, 26 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index 16ba667434..f1a0f45f9c 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -24,6 +24,9 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
|
||||
+GlobalProperty hw_compat_4_0_1[] = {};
|
||||
+const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1);
|
||||
+
|
||||
GlobalProperty hw_compat_4_0[] = {};
|
||||
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
|
||||
|
||||
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||
index 2632b73f80..edc240bcbf 100644
|
||||
--- a/hw/i386/pc.c
|
||||
+++ b/hw/i386/pc.c
|
||||
@@ -110,6 +110,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
|
||||
/* Physical Address of PVH entry point read from kernel ELF NOTE */
|
||||
static size_t pvh_start_addr;
|
||||
|
||||
+GlobalProperty pc_compat_4_0_1[] = {};
|
||||
+const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1);
|
||||
+
|
||||
GlobalProperty pc_compat_4_0[] = {};
|
||||
const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
|
||||
|
||||
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||
index 37dd350511..dcddc64662 100644
|
||||
--- a/hw/i386/pc_q35.c
|
||||
+++ b/hw/i386/pc_q35.c
|
||||
@@ -357,7 +357,7 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||
m->units_per_default_bus = 1;
|
||||
m->default_machine_opts = "firmware=bios-256k.bin";
|
||||
m->default_display = "std";
|
||||
- m->default_kernel_irqchip_split = true;
|
||||
+ m->default_kernel_irqchip_split = false;
|
||||
m->no_floppy = 1;
|
||||
machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE);
|
||||
machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE);
|
||||
@@ -374,10 +374,22 @@ static void pc_q35_4_1_machine_options(MachineClass *m)
|
||||
DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
|
||||
pc_q35_4_1_machine_options);
|
||||
|
||||
-static void pc_q35_4_0_machine_options(MachineClass *m)
|
||||
+static void pc_q35_4_0_1_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_q35_4_1_machine_options(m);
|
||||
m->alias = NULL;
|
||||
+ compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len);
|
||||
+ compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len);
|
||||
+}
|
||||
+
|
||||
+DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL,
|
||||
+ pc_q35_4_0_1_machine_options);
|
||||
+
|
||||
+static void pc_q35_4_0_machine_options(MachineClass *m)
|
||||
+{
|
||||
+ pc_q35_4_0_1_machine_options(m);
|
||||
+ m->default_kernel_irqchip_split = true;
|
||||
+ m->alias = NULL;
|
||||
compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
|
||||
compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
|
||||
}
|
||||
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||
index 6f7916f88f..6ff02bf3e4 100644
|
||||
--- a/include/hw/boards.h
|
||||
+++ b/include/hw/boards.h
|
||||
@@ -292,6 +292,9 @@ struct MachineState {
|
||||
} \
|
||||
type_init(machine_initfn##_register_types)
|
||||
|
||||
+extern GlobalProperty hw_compat_4_0_1[];
|
||||
+extern const size_t hw_compat_4_0_1_len;
|
||||
+
|
||||
extern GlobalProperty hw_compat_4_0[];
|
||||
extern const size_t hw_compat_4_0_len;
|
||||
|
||||
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||
index 43df7230a2..5d5636241e 100644
|
||||
--- a/include/hw/i386/pc.h
|
||||
+++ b/include/hw/i386/pc.h
|
||||
@@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
||||
int e820_get_num_entries(void);
|
||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
+extern GlobalProperty pc_compat_4_0_1[];
|
||||
+extern const size_t pc_compat_4_0_1_len;
|
||||
+
|
||||
extern GlobalProperty pc_compat_4_0[];
|
||||
extern const size_t pc_compat_4_0_len;
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
From 360bd07471dfd1830246e8403ffdc9ba9d82f9d4 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Mon, 15 Apr 2019 16:56:07 +0200
|
||||
Subject: [PATCH] qcow2: Add errp to preallocate_co()
|
||||
|
||||
We'll add a bdrv_co_truncate() call in the next patch which can return
|
||||
an Error that we don't want to discard. So add an errp parameter to
|
||||
preallocate_co().
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
(cherry-picked from commit 360bd07471dfd1830246e8403ffdc9ba9d82f9d4)
|
||||
---
|
||||
block/qcow2.c | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index dfac74c264..b4f9f5a240 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -2721,7 +2721,7 @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
|
||||
* Returns: 0 on success, -errno on failure.
|
||||
*/
|
||||
static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
- uint64_t new_length)
|
||||
+ uint64_t new_length, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t bytes;
|
||||
@@ -2738,6 +2738,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
|
||||
&host_offset, &meta);
|
||||
if (ret < 0) {
|
||||
+ error_setg_errno(errp, -ret, "Allocating clusters failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2746,6 +2747,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
ret = qcow2_alloc_cluster_link_l2(bs, meta);
|
||||
if (ret < 0) {
|
||||
+ error_setg_errno(errp, -ret, "Mapping clusters failed");
|
||||
qcow2_free_any_clusters(bs, meta->alloc_offset,
|
||||
meta->nb_clusters, QCOW2_DISCARD_NEVER);
|
||||
return ret;
|
||||
@@ -2775,6 +2777,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
ret = bdrv_pwrite(s->data_file, (host_offset + cur_bytes) - 1,
|
||||
&data, 1);
|
||||
if (ret < 0) {
|
||||
+ error_setg_errno(errp, -ret, "Writing to EOF failed");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -3748,9 +3751,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
break;
|
||||
|
||||
case PREALLOC_MODE_METADATA:
|
||||
- ret = preallocate_co(bs, old_length, offset);
|
||||
+ ret = preallocate_co(bs, old_length, offset, errp);
|
||||
if (ret < 0) {
|
||||
- error_setg_errno(errp, -ret, "Preallocation failed");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
@@ -3766,9 +3768,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
/* With a data file, preallocation means just allocating the metadata
|
||||
* and forwarding the truncate request to the data file */
|
||||
if (has_data_file(bs)) {
|
||||
- ret = preallocate_co(bs, old_length, offset);
|
||||
+ ret = preallocate_co(bs, old_length, offset, errp);
|
||||
if (ret < 0) {
|
||||
- error_setg_errno(errp, -ret, "Preallocation failed");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
From f29fbf7c6b1c9a84f6931c1c222716fbe073e6e4 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Mon, 15 Apr 2019 16:25:01 +0200
|
||||
Subject: [PATCH] qcow2: Avoid COW during metadata preallocation
|
||||
|
||||
Limiting the allocation to INT_MAX bytes isn't particularly clever
|
||||
because it means that the final cluster will be a partial cluster which
|
||||
will be completed through a COW operation. This results in unnecessary
|
||||
data read and write requests which lead to an unwanted non-sparse
|
||||
filesystem block for metadata preallocation.
|
||||
|
||||
Align the maximum allocation size down to the cluster size to avoid this
|
||||
situation.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
(cherry-picked from commit f29fbf7c6b1c9a84f6931c1c222716fbe073e6e4)
|
||||
---
|
||||
block/qcow2.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index 3ace3b2209..dfac74c264 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -2734,7 +2734,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
bytes = new_length - offset;
|
||||
|
||||
while (bytes) {
|
||||
- cur_bytes = MIN(bytes, INT_MAX);
|
||||
+ cur_bytes = MIN(bytes, QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size));
|
||||
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
|
||||
&host_offset, &meta);
|
||||
if (ret < 0) {
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,116 +0,0 @@
|
||||
From 718c0fce2f56755a8d8f737607779a98aa6e7cc4 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Mon, 15 Apr 2019 16:34:30 +0200
|
||||
Subject: [PATCH] qcow2: Fix full preallocation with external data file
|
||||
|
||||
preallocate_co() already gave the data file the full size without
|
||||
forwarding the requested preallocation mode to the protocol. When
|
||||
bdrv_co_truncate() was called later with the preallocation mode, the
|
||||
file didn't actually grow any more, so the data file stayed unallocated
|
||||
even if full preallocation was requested.
|
||||
|
||||
Pass the right preallocation mode to preallocate_co() and remove the
|
||||
second bdrv_co_truncate() to fix this. As a side effect, the ugly
|
||||
one-byte write in preallocate_co() is replaced with a truncate call,
|
||||
now leaving the last block unallocated on the protocol level as it
|
||||
should be.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
(cherry-picked from commit 718c0fce2f56755a8d8f737607779a98aa6e7cc4)
|
||||
---
|
||||
block/qcow2.c | 41 +++++++++++++++++++++++------------------
|
||||
1 file changed, 23 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index b4f9f5a240..7fbef97aab 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -2721,11 +2721,13 @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
|
||||
* Returns: 0 on success, -errno on failure.
|
||||
*/
|
||||
static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
- uint64_t new_length, Error **errp)
|
||||
+ uint64_t new_length, PreallocMode mode,
|
||||
+ Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t bytes;
|
||||
uint64_t host_offset = 0;
|
||||
+ int64_t file_length;
|
||||
unsigned int cur_bytes;
|
||||
int ret;
|
||||
QCowL2Meta *meta;
|
||||
@@ -2772,12 +2774,19 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
|
||||
* all of the allocated clusters (otherwise we get failing reads after
|
||||
* EOF). Extend the image to the last allocated sector.
|
||||
*/
|
||||
- if (host_offset != 0) {
|
||||
- uint8_t data = 0;
|
||||
- ret = bdrv_pwrite(s->data_file, (host_offset + cur_bytes) - 1,
|
||||
- &data, 1);
|
||||
+ file_length = bdrv_getlength(s->data_file->bs);
|
||||
+ if (file_length < 0) {
|
||||
+ error_setg_errno(errp, -file_length, "Could not get file size");
|
||||
+ return file_length;
|
||||
+ }
|
||||
+
|
||||
+ if (host_offset + cur_bytes > file_length) {
|
||||
+ if (mode == PREALLOC_MODE_METADATA) {
|
||||
+ mode = PREALLOC_MODE_OFF;
|
||||
+ }
|
||||
+ ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, mode,
|
||||
+ errp);
|
||||
if (ret < 0) {
|
||||
- error_setg_errno(errp, -ret, "Writing to EOF failed");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -3748,10 +3757,16 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
switch (prealloc) {
|
||||
case PREALLOC_MODE_OFF:
|
||||
+ if (has_data_file(bs)) {
|
||||
+ ret = bdrv_co_truncate(s->data_file, offset, prealloc, errp);
|
||||
+ if (ret < 0) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
break;
|
||||
|
||||
case PREALLOC_MODE_METADATA:
|
||||
- ret = preallocate_co(bs, old_length, offset, errp);
|
||||
+ ret = preallocate_co(bs, old_length, offset, prealloc, errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -3768,7 +3783,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
/* With a data file, preallocation means just allocating the metadata
|
||||
* and forwarding the truncate request to the data file */
|
||||
if (has_data_file(bs)) {
|
||||
- ret = preallocate_co(bs, old_length, offset, errp);
|
||||
+ ret = preallocate_co(bs, old_length, offset, prealloc, errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -3883,16 +3898,6 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
|
||||
bs->total_sectors = offset / BDRV_SECTOR_SIZE;
|
||||
|
||||
- if (has_data_file(bs)) {
|
||||
- if (prealloc == PREALLOC_MODE_METADATA) {
|
||||
- prealloc = PREALLOC_MODE_OFF;
|
||||
- }
|
||||
- ret = bdrv_co_truncate(s->data_file, offset, prealloc, errp);
|
||||
- if (ret < 0) {
|
||||
- goto fail;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
/* write updated header.size */
|
||||
offset = cpu_to_be64(offset);
|
||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
From db04524f820582ebf1189223b6378de238511da1 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Mon, 29 Apr 2019 12:52:21 +0200
|
||||
Subject: [PATCH] qcow2: Fix qcow2_make_empty() with external data file
|
||||
|
||||
make_completely_empty() is an optimisated path for bdrv_make_empty()
|
||||
where completely new metadata is created inside the image file instead
|
||||
of going through all clusters and discarding them. For an external data
|
||||
file, however, we actually need to do discard operations on the data
|
||||
file; just overwriting the qcow2 file doesn't get rid of the data.
|
||||
|
||||
The necessary slow path with an explicit discard operation already
|
||||
exists for other cases. Use it for external data files, too.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
(cherry-picked from commit db04524f820582ebf1189223b6378de238511da1)
|
||||
---
|
||||
block/qcow2.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index 7fbef97aab..840f289a48 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -4384,14 +4384,17 @@ static int qcow2_make_empty(BlockDriverState *bs)
|
||||
|
||||
if (s->qcow_version >= 3 && !s->snapshots && !s->nb_bitmaps &&
|
||||
3 + l1_clusters <= s->refcount_block_size &&
|
||||
- s->crypt_method_header != QCOW_CRYPT_LUKS) {
|
||||
+ s->crypt_method_header != QCOW_CRYPT_LUKS &&
|
||||
+ !has_data_file(bs)) {
|
||||
/* The following function only works for qcow2 v3 images (it
|
||||
* requires the dirty flag) and only as long as there are no
|
||||
* features that reserve extra clusters (such as snapshots,
|
||||
* LUKS header, or persistent bitmaps), because it completely
|
||||
* empties the image. Furthermore, the L1 table and three
|
||||
* additional clusters (image header, refcount table, one
|
||||
- * refcount block) have to fit inside one refcount block. */
|
||||
+ * refcount block) have to fit inside one refcount block. It
|
||||
+ * only resets the image file, i.e. does not work with an
|
||||
+ * external data file. */
|
||||
return make_completely_empty(bs);
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
From cb7630af20d353cbde66ddfb14d858737ffaf877 Mon Sep 17 00:00:00 2001
|
||||
From: Alberto Garcia <berto@igalia.com>
|
||||
Date: Fri, 16 Aug 2019 15:17:42 +0300
|
||||
Subject: [PATCH] qcow2: Fix the calculation of the maximum L2 cache size
|
||||
|
||||
The size of the qcow2 L2 cache defaults to 32 MB, which can be easily
|
||||
larger than the maximum amount of L2 metadata that the image can have.
|
||||
For example: with 64 KB clusters the user would need a qcow2 image
|
||||
with a virtual size of 256 GB in order to have 32 MB of L2 metadata.
|
||||
|
||||
Because of that, since commit b749562d9822d14ef69c9eaa5f85903010b86c30
|
||||
we forbid the L2 cache to become larger than the maximum amount of L2
|
||||
metadata for the image, calculated using this formula:
|
||||
|
||||
uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
|
||||
|
||||
The problem with this formula is that the result should be rounded up
|
||||
to the cluster size because an L2 table on disk always takes one full
|
||||
cluster.
|
||||
|
||||
For example, a 1280 MB qcow2 image with 64 KB clusters needs exactly
|
||||
160 KB of L2 metadata, but we need 192 KB on disk (3 clusters) even if
|
||||
the last 32 KB of those are not going to be used.
|
||||
|
||||
However QEMU rounds the numbers down and only creates 2 cache tables
|
||||
(128 KB), which is not enough for the image.
|
||||
|
||||
A quick test doing 4KB random writes on a 1280 MB image gives me
|
||||
around 500 IOPS, while with the correct cache size I get 16K IOPS.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Alberto Garcia <berto@igalia.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit b70d08205b2e4044c529eefc21df2c8ab61b473b)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
block/qcow2.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index 840f289a48..c80f48a02b 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -831,7 +831,11 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
|
||||
bool l2_cache_entry_size_set;
|
||||
int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
|
||||
uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
- uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
|
||||
+ uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size);
|
||||
+ /* An L2 table is always one cluster in size so the max cache size
|
||||
+ * should be a multiple of the cluster size. */
|
||||
+ uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t),
|
||||
+ s->cluster_size);
|
||||
|
||||
combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
|
||||
l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
Name: qemu
|
||||
Version: 4.0.0
|
||||
Release: 6
|
||||
Version: 4.0.1
|
||||
Release: 7
|
||||
Epoch: 2
|
||||
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
||||
License: GPLv2 and BSD and MIT and CC-BY
|
||||
|
||||
@ -1,104 +0,0 @@
|
||||
From dee1c7242e6b11d502728840f36d021ceedce140 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Wed, 14 Aug 2019 17:35:21 +0530
|
||||
Subject: [PATCH 3/5] scsi: lsi: exit infinite loop while executing script
|
||||
(CVE-2019-12068)
|
||||
|
||||
When executing script in lsi_execute_script(), the LSI scsi adapter
|
||||
emulator advances 's->dsp' index to read next opcode. This can lead
|
||||
to an infinite loop if the next opcode is empty. Move the existing
|
||||
loop exit after 10k iterations so that it covers no-op opcodes as
|
||||
well.
|
||||
|
||||
Reported-by: Bugs SysSec <bugs-syssec@rub.de>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry-picked from commit de594e47659029316bbf9391efb79da0a1a08e08)
|
||||
---
|
||||
hw/scsi/lsi53c895a.c | 41 +++++++++++++++++++++++++++--------------
|
||||
1 file changed, 27 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
|
||||
index da7239d..d3380b6 100644
|
||||
--- a/hw/scsi/lsi53c895a.c
|
||||
+++ b/hw/scsi/lsi53c895a.c
|
||||
@@ -184,6 +184,9 @@ static const char *names[] = {
|
||||
/* Flag set if this is a tagged command. */
|
||||
#define LSI_TAG_VALID (1 << 16)
|
||||
|
||||
+/* Maximum instructions to process. */
|
||||
+#define LSI_MAX_INSN 10000
|
||||
+
|
||||
typedef struct lsi_request {
|
||||
SCSIRequest *req;
|
||||
uint32_t tag;
|
||||
@@ -1131,7 +1134,21 @@ static void lsi_execute_script(LSIState *s)
|
||||
|
||||
s->istat1 |= LSI_ISTAT1_SRUN;
|
||||
again:
|
||||
- insn_processed++;
|
||||
+ if (++insn_processed > LSI_MAX_INSN) {
|
||||
+ /* Some windows drivers make the device spin waiting for a memory
|
||||
+ location to change. If we have been executed a lot of code then
|
||||
+ assume this is the case and force an unexpected device disconnect.
|
||||
+ This is apparently sufficient to beat the drivers into submission.
|
||||
+ */
|
||||
+ if (!(s->sien0 & LSI_SIST0_UDC)) {
|
||||
+ qemu_log_mask(LOG_GUEST_ERROR,
|
||||
+ "lsi_scsi: inf. loop with UDC masked");
|
||||
+ }
|
||||
+ lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
|
||||
+ lsi_disconnect(s);
|
||||
+ trace_lsi_execute_script_stop();
|
||||
+ return;
|
||||
+ }
|
||||
insn = read_dword(s, s->dsp);
|
||||
if (!insn) {
|
||||
/* If we receive an empty opcode increment the DSP by 4 bytes
|
||||
@@ -1568,19 +1585,7 @@ again:
|
||||
}
|
||||
}
|
||||
}
|
||||
- if (insn_processed > 10000 && s->waiting == LSI_NOWAIT) {
|
||||
- /* Some windows drivers make the device spin waiting for a memory
|
||||
- location to change. If we have been executed a lot of code then
|
||||
- assume this is the case and force an unexpected device disconnect.
|
||||
- This is apparently sufficient to beat the drivers into submission.
|
||||
- */
|
||||
- if (!(s->sien0 & LSI_SIST0_UDC)) {
|
||||
- qemu_log_mask(LOG_GUEST_ERROR,
|
||||
- "lsi_scsi: inf. loop with UDC masked");
|
||||
- }
|
||||
- lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
|
||||
- lsi_disconnect(s);
|
||||
- } else if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) {
|
||||
+ if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) {
|
||||
if (s->dcntl & LSI_DCNTL_SSM) {
|
||||
lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
|
||||
} else {
|
||||
@@ -1968,6 +1973,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
case 0x2f: /* DSP[24:31] */
|
||||
s->dsp &= 0x00ffffff;
|
||||
s->dsp |= val << 24;
|
||||
+ /*
|
||||
+ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one
|
||||
+ * instruction. Is this correct?
|
||||
+ */
|
||||
if ((s->dmode & LSI_DMODE_MAN) == 0
|
||||
&& (s->istat1 & LSI_ISTAT1_SRUN) == 0)
|
||||
lsi_execute_script(s);
|
||||
@@ -1986,6 +1995,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
|
||||
break;
|
||||
case 0x3b: /* DCNTL */
|
||||
s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
|
||||
+ /*
|
||||
+ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one
|
||||
+ * instruction. Is this correct?
|
||||
+ */
|
||||
if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
|
||||
lsi_execute_script(s);
|
||||
break;
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
From c2e03e2aa42d0f4f41deb08c2655503835840afa Mon Sep 17 00:00:00 2001
|
||||
From: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
Date: Tue, 24 Sep 2019 15:57:59 -0500
|
||||
Subject: [PATCH] slirp: Fix heap overflow in ip_reass on big packet input
|
||||
|
||||
When the first fragment does not fit in the preallocated buffer, q will
|
||||
already be pointing to the ext buffer, so we mustn't try to update it.
|
||||
|
||||
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
(from libslirp.git commit 126c04acbabd7ad32c2b018fe10dfac2a3bc1210)
|
||||
(from libslirp.git commit e0be80430c390bce181ea04dfcdd6ea3dfa97de1)
|
||||
*squash in e0be80 (clarifying comments)
|
||||
Fixes: CVE-2019-14378
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
slirp/src/ip_input.c | 13 +++++++------
|
||||
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c
|
||||
index a714fecd58..68a99de5b5 100644
|
||||
--- a/slirp/src/ip_input.c
|
||||
+++ b/slirp/src/ip_input.c
|
||||
@@ -331,6 +331,8 @@ insert:
|
||||
q = fp->frag_link.next;
|
||||
m = dtom(slirp, q);
|
||||
|
||||
+ int was_ext = m->m_flags & M_EXT;
|
||||
+
|
||||
q = (struct ipasfrag *) q->ipf_next;
|
||||
while (q != (struct ipasfrag*)&fp->frag_link) {
|
||||
struct mbuf *t = dtom(slirp, q);
|
||||
@@ -347,13 +349,12 @@ insert:
|
||||
q = fp->frag_link.next;
|
||||
|
||||
/*
|
||||
- * If the fragments concatenated to an mbuf that's
|
||||
- * bigger than the total size of the fragment, then and
|
||||
- * m_ext buffer was alloced. But fp->ipq_next points to
|
||||
- * the old buffer (in the mbuf), so we must point ip
|
||||
- * into the new buffer.
|
||||
+ * If the fragments concatenated to an mbuf that's bigger than the total
|
||||
+ * size of the fragment and the mbuf was not already using an m_ext buffer,
|
||||
+ * then an m_ext buffer was alloced. But fp->ipq_next points to the old
|
||||
+ * buffer (in the mbuf), so we must point ip into the new buffer.
|
||||
*/
|
||||
- if (m->m_flags & M_EXT) {
|
||||
+ if (!was_ext && m->m_flags & M_EXT) {
|
||||
int delta = (char *)q - m->m_dat;
|
||||
q = (struct ipasfrag *)(m->m_ext + delta);
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
From b27192be13da3fb59f51185d9a1f944b3474b2fc Mon Sep 17 00:00:00 2001
|
||||
From: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
Date: Tue, 24 Sep 2019 16:04:04 -0500
|
||||
Subject: [PATCH] slirp: ip_reass: Fix use after free
|
||||
|
||||
Using ip_deq after m_free might read pointers from an allocation reuse.
|
||||
|
||||
This would be difficult to exploit, but that is still related with
|
||||
CVE-2019-14378 which generates fragmented IP packets that would trigger this
|
||||
issue and at least produce a DoS.
|
||||
|
||||
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
(from libslirp.git commit c59279437eda91841b9d26079c70b8a540d41204)
|
||||
Fixes: CVE-2019-15890
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
slirp/src/ip_input.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c
|
||||
index 68a99de5b5..89ae04e0c1 100644
|
||||
--- a/slirp/src/ip_input.c
|
||||
+++ b/slirp/src/ip_input.c
|
||||
@@ -297,6 +297,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
|
||||
*/
|
||||
while (q != (struct ipasfrag*)&fp->frag_link &&
|
||||
ip->ip_off + ip->ip_len > q->ipf_off) {
|
||||
+ struct ipasfrag *prev;
|
||||
i = (ip->ip_off + ip->ip_len) - q->ipf_off;
|
||||
if (i < q->ipf_len) {
|
||||
q->ipf_len -= i;
|
||||
@@ -304,9 +305,10 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
|
||||
m_adj(dtom(slirp, q), i);
|
||||
break;
|
||||
}
|
||||
+ prev = q;
|
||||
q = q->ipf_next;
|
||||
- m_free(dtom(slirp, q->ipf_prev));
|
||||
- ip_deq(q->ipf_prev);
|
||||
+ ip_deq(prev);
|
||||
+ m_free(dtom(slirp, prev));
|
||||
}
|
||||
|
||||
insert:
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From 41e1564fb50515d7902628d25c0c8421a8516cc1 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Thu, 6 Jun 2019 16:12:03 +0200
|
||||
Subject: [PATCH] target/i386: add MDS-NO feature
|
||||
|
||||
Microarchitectural Data Sampling is a hardware vulnerability which allows
|
||||
unprivileged speculative access to data which is available in various CPU
|
||||
internal buffers.
|
||||
|
||||
Some Intel processors use the ARCH_CAP_MDS_NO bit in the
|
||||
IA32_ARCH_CAPABILITIES
|
||||
MSR to report that they are not vulnerable, make it available to guests.
|
||||
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Message-Id: <20190516185320.28340-1-pbonzini@redhat.com>
|
||||
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||
(cherry picked from commit 20140a82c67467f53814ca197403d5e1b561a5e5)
|
||||
Signed-off-by: Oguz Bektas <o.bektas@proxmox.com>
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
target/i386/cpu.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||
index d6bb57d210..ee4b8b47e2 100644
|
||||
--- a/target/i386/cpu.c
|
||||
+++ b/target/i386/cpu.c
|
||||
@@ -1183,7 +1183,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
.type = MSR_FEATURE_WORD,
|
||||
.feat_names = {
|
||||
"rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry",
|
||||
- "ssb-no", NULL, NULL, NULL,
|
||||
+ "ssb-no", "mds-no", NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Wed, 15 May 2019 15:10:10 +0100
|
||||
Subject: [PATCH] target/i386: define md-clear bit
|
||||
|
||||
md-clear is a new CPUID bit which is set when microcode provides the
|
||||
mechanism to invoke a flush of various exploitable CPU buffers by invoking
|
||||
the VERW instruction.
|
||||
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Message-Id: <20190515141011.5315-2-berrange@redhat.com>
|
||||
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||
(cherry picked from commit b2ae52101fca7f9547ac2f388085dbc58f8fe1c0)
|
||||
---
|
||||
target/i386/cpu.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||
index d6bb57d210..4ea78a4939 100644
|
||||
--- a/target/i386/cpu.c
|
||||
+++ b/target/i386/cpu.c
|
||||
@@ -1076,7 +1076,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||
.feat_names = {
|
||||
NULL, NULL, "avx512-4vnniw", "avx512-4fmaps",
|
||||
NULL, NULL, NULL, NULL,
|
||||
- NULL, NULL, NULL, NULL,
|
||||
+ NULL, NULL, "md-clear", NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
@ -1,39 +0,0 @@
|
||||
From 665218cc085c5c1ec871d8af6986903313638fbf Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Mon, 20 May 2019 10:18:05 +0200
|
||||
Subject: [PATCH] usb-tablet: fix serial compat property
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
s/kbd/tablet/, fixes cut+paste bug.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
Message-id: 20190520081805.15019-1-kraxel@redhat.com
|
||||
(cherry picked from commit 442bac16a6cd708a9f87adb0a263f9d833f03ed5)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/core/machine.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index 743fef2898..b6766632d9 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -33,7 +33,7 @@ GlobalProperty hw_compat_3_1[] = {
|
||||
{ "tpm-tis", "ppi", "false" },
|
||||
{ "usb-kbd", "serial", "42" },
|
||||
{ "usb-mouse", "serial", "42" },
|
||||
- { "usb-kbd", "serial", "42" },
|
||||
+ { "usb-tablet", "serial", "42" },
|
||||
{ "virtio-blk-device", "discard", "false" },
|
||||
{ "virtio-blk-device", "write-zeroes", "false" },
|
||||
};
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
From e86e620656becb37890a6d91e0148c74f3e43f3d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
||||
Date: Wed, 7 Aug 2019 12:40:48 +0400
|
||||
Subject: [PATCH] usbredir: fix buffer-overflow on vmload
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
If interface_count is NO_INTERFACE_INFO, let's not access the arrays
|
||||
out-of-bounds.
|
||||
|
||||
==994==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x625000243930 at pc 0x5642068086a8 bp 0x7f0b6f9ffa50 sp 0x7f0b6f9ffa40
|
||||
READ of size 1 at 0x625000243930 thread T0
|
||||
#0 0x5642068086a7 in usbredir_check_bulk_receiving /home/elmarco/src/qemu/hw/usb/redirect.c:1503
|
||||
#1 0x56420681301c in usbredir_post_load /home/elmarco/src/qemu/hw/usb/redirect.c:2154
|
||||
#2 0x5642068a56c2 in vmstate_load_state /home/elmarco/src/qemu/migration/vmstate.c:168
|
||||
#3 0x56420688e2ac in vmstate_load /home/elmarco/src/qemu/migration/savevm.c:829
|
||||
#4 0x5642068980cb in qemu_loadvm_section_start_full /home/elmarco/src/qemu/migration/savevm.c:2211
|
||||
#5 0x564206899645 in qemu_loadvm_state_main /home/elmarco/src/qemu/migration/savevm.c:2395
|
||||
#6 0x5642068998cf in qemu_loadvm_state /home/elmarco/src/qemu/migration/savevm.c:2467
|
||||
#7 0x56420685f3e9 in process_incoming_migration_co /home/elmarco/src/qemu/migration/migration.c:449
|
||||
#8 0x564207106c47 in coroutine_trampoline /home/elmarco/src/qemu/util/coroutine-ucontext.c:115
|
||||
#9 0x7f0c0604e37f (/lib64/libc.so.6+0x4d37f)
|
||||
|
||||
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
|
||||
Reviewed-by: Li Qiang <liq3ea@gmail.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
Message-id: 20190807084048.4258-1-marcandre.lureau@redhat.com
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
(cherry picked from commit 7b84b90966568da0e05655ecaa78c209300aae6e)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/usb/redirect.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
|
||||
index 7cb6b120d4..586c7db025 100644
|
||||
--- a/hw/usb/redirect.c
|
||||
+++ b/hw/usb/redirect.c
|
||||
@@ -1494,6 +1494,11 @@ static void usbredir_check_bulk_receiving(USBRedirDevice *dev)
|
||||
for (i = EP2I(USB_DIR_IN); i < MAX_ENDPOINTS; i++) {
|
||||
dev->endpoint[i].bulk_receiving_enabled = 0;
|
||||
}
|
||||
+
|
||||
+ if (dev->interface_info.interface_count == NO_INTERFACE_INFO) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < dev->interface_info.interface_count; i++) {
|
||||
quirks = usb_get_quirks(dev->device_info.vendor_id,
|
||||
dev->device_info.product_id,
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
From fc5c701636127a0b90cd7ab564da0354d06809dc Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Date: Mon, 5 Aug 2019 15:01:20 +0300
|
||||
Subject: [PATCH] util/hbitmap: update orig_size on truncate
|
||||
|
||||
Without this, hbitmap_next_zero and hbitmap_next_dirty_area are broken
|
||||
after truncate. So, orig_size is broken since it's introduction in
|
||||
76d570dc495c56bb.
|
||||
|
||||
Fixes: 76d570dc495c56bb
|
||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||
Message-id: 20190805120120.23585-1-vsementsov@virtuozzo.com
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit 4e4de222799634d8159ee7b9303b9e1b45c6be2c)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
util/hbitmap.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/util/hbitmap.c b/util/hbitmap.c
|
||||
index 7905212a8b..bcc0acdc6a 100644
|
||||
--- a/util/hbitmap.c
|
||||
+++ b/util/hbitmap.c
|
||||
@@ -53,7 +53,9 @@
|
||||
*/
|
||||
|
||||
struct HBitmap {
|
||||
- /* Size of the bitmap, as requested in hbitmap_alloc. */
|
||||
+ /*
|
||||
+ * Size of the bitmap, as requested in hbitmap_alloc or in hbitmap_truncate.
|
||||
+ */
|
||||
uint64_t orig_size;
|
||||
|
||||
/* Number of total bits in the bottom level. */
|
||||
@@ -732,6 +734,8 @@ void hbitmap_truncate(HBitmap *hb, uint64_t size)
|
||||
uint64_t num_elements = size;
|
||||
uint64_t old;
|
||||
|
||||
+ hb->orig_size = size;
|
||||
+
|
||||
/* Size comes in as logical elements, adjust for granularity. */
|
||||
size = (size + (1ULL << hb->granularity) - 1) >> hb->granularity;
|
||||
assert(size <= ((uint64_t)1 << HBITMAP_LOG_MAX_SIZE));
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,69 +0,0 @@
|
||||
From 240e647a14df9677b3a501f7b8b870e40aac3fd5 Mon Sep 17 00:00:00 2001
|
||||
From: Li Hangjing <lihangjing@baidu.com>
|
||||
Date: Mon, 3 Jun 2019 14:15:24 +0800
|
||||
Subject: [PATCH] vhost: fix vhost_log size overflow during migration
|
||||
|
||||
When a guest which doesn't support multiqueue is migrated with a multi queues
|
||||
vhost-user-blk deivce, a crash will occur like:
|
||||
|
||||
0 qemu_memfd_alloc (name=<value optimized out>, size=562949953421312, seals=<value optimized out>, fd=0x7f87171fe8b4, errp=0x7f87171fe8a8) at util/memfd.c:153
|
||||
1 0x00007f883559d7cf in vhost_log_alloc (size=70368744177664, share=true) at hw/virtio/vhost.c:186
|
||||
2 0x00007f88355a0758 in vhost_log_get (listener=0x7f8838bd7940, enable=1) at qemu-2-12/hw/virtio/vhost.c:211
|
||||
3 vhost_dev_log_resize (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:263
|
||||
4 vhost_migration_log (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:787
|
||||
5 0x00007f88355463d6 in memory_global_dirty_log_start () at memory.c:2503
|
||||
6 0x00007f8835550577 in ram_init_bitmaps (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2173
|
||||
7 ram_init_all (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2192
|
||||
8 ram_save_setup (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2219
|
||||
9 0x00007f88357a419d in qemu_savevm_state_setup (f=0x7f88384ce600) at migration/savevm.c:1002
|
||||
10 0x00007f883579fc3e in migration_thread (opaque=0x7f8837530400) at migration/migration.c:2382
|
||||
11 0x00007f8832447893 in start_thread () from /lib64/libpthread.so.0
|
||||
12 0x00007f8832178bfd in clone () from /lib64/libc.so.6
|
||||
|
||||
This is because vhost_get_log_size() returns a overflowed vhost-log size.
|
||||
In this function, it uses the uninitialized variable vqs->used_phys and
|
||||
vqs->used_size to get the vhost-log size.
|
||||
|
||||
Signed-off-by: Li Hangjing <lihangjing@baidu.com>
|
||||
Reviewed-by: Xie Yongji <xieyongji@baidu.com>
|
||||
Reviewed-by: Chai Wen <chaiwen@baidu.com>
|
||||
Message-Id: <20190603061524.24076-1-lihangjing@baidu.com>
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-pick from commit 240e647a14df9677b3a501f7b8b870e40aac3fd5)
|
||||
---
|
||||
hw/virtio/vhost.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
|
||||
index 60747a6f93..bc899fc60e 100644
|
||||
--- a/hw/virtio/vhost.c
|
||||
+++ b/hw/virtio/vhost.c
|
||||
@@ -131,6 +131,11 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
|
||||
}
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
struct vhost_virtqueue *vq = dev->vqs + i;
|
||||
+
|
||||
+ if (!vq->used_phys && !vq->used_size) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys,
|
||||
range_get_last(vq->used_phys, vq->used_size));
|
||||
}
|
||||
@@ -168,6 +173,11 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
|
||||
}
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
struct vhost_virtqueue *vq = dev->vqs + i;
|
||||
+
|
||||
+ if (!vq->used_phys && !vq->used_size) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
uint64_t last = vq->used_phys + vq->used_size - 1;
|
||||
log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
|
||||
}
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,113 +0,0 @@
|
||||
From e6129b271b9dccca22c84870e313c315f2c70063 Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Mon, 22 Jul 2019 15:41:06 +0200
|
||||
Subject: [PATCH] virtio-balloon: Better names for offset variables in
|
||||
inflate/deflate code
|
||||
|
||||
"host_page_base" is really confusing, let's make this clearer, also
|
||||
rename the other offsets to indicate to which base they apply.
|
||||
|
||||
offset -> mr_offset
|
||||
ram_offset -> rb_offset
|
||||
host_page_base -> rb_aligned_offset
|
||||
|
||||
While at it, use QEMU_ALIGN_DOWN() instead of a handcrafted computation
|
||||
and move the computation to the place where it is needed.
|
||||
|
||||
Acked-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Message-Id: <20190722134108.22151-5-david@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-picked from commit e6129b271b9dccca22c84870e313c315f2c70063)
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index 04a7e6c772..f206cc8bf7 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -41,24 +41,23 @@ struct PartiallyBalloonedPage {
|
||||
};
|
||||
|
||||
static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
- MemoryRegion *mr, hwaddr offset)
|
||||
+ MemoryRegion *mr, hwaddr mr_offset)
|
||||
{
|
||||
- void *addr = memory_region_get_ram_ptr(mr) + offset;
|
||||
+ void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||
+ ram_addr_t rb_offset, rb_aligned_offset;
|
||||
RAMBlock *rb;
|
||||
size_t rb_page_size;
|
||||
int subpages;
|
||||
- ram_addr_t ram_offset, host_page_base;
|
||||
|
||||
/* XXX is there a better way to get to the RAMBlock than via a
|
||||
* host address? */
|
||||
- rb = qemu_ram_block_from_host(addr, false, &ram_offset);
|
||||
+ rb = qemu_ram_block_from_host(addr, false, &rb_offset);
|
||||
rb_page_size = qemu_ram_pagesize(rb);
|
||||
- host_page_base = ram_offset & ~(rb_page_size - 1);
|
||||
|
||||
if (rb_page_size == BALLOON_PAGE_SIZE) {
|
||||
/* Easy case */
|
||||
|
||||
- ram_block_discard_range(rb, ram_offset, rb_page_size);
|
||||
+ ram_block_discard_range(rb, rb_offset, rb_page_size);
|
||||
/* We ignore errors from ram_block_discard_range(), because it
|
||||
* has already reported them, and failing to discard a balloon
|
||||
* page is not fatal */
|
||||
@@ -74,11 +73,12 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
warn_report_once(
|
||||
"Balloon used with backing page size > 4kiB, this may not be reliable");
|
||||
|
||||
+ rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size);
|
||||
subpages = rb_page_size / BALLOON_PAGE_SIZE;
|
||||
|
||||
if (balloon->pbp
|
||||
&& (rb != balloon->pbp->rb
|
||||
- || host_page_base != balloon->pbp->base)) {
|
||||
+ || rb_aligned_offset != balloon->pbp->base)) {
|
||||
/* We've partially ballooned part of a host page, but now
|
||||
* we're trying to balloon part of a different one. Too hard,
|
||||
* give up on the old partial page */
|
||||
@@ -91,10 +91,10 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long);
|
||||
balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen);
|
||||
balloon->pbp->rb = rb;
|
||||
- balloon->pbp->base = host_page_base;
|
||||
+ balloon->pbp->base = rb_aligned_offset;
|
||||
}
|
||||
|
||||
- set_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
+ set_bit((rb_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
balloon->pbp->bitmap);
|
||||
|
||||
if (bitmap_full(balloon->pbp->bitmap, subpages)) {
|
||||
@@ -112,18 +112,18 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
}
|
||||
|
||||
static void balloon_deflate_page(VirtIOBalloon *balloon,
|
||||
- MemoryRegion *mr, hwaddr offset)
|
||||
+ MemoryRegion *mr, hwaddr mr_offset)
|
||||
{
|
||||
- void *addr = memory_region_get_ram_ptr(mr) + offset;
|
||||
+ void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||
+ ram_addr_t rb_offset;
|
||||
RAMBlock *rb;
|
||||
size_t rb_page_size;
|
||||
- ram_addr_t ram_offset;
|
||||
void *host_addr;
|
||||
int ret;
|
||||
|
||||
/* XXX is there a better way to get to the RAMBlock than via a
|
||||
* host address? */
|
||||
- rb = qemu_ram_block_from_host(addr, false, &ram_offset);
|
||||
+ rb = qemu_ram_block_from_host(addr, false, &rb_offset);
|
||||
rb_page_size = qemu_ram_pagesize(rb);
|
||||
|
||||
if (balloon->pbp) {
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
From 483f13524bb2a08b7ff6a7560b846564ed3b0c33 Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Mon, 22 Jul 2019 15:41:04 +0200
|
||||
Subject: [PATCH] virtio-balloon: Fix QEMU crashes on pagesize >
|
||||
BALLOON_PAGE_SIZE
|
||||
|
||||
We are using the wrong functions to set/clear bits, effectively touching
|
||||
multiple bits, writing out of range of the bitmap, resulting in memory
|
||||
corruptions. We have to use set_bit()/clear_bit() instead.
|
||||
|
||||
Can easily be reproduced by starting a qemu guest on hugetlbfs memory,
|
||||
inflating the balloon. QEMU crashes. This never could have worked
|
||||
properly - especially, also pages would have been discarded when the
|
||||
first sub-page would be inflated (the whole bitmap would be set).
|
||||
|
||||
While testing I realized, that on hugetlbfs it is pretty much impossible
|
||||
to discard a page - the guest just frees the 4k sub-pages in random order
|
||||
most of the time. I was only able to discard a hugepage a handful of
|
||||
times - so I hope that now works correctly.
|
||||
|
||||
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
|
||||
Fixes: b27b32391404 ("virtio-balloon: Fix possible guest memory corruption with inflates & deflates")
|
||||
Cc: qemu-stable@nongnu.org #v4.0.0
|
||||
Acked-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Message-Id: <20190722134108.22151-3-david@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-pick from commit 483f13524bb2a08b7ff6a7560b846564ed3b0c33)
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 10 ++++------
|
||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index 515abf6553..a78d2d2184 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -94,9 +94,8 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
balloon->pbp->base = host_page_base;
|
||||
}
|
||||
|
||||
- bitmap_set(balloon->pbp->bitmap,
|
||||
- (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
- subpages);
|
||||
+ set_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
+ balloon->pbp->bitmap);
|
||||
|
||||
if (bitmap_full(balloon->pbp->bitmap, subpages)) {
|
||||
/* We've accumulated a full host page, we can actually discard
|
||||
@@ -140,9 +139,8 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
|
||||
* for a guest to do this in practice, but handle it anyway,
|
||||
* since getting it wrong could mean discarding memory the
|
||||
* guest is still using. */
|
||||
- bitmap_clear(balloon->pbp->bitmap,
|
||||
- (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
- subpages);
|
||||
+ clear_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
+ balloon->pbp->bitmap);
|
||||
|
||||
if (bitmap_empty(balloon->pbp->bitmap, subpages)) {
|
||||
g_free(balloon->pbp);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
From ffa207d08253ffffb3993a1dbe09e40af4fc91f1 Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Mon, 22 Jul 2019 15:41:03 +0200
|
||||
Subject: [PATCH] virtio-balloon: Fix wrong sign extension of PFNs
|
||||
|
||||
If we directly cast from int to uint64_t, we will first sign-extend to
|
||||
an int64_t, which is wrong. We actually want to treat the PFNs like
|
||||
unsigned values.
|
||||
|
||||
As far as I can see, this dates back to the initial virtio-balloon
|
||||
commit, but wasn't triggered as fairly big guests would be required.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reported-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Message-Id: <20190722134108.22151-2-david@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
(cherry-picked from commit ffa207d08253ffffb3993a1dbe09e40af4fc91f1)
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index e85d1c0d5c..515abf6553 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -343,8 +343,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
}
|
||||
|
||||
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
|
||||
+ unsigned int p = virtio_ldl_p(vdev, &pfn);
|
||||
hwaddr pa;
|
||||
- int p = virtio_ldl_p(vdev, &pfn);
|
||||
|
||||
pa = (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT;
|
||||
offset += 4;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,144 +0,0 @@
|
||||
From 1c5cfc2b7153dd72bf4b8ddc456408eb2b9b66d8 Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Mon, 22 Jul 2019 15:41:07 +0200
|
||||
Subject: [PATCH] virtio-balloon: Rework pbp tracking data
|
||||
|
||||
Using the address of a RAMBlock to test for a matching pbp is not really
|
||||
safe. Instead, let's use the guest physical address of the base page
|
||||
along with the page size (via the number of subpages).
|
||||
|
||||
Also, let's allocate the bitmap separately. This makes the code
|
||||
easier to read and maintain - we can reuse bitmap_new().
|
||||
|
||||
Prepare the code to move the PBP out of the device.
|
||||
|
||||
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
|
||||
Fixes: b27b32391404 ("virtio-balloon: Fix possible guest memory corruption with inflates & deflates")
|
||||
Cc: qemu-stable@nongnu.org #v4.0.0
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Message-Id: <20190722134108.22151-6-david@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-picked from commit 1c5cfc2b7153dd72bf4b8ddc456408eb2b9b66d8)
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 69 +++++++++++++++++++++++++-------------
|
||||
1 file changed, 46 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index f206cc8bf7..40d493a31a 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -35,16 +35,44 @@
|
||||
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
|
||||
|
||||
struct PartiallyBalloonedPage {
|
||||
- RAMBlock *rb;
|
||||
- ram_addr_t base;
|
||||
- unsigned long bitmap[];
|
||||
+ ram_addr_t base_gpa;
|
||||
+ long subpages;
|
||||
+ unsigned long *bitmap;
|
||||
};
|
||||
|
||||
+static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp)
|
||||
+{
|
||||
+ if (!pbp) {
|
||||
+ return;
|
||||
+ }
|
||||
+ g_free(pbp->bitmap);
|
||||
+ g_free(pbp);
|
||||
+}
|
||||
+
|
||||
+static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa,
|
||||
+ long subpages)
|
||||
+{
|
||||
+ PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1);
|
||||
+
|
||||
+ pbp->base_gpa = base_gpa;
|
||||
+ pbp->subpages = subpages;
|
||||
+ pbp->bitmap = bitmap_new(subpages);
|
||||
+
|
||||
+ return pbp;
|
||||
+}
|
||||
+
|
||||
+static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
|
||||
+ ram_addr_t base_gpa, long subpages)
|
||||
+{
|
||||
+ return pbp->subpages == subpages && pbp->base_gpa == base_gpa;
|
||||
+}
|
||||
+
|
||||
static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
MemoryRegion *mr, hwaddr mr_offset)
|
||||
{
|
||||
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||
- ram_addr_t rb_offset, rb_aligned_offset;
|
||||
+ ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
|
||||
+ PartiallyBalloonedPage **pbp = &balloon->pbp;
|
||||
RAMBlock *rb;
|
||||
size_t rb_page_size;
|
||||
int subpages;
|
||||
@@ -75,39 +103,34 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
|
||||
rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size);
|
||||
subpages = rb_page_size / BALLOON_PAGE_SIZE;
|
||||
+ base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
|
||||
+ (rb_offset - rb_aligned_offset);
|
||||
|
||||
- if (balloon->pbp
|
||||
- && (rb != balloon->pbp->rb
|
||||
- || rb_aligned_offset != balloon->pbp->base)) {
|
||||
+ if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa, subpages)) {
|
||||
/* We've partially ballooned part of a host page, but now
|
||||
* we're trying to balloon part of a different one. Too hard,
|
||||
* give up on the old partial page */
|
||||
- g_free(balloon->pbp);
|
||||
- balloon->pbp = NULL;
|
||||
+ virtio_balloon_pbp_free(*pbp);
|
||||
+ *pbp = NULL;
|
||||
}
|
||||
|
||||
- if (!balloon->pbp) {
|
||||
- /* Starting on a new host page */
|
||||
- size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long);
|
||||
- balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen);
|
||||
- balloon->pbp->rb = rb;
|
||||
- balloon->pbp->base = rb_aligned_offset;
|
||||
+ if (!*pbp) {
|
||||
+ *pbp = virtio_balloon_pbp_alloc(base_gpa, subpages);
|
||||
}
|
||||
|
||||
- set_bit((rb_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
- balloon->pbp->bitmap);
|
||||
+ set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE,
|
||||
+ (*pbp)->bitmap);
|
||||
|
||||
- if (bitmap_full(balloon->pbp->bitmap, subpages)) {
|
||||
+ if (bitmap_full((*pbp)->bitmap, subpages)) {
|
||||
/* We've accumulated a full host page, we can actually discard
|
||||
* it now */
|
||||
|
||||
- ram_block_discard_range(rb, balloon->pbp->base, rb_page_size);
|
||||
+ ram_block_discard_range(rb, rb_aligned_offset, rb_page_size);
|
||||
/* We ignore errors from ram_block_discard_range(), because it
|
||||
* has already reported them, and failing to discard a balloon
|
||||
* page is not fatal */
|
||||
-
|
||||
- g_free(balloon->pbp);
|
||||
- balloon->pbp = NULL;
|
||||
+ virtio_balloon_pbp_free(*pbp);
|
||||
+ *pbp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +151,7 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
|
||||
|
||||
if (balloon->pbp) {
|
||||
/* Let's play safe and always reset the pbp on deflation requests. */
|
||||
- g_free(balloon->pbp);
|
||||
+ virtio_balloon_pbp_free(balloon->pbp);
|
||||
balloon->pbp = NULL;
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
From 2ffc49eea1bbd454913a88a0ad872c2649b36950 Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Mon, 22 Jul 2019 15:41:05 +0200
|
||||
Subject: [PATCH] virtio-balloon: Simplify deflate with pbp
|
||||
|
||||
Let's simplify this - the case we are optimizing for is very hard to
|
||||
trigger and not worth the effort. If we're switching from inflation to
|
||||
deflation, let's reset the pbp.
|
||||
|
||||
Acked-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Message-Id: <20190722134108.22151-4-david@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-picked from commit 2ffc49eea1bbd454913a88a0ad872c2649b36950)
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 26 +++++---------------------
|
||||
1 file changed, 5 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index a78d2d2184..04a7e6c772 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -117,7 +117,7 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
|
||||
void *addr = memory_region_get_ram_ptr(mr) + offset;
|
||||
RAMBlock *rb;
|
||||
size_t rb_page_size;
|
||||
- ram_addr_t ram_offset, host_page_base;
|
||||
+ ram_addr_t ram_offset;
|
||||
void *host_addr;
|
||||
int ret;
|
||||
|
||||
@@ -125,27 +125,11 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
|
||||
* host address? */
|
||||
rb = qemu_ram_block_from_host(addr, false, &ram_offset);
|
||||
rb_page_size = qemu_ram_pagesize(rb);
|
||||
- host_page_base = ram_offset & ~(rb_page_size - 1);
|
||||
-
|
||||
- if (balloon->pbp
|
||||
- && rb == balloon->pbp->rb
|
||||
- && host_page_base == balloon->pbp->base) {
|
||||
- int subpages = rb_page_size / BALLOON_PAGE_SIZE;
|
||||
|
||||
- /*
|
||||
- * This means the guest has asked to discard some of the 4kiB
|
||||
- * subpages of a host page, but then changed its mind and
|
||||
- * asked to keep them after all. It's exceedingly unlikely
|
||||
- * for a guest to do this in practice, but handle it anyway,
|
||||
- * since getting it wrong could mean discarding memory the
|
||||
- * guest is still using. */
|
||||
- clear_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
|
||||
- balloon->pbp->bitmap);
|
||||
-
|
||||
- if (bitmap_empty(balloon->pbp->bitmap, subpages)) {
|
||||
- g_free(balloon->pbp);
|
||||
- balloon->pbp = NULL;
|
||||
- }
|
||||
+ if (balloon->pbp) {
|
||||
+ /* Let's play safe and always reset the pbp on deflation requests. */
|
||||
+ g_free(balloon->pbp);
|
||||
+ balloon->pbp = NULL;
|
||||
}
|
||||
|
||||
host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1));
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,136 +0,0 @@
|
||||
From 8e20acad634e38f29afd54b951c42eec113288bc Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Mon, 22 Jul 2019 15:41:08 +0200
|
||||
Subject: [PATCH] virtio-balloon: Use temporary PBP only
|
||||
|
||||
We still have multiple issues in the current code
|
||||
- The PBP is not freed during unrealize()
|
||||
- The PBP is not reset on device resets: After a reset, the PBP is stale.
|
||||
- We are not indicating VIRTIO_BALLOON_F_MUST_TELL_HOST, therefore
|
||||
guests (esp. legacy guests) will reuse pages without deflating,
|
||||
turning the PBP stale. Adding that would require compat handling.
|
||||
|
||||
Instead, let's use the PBP only temporarily, when processing one bulk of
|
||||
inflation requests. This will keep guest_page_size > 4k working (with
|
||||
Linux guests). There is nothing to do for deflation requests anymore.
|
||||
The pbp is only used for a limited amount of time.
|
||||
|
||||
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
|
||||
Cc: qemu-stable@nongnu.org #v4.0.0
|
||||
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Message-Id: <20190722134108.22151-7-david@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Acked-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
(cherry picked from commit a8cd64d488325f3be5c4ddec4bf07efb3b8c7330)
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 21 +++++++++------------
|
||||
include/hw/virtio/virtio-balloon.h | 3 ---
|
||||
2 files changed, 9 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index 49999d0bbe..bd54e302de 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -34,11 +34,11 @@
|
||||
|
||||
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
|
||||
|
||||
-struct PartiallyBalloonedPage {
|
||||
+typedef struct PartiallyBalloonedPage {
|
||||
ram_addr_t base_gpa;
|
||||
long subpages;
|
||||
unsigned long *bitmap;
|
||||
-};
|
||||
+} PartiallyBalloonedPage;
|
||||
|
||||
static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp)
|
||||
{
|
||||
@@ -68,11 +68,11 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
|
||||
}
|
||||
|
||||
static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
- MemoryRegion *mr, hwaddr mr_offset)
|
||||
+ MemoryRegion *mr, hwaddr mr_offset,
|
||||
+ PartiallyBalloonedPage **pbp)
|
||||
{
|
||||
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||
ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
|
||||
- PartiallyBalloonedPage **pbp = &balloon->pbp;
|
||||
RAMBlock *rb;
|
||||
size_t rb_page_size;
|
||||
int subpages;
|
||||
@@ -149,12 +149,6 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
|
||||
rb = qemu_ram_block_from_host(addr, false, &rb_offset);
|
||||
rb_page_size = qemu_ram_pagesize(rb);
|
||||
|
||||
- if (balloon->pbp) {
|
||||
- /* Let's play safe and always reset the pbp on deflation requests. */
|
||||
- virtio_balloon_pbp_free(balloon->pbp);
|
||||
- balloon->pbp = NULL;
|
||||
- }
|
||||
-
|
||||
host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1));
|
||||
|
||||
/* When a page is deflated, we hint the whole host page it lives
|
||||
@@ -336,6 +330,7 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v,
|
||||
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
||||
+ PartiallyBalloonedPage *pbp = NULL;
|
||||
VirtQueueElement *elem;
|
||||
MemoryRegionSection section;
|
||||
|
||||
@@ -344,7 +339,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
uint32_t pfn;
|
||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||
if (!elem) {
|
||||
- return;
|
||||
+ break;
|
||||
}
|
||||
|
||||
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
|
||||
@@ -373,7 +368,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
if (!qemu_balloon_is_inhibited()) {
|
||||
if (vq == s->ivq) {
|
||||
balloon_inflate_page(s, section.mr,
|
||||
- section.offset_within_region);
|
||||
+ section.offset_within_region, &pbp);
|
||||
} else if (vq == s->dvq) {
|
||||
balloon_deflate_page(s, section.mr, section.offset_within_region);
|
||||
} else {
|
||||
@@ -387,6 +382,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
virtio_notify(vdev, vq);
|
||||
g_free(elem);
|
||||
}
|
||||
+
|
||||
+ virtio_balloon_pbp_free(pbp);
|
||||
}
|
||||
|
||||
static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
|
||||
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
|
||||
index 5a99293a45..d1c968d237 100644
|
||||
--- a/include/hw/virtio/virtio-balloon.h
|
||||
+++ b/include/hw/virtio/virtio-balloon.h
|
||||
@@ -33,8 +33,6 @@ typedef struct virtio_balloon_stat_modern {
|
||||
uint64_t val;
|
||||
} VirtIOBalloonStatModern;
|
||||
|
||||
-typedef struct PartiallyBalloonedPage PartiallyBalloonedPage;
|
||||
-
|
||||
enum virtio_balloon_free_page_report_status {
|
||||
FREE_PAGE_REPORT_S_STOP = 0,
|
||||
FREE_PAGE_REPORT_S_REQUESTED = 1,
|
||||
@@ -70,7 +68,6 @@ typedef struct VirtIOBalloon {
|
||||
int64_t stats_last_update;
|
||||
int64_t stats_poll_interval;
|
||||
uint32_t host_features;
|
||||
- PartiallyBalloonedPage *pbp;
|
||||
|
||||
bool qemu_4_0_config_size;
|
||||
} VirtIOBalloon;
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
From 9a7ca8a7c920360db9dcaf616ca6f1440c025043 Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Thu, 25 Jul 2019 13:36:38 +0200
|
||||
Subject: [PATCH] virtio-balloon: don't track subpages for the PBP
|
||||
|
||||
As ramblocks cannot get removed/readded while we are processing a bulk
|
||||
of inflation requests, there is no more need to track the page size
|
||||
in form of the number of subpages.
|
||||
|
||||
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Message-Id: <20190725113638.4702-8-david@redhat.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-picked from commit 9a7ca8a7c920360db9dcaf616ca6f1440c025043)
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index a6282d58d4..fe9664e42c 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
typedef struct PartiallyBalloonedPage {
|
||||
ram_addr_t base_gpa;
|
||||
- long subpages;
|
||||
unsigned long *bitmap;
|
||||
} PartiallyBalloonedPage;
|
||||
|
||||
@@ -55,16 +54,15 @@ static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa,
|
||||
PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1);
|
||||
|
||||
pbp->base_gpa = base_gpa;
|
||||
- pbp->subpages = subpages;
|
||||
pbp->bitmap = bitmap_new(subpages);
|
||||
|
||||
return pbp;
|
||||
}
|
||||
|
||||
static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
|
||||
- ram_addr_t base_gpa, long subpages)
|
||||
+ ram_addr_t base_gpa)
|
||||
{
|
||||
- return pbp->subpages == subpages && pbp->base_gpa == base_gpa;
|
||||
+ return pbp->base_gpa == base_gpa;
|
||||
}
|
||||
|
||||
static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
@@ -106,7 +104,7 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
|
||||
(rb_offset - rb_aligned_offset);
|
||||
|
||||
- if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa, subpages)) {
|
||||
+ if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa)) {
|
||||
/* We've partially ballooned part of a host page, but now
|
||||
* we're trying to balloon part of a different one. Too hard,
|
||||
* give up on the old partial page */
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,148 +0,0 @@
|
||||
From a6fe4a3aa8007524ffe4758109c08f3ac102c628 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Wed, 10 Jul 2019 16:14:40 +0200
|
||||
Subject: [PATCH] virtio-balloon: fix QEMU 4.0 config size migration
|
||||
incompatibility
|
||||
|
||||
The virtio-balloon config size changed in QEMU 4.0 even for existing
|
||||
machine types. Migration from QEMU 3.1 to 4.0 can fail in some
|
||||
circumstances with the following error:
|
||||
|
||||
qemu-system-x86_64: get_pci_config_device: Bad config data: i=0x10 read: a1 device: 1 cmask: ff wmask: c0 w1cmask:0
|
||||
|
||||
This happens because the virtio-balloon config size affects the VIRTIO
|
||||
Legacy I/O Memory PCI BAR size.
|
||||
|
||||
Introduce a qdev property called "qemu-4-0-config-size" and enable it
|
||||
only for the QEMU 4.0 machine types. This way <4.0 machine types use
|
||||
the old size, 4.0 uses the larger size, and >4.0 machine types use the
|
||||
appropriate size depending on enabled virtio-balloon features.
|
||||
|
||||
Live migration to and from old QEMUs to QEMU 4.1 works again as long as
|
||||
a versioned machine type is specified (do not use just "pc"!).
|
||||
|
||||
Originally-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-Id: <20190710141440.27635-1-stefanha@redhat.com>
|
||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Tested-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Tested-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry picked from commit 2bbadb08ce272d65e1f78621002008b07d1e0f03)
|
||||
Conflicts:
|
||||
hw/core/machine.c
|
||||
* drop context dep. on 0a71966253c
|
||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/core/machine.c | 5 ++++-
|
||||
hw/virtio/virtio-balloon.c | 28 +++++++++++++++++++++++++---
|
||||
include/hw/virtio/virtio-balloon.h | 2 ++
|
||||
3 files changed, 31 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index eb34f53a85..55b08f1466 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
|
||||
-GlobalProperty hw_compat_4_0[] = {};
|
||||
+GlobalProperty hw_compat_4_0[] = {
|
||||
+ { "virtio-balloon-device", "qemu-4-0-config-size", "true" },
|
||||
+};
|
||||
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
|
||||
|
||||
GlobalProperty hw_compat_3_1[] = {
|
||||
@@ -39,6 +41,7 @@ GlobalProperty hw_compat_3_1[] = {
|
||||
{ "usb-tablet", "serial", "42" },
|
||||
{ "virtio-blk-device", "discard", "false" },
|
||||
{ "virtio-blk-device", "write-zeroes", "false" },
|
||||
+ { "virtio-balloon-device", "qemu-4-0-config-size", "false" },
|
||||
};
|
||||
const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index 2112874055..5579260fd4 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -615,6 +615,22 @@ virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static size_t virtio_balloon_config_size(VirtIOBalloon *s)
|
||||
+{
|
||||
+ uint64_t features = s->host_features;
|
||||
+
|
||||
+ if (s->qemu_4_0_config_size) {
|
||||
+ return sizeof(struct virtio_balloon_config);
|
||||
+ }
|
||||
+ if (virtio_has_feature(features, VIRTIO_BALLOON_F_PAGE_POISON)) {
|
||||
+ return sizeof(struct virtio_balloon_config);
|
||||
+ }
|
||||
+ if (virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
|
||||
+ return offsetof(struct virtio_balloon_config, poison_val);
|
||||
+ }
|
||||
+ return offsetof(struct virtio_balloon_config, free_page_report_cmd_id);
|
||||
+}
|
||||
+
|
||||
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
||||
{
|
||||
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
||||
@@ -635,7 +651,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
||||
}
|
||||
|
||||
trace_virtio_balloon_get_config(config.num_pages, config.actual);
|
||||
- memcpy(config_data, &config, sizeof(struct virtio_balloon_config));
|
||||
+ memcpy(config_data, &config, virtio_balloon_config_size(dev));
|
||||
}
|
||||
|
||||
static int build_dimm_list(Object *obj, void *opaque)
|
||||
@@ -679,7 +695,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
|
||||
uint32_t oldactual = dev->actual;
|
||||
ram_addr_t vm_ram_size = get_current_ram_size();
|
||||
|
||||
- memcpy(&config, config_data, sizeof(struct virtio_balloon_config));
|
||||
+ memcpy(&config, config_data, virtio_balloon_config_size(dev));
|
||||
dev->actual = le32_to_cpu(config.actual);
|
||||
if (dev->actual != oldactual) {
|
||||
qapi_event_send_balloon_change(vm_ram_size -
|
||||
@@ -766,7 +782,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
|
||||
int ret;
|
||||
|
||||
virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON,
|
||||
- sizeof(struct virtio_balloon_config));
|
||||
+ virtio_balloon_config_size(s));
|
||||
|
||||
ret = qemu_add_balloon_handler(virtio_balloon_to_target,
|
||||
virtio_balloon_stat, s);
|
||||
@@ -897,6 +913,12 @@ static Property virtio_balloon_properties[] = {
|
||||
VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false),
|
||||
DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features,
|
||||
VIRTIO_BALLOON_F_FREE_PAGE_HINT, false),
|
||||
+ /* QEMU 4.0 accidentally changed the config size even when free-page-hint
|
||||
+ * is disabled, resulting in QEMU 3.1 migration incompatibility. This
|
||||
+ * property retains this quirk for QEMU 4.1 machine types.
|
||||
+ */
|
||||
+ DEFINE_PROP_BOOL("qemu-4-0-config-size", VirtIOBalloon,
|
||||
+ qemu_4_0_config_size, false),
|
||||
DEFINE_PROP_LINK("iothread", VirtIOBalloon, iothread, TYPE_IOTHREAD,
|
||||
IOThread *),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
|
||||
index 1afafb12f6..5a99293a45 100644
|
||||
--- a/include/hw/virtio/virtio-balloon.h
|
||||
+++ b/include/hw/virtio/virtio-balloon.h
|
||||
@@ -71,6 +71,8 @@ typedef struct VirtIOBalloon {
|
||||
int64_t stats_poll_interval;
|
||||
uint32_t host_features;
|
||||
PartiallyBalloonedPage *pbp;
|
||||
+
|
||||
+ bool qemu_4_0_config_size;
|
||||
} VirtIOBalloon;
|
||||
|
||||
#endif
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,130 +0,0 @@
|
||||
From 1b47b37c33ec01ae1efc527f4c97f97f93723bc4 Mon Sep 17 00:00:00 2001
|
||||
From: "Michael S. Tsirkin" <mst@redhat.com>
|
||||
Date: Thu, 25 Jul 2019 07:54:25 -0400
|
||||
Subject: [PATCH] virtio-balloon: free pbp more aggressively
|
||||
|
||||
Previous patches switched to a temporary pbp but that does not go far
|
||||
enough: after device uses a buffer, guest is free to reuse it, so
|
||||
tracking the page and freeing it later is wrong.
|
||||
|
||||
Free and reset the pbp after we push each element.
|
||||
|
||||
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
|
||||
Cc: qemu-stable@nongnu.org #v4.0.0
|
||||
Cc: David Hildenbrand <david@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
(cherry-picked from commit 1b47b37c33ec01ae1efc527f4c97f97f93723bc4)
|
||||
---
|
||||
hw/virtio/virtio-balloon.c | 37 ++++++++++++++++---------------------
|
||||
1 file changed, 16 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
|
||||
index fe9664e42c..25de154307 100644
|
||||
--- a/hw/virtio/virtio-balloon.c
|
||||
+++ b/hw/virtio/virtio-balloon.c
|
||||
@@ -41,22 +41,19 @@ typedef struct PartiallyBalloonedPage {
|
||||
|
||||
static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp)
|
||||
{
|
||||
- if (!pbp) {
|
||||
+ if (!pbp->bitmap) {
|
||||
return;
|
||||
}
|
||||
g_free(pbp->bitmap);
|
||||
- g_free(pbp);
|
||||
+ pbp->bitmap = NULL;
|
||||
}
|
||||
|
||||
-static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa,
|
||||
- long subpages)
|
||||
+static void virtio_balloon_pbp_alloc(PartiallyBalloonedPage *pbp,
|
||||
+ ram_addr_t base_gpa,
|
||||
+ long subpages)
|
||||
{
|
||||
- PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1);
|
||||
-
|
||||
pbp->base_gpa = base_gpa;
|
||||
pbp->bitmap = bitmap_new(subpages);
|
||||
-
|
||||
- return pbp;
|
||||
}
|
||||
|
||||
static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
|
||||
@@ -67,7 +64,7 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
|
||||
|
||||
static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
MemoryRegion *mr, hwaddr mr_offset,
|
||||
- PartiallyBalloonedPage **pbp)
|
||||
+ PartiallyBalloonedPage *pbp)
|
||||
{
|
||||
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
|
||||
ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
|
||||
@@ -104,22 +101,21 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
|
||||
(rb_offset - rb_aligned_offset);
|
||||
|
||||
- if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa)) {
|
||||
+ if (pbp->bitmap && !virtio_balloon_pbp_matches(pbp, base_gpa)) {
|
||||
/* We've partially ballooned part of a host page, but now
|
||||
* we're trying to balloon part of a different one. Too hard,
|
||||
* give up on the old partial page */
|
||||
- virtio_balloon_pbp_free(*pbp);
|
||||
- *pbp = NULL;
|
||||
+ virtio_balloon_pbp_free(pbp);
|
||||
}
|
||||
|
||||
- if (!*pbp) {
|
||||
- *pbp = virtio_balloon_pbp_alloc(base_gpa, subpages);
|
||||
+ if (!pbp->bitmap) {
|
||||
+ virtio_balloon_pbp_alloc(pbp, base_gpa, subpages);
|
||||
}
|
||||
|
||||
set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE,
|
||||
- (*pbp)->bitmap);
|
||||
+ pbp->bitmap);
|
||||
|
||||
- if (bitmap_full((*pbp)->bitmap, subpages)) {
|
||||
+ if (bitmap_full(pbp->bitmap, subpages)) {
|
||||
/* We've accumulated a full host page, we can actually discard
|
||||
* it now */
|
||||
|
||||
@@ -127,8 +123,7 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
|
||||
/* We ignore errors from ram_block_discard_range(), because it
|
||||
* has already reported them, and failing to discard a balloon
|
||||
* page is not fatal */
|
||||
- virtio_balloon_pbp_free(*pbp);
|
||||
- *pbp = NULL;
|
||||
+ virtio_balloon_pbp_free(pbp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,13 +323,14 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v,
|
||||
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
||||
- PartiallyBalloonedPage *pbp = NULL;
|
||||
VirtQueueElement *elem;
|
||||
MemoryRegionSection section;
|
||||
|
||||
for (;;) {
|
||||
+ PartiallyBalloonedPage pbp = {};
|
||||
size_t offset = 0;
|
||||
uint32_t pfn;
|
||||
+
|
||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||
if (!elem) {
|
||||
break;
|
||||
@@ -379,9 +375,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
virtqueue_push(vq, elem, offset);
|
||||
virtio_notify(vdev, vq);
|
||||
g_free(elem);
|
||||
+ virtio_balloon_pbp_free(&pbp);
|
||||
}
|
||||
-
|
||||
- virtio_balloon_pbp_free(pbp);
|
||||
}
|
||||
|
||||
static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
From b728ea5f2597f97088db8517576caa2877118cb0 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
||||
Date: Mon, 5 Aug 2019 16:04:40 +0800
|
||||
Subject: [PATCH] virtio-pci: fix missing device properties
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Since commit a4ee4c8baa37154 ("virtio: Helper for registering virtio
|
||||
device types"), virtio-gpu-pci, virtio-vga, and virtio-crypto-pci lost
|
||||
some properties: "ioeventfd" and "vectors". This may cause various
|
||||
issues, such as failing migration or invalid properties.
|
||||
|
||||
Since those VirtioPCI devices do not have a base name, their class are
|
||||
initialized with virtio_pci_generic_base_class_init(). However, if the
|
||||
VirtioPCIDeviceTypeInfo provided a class_init which sets dc->props,
|
||||
the properties were overwritten by virtio_pci_generic_class_init().
|
||||
|
||||
Instead, introduce an intermediary base-type to register the generic
|
||||
properties.
|
||||
|
||||
Fixes: a4ee4c8baa37154f42b4dc6a13fee79268d15238
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Message-Id: <20190625232333.30752-1-marcandre.lureau@redhat.com>
|
||||
(cherry-pick from commit 683c1d89efd1eeb111c129a9a91f629b94d90d45)
|
||||
---
|
||||
hw/virtio/virtio-pci.c | 28 ++++++++++++++--------------
|
||||
1 file changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
|
||||
index cb44e19b..497092e8 100644
|
||||
--- a/hw/virtio/virtio-pci.c
|
||||
+++ b/hw/virtio/virtio-pci.c
|
||||
@@ -1905,13 +1905,6 @@ static void virtio_pci_generic_class_init(ObjectClass *klass, void *data)
|
||||
dc->props = virtio_pci_generic_properties;
|
||||
}
|
||||
|
||||
-/* Used when the generic type and the base type is the same */
|
||||
-static void virtio_pci_generic_base_class_init(ObjectClass *klass, void *data)
|
||||
-{
|
||||
- virtio_pci_base_class_init(klass, data);
|
||||
- virtio_pci_generic_class_init(klass, NULL);
|
||||
-}
|
||||
-
|
||||
static void virtio_pci_transitional_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOPCIProxy *proxy = VIRTIO_PCI(obj);
|
||||
@@ -1930,14 +1923,13 @@ static void virtio_pci_non_transitional_instance_init(Object *obj)
|
||||
|
||||
void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
|
||||
{
|
||||
+ char *base_name = NULL;
|
||||
TypeInfo base_type_info = {
|
||||
.name = t->base_name,
|
||||
.parent = t->parent ? t->parent : TYPE_VIRTIO_PCI,
|
||||
.instance_size = t->instance_size,
|
||||
.instance_init = t->instance_init,
|
||||
.class_size = t->class_size,
|
||||
- .class_init = virtio_pci_base_class_init,
|
||||
- .class_data = (void *)t,
|
||||
.abstract = true,
|
||||
};
|
||||
TypeInfo generic_type_info = {
|
||||
@@ -1953,13 +1945,20 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
|
||||
|
||||
if (!base_type_info.name) {
|
||||
/* No base type -> register a single generic device type */
|
||||
- base_type_info.name = t->generic_name;
|
||||
- base_type_info.class_init = virtio_pci_generic_base_class_init;
|
||||
- base_type_info.interfaces = generic_type_info.interfaces;
|
||||
- base_type_info.abstract = false;
|
||||
- generic_type_info.name = NULL;
|
||||
+ /* use intermediate %s-base-type to add generic device props */
|
||||
+ base_name = g_strdup_printf("%s-base-type", t->generic_name);
|
||||
+ base_type_info.name = base_name;
|
||||
+ base_type_info.class_init = virtio_pci_generic_class_init;
|
||||
+
|
||||
+ generic_type_info.parent = base_name;
|
||||
+ generic_type_info.class_init = virtio_pci_base_class_init;
|
||||
+ generic_type_info.class_data = (void *)t;
|
||||
+
|
||||
assert(!t->non_transitional_name);
|
||||
assert(!t->transitional_name);
|
||||
+ } else {
|
||||
+ base_type_info.class_init = virtio_pci_base_class_init;
|
||||
+ base_type_info.class_data = (void *)t;
|
||||
}
|
||||
|
||||
type_register(&base_type_info);
|
||||
@@ -1997,6 +1996,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
|
||||
};
|
||||
type_register(&transitional_type_info);
|
||||
}
|
||||
+ g_free(base_name);
|
||||
}
|
||||
|
||||
/* virtio-pci-bus */
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
From 9ea18ed25a36527167e9676f25d983df5e7f76e6 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Armbruster <armbru@redhat.com>
|
||||
Date: Tue, 4 Jun 2019 17:12:50 +0200
|
||||
Subject: [PATCH] vl: Fix -drive / -blockdev persistent reservation management
|
||||
|
||||
qemu-system-FOO's main() acts on command line arguments in its own
|
||||
idiosyncratic order. There's not much method to its madness.
|
||||
Whenever we find a case where one kind of command line argument needs
|
||||
to refer to something created for another kind later, we rejigger the
|
||||
order.
|
||||
|
||||
Recent commit cda4aa9a5a "vl: Create block backends before setting
|
||||
machine properties" was such a rejigger. Block backends are now
|
||||
created before "delayed" objects. This broke persistent reservation
|
||||
management. Reproducer:
|
||||
|
||||
$ qemu-system-x86_64 -object pr-manager-helper,id=pr-helper0,path=/tmp/pr-helper0.sock-drive -drive file=/dev/mapper/crypt,file.pr-manager=pr-helper0,format=raw,if=none,id=drive-scsi0-0-0-2
|
||||
qemu-system-x86_64: -drive file=/dev/mapper/crypt,file.pr-manager=pr-helper0,format=raw,if=none,id=drive-scsi0-0-0-2: No persistent reservation manager with id 'pr-helper0'
|
||||
|
||||
The delayed pr-manager-helper object is created too late for use by
|
||||
-drive or -blockdev. Normal objects are still created in time.
|
||||
|
||||
pr-manager-helper has always been a delayed object (commit 7c9e527659
|
||||
"scsi, file-posix: add support for persistent reservation
|
||||
management"). Turns out there's no real reason for that. Make it a
|
||||
normal object.
|
||||
|
||||
Fixes: cda4aa9a5a08777cf13e164c0543bd4888b8adce
|
||||
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
||||
Message-Id: <20190604151251.9903-2-armbru@redhat.com>
|
||||
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry-picked from commit 9ea18ed25a36527167e9676f25d983df5e7f76e6)
|
||||
---
|
||||
vl.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/vl.c b/vl.c
|
||||
index f023a8ca73..cc6246d2af 100644
|
||||
--- a/vl.c
|
||||
+++ b/vl.c
|
||||
@@ -2751,8 +2751,7 @@ static bool object_create_initial(const char *type, QemuOpts *opts)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
- if (g_str_equal(type, "rng-egd") ||
|
||||
- g_str_has_prefix(type, "pr-manager-")) {
|
||||
+ if (g_str_equal(type, "rng-egd")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user