From patchwork Thu May 6 08:26:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 51839 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 804EDB7D42 for ; Fri, 7 May 2010 01:37:49 +1000 (EST) Received: from localhost ([127.0.0.1]:58853 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OA390-0001fp-Hw for incoming@patchwork.ozlabs.org; Thu, 06 May 2010 11:37:46 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O9wTN-0005k8-TV for qemu-devel@nongnu.org; Thu, 06 May 2010 04:30:22 -0400 Received: from [140.186.70.92] (port=41069 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O9wTL-0005eG-9S for qemu-devel@nongnu.org; Thu, 06 May 2010 04:30:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O9wTJ-0006gP-6P for qemu-devel@nongnu.org; Thu, 06 May 2010 04:30:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:7490) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O9wTI-0006gF-VS for qemu-devel@nongnu.org; Thu, 06 May 2010 04:30:17 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o468UDGW031376 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 6 May 2010 04:30:13 -0400 Received: from redhat.com (vpn-6-247.tlv.redhat.com [10.35.6.247]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id o468UBaO019088; Thu, 6 May 2010 04:30:12 -0400 Date: Thu, 6 May 2010 11:26:16 +0300 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org, Anthony Liguori , kvm@vger.kernel.org Message-ID: <20100506082615.GA15461@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.19 (2009-01-05) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Subject: [Qemu-devel] [PATCH RFC] qemu/virtio: use last used index published by guest X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Reduces irq_window in guest by only injecting an interrupt if guest has handled all buffers we used so far. Signed-off-by: Michael S. Tsirkin --- This is the qemu part of the story. hw/vhost_net.c | 6 ++++++ hw/virtio.c | 15 +++++++++++++++ hw/virtio.h | 4 ++++ 3 files changed, 25 insertions(+), 0 deletions(-) diff --git a/hw/vhost_net.c b/hw/vhost_net.c index 2e292ee..d77c9b2 100644 --- a/hw/vhost_net.c +++ b/hw/vhost_net.c @@ -51,6 +51,9 @@ unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) { features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC); } + if (!(net->dev.features & (1 << VIRTIO_RING_F_PUBLISH_USED))) { + features &= ~(1 << VIRTIO_RING_F_PUBLISH_USED); + } features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF); return features; } @@ -64,6 +67,9 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features) if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC)) { net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC); } + if (features & (1 << VIRTIO_RING_F_PUBLISH_USED)) { + net->dev.acked_features |= (1 << VIRTIO_RING_F_PUBLISH_USED); + } } static int vhost_net_get_fd(VLANClientState *backend) diff --git a/hw/virtio.c b/hw/virtio.c index e7657ae..5d686f0 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -71,6 +71,7 @@ struct VirtQueue target_phys_addr_t pa; uint16_t last_avail_idx; int inuse; + int num_notify; uint16_t vector; void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq); VirtIODevice *vdev; @@ -139,6 +140,11 @@ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i) return lduw_phys(pa); } +static inline uint16_t vring_last_used_idx(VirtQueue *vq) +{ + return vring_avail_ring(vq, vq->vring.num); +} + static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val) { target_phys_addr_t pa; @@ -234,6 +240,7 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count) wmb(); vring_used_idx_increment(vq, count); vq->inuse -= count; + vq->num_notify += count; } void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, @@ -603,6 +610,14 @@ void virtio_irq(VirtQueue *vq) void virtio_notify(VirtIODevice *vdev, VirtQueue *vq) { + /* Do not notify if guest did not yet see the last update. */ + if ((vdev->guest_features & (1 << VIRTIO_RING_F_PUBLISH_USED)) && + vring_last_used_idx(vq) != + (uint16_t)(vring_used_idx(vq) + vq->num_notify)) + return; + + vq->num_notify = 0; + /* Always notify when queue is empty (when feature acknowledge) */ if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) && (!(vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) || diff --git a/hw/virtio.h b/hw/virtio.h index f885f1b..4bdfded 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -43,6 +43,8 @@ #define VIRTIO_F_NOTIFY_ON_EMPTY 24 /* We support indirect buffer descriptors */ #define VIRTIO_RING_F_INDIRECT_DESC 28 +/* The Guest publishes last-seen used index at the end of the avail ring. */ +#define VIRTIO_RING_F_PUBLISH_USED 29 /* A guest should never accept this. It implies negotiation is broken. */ #define VIRTIO_F_BAD_FEATURE 30 @@ -189,6 +191,8 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev); void virtio_net_exit(VirtIODevice *vdev); #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ + DEFINE_PROP_BIT("publish_used", _state, _field, \ + VIRTIO_RING_F_PUBLISH_USED, true), \ DEFINE_PROP_BIT("indirect_desc", _state, _field, \ VIRTIO_RING_F_INDIRECT_DESC, true)