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: 97287 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o468ULJo009736 for ; Thu, 6 May 2010 08:30:39 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755279Ab0EFIaT (ORCPT ); Thu, 6 May 2010 04:30:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49678 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751465Ab0EFIaR (ORCPT ); Thu, 6 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 Subject: [PATCH RFC] qemu/virtio: use last used index published by guest 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 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 06 May 2010 08:30:39 +0000 (UTC) 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)