From patchwork Sun Jan 31 10:29:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 8173271 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 341D09F96D for ; Sun, 31 Jan 2016 10:31:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 693C1202FE for ; Sun, 31 Jan 2016 10:31:27 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9140A202F0 for ; Sun, 31 Jan 2016 10:31:26 +0000 (UTC) Received: from localhost ([::1]:41118 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aPpHx-0002dZ-Vu for patchwork-qemu-devel@patchwork.kernel.org; Sun, 31 Jan 2016 05:31:26 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45084) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aPpFx-0007Vt-BI for qemu-devel@nongnu.org; Sun, 31 Jan 2016 05:29:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aPpFw-0007nt-B8 for qemu-devel@nongnu.org; Sun, 31 Jan 2016 05:29:21 -0500 Received: from mail-wm0-x242.google.com ([2a00:1450:400c:c09::242]:35193) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aPpFw-0007nm-1g for qemu-devel@nongnu.org; Sun, 31 Jan 2016 05:29:20 -0500 Received: by mail-wm0-x242.google.com with SMTP id l66so4656455wml.2 for ; Sun, 31 Jan 2016 02:29:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=PeUEyEYKOVIH/JzFJRx4BURK+r84yDS3allb51qOL2c=; b=X0SkciSQ7YCVbWwXmIUJ5nU8rpgdh3NsWVtdpWOD3CflYA+g0KQwDaolJ8DWyIQypz r7+H03lMCwCJ3QO1M4xIzunTfhGHcSJdt6Ps7ttNLqUgq3IlPQrYUQDqCAUGH3I1wCWM fhH1IFXg/akuL+x9Qw64udazAJa7vGgjtp/Zw/VSiKZ2yb4lS8fTeHK7P/K7J8Xifs65 peK36E4RPitU1AnGL6N+KnGExUPRzzwgFnwjmGwhtpJc488kpArcipqewRCd9UNUJ6yQ eBJi7iJNaMW03u1VQ/YgxV8/CDpKly5qohChn1GpBSL8+bgWoaZ6losbrCYw6P1EDQFS DciQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=PeUEyEYKOVIH/JzFJRx4BURK+r84yDS3allb51qOL2c=; b=ZO8QMpwUJ55qFAkv5ajRmRZDajP4alHx7F1q3DntfnTgbToZJi06oOXeCIFCdANbOc X57z25KGUGklq3gbKr5gsQtQwomdhztpgGuv1Alsh3PoIlt6Wl/mIyVJseNHtC34WH9f Fnr6a87hRDz7Q86RJQ8E2yPqFaYfXOVZKnL48CGkkRm7BIRjNbg03UOoor4X8HwQkoKe wQbvQl3Yihp7Q5EASNoCcUiaRjkacrOBqDKoiwGDYv5/iekwyCTcsiyBWvTHrRFS4eWd ghdA9iAY6axOXT8K08Ks3JfeiJYmdcAyzw0+0X6u/olq57B70e+HgzvsRAh9u/jvI7yL ALxg== X-Gm-Message-State: AG10YORP8CKUFnfTTGI9PuYHpkCK+3OvZkAOqdj9DP4bExa4PCCf04UthofzDTf5KrjGyQ== X-Received: by 10.28.21.19 with SMTP id 19mr5919406wmv.43.1454236159548; Sun, 31 Jan 2016 02:29:19 -0800 (PST) Received: from donizetti.fosdem.net ([2001:67c:1810:f051:7105:9465:633c:859]) by smtp.gmail.com with ESMTPSA id i79sm2349430wmf.24.2016.01.31.02.29.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 31 Jan 2016 02:29:18 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Sun, 31 Jan 2016 11:29:05 +0100 Message-Id: <1454236146-23293-10-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1454236146-23293-1-git-send-email-pbonzini@redhat.com> References: <1454236146-23293-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::242 Cc: cornelia.huck@de.ibm.com, Vincenzo Maffione , mst@redhat.com Subject: [Qemu-devel] [PATCH 09/10] virtio: read avail_idx from VQ only when necessary X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Vincenzo Maffione 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 Message-Id: Reviewed-by: Cornelia Huck Signed-off-by: Paolo Bonzini --- v1->v2: update shadow avail_idx in virtio_queue_set_last_avail_idx [Michael] 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 5116a2e..6842938 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)