qemu-block
[Top][All Lists]
Advanced

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

[Qemu-block] [PATCH 05/40] virtio: read/write the VirtQueueElement a fie


From: Paolo Bonzini
Subject: [Qemu-block] [PATCH 05/40] virtio: read/write the VirtQueueElement a field at a time
Date: Tue, 24 Nov 2015 19:00:56 +0100

Signed-off-by: Paolo Bonzini <address@hidden>
---
 hw/virtio/virtio.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 93 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index fd63206..f5f8108 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -578,14 +578,105 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
 void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz)
 {
     VirtQueueElement *elem = g_malloc(sz);
-    qemu_get_buffer(f, (uint8_t *)elem, sizeof(VirtQueueElement));
+    bool swap;
+    hwaddr addr[VIRTQUEUE_MAX_SIZE];
+    struct iovec iov[VIRTQUEUE_MAX_SIZE];
+    uint64_t scratch;
+    int i;
+
+    qemu_get_be32s(f, &elem->index);
+    qemu_get_be32s(f, &elem->out_num);
+    qemu_get_be32s(f, &elem->in_num);
+
+    swap = (elem->out_num & 0xFFFF0000) || (elem->in_num & 0xFFFF0000);
+    if (swap) {
+        bswap32s(&elem->index);
+        bswap32s(&elem->out_num);
+        bswap32s(&elem->in_num);
+    }
+
+    for (i = 0; i < elem->in_num; i++) {
+        qemu_get_be64s(f, &elem->in_addr[i]);
+        if (swap) {
+            bswap64s(&elem->in_addr[i]);
+        }
+    }
+    if (i < ARRAY_SIZE(addr)) {
+        qemu_get_buffer(f, (uint8_t *)addr, sizeof(addr) - i * 
sizeof(addr[0]));
+    }
+
+    for (i = 0; i < elem->out_num; i++) {
+        qemu_get_be64s(f, &elem->out_addr[i]);
+        if (swap) {
+            bswap64s(&elem->out_addr[i]);
+        }
+    }
+    if (i < ARRAY_SIZE(addr)) {
+        qemu_get_buffer(f, (uint8_t *)addr, sizeof(addr) - i * 
sizeof(addr[0]));
+    }
+
+    for (i = 0; i < elem->in_num; i++) {
+        (void) qemu_get_be64(f); /* base */
+       qemu_get_be64s(f, &scratch); /* length */
+        if (swap) {
+            bswap64s(&scratch);
+        }
+       elem->in_sg[i].iov_len = scratch;
+    }
+    if (i < ARRAY_SIZE(iov)) {
+        qemu_get_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0]));
+    }
+
+    for (i = 0; i < elem->out_num; i++) {
+        (void) qemu_get_be64(f); /* base */
+        qemu_get_be64s(f, &scratch); /* length */
+        if (swap) {
+            bswap64s(&scratch);
+        }
+       elem->out_sg[i].iov_len = scratch;
+    }
+    if (i < ARRAY_SIZE(iov)) {
+        qemu_get_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0]));
+    }
+
     virtqueue_map(elem);
     return elem;
 }
 
 void qemu_put_virtqueue_element(QEMUFile *f, VirtQueueElement *elem)
 {
-    qemu_put_buffer(f, (uint8_t *)elem, sizeof(VirtQueueElement));
+    hwaddr addr[VIRTQUEUE_MAX_SIZE];
+    struct iovec iov[VIRTQUEUE_MAX_SIZE];
+    int i;
+
+    memset(addr, 0, sizeof(addr));
+    memset(iov, 0, sizeof(iov));
+
+    qemu_put_be32s(f, &elem->index);
+    qemu_put_be32s(f, &elem->out_num);
+    qemu_put_be32s(f, &elem->in_num);
+
+    for (i = 0; i < elem->in_num; i++) {
+        qemu_put_be64s(f, &elem->in_addr[i]);
+    }
+    qemu_put_buffer(f, (uint8_t *)addr, sizeof(addr) - i * sizeof(addr[0]));
+
+    for (i = 0; i < elem->out_num; i++) {
+        qemu_put_be64s(f, &elem->out_addr[i]);
+    }
+    qemu_put_buffer(f, (uint8_t *)addr, sizeof(addr) - i * sizeof(addr[0]));
+
+    for (i = 0; i < elem->in_num; i++) {
+        qemu_put_be64(f, 0);
+        qemu_put_be64(f, elem->in_sg[i].iov_len);
+    }
+    qemu_put_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0]));
+
+    for (i = 0; i < elem->out_num; i++) {
+        qemu_put_be64(f, 0);
+        qemu_put_be64(f, elem->out_sg[i].iov_len);
+    }
+    qemu_put_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0]));
 }
 
 /* virtio device */
-- 
1.8.3.1





reply via email to

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