qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/4] virtio: modify savevm to have a stable wire for


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH 3/4] virtio: modify savevm to have a stable wire format
Date: Mon, 10 Dec 2012 08:29:49 -0600

We were memcpy()'ing a structure to the wire :-/  Since savevm really
only works on x86 today, lets just declare that this element is sent
over the wire as a little endian value in order to fix the bitness.

Unfortunately, we also send raw pointers and size_t which are going
to be different values on a 32-bit vs. 64-bit QEMU so we need to also
deal with that case.

A lot of values that should have been previously ignored are now sent
as 0 and ignored on the receive side too.

Signed-off-by: Anthony Liguori <address@hidden>
---
 hw/virtio.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 112 insertions(+), 2 deletions(-)

diff --git a/hw/virtio.c b/hw/virtio.c
index 8eb8f69..0108d62 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -875,14 +875,124 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     return 0;
 }
 
+/* We used to memcpy the structure to the wire so that's the reason for all of
+ * this ugliness */
+
+#if HOST_LONG_BITS == 32
+static uint32 virtio_get_long(QEMUFile *f)
+{
+    return qemu_get_le32(f);
+}
+
+static void virtio_put_long(QEMUFile *f, uint32_t value)
+{
+    qemu_put_le32(f, value);
+}
+#elif HOST_LONG_BITS == 64
+static uint64 virtio_get_long(QEMUFile *f)
+{
+    return qemu_get_le64(f);
+}
+
+static void virtio_put_long(QEMUFile *f, uint64_t value)
+{
+    qemu_put_le64(f, value);
+}
+#else
+#error Invalid HOST_LONG_BITS
+#endif
+
 void virtio_put_virt_queue_element(QEMUFile *f, const VirtQueueElement *elem)
 {
-    qemu_put_buffer(f, (unsigned char*)elem, sizeof(*elem));
+    int i;
+
+    qemu_put_le32(f, elem->index);
+    qemu_put_le32(f, elem->out_num);
+    qemu_put_le32(f, elem->in_num);
+
+    qemu_put_le32(f, 0); /* padding for structure */
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        if (i < elem->in_num) {
+            qemu_put_le64(f, elem->in_addr[i]);
+        } else {
+            qemu_put_le64(f, 0);
+        }
+    }
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        if (i < elem->out_num) {
+            qemu_put_le64(f, elem->out_addr[i]);
+        } else {
+            qemu_put_le64(f, 0);
+        }
+    }
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        virtio_put_long(f, 0);
+        if (i < elem->in_num) {
+            virtio_put_long(f, elem->in_sg[i].iov_len);
+        } else {
+            virtio_put_long(f, 0);
+        }
+    }
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        virtio_put_long(f, 0);
+        if (i < elem->out_num) {
+            virtio_put_long(f, elem->out_sg[i].iov_len);
+        } else {
+            virtio_put_long(f, 0);
+        }
+    }
 }
 
 void virtio_get_virt_queue_element(QEMUFile *f, VirtQueueElement *elem)
 {
-    qemu_get_buffer(f, (unsigned char *)elem, sizeof(*elem));
+    int i;
+
+    elem->index = qemu_get_le32(f);
+    elem->out_num = qemu_get_le32(f);
+    elem->in_num = qemu_get_le32(f);
+
+    assert(elem->out_num <= VIRTQUEUE_MAX_SIZE &&
+           elem->in_num <= VIRTQUEUE_MAX_SIZE);
+
+    qemu_get_le32(f); /* padding for structure */
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        if (i < elem->in_num) {
+            elem->in_addr[i] = qemu_get_le64(f);
+        } else {
+            qemu_get_le64(f);
+        }
+    }
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        if (i < elem->out_num) {
+            elem->out_addr[i] = qemu_get_le64(f);
+        } else {
+            qemu_get_le64(f);
+        }
+    }
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        virtio_get_long(f);
+        if (i < elem->in_num) {
+            elem->in_sg[i].iov_len = virtio_get_long(f);
+        } else {
+            virtio_get_long(f);
+        }
+    }
+
+    for (i = 0; i < VIRTQUEUE_MAX_SIZE; i++) {
+        virtio_get_long(f);
+        if (i < elem->out_num) {
+            elem->out_sg[i].iov_len = virtio_get_long(f);
+        } else {
+            virtio_get_long(f);
+        }
+    }
 
     virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1);
     virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0);
-- 
1.8.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]