From patchwork Tue May 18 01:19:31 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: 100288 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 o4I1OOmx005349 for ; Tue, 18 May 2010 01:24:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755778Ab0ERBX6 (ORCPT ); Mon, 17 May 2010 21:23:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43241 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753913Ab0ERBX5 (ORCPT ); Mon, 17 May 2010 21:23:57 -0400 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o4I1NTaQ030840 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 17 May 2010 21:23:29 -0400 Received: from redhat.com (vpn2-11-106.ams2.redhat.com [10.36.11.106]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id o4I1NPeq009038; Mon, 17 May 2010 21:23:26 -0400 Date: Tue, 18 May 2010 04:19:31 +0300 From: "Michael S. Tsirkin" To: davem@davemloft.net, Juan Quintela , Rusty Russell , "Paul E. McKenney" , Arnd Bergmann , kvm@vger.kernel.org, virtualization@lists.osdl.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, alex.williamson@redhat.com, amit.shah@redhat.com Subject: [PATCH] vhost-net: utilize PUBLISH_USED_IDX feature Message-ID: <20100518011931.GA21918@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.17 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]); Tue, 18 May 2010 01:24:25 +0000 (UTC) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 750effe..2a66cf3 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -278,14 +278,15 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem, return 1; } -static int vq_access_ok(unsigned int num, +static int vq_access_ok(struct vhost_dev *d, unsigned int num, struct vring_desc __user *desc, struct vring_avail __user *avail, struct vring_used __user *used) { + size_t s = vhost_has_feature(d, VIRTIO_RING_F_PUBLISH_USED) ? 2 : 0; return access_ok(VERIFY_READ, desc, num * sizeof *desc) && access_ok(VERIFY_READ, avail, - sizeof *avail + num * sizeof *avail->ring) && + sizeof *avail + num * sizeof *avail->ring + s) && access_ok(VERIFY_WRITE, used, sizeof *used + num * sizeof *used->ring); } @@ -312,7 +313,7 @@ static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base) /* Caller should have vq mutex and device mutex */ int vhost_vq_access_ok(struct vhost_virtqueue *vq) { - return vq_access_ok(vq->num, vq->desc, vq->avail, vq->used) && + return vq_access_ok(vq->dev, vq->num, vq->desc, vq->avail, vq->used,) && vq_log_access_ok(vq, vq->log_base); } @@ -448,7 +449,7 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) * If it is not, we don't as size might not have been setup. * We will verify when backend is configured. */ if (vq->private_data) { - if (!vq_access_ok(vq->num, + if (!vq_access_ok(d, vq->num, (void __user *)(unsigned long)a.desc_user_addr, (void __user *)(unsigned long)a.avail_user_addr, (void __user *)(unsigned long)a.used_user_addr)) { @@ -473,6 +474,7 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG)); vq->desc = (void __user *)(unsigned long)a.desc_user_addr; vq->avail = (void __user *)(unsigned long)a.avail_user_addr; + vq->last_used = (u16 __user *)&vq->avail->ring[vq->num]; vq->log_addr = a.log_guest_addr; vq->used = (void __user *)(unsigned long)a.used_user_addr; break; @@ -993,7 +995,8 @@ void vhost_discard_vq_desc(struct vhost_virtqueue *vq) /* After we've used one of their buffers, we tell them about it. We'll then * want to notify the guest, using eventfd. */ -int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) +static int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, + int len) { struct vring_used_elem __user *used; @@ -1034,9 +1037,10 @@ int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) } /* This actually signals the guest, using eventfd. */ -void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) +static void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) { __u16 flags; + __u16 used; /* Flush out used index updates. This is paired * with the barrier that the Guest executes when enabling * interrupts. */ @@ -1053,6 +1057,17 @@ void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) !vhost_has_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY))) return; + if (vhost_has_feature(d, VIRTIO_RING_F_PUBLISH_USED)) { + __u16 used; + if (get_user(used, vq->last_used)) { + vq_err(vq, "Failed to get last used idx"); + return; + } + + if (used != (u16)(vq->last_used_idx - 1)) + return; + } + /* Signal the Guest tell them we used something up. */ if (vq->call_ctx) eventfd_signal(vq->call_ctx, 1); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 44591ba..00e9784 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -52,6 +52,7 @@ struct vhost_virtqueue { unsigned int num; struct vring_desc __user *desc; struct vring_avail __user *avail; + u16 __user *last_used; struct vring_used __user *used; struct file *kick; struct file *call; @@ -148,6 +149,7 @@ void vhost_cleanup(void); enum { VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_RING_F_INDIRECT_DESC) | + (1 << VIRTIO_RING_F_PUBLISH_USED) | (1 << VHOST_F_LOG_ALL) | (1 << VHOST_NET_F_VIRTIO_NET_HDR), };