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>,
	Vincenzo Maffione <v.maffione@gmail.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: [Qemu-devel] [PULL 13/49] virtio: read avail_idx from VQ only when necessary
Date: Thu, 4 Feb 2016 23:51:49 +0200	[thread overview]
Message-ID: <1454612376-7072-14-git-send-email-mst@redhat.com> (raw)
In-Reply-To: <1454612376-7072-1-git-send-email-mst@redhat.com>

From: Vincenzo Maffione <v.maffione@gmail.com>

The virtqueue_pop() implementation needs to check if the avail ring
contains some pending buffers. To perform this check, it is not
always necessary to fetch the avail_idx in the VQ memory, which is
expensive. This patch introduces a shadow variable tracking avail_idx
and modifies virtio_queue_empty() to access avail_idx in physical
memory only when necessary.

Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
Message-Id: <b617d6459902773d9f4ab843bfaca764f5af8eda.1450218353.git.v.maffione@gmail.com>
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 | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 82e6414..9608358 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -70,8 +70,13 @@ typedef struct VRing
 struct VirtQueue
 {
     VRing vring;
+
+    /* Next head to pop */
     uint16_t last_avail_idx;
 
+    /* Last avail_idx read from VQ. */
+    uint16_t shadow_avail_idx;
+
     uint16_t used_idx;
 
     /* Last used index value we have signalled on */
@@ -132,7 +137,8 @@ static inline uint16_t vring_avail_idx(VirtQueue *vq)
 {
     hwaddr pa;
     pa = vq->vring.avail + offsetof(VRingAvail, idx);
-    return virtio_lduw_phys(vq->vdev, pa);
+    vq->shadow_avail_idx = virtio_lduw_phys(vq->vdev, pa);
+    return vq->shadow_avail_idx;
 }
 
 static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
@@ -223,8 +229,14 @@ int virtio_queue_ready(VirtQueue *vq)
     return vq->vring.avail != 0;
 }
 
+/* Fetch avail_idx from VQ memory only when we really need to know if
+ * guest has added some buffers. */
 int virtio_queue_empty(VirtQueue *vq)
 {
+    if (vq->shadow_avail_idx != vq->last_avail_idx) {
+        return 0;
+    }
+
     return vring_avail_idx(vq) == vq->last_avail_idx;
 }
 
@@ -300,7 +312,7 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
     /* Check it isn't doing very strange things with descriptor numbers. */
     if (num_heads > vq->vring.num) {
         error_report("Guest moved used index from %u to %u",
-                     idx, vring_avail_idx(vq));
+                     idx, vq->shadow_avail_idx);
         exit(1);
     }
     /* On success, callers read a descriptor at vq->last_avail_idx.
@@ -535,9 +547,12 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
     struct iovec iov[VIRTQUEUE_MAX_SIZE];
     VRingDesc desc;
 
-    if (!virtqueue_num_heads(vq, vq->last_avail_idx)) {
+    if (virtio_queue_empty(vq)) {
         return NULL;
     }
+    /* Needed after virtio_queue_empty(), see comment in
+     * virtqueue_num_heads(). */
+    smp_rmb();
 
     /* When we start there are none of either input nor output. */
     out_num = in_num = 0;
@@ -786,6 +801,7 @@ void virtio_reset(void *opaque)
         vdev->vq[i].vring.avail = 0;
         vdev->vq[i].vring.used = 0;
         vdev->vq[i].last_avail_idx = 0;
+        vdev->vq[i].shadow_avail_idx = 0;
         vdev->vq[i].used_idx = 0;
         virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR);
         vdev->vq[i].signalled_used = 0;
@@ -1155,7 +1171,7 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
     smp_mb();
     /* Always notify when queue is empty (when feature acknowledge) */
     if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
-        !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) {
+        !vq->inuse && virtio_queue_empty(vq)) {
         return true;
     }
 
@@ -1579,6 +1595,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
                 return -1;
             }
             vdev->vq[i].used_idx = vring_used_idx(&vdev->vq[i]);
+            vdev->vq[i].shadow_avail_idx = vring_avail_idx(&vdev->vq[i]);
         }
     }
 
@@ -1714,6 +1731,7 @@ uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n)
 void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx)
 {
     vdev->vq[n].last_avail_idx = idx;
+    vdev->vq[n].shadow_avail_idx = idx;
 }
 
 void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n)
-- 
MST

  parent reply	other threads:[~2016-02-04 21:51 UTC|newest]

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

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=1454612376-7072-14-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 \
    --cc=v.maffione@gmail.com \
    /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).