[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH 06/40] virtio: introduce virtqueue_alloc_element
From: |
Paolo Bonzini |
Subject: |
[Qemu-block] [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
- [Qemu-block] [RFC PATCH 00/40] Sneak peek of virtio and dataplane changes for 2.6, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 02/40] virtio: move VirtQueueElement at the beginning of the structs, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 01/40] 9pfs: allocate pdus with g_malloc/g_free, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 03/40] virtio: move allocation to virtqueue_pop/vring_pop, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 06/40] virtio: introduce virtqueue_alloc_element,
Paolo Bonzini <=
- [Qemu-block] [PATCH 04/40] virtio: introduce qemu_get/put_virtqueue_element, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 07/40] virtio: slim down allocation of VirtQueueElements, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 09/40] vring: make vring_enable_notification return void, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 08/40] vring: slim down allocation of VirtQueueElements, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 05/40] virtio: read/write the VirtQueueElement a field at a time, Paolo Bonzini, 2015/11/24
- [Qemu-block] [PATCH 10/40] virtio: combine the read of a descriptor, Paolo Bonzini, 2015/11/24