aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkihiko Odaki <akihiko.odaki@daynix.com>2025-04-21 21:17:20 +0900
committerMichael S. Tsirkin <mst@redhat.com>2025-05-14 05:39:15 -0400
commit0caed25cd171c611781589b5402161d27d57229c (patch)
treefd84fcdb0ba5749a7ad1366d387f8df54caf8c38
parent1a5a2629eab94297a37e4adcc5fb69beb7bb0b0c (diff)
downloadqemu-0caed25cd171c611781589b5402161d27d57229c.zip
qemu-0caed25cd171c611781589b5402161d27d57229c.tar.gz
qemu-0caed25cd171c611781589b5402161d27d57229c.tar.bz2
virtio: Call set_features during reset
virtio-net expects set_features() will be called when the feature set used by the guest changes to update the number of virtqueues but it is not called during reset, which will clear all features, leaving the queues added for VIRTIO_NET_F_MQ or VIRTIO_NET_F_RSS. Not only these extra queues are visible to the guest, they will cause segmentation fault during migration. Call set_features() during reset to remove those queues for virtio-net as we call set_status(). It will also prevent similar bugs for virtio-net and other devices in the future. Fixes: f9d6dbf0bf6e ("virtio-net: remove virtio queues if the guest doesn't support multiqueue") Buglink: https://issues.redhat.com/browse/RHEL-73842 Cc: qemu-stable@nongnu.org Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Message-Id: <20250421-reset-v2-1-e4c1ead88ea1@daynix.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/virtio/virtio.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 1b55d8d..3300f4a 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2320,6 +2320,8 @@ void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
}
}
+static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val);
+
void virtio_reset(void *opaque)
{
VirtIODevice *vdev = opaque;
@@ -2350,7 +2352,7 @@ void virtio_reset(void *opaque)
vdev->start_on_kick = false;
vdev->started = false;
vdev->broken = false;
- vdev->guest_features = 0;
+ virtio_set_features_nocheck(vdev, 0);
vdev->queue_sel = 0;
vdev->status = 0;
vdev->disabled = false;