- kvm-rbd-Run-co-BH-CB-in-the-coroutine-s-AioContext.patch [RHEL-79118] - kvm-curl-Fix-coroutine-waking.patch [RHEL-79118] - kvm-block-io-Take-reqs_lock-for-tracked_requests.patch [RHEL-79118] - kvm-qcow2-Re-initialize-lock-in-invalidate_cache.patch [RHEL-79118] - kvm-qcow2-Fix-cache_clean_timer.patch [RHEL-79118] - kvm-net-bundle-all-offloads-in-a-single-struct.patch [RHEL-143785] - kvm-linux-headers-deal-with-counted_by-annotation.patch [RHEL-143785] - kvm-linux-headers-Update-to-Linux-v6.17-rc1.patch [RHEL-143785] - kvm-virtio-introduce-extended-features-type.patch [RHEL-143785] - kvm-virtio-serialize-extended-features-state.patch [RHEL-143785] - kvm-virtio-add-support-for-negotiating-extended-features.patch [RHEL-143785] - kvm-virtio-pci-implement-support-for-extended-features.patch [RHEL-143785] - kvm-vhost-add-support-for-negotiating-extended-features.patch [RHEL-143785] - kvm-qmp-update-virtio-features-map-to-support-extended-f.patch [RHEL-143785] - kvm-vhost-backend-implement-extended-features-support.patch [RHEL-143785] - kvm-vhost-net-implement-extended-features-support.patch [RHEL-143785] - kvm-virtio-net-implement-extended-features-support.patch [RHEL-143785] - kvm-net-implement-tunnel-probing.patch [RHEL-143785] - kvm-net-implement-UDP-tunnel-features-offloading.patch [RHEL-143785] - Resolves: RHEL-79118 ([network-storage][rbd][core-dump]installation of guest failed sometimes with multiqueue enabled [rhel10]) - Resolves: RHEL-143785 (backport support for GSO over UDP tunnel offload)
223 lines
8.1 KiB
Diff
223 lines
8.1 KiB
Diff
From 0f4e78c05a49b1ab51bd057df02b5c42f7914ebf Mon Sep 17 00:00:00 2001
|
|
From: Paolo Abeni <pabeni@redhat.com>
|
|
Date: Mon, 22 Sep 2025 16:18:19 +0200
|
|
Subject: [PATCH 10/19] virtio: serialize extended features state
|
|
|
|
RH-Author: Laurent Vivier <lvivier@redhat.com>
|
|
RH-MergeRequest: 456: backport support for GSO over UDP tunnel offload
|
|
RH-Jira: RHEL-143785
|
|
RH-Acked-by: Cindy Lu <lulu@redhat.com>
|
|
RH-Acked-by: MST <mst@redhat.com>
|
|
RH-Commit: [5/14] 3448a1d2d4b7b6952819257c1bc2f5e5dcee8935 (lvivier/qemu-kvm-centos)
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-143785
|
|
|
|
If the driver uses any of the extended features (i.e. 64 or above),
|
|
store the extended features range (64-127 bits).
|
|
|
|
At load time, let legacy features initialize the full features range
|
|
and pass it to the set helper; sub-states loading will have filled-up
|
|
the extended part as needed.
|
|
|
|
This is one of the few spots that need explicitly to know and set
|
|
in stone the extended features array size; add a build bug to prevent
|
|
breaking the migration should such size change again in the future:
|
|
more serialization plumbing will be needed.
|
|
|
|
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
|
|
Acked-by: Jason Wang <jasowang@redhat.com>
|
|
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
Tested-by: Lei Yang <leiyang@redhat.com>
|
|
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Message-ID: <d5d9d398675bee6c4c7d7308c5d3d5d3c6d17d87.1758549625.git.pabeni@redhat.com>
|
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
(cherry picked from commit 0a49a97433279512a03f3d9f36164a46caf498c6)
|
|
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
|
|
---
|
|
hw/virtio/virtio.c | 88 ++++++++++++++++++++++++++++++----------------
|
|
1 file changed, 57 insertions(+), 31 deletions(-)
|
|
|
|
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
|
|
index 9a81ad912e..bf53c211e5 100644
|
|
--- a/hw/virtio/virtio.c
|
|
+++ b/hw/virtio/virtio.c
|
|
@@ -2964,6 +2964,30 @@ static const VMStateDescription vmstate_virtio_disabled = {
|
|
}
|
|
};
|
|
|
|
+static bool virtio_128bit_features_needed(void *opaque)
|
|
+{
|
|
+ VirtIODevice *vdev = opaque;
|
|
+
|
|
+ return virtio_features_use_ex(vdev->host_features_ex);
|
|
+}
|
|
+
|
|
+static const VMStateDescription vmstate_virtio_128bit_features = {
|
|
+ .name = "virtio/128bit_features",
|
|
+ .version_id = 1,
|
|
+ .minimum_version_id = 1,
|
|
+ .needed = &virtio_128bit_features_needed,
|
|
+ .fields = (const VMStateField[]) {
|
|
+ VMSTATE_UINT64(guest_features_ex[1], VirtIODevice),
|
|
+ VMSTATE_END_OF_LIST()
|
|
+ }
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Avoid silently breaking migration should the feature space increase
|
|
+ * even more in the (far away) future
|
|
+ */
|
|
+QEMU_BUILD_BUG_ON(VIRTIO_FEATURES_NU64S != 2);
|
|
+
|
|
static const VMStateDescription vmstate_virtio = {
|
|
.name = "virtio",
|
|
.version_id = 1,
|
|
@@ -2973,6 +2997,7 @@ static const VMStateDescription vmstate_virtio = {
|
|
},
|
|
.subsections = (const VMStateDescription * const []) {
|
|
&vmstate_virtio_device_endian,
|
|
+ &vmstate_virtio_128bit_features,
|
|
&vmstate_virtio_64bit_features,
|
|
&vmstate_virtio_virtqueues,
|
|
&vmstate_virtio_ringsize,
|
|
@@ -3069,23 +3094,28 @@ const VMStateInfo virtio_vmstate_info = {
|
|
.put = virtio_device_put,
|
|
};
|
|
|
|
-static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val)
|
|
+static int virtio_set_features_nocheck(VirtIODevice *vdev, const uint64_t *val)
|
|
{
|
|
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
|
|
- bool bad = (val & ~(vdev->host_features)) != 0;
|
|
+ uint64_t tmp[VIRTIO_FEATURES_NU64S];
|
|
+ bool bad;
|
|
+
|
|
+ bad = virtio_features_andnot(tmp, val, vdev->host_features_ex);
|
|
+ virtio_features_and(tmp, val, vdev->host_features_ex);
|
|
|
|
- val &= vdev->host_features;
|
|
if (k->set_features) {
|
|
- k->set_features(vdev, val);
|
|
+ bad = bad || virtio_features_use_ex(tmp);
|
|
+ k->set_features(vdev, tmp[0]);
|
|
}
|
|
- vdev->guest_features = val;
|
|
+
|
|
+ virtio_features_copy(vdev->guest_features_ex, tmp);
|
|
return bad ? -1 : 0;
|
|
}
|
|
|
|
typedef struct VirtioSetFeaturesNocheckData {
|
|
Coroutine *co;
|
|
VirtIODevice *vdev;
|
|
- uint64_t val;
|
|
+ uint64_t val[VIRTIO_FEATURES_NU64S];
|
|
int ret;
|
|
} VirtioSetFeaturesNocheckData;
|
|
|
|
@@ -3098,14 +3128,15 @@ static void virtio_set_features_nocheck_bh(void *opaque)
|
|
}
|
|
|
|
static int coroutine_mixed_fn
|
|
-virtio_set_features_nocheck_maybe_co(VirtIODevice *vdev, uint64_t val)
|
|
+virtio_set_features_nocheck_maybe_co(VirtIODevice *vdev,
|
|
+ const uint64_t *val)
|
|
{
|
|
if (qemu_in_coroutine()) {
|
|
VirtioSetFeaturesNocheckData data = {
|
|
.co = qemu_coroutine_self(),
|
|
.vdev = vdev,
|
|
- .val = val,
|
|
};
|
|
+ virtio_features_copy(data.val, val);
|
|
aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
|
|
virtio_set_features_nocheck_bh, &data);
|
|
qemu_coroutine_yield();
|
|
@@ -3117,6 +3148,7 @@ virtio_set_features_nocheck_maybe_co(VirtIODevice *vdev, uint64_t val)
|
|
|
|
int virtio_set_features(VirtIODevice *vdev, uint64_t val)
|
|
{
|
|
+ uint64_t features[VIRTIO_FEATURES_NU64S];
|
|
int ret;
|
|
/*
|
|
* The driver must not attempt to set features after feature negotiation
|
|
@@ -3132,7 +3164,8 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val)
|
|
__func__, vdev->name);
|
|
}
|
|
|
|
- ret = virtio_set_features_nocheck(vdev, val);
|
|
+ virtio_features_from_u64(features, val);
|
|
+ ret = virtio_set_features_nocheck(vdev, features);
|
|
if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
|
/* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */
|
|
int i;
|
|
@@ -3155,6 +3188,7 @@ void virtio_reset(void *opaque)
|
|
{
|
|
VirtIODevice *vdev = opaque;
|
|
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
|
|
+ uint64_t features[VIRTIO_FEATURES_NU64S];
|
|
int i;
|
|
|
|
virtio_set_status(vdev, 0);
|
|
@@ -3181,7 +3215,8 @@ void virtio_reset(void *opaque)
|
|
vdev->start_on_kick = false;
|
|
vdev->started = false;
|
|
vdev->broken = false;
|
|
- virtio_set_features_nocheck(vdev, 0);
|
|
+ virtio_features_clear(features);
|
|
+ virtio_set_features_nocheck(vdev, features);
|
|
vdev->queue_sel = 0;
|
|
vdev->status = 0;
|
|
vdev->disabled = false;
|
|
@@ -3264,7 +3299,7 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
|
* Note: devices should always test host features in future - don't create
|
|
* new dependencies like this.
|
|
*/
|
|
- vdev->guest_features = features;
|
|
+ virtio_features_from_u64(vdev->guest_features_ex, features);
|
|
|
|
config_len = qemu_get_be32(f);
|
|
|
|
@@ -3343,26 +3378,17 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
|
vdev->device_endian = virtio_default_endian();
|
|
}
|
|
|
|
- if (virtio_64bit_features_needed(vdev)) {
|
|
- /*
|
|
- * Subsection load filled vdev->guest_features. Run them
|
|
- * through virtio_set_features to sanity-check them against
|
|
- * host_features.
|
|
- */
|
|
- uint64_t features64 = vdev->guest_features;
|
|
- if (virtio_set_features_nocheck_maybe_co(vdev, features64) < 0) {
|
|
- error_report("Features 0x%" PRIx64 " unsupported. "
|
|
- "Allowed features: 0x%" PRIx64,
|
|
- features64, vdev->host_features);
|
|
- return -1;
|
|
- }
|
|
- } else {
|
|
- if (virtio_set_features_nocheck_maybe_co(vdev, features) < 0) {
|
|
- error_report("Features 0x%x unsupported. "
|
|
- "Allowed features: 0x%" PRIx64,
|
|
- features, vdev->host_features);
|
|
- return -1;
|
|
- }
|
|
+ /*
|
|
+ * guest_features_ex is fully initialized with u32 features and upper
|
|
+ * bits have been filled as needed by the later load.
|
|
+ */
|
|
+ if (virtio_set_features_nocheck_maybe_co(vdev,
|
|
+ vdev->guest_features_ex) < 0) {
|
|
+ error_report("Features 0x" VIRTIO_FEATURES_FMT " unsupported. "
|
|
+ "Allowed features: 0x" VIRTIO_FEATURES_FMT,
|
|
+ VIRTIO_FEATURES_PR(vdev->guest_features_ex),
|
|
+ VIRTIO_FEATURES_PR(vdev->host_features_ex));
|
|
+ return -1;
|
|
}
|
|
|
|
if (!virtio_device_started(vdev, vdev->status) &&
|
|
--
|
|
2.47.3
|
|
|