qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 06/40] virtio: introduce virtqueue_alloc_element


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 06/40] virtio: introduce virtqueue_alloc_element
Date: Tue, 24 Nov 2015 19:00:57 +0100

Allocate the arrays for in_addr/out_addr/in_sg/out_sg outside the
VirtQueueElement.  For now, virtqueue_pop and vring_pop keep
allocating a very large VirtQueueElement.

Signed-off-by: Paolo Bonzini <address@hidden>
---
 hw/virtio/dataplane/vring.c |  2 +-
 hw/virtio/virtio.c          | 60 +++++++++++++++++++++++++++++++--------------
 include/hw/virtio/virtio.h  |  9 ++++---
 3 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 1b900fc..c950caa 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -402,7 +402,7 @@ void *vring_pop(VirtIODevice *vdev, Vring *vring, size_t sz)
         goto out;
     }
 
-    elem = g_malloc(sz);
+    elem = virtqueue_alloc_element(sz, VIRTQUEUE_MAX_SIZE, VIRTQUEUE_MAX_SIZE);
 
     /* Initialize elem so it can be safely unmapped */
     elem->in_num = elem->out_num = 0;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index f5f8108..32c89eb 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -494,11 +494,29 @@ static void virtqueue_map_iovec(struct iovec *sg, hwaddr 
*addr,
 void virtqueue_map(VirtQueueElement *elem)
 {
     virtqueue_map_iovec(elem->in_sg, elem->in_addr, &elem->in_num,
-                        MIN(ARRAY_SIZE(elem->in_sg), 
ARRAY_SIZE(elem->in_addr)),
-                        1);
+                        VIRTQUEUE_MAX_SIZE, 1);
     virtqueue_map_iovec(elem->out_sg, elem->out_addr, &elem->out_num,
-                        MIN(ARRAY_SIZE(elem->out_sg), 
ARRAY_SIZE(elem->out_addr)),
-                        0);
+                        VIRTQUEUE_MAX_SIZE, 0);
+}
+
+void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num)
+{
+    VirtQueueElement *elem;
+    size_t in_addr_ofs = QEMU_ALIGN_UP(sz, __alignof__(elem->in_addr[0]));
+    size_t out_addr_ofs = in_addr_ofs + in_num * sizeof (elem->in_addr[0]);
+    size_t out_addr_end = out_addr_ofs + out_num * sizeof (elem->out_addr[0]);
+    size_t in_sg_ofs = QEMU_ALIGN_UP(out_addr_end, 
__alignof__(elem->in_sg[0]));
+    size_t out_sg_ofs = in_sg_ofs + in_num * sizeof (elem->in_sg[0]);
+    size_t out_sg_end = out_sg_ofs + out_num * sizeof (elem->out_sg[0]);
+
+    elem = g_malloc(out_sg_end);
+    elem->out_num = out_num;
+    elem->in_num = in_num;
+    elem->in_addr = (void*)elem + in_addr_ofs;
+    elem->out_addr = (void*)elem + out_addr_ofs;
+    elem->in_sg = (void*)elem + in_sg_ofs;
+    elem->out_sg = (void*)elem + out_sg_ofs;
+    return elem;
 }
 
 void *virtqueue_pop(VirtQueue *vq, size_t sz)
@@ -513,7 +531,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
     }
 
     /* When we start there are none of either input nor output. */
-    elem = g_malloc(sz);
+    elem = virtqueue_alloc_element(sz, VIRTQUEUE_MAX_SIZE, VIRTQUEUE_MAX_SIZE);
     elem->out_num = elem->in_num = 0;
 
     max = vq->vring.num;
@@ -540,14 +558,14 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
         struct iovec *sg;
 
         if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_WRITE) {
-            if (elem->in_num >= ARRAY_SIZE(elem->in_sg)) {
+            if (elem->in_num >= VIRTQUEUE_MAX_SIZE) {
                 error_report("Too many write descriptors in indirect table");
                 exit(1);
             }
             elem->in_addr[elem->in_num] = vring_desc_addr(vdev, desc_pa, i);
             sg = &elem->in_sg[elem->in_num++];
         } else {
-            if (elem->out_num >= ARRAY_SIZE(elem->out_sg)) {
+            if (elem->out_num >= VIRTQUEUE_MAX_SIZE) {
                 error_report("Too many read descriptors in indirect table");
                 exit(1);
             }
@@ -577,31 +595,35 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
 
 void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz)
 {
-    VirtQueueElement *elem = g_malloc(sz);
+    VirtQueueElement *elem;
     bool swap;
     hwaddr addr[VIRTQUEUE_MAX_SIZE];
     struct iovec iov[VIRTQUEUE_MAX_SIZE];
+    uint32_t index, out_num, in_num;
     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);
+    qemu_get_be32s(f, &index);
+    qemu_get_be32s(f, &out_num);
+    qemu_get_be32s(f, &in_num);
 
-    swap = (elem->out_num & 0xFFFF0000) || (elem->in_num & 0xFFFF0000);
+    swap = (out_num & 0xFFFF0000) || (in_num & 0xFFFF0000);
     if (swap) {
-        bswap32s(&elem->index);
-        bswap32s(&elem->out_num);
-        bswap32s(&elem->in_num);
+        bswap32s(&index);
+        bswap32s(&out_num);
+        bswap32s(&in_num);
     }
 
+    elem = virtqueue_alloc_element(sz, out_num, in_num);
+    elem->index = index;
+
     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)) {
+    if (i < VIRTQUEUE_MAX_SIZE) {
         qemu_get_buffer(f, (uint8_t *)addr, sizeof(addr) - i * 
sizeof(addr[0]));
     }
 
@@ -611,7 +633,7 @@ void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz)
             bswap64s(&elem->out_addr[i]);
         }
     }
-    if (i < ARRAY_SIZE(addr)) {
+    if (i < VIRTQUEUE_MAX_SIZE) {
         qemu_get_buffer(f, (uint8_t *)addr, sizeof(addr) - i * 
sizeof(addr[0]));
     }
 
@@ -623,7 +645,7 @@ void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz)
         }
        elem->in_sg[i].iov_len = scratch;
     }
-    if (i < ARRAY_SIZE(iov)) {
+    if (i < VIRTQUEUE_MAX_SIZE) {
         qemu_get_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0]));
     }
 
@@ -635,7 +657,7 @@ void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz)
         }
        elem->out_sg[i].iov_len = scratch;
     }
-    if (i < ARRAY_SIZE(iov)) {
+    if (i < VIRTQUEUE_MAX_SIZE) {
         qemu_get_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0]));
     }
 
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 44da9a8..108cdb0 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -46,10 +46,10 @@ typedef struct VirtQueueElement
     unsigned int index;
     unsigned int out_num;
     unsigned int in_num;
-    hwaddr in_addr[VIRTQUEUE_MAX_SIZE];
-    hwaddr out_addr[VIRTQUEUE_MAX_SIZE];
-    struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
-    struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
+    hwaddr *in_addr;
+    hwaddr *out_addr;
+    struct iovec *in_sg;
+    struct iovec *out_sg;
 } VirtQueueElement;
 
 #define VIRTIO_QUEUE_MAX 1024
@@ -143,6 +143,7 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int 
queue_size,
 
 void virtio_del_queue(VirtIODevice *vdev, int n);
 
+void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num);
 void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
                     unsigned int len);
 void virtqueue_flush(VirtQueue *vq, unsigned int count);
-- 
1.8.3.1





reply via email to

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