From: Paolo Abeni <pabeni@redhat.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Dmitry Fleytman <dmitry.fleytman@gmail.com>,
Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>,
Jason Wang <jasowang@redhat.com>,
Sriram Yagnaraman <sriram.yagnaraman@ericsson.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
Stefano Garzarella <sgarzare@redhat.com>,
Cornelia Huck <cohuck@redhat.com>,
Luigi Rizzo <lrizzo@google.com>,
Giuseppe Lettieri <g.lettieri@iet.unipi.it>,
Vincenzo Maffione <v.maffione@gmail.com>,
Eric Blake <eblake@redhat.com>,
Markus Armbruster <armbru@redhat.com>,
kvm@vger.kernel.org
Subject: [PATCH RFC v2 06/13] virtio-pci: implement support for extended features
Date: Fri, 11 Jul 2025 15:02:11 +0200 [thread overview]
Message-ID: <eb1aa9c8442d9b482b5c84fdca54b92c8a824495.1752229731.git.pabeni@redhat.com> (raw)
In-Reply-To: <cover.1752229731.git.pabeni@redhat.com>
Extend the features configuration space to 128 bits, and allow the
common read/write operation to access all of it.
On migration, save the 128 bit version of the features only if the
upper bits are non zero; after load zero the upper bits if the extended
features were not loaded.
Note that we must clear the proxy-ed features on device reset, otherwise
a guest kernel not supporting extended features booted after an extended
features enabled one could end-up wrongly inheriting extended features.
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
v1 -> v2:
- use separate VMStateDescription and pre/post load to avoid breaking
migration
- clear proxy features on device reset
---
hw/virtio/virtio-pci.c | 101 +++++++++++++++++++++++++++++----
include/hw/virtio/virtio-pci.h | 6 +-
2 files changed, 96 insertions(+), 11 deletions(-)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index fba2372c93..dc5e7eaf81 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -108,6 +108,39 @@ static const VMStateDescription vmstate_virtio_pci_modern_queue_state = {
}
};
+static bool virtio_pci_modern_state_features128_needed(void *opaque)
+{
+ VirtIOPCIProxy *proxy = opaque;
+ uint32_t features = 0;
+ int i;
+
+ for (i = 2; i < ARRAY_SIZE(proxy->guest_features128); ++i) {
+ features |= proxy->guest_features128[i];
+ }
+ return !!features;
+}
+
+static int virtio_pci_modern_state_features128_post_load(void *opaque,
+ int version_id)
+{
+ VirtIOPCIProxy *proxy = opaque;
+
+ proxy->extended_features_loaded = true;
+ return 0;
+}
+
+static const VMStateDescription vmstate_virtio_pci_modern_state_features128 = {
+ .name = "virtio_pci/modern_state/features128",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = &virtio_pci_modern_state_features128_post_load,
+ .needed = &virtio_pci_modern_state_features128_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(guest_features128, VirtIOPCIProxy, 4),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool virtio_pci_modern_state_needed(void *opaque)
{
VirtIOPCIProxy *proxy = opaque;
@@ -115,10 +148,40 @@ static bool virtio_pci_modern_state_needed(void *opaque)
return virtio_pci_modern(proxy);
}
+static int virtio_pci_modern_state_pre_load(void *opaque)
+{
+ VirtIOPCIProxy *proxy = opaque;
+
+ proxy->extended_features_loaded = false;
+ return 0;
+}
+
+static int virtio_pci_modern_state_post_load(void *opaque, int version_id)
+{
+ VirtIOPCIProxy *proxy = opaque;
+ int i;
+
+ if (proxy->extended_features_loaded) {
+ return 0;
+ }
+
+ QEMU_BUILD_BUG_ON(offsetof(VirtIOPCIProxy, guest_features[0]) !=
+ offsetof(VirtIOPCIProxy, guest_features128[0]));
+ QEMU_BUILD_BUG_ON(offsetof(VirtIOPCIProxy, guest_features[1]) !=
+ offsetof(VirtIOPCIProxy, guest_features128[1]));
+
+ for (i = 2; i < ARRAY_SIZE(proxy->guest_features128); ++i) {
+ proxy->guest_features128[i] = 0;
+ }
+ return 0;
+}
+
static const VMStateDescription vmstate_virtio_pci_modern_state_sub = {
.name = "virtio_pci/modern_state",
.version_id = 1,
.minimum_version_id = 1,
+ .pre_load = &virtio_pci_modern_state_pre_load,
+ .post_load = &virtio_pci_modern_state_post_load,
.needed = &virtio_pci_modern_state_needed,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(dfselect, VirtIOPCIProxy),
@@ -128,6 +191,10 @@ static const VMStateDescription vmstate_virtio_pci_modern_state_sub = {
vmstate_virtio_pci_modern_queue_state,
VirtIOPCIQueue),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription * const []) {
+ &vmstate_virtio_pci_modern_state_features128,
+ NULL
}
};
@@ -1493,19 +1560,22 @@ static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr,
val = proxy->dfselect;
break;
case VIRTIO_PCI_COMMON_DF:
- if (proxy->dfselect <= 1) {
+ if (proxy->dfselect < VIRTIO_FEATURES_WORDS) {
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
- val = (vdev->host_features & ~vdc->legacy_features) >>
- (32 * proxy->dfselect);
+ val = vdev->host_features_array[proxy->dfselect >> 1] >>
+ (32 * (proxy->dfselect & 1));
+ if (proxy->dfselect <= 1) {
+ val &= (~vdc->legacy_features) >> (32 * proxy->dfselect);
+ }
}
break;
case VIRTIO_PCI_COMMON_GFSELECT:
val = proxy->gfselect;
break;
case VIRTIO_PCI_COMMON_GF:
- if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features)) {
- val = proxy->guest_features[proxy->gfselect];
+ if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features128)) {
+ val = proxy->guest_features128[proxy->gfselect];
}
break;
case VIRTIO_PCI_COMMON_MSIX:
@@ -1587,11 +1657,18 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
proxy->gfselect = val;
break;
case VIRTIO_PCI_COMMON_GF:
- if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features)) {
- proxy->guest_features[proxy->gfselect] = val;
- virtio_set_features(vdev,
- (((uint64_t)proxy->guest_features[1]) << 32) |
- proxy->guest_features[0]);
+ if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features128)) {
+ uint64_t features[VIRTIO_FEATURES_DWORDS];
+ int i;
+
+ proxy->guest_features128[proxy->gfselect] = val;
+ virtio_features_clear(features);
+ for (i = 0; i < ARRAY_SIZE(proxy->guest_features128); ++i) {
+ uint64_t cur = proxy->guest_features128[i];
+
+ features[i >> 1] |= cur << ((i & 1) * 32);
+ }
+ virtio_set_features_ex(vdev, features);
}
break;
case VIRTIO_PCI_COMMON_MSIX:
@@ -2310,6 +2387,10 @@ static void virtio_pci_reset(DeviceState *qdev)
virtio_bus_reset(bus);
msix_unuse_all_vectors(&proxy->pci_dev);
+ /* be sure to not carry over any feature across reset */
+ memset(proxy->guest_features128, 0, sizeof(uint32_t) *
+ ARRAY_SIZE(proxy->guest_features128));
+
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
proxy->vqs[i].enabled = 0;
proxy->vqs[i].reset = 0;
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index eab5394898..1868e3b106 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -151,6 +151,7 @@ struct VirtIOPCIProxy {
uint32_t flags;
bool disable_modern;
bool ignore_backend_features;
+ bool extended_features_loaded;
OnOffAuto disable_legacy;
/* Transitional device id */
uint16_t trans_devid;
@@ -158,7 +159,10 @@ struct VirtIOPCIProxy {
uint32_t nvectors;
uint32_t dfselect;
uint32_t gfselect;
- uint32_t guest_features[2];
+ union {
+ uint32_t guest_features[2];
+ uint32_t guest_features128[4];
+ };
VirtIOPCIQueue vqs[VIRTIO_QUEUE_MAX];
VirtIOIRQFD *vector_irqfd;
--
2.50.0
next prev parent reply other threads:[~2025-07-11 13:03 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-11 13:02 [PATCH RFC v2 00/13] virtio: introduce support for GSO over UDP tunnel Paolo Abeni
2025-07-11 13:02 ` [PATCH RFC v2 01/13] net: bundle all offloads in a single struct Paolo Abeni
2025-07-15 6:36 ` Akihiko Odaki
2025-07-15 14:52 ` Paolo Abeni
2025-07-16 11:32 ` Akihiko Odaki
2025-07-11 13:02 ` [PATCH RFC v2 02/13] linux-headers: Update to Linux ~v6.16-rc5 net-next Paolo Abeni
2025-07-11 13:02 ` [PATCH RFC v2 03/13] virtio: introduce extended features type Paolo Abeni
2025-07-15 6:57 ` Akihiko Odaki
2025-07-11 13:02 ` [PATCH RFC v2 04/13] virtio: serialize extended features state Paolo Abeni
2025-07-15 7:24 ` Akihiko Odaki
2025-07-15 15:40 ` Paolo Abeni
2025-07-16 11:52 ` Akihiko Odaki
2025-07-11 13:02 ` [PATCH RFC v2 05/13] virtio: add support for negotiating extended features Paolo Abeni
2025-07-11 13:02 ` Paolo Abeni [this message]
2025-07-15 7:42 ` [PATCH RFC v2 06/13] virtio-pci: implement support for " Akihiko Odaki
2025-07-15 16:21 ` Paolo Abeni
2025-07-16 9:14 ` Paolo Abeni
2025-07-16 11:55 ` Akihiko Odaki
2025-07-11 13:02 ` [PATCH RFC v2 07/13] vhost: add support for negotiating " Paolo Abeni
2025-07-11 13:02 ` [PATCH RFC v2 08/13] qmp: update virtio features map to support " Paolo Abeni
2025-07-15 7:59 ` Akihiko Odaki
2025-07-15 15:43 ` Paolo Abeni
2025-07-16 12:00 ` Akihiko Odaki
2025-07-11 13:02 ` [PATCH RFC v2 09/13] vhost-backend: implement extended features support Paolo Abeni
2025-07-11 13:02 ` [PATCH RFC v2 10/13] vhost-net: " Paolo Abeni
2025-07-11 13:02 ` [PATCH RFC v2 11/13] virtio-net: " Paolo Abeni
2025-07-11 13:02 ` [PATCH RFC v2 12/13] net: implement tunnel probing Paolo Abeni
2025-07-15 8:05 ` Akihiko Odaki
2025-07-15 15:49 ` Paolo Abeni
2025-07-18 4:38 ` Akihiko Odaki
2025-07-11 13:02 ` [PATCH RFC v2 13/13] net: implement UDP tunnel features offloading Paolo Abeni
2025-07-15 8:07 ` Akihiko Odaki
2025-07-16 10:13 ` Paolo Abeni
2025-07-16 12:04 ` Akihiko Odaki
2025-07-14 8:43 ` [PATCH RFC v2 00/13] virtio: introduce support for GSO over UDP tunnel Lei Yang
2025-07-14 9:05 ` Paolo Abeni
2025-07-14 9:09 ` Lei Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=eb1aa9c8442d9b482b5c84fdca54b92c8a824495.1752229731.git.pabeni@redhat.com \
--to=pabeni@redhat.com \
--cc=armbru@redhat.com \
--cc=cohuck@redhat.com \
--cc=dmitry.fleytman@gmail.com \
--cc=eblake@redhat.com \
--cc=g.lettieri@iet.unipi.it \
--cc=jasowang@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=lrizzo@google.com \
--cc=mst@redhat.com \
--cc=odaki@rsg.ci.i.u-tokyo.ac.jp \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=sgarzare@redhat.com \
--cc=sriram.yagnaraman@ericsson.com \
--cc=v.maffione@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).