qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>,
	Peter Maydell <peter.maydell@linaro.org>,
	Eduardo Habkost <ehabkost@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: [Qemu-devel] [PULL v2 09/45] virtio: slim down allocation of VirtQueueElements
Date: Sat, 6 Feb 2016 21:12:46 +0200	[thread overview]
Message-ID: <1454784308-21177-10-git-send-email-mst@redhat.com> (raw)
In-Reply-To: <1454784308-21177-1-git-send-email-mst@redhat.com>

From: Paolo Bonzini <pbonzini@redhat.com>

Build the addresses and s/g lists on the stack, and then copy them
to a VirtQueueElement that is just as big as required to contain this
particular s/g list.  The cost of the copy is minimal compared to that
of a large malloc.

When virtqueue_map is used on the destination side of migration or on
loadvm, the iovecs have already been split at memory region boundary,
so we can just reuse the out_num/in_num we find in the file.

Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/virtio/virtio.c | 82 +++++++++++++++++++++++++++++++++---------------------
 1 file changed, 51 insertions(+), 31 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 661a1e1..c3e00a8 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -448,6 +448,32 @@ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
     return in_bytes <= in_total && out_bytes <= out_total;
 }
 
+static void virtqueue_map_desc(unsigned int *p_num_sg, hwaddr *addr, struct iovec *iov,
+                               unsigned int max_num_sg, bool is_write,
+                               hwaddr pa, size_t sz)
+{
+    unsigned num_sg = *p_num_sg;
+    assert(num_sg <= max_num_sg);
+
+    while (sz) {
+        hwaddr len = sz;
+
+        if (num_sg == max_num_sg) {
+            error_report("virtio: too many write descriptors in indirect table");
+            exit(1);
+        }
+
+        iov[num_sg].iov_base = cpu_physical_memory_map(pa, &len, is_write);
+        iov[num_sg].iov_len = len;
+        addr[num_sg] = pa;
+
+        sz -= len;
+        pa += len;
+        num_sg++;
+    }
+    *p_num_sg = num_sg;
+}
+
 static void virtqueue_map_iovec(struct iovec *sg, hwaddr *addr,
                                 unsigned int *num_sg, unsigned int max_size,
                                 int is_write)
@@ -474,20 +500,10 @@ static void virtqueue_map_iovec(struct iovec *sg, hwaddr *addr,
             error_report("virtio: error trying to map MMIO memory");
             exit(1);
         }
-        if (len == sg[i].iov_len) {
-            continue;
-        }
-        if (*num_sg >= max_size) {
-            error_report("virtio: memory split makes iovec too large");
+        if (len != sg[i].iov_len) {
+            error_report("virtio: unexpected memory split");
             exit(1);
         }
-        memmove(sg + i + 1, sg + i, sizeof(*sg) * (*num_sg - i));
-        memmove(addr + i + 1, addr + i, sizeof(*addr) * (*num_sg - i));
-        assert(len < sg[i + 1].iov_len);
-        sg[i].iov_len = len;
-        addr[i + 1] += len;
-        sg[i + 1].iov_len -= len;
-        ++*num_sg;
     }
 }
 
@@ -526,14 +542,16 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
     hwaddr desc_pa = vq->vring.desc;
     VirtIODevice *vdev = vq->vdev;
     VirtQueueElement *elem;
+    unsigned out_num, in_num;
+    hwaddr addr[VIRTQUEUE_MAX_SIZE];
+    struct iovec iov[VIRTQUEUE_MAX_SIZE];
 
     if (!virtqueue_num_heads(vq, vq->last_avail_idx)) {
         return NULL;
     }
 
     /* When we start there are none of either input nor output. */
-    elem = virtqueue_alloc_element(sz, VIRTQUEUE_MAX_SIZE, VIRTQUEUE_MAX_SIZE);
-    elem->out_num = elem->in_num = 0;
+    out_num = in_num = 0;
 
     max = vq->vring.num;
 
@@ -556,37 +574,39 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
 
     /* Collect all the descriptors */
     do {
-        struct iovec *sg;
+        hwaddr pa = vring_desc_addr(vdev, desc_pa, i);
+        size_t len = vring_desc_len(vdev, desc_pa, i);
 
         if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_WRITE) {
-            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++];
+            virtqueue_map_desc(&in_num, addr + out_num, iov + out_num,
+                               VIRTQUEUE_MAX_SIZE - out_num, true, pa, len);
         } else {
-            if (elem->out_num >= VIRTQUEUE_MAX_SIZE) {
-                error_report("Too many read descriptors in indirect table");
+            if (in_num) {
+                error_report("Incorrect order for descriptors");
                 exit(1);
             }
-            elem->out_addr[elem->out_num] = vring_desc_addr(vdev, desc_pa, i);
-            sg = &elem->out_sg[elem->out_num++];
+            virtqueue_map_desc(&out_num, addr, iov,
+                               VIRTQUEUE_MAX_SIZE, false, pa, len);
         }
 
-        sg->iov_len = vring_desc_len(vdev, desc_pa, i);
-
         /* If we've got too many, that implies a descriptor loop. */
-        if ((elem->in_num + elem->out_num) > max) {
+        if ((in_num + out_num) > max) {
             error_report("Looped descriptor");
             exit(1);
         }
     } while ((i = virtqueue_next_desc(vdev, desc_pa, i, max)) != max);
 
-    /* Now map what we have collected */
-    virtqueue_map(elem);
-
+    /* Now copy what we have collected and mapped */
+    elem = virtqueue_alloc_element(sz, out_num, in_num);
     elem->index = head;
+    for (i = 0; i < out_num; i++) {
+        elem->out_addr[i] = addr[i];
+        elem->out_sg[i] = iov[i];
+    }
+    for (i = 0; i < in_num; i++) {
+        elem->in_addr[i] = addr[out_num + i];
+        elem->in_sg[i] = iov[out_num + i];
+    }
 
     vq->inuse++;
 
-- 
MST

  parent reply	other threads:[~2016-02-06 19:12 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-06 19:12 [Qemu-devel] [PULL v2 00/45] pc and misc cleanups and fixes, virtio optimizations Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 01/45] Fix virtio migration Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 02/45] pc: acpi: merge SSDT into DSDT Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 03/45] tests: pc: acpi: drop not needed 'expected SSDT' blobs Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 04/45] tests: pc: acpi: add expected DSDT.bridge blobs and update DSDT blobs Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 05/45] virtio: move VirtQueueElement at the beginning of the structs Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 06/45] virtio: move allocation to virtqueue_pop/vring_pop Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 07/45] virtio: introduce qemu_get/put_virtqueue_element Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 08/45] virtio: introduce virtqueue_alloc_element Michael S. Tsirkin
2016-02-06 19:12 ` Michael S. Tsirkin [this message]
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 10/45] vring: slim down allocation of VirtQueueElements Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 11/45] virtio: combine the read of a descriptor Michael S. Tsirkin
2016-02-06 19:12 ` [Qemu-devel] [PULL v2 12/45] virtio: cache used_idx in a VirtQueue field Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 13/45] virtio: read avail_idx from VQ only when necessary Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 14/45] virtio: combine write of an entry into used ring Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 15/45] hw/pxb: add pxb devices to the bridge category Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 16/45] vhost-user-test: use correct ROM to speed up and avoid spurious failures Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 17/45] hw/pci: ensure that only PCI/PCIe bridges can be attached to pxb/pxb-pcie devices Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 18/45] ipmi: replace goto by a return statement Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 19/45] ipmi: replace *_MAXCMD defines Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 20/45] ipmi: cleanup error_report messages Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 21/45] ipmi: fix SDR length value Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 22/45] ipmi: introduce a struct ipmi_sdr_compact Michael S. Tsirkin
2016-02-16  7:45   ` Paolo Bonzini
2016-02-16  8:11     ` Cédric Le Goater
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 23/45] ipmi: add get and set SENSOR_TYPE commands Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 24/45] ipmi: add GET_SYS_RESTART_CAUSE chassis command Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 25/45] ipmi: add ACPI power and GUID commands Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 26/45] pc: Move PcGuestInfo declaration to top of file Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 27/45] pc: Eliminate struct PcGuestInfoState Michael S. Tsirkin
2016-02-06 19:13 ` [Qemu-devel] [PULL v2 28/45] pc: Simplify pc_memory_init() signature Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 29/45] pc: Simplify xen_load_linux() signature Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 30/45] acpi: Remove guest_info parameters from functions Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 31/45] acpi: Don't save PcGuestInfo on AcpiBuildState Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 32/45] pc: Remove compat fields from PcGuestInfo Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 33/45] pc: Remove RAM size " Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 34/45] pc: Remove PcGuestInfo.isapc_ram_fw field Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 35/45] pc: Move PcGuestInfo.fw_cfg to PCMachineState Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 36/45] pc: Move APIC and NUMA data from PcGuestInfo " Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 37/45] pc: Eliminate PcGuestInfo struct Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 38/45] acpi: take oem_id in build_header(), optionally Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 39/45] acpi: expose oem_id and oem_table_id in build_rsdt() Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 40/45] acpi: add function to extract oem_id and oem_table_id from the user's SLIC Michael S. Tsirkin
2016-02-06 19:14 ` [Qemu-devel] [PULL v2 41/45] pc: set the OEM fields in the RSDT and the FADT from the SLIC Michael S. Tsirkin
2016-02-06 19:15 ` [Qemu-devel] [PULL v2 42/45] dimm: Correct type of MemoryHotplugState->base Michael S. Tsirkin
2016-02-06 19:15 ` [Qemu-devel] [PULL v2 43/45] intel_iommu: large page support Michael S. Tsirkin
2016-02-06 19:15 ` [Qemu-devel] [PULL v2 44/45] fix MSI injection on Xen Michael S. Tsirkin
2016-02-12 21:55   ` Daniel P. Berrange
2016-02-06 19:15 ` [Qemu-devel] [PULL v2 45/45] net: set endianness on all backend devices Michael S. Tsirkin
2016-02-08 12:32 ` [Qemu-devel] [PULL v2 00/45] pc and misc cleanups and fixes, virtio optimizations Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1454784308-21177-10-git-send-email-mst@redhat.com \
    --to=mst@redhat.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=ehabkost@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).