If the host supports 128 bit-wide features, and the driver
use any of them, serialize the full features range leveraging
newly introduced 128bits integer helpers.

Signed-off-by: Paolo Abeni <pab...@redhat.com>
---
 hw/virtio/virtio.c | 76 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 701f59884d..ef15a1835e 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2982,6 +2982,26 @@ static const VMStateDescription vmstate_virtio_disabled 
= {
     }
 };
 
+#ifdef CONFIG_INT128
+static bool virtio_128bit_features_needed(void *opaque)
+{
+    VirtIODevice *vdev = opaque;
+
+    return (vdev->host_features_ex >> 64) != 0;
+}
+
+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_UINT128(guest_features_ex, VirtIODevice),
+        VMSTATE_END_OF_LIST()
+    }
+};
+#endif
+
 static const VMStateDescription vmstate_virtio = {
     .name = "virtio",
     .version_id = 1,
@@ -2991,6 +3011,9 @@ static const VMStateDescription vmstate_virtio = {
     },
     .subsections = (const VMStateDescription * const []) {
         &vmstate_virtio_device_endian,
+#ifdef CONFIG_INT128
+        &vmstate_virtio_128bit_features,
+#endif
         &vmstate_virtio_64bit_features,
         &vmstate_virtio_virtqueues,
         &vmstate_virtio_ringsize,
@@ -3087,7 +3110,8 @@ 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,
+                                       virtio_features_t val)
 {
     VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     bool bad = (val & ~(vdev->host_features)) != 0;
@@ -3133,6 +3157,42 @@ virtio_set_features_nocheck_maybe_co(VirtIODevice *vdev, 
uint64_t val)
     }
 }
 
+#ifdef CONFIG_INT128
+typedef struct VirtioSetFeaturesExNocheckData {
+    Coroutine *co;
+    VirtIODevice *vdev;
+    __uint128_t val;
+    int ret;
+} VirtioSetFeaturesExNocheckData;
+
+static void virtio_set_features_ex_nocheck_bh(void *opaque)
+{
+    VirtioSetFeaturesExNocheckData *data = opaque;
+
+    data->ret = virtio_set_features_nocheck(data->vdev, data->val);
+    aio_co_wake(data->co);
+}
+
+static int coroutine_mixed_fn
+virtio_set_features_ex_nocheck_maybe_co(VirtIODevice *vdev, __uint128_t val)
+{
+    if (qemu_in_coroutine()) {
+        VirtioSetFeaturesExNocheckData data = {
+            .co = qemu_coroutine_self(),
+            .vdev = vdev,
+            .val = val,
+        };
+        aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
+                                virtio_set_features_ex_nocheck_bh, &data);
+        qemu_coroutine_yield();
+        return data.ret;
+    } else {
+        return virtio_set_features_nocheck(vdev, val);
+    }
+}
+
+#endif
+
 int virtio_set_features(VirtIODevice *vdev, uint64_t val)
 {
     int ret;
@@ -3318,6 +3378,20 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int 
version_id)
         vdev->device_endian = virtio_default_endian();
     }
 
+#ifdef CONFIG_INT128
+    if (virtio_128bit_features_needed(vdev)) {
+        __int128_t features128 = vdev->guest_features_ex;
+        if (virtio_set_features_ex_nocheck_maybe_co(vdev, features128) < 0) {
+            error_report("Features 0x" VIRTIO_FEATURES_FMT " unsupported. "
+                         "Allowed features: 0x" VIRTIO_FEATURES_FMT,
+                         VIRTIO_FEATURES_HI(features128),
+                         VIRTIO_FEATURES_LOW(features128),
+                         VIRTIO_FEATURES_HI(vdev->host_features_ex),
+                         VIRTIO_FEATURES_LOW(vdev->host_features_ex));
+            return -1;
+        }
+    } else
+#endif
     if (virtio_64bit_features_needed(vdev)) {
         /*
          * Subsection load filled vdev->guest_features.  Run them
-- 
2.49.0


Reply via email to