Move host-side virtio ring functions to file virtio_ring_host.c The functions vring_avail_desc_user(), vring_add_used_user() and vring_next_desc() are moved from vhost.c to the new file virtio_ring_host.c. (The functions are copied as is without any changes) Signed-off-by: Sjur Brændeland <sjur.brandeland@xxxxxxxxxxxxxx> --- drivers/vhost/Kconfig | 2 + drivers/vhost/vhost.c | 92 ----------------------------- drivers/virtio/Kconfig | 3 + drivers/virtio/Makefile | 1 + drivers/virtio/virtio_ring_host.c | 117 +++++++++++++++++++++++++++++++++++++ include/linux/virtio_ring.h | 8 +++ 6 files changed, 131 insertions(+), 92 deletions(-) create mode 100644 drivers/virtio/virtio_ring_host.c diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 202bba6..5bfdaa9 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -1,4 +1,6 @@ config VHOST_NET + select VIRTIO_RING_HOST + select VIRTIO tristate "Host kernel accelerator for virtio net (EXPERIMENTAL)" depends on NET && EVENTFD && (TUN || !TUN) && (MACVTAP || !MACVTAP) && EXPERIMENTAL ---help--- diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5e91048..6634f0a 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1097,27 +1097,6 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, return ret; } -/* Each buffer in the virtqueues is actually a chain of descriptors. This - * function returns the next descriptor in the chain, - * or -1U if we're at the end. */ -unsigned vring_next_desc(struct vring_desc *desc) -{ - unsigned int next; - - /* If this descriptor says it doesn't chain, we're done. */ - if (!(desc->flags & VRING_DESC_F_NEXT)) - return -1U; - - /* Check they're not leading us off end of descriptors. */ - next = desc->next; - /* Make sure compiler knows to grab that: we don't want it changing! */ - /* We will use the result as an index in an array, so most - * architectures only need a compiler barrier here. */ - read_barrier_depends(); - - return next; -} - static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, struct iovec iov[], unsigned int iov_size, unsigned int *out_num, unsigned int *in_num, @@ -1206,51 +1185,6 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, return 0; } -static int vring_avail_desc_user(struct vring_host *vh) -{ - int head; - u16 last_avail_idx; - - /* Check it isn't doing very strange things with descriptor numbers. */ - last_avail_idx = vh->last_avail_idx; - if (unlikely(__get_user(vh->avail_idx, &vh->vr.avail->idx))) { - pr_debug("Failed to access avail idx at %p\n", - &vh->vr.avail->idx); - return -EFAULT; - } - - if (unlikely((u16)(vh->avail_idx - last_avail_idx) > vh->vr.num)) - return -EFAULT; - - /* If there's nothing new since last we looked, return invalid. */ - if (vh->avail_idx == last_avail_idx) - return vh->vr.num; - - /* Only get avail ring entries after they have been exposed by guest. */ - smp_rmb(); - - /* Grab the next descriptor number they're advertising, and increment - * the index we've seen. */ - if (unlikely(__get_user(head, - &vh->vr.avail->ring[last_avail_idx % - vh->vr.num]))) { - pr_debug("Failed to read head: idx %d address %p\n", - last_avail_idx, - &vh->vr.avail->ring[last_avail_idx % - vh->vr.num]); - return -EFAULT; - } - - /* If their number is silly, that's an error. */ - if (unlikely(head >= vh->vr.num)) { - pr_debug("Guest says index %u > %u is available", - head, vh->vr.num); - return -EINVAL; - } - - return head; -} - /* This looks in the virtqueue and for the first available buffer, and converts * it to an iovec for convenient access. Since descriptors consist of some * number of output then some number of input descriptors, it's actually two @@ -1352,32 +1286,6 @@ void vhost_discard_vq_desc(struct vhost_virtqueue *vq, int n) vq->hst.last_avail_idx -= n; } -struct vring_used_elem *vring_add_used_user(struct vring_host *vh, - unsigned int head, int len) -{ - struct vring_used_elem *used; - - /* The virtqueue contains a ring of used buffers. Get a pointer to the - * next entry in that used ring. */ - used = &vh->vr.used->ring[vh->last_used_idx % vh->vr.num]; - if (__put_user(head, &used->id)) { - pr_debug("Failed to write used id"); - return NULL; - } - if (__put_user(len, &used->len)) { - pr_debug("Failed to write used len"); - return NULL; - } - /* Make sure buffer is written before we update index. */ - smp_wmb(); - if (__put_user(vh->last_used_idx + 1, &vh->vr.used->idx)) { - pr_debug("Failed to increment used idx"); - return NULL; - } - vh->last_used_idx++; - return used; -} - /* 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) diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 8d5bddb..4e72892 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -5,6 +5,9 @@ config VIRTIO bus, such as CONFIG_VIRTIO_PCI, CONFIG_VIRTIO_MMIO, CONFIG_LGUEST, CONFIG_RPMSG or CONFIG_S390_GUEST. +config VIRTIO_RING_HOST + tristate + menu "Virtio drivers" config VIRTIO_PCI diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile index 9076635..54831f4 100644 --- a/drivers/virtio/Makefile +++ b/drivers/virtio/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_VIRTIO) += virtio.o virtio_ring.o +obj-$(CONFIG_VIRTIO_RING_HOST) += virtio_ring_host.o obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o diff --git a/drivers/virtio/virtio_ring_host.c b/drivers/virtio/virtio_ring_host.c new file mode 100644 index 0000000..192b838 --- /dev/null +++ b/drivers/virtio/virtio_ring_host.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) ST-Ericsson AB 2012 + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * Copyring + * + * Author: Sjur Brendeland / sjur.brandeland@xxxxxxxxxxxxxx + * Copied from vhost.c, author Michael S. Tsirkin <mst@xxxxxxxxxx> + * + * License terms: GNU General Public License (GPL) version 2. + * + * Inspiration, some code, and most witty comments come from + * Documentation/virtual/lguest/lguest.c, by Rusty Russell + * + * Generic code for virtio server in host kernel. + */ +#include <linux/virtio.h> +#include <linux/virtio_ring.h> +#include <linux/module.h> +#include <linux/uaccess.h> + +MODULE_LICENSE("GPL"); + +struct vring_used_elem *vring_add_used_user(struct vring_host *vh, + unsigned int head, int len) +{ + struct vring_used_elem *used; + + /* The virtqueue contains a ring of used buffers. Get a pointer to the + * next entry in that used ring. */ + used = &vh->vr.used->ring[vh->last_used_idx % vh->vr.num]; + if (__put_user(head, &used->id)) { + pr_debug("Failed to write used id"); + return NULL; + } + if (__put_user(len, &used->len)) { + pr_debug("Failed to write used len"); + return NULL; + } + /* Make sure buffer is written before we update index. */ + smp_wmb(); + if (__put_user(vh->last_used_idx + 1, &vh->vr.used->idx)) { + pr_debug("Failed to increment used idx"); + return NULL; + } + vh->last_used_idx++; + return used; +} +EXPORT_SYMBOL(vring_add_used_user); + +int vring_avail_desc_user(struct vring_host *vh) +{ + int head; + u16 last_avail_idx; + + /* Check it isn't doing very strange things with descriptor numbers. */ + last_avail_idx = vh->last_avail_idx; + if (unlikely(__get_user(vh->avail_idx, &vh->vr.avail->idx))) { + pr_debug("Failed to access avail idx at %p\n", + &vh->vr.avail->idx); + return -EFAULT; + } + + if (unlikely((u16)(vh->avail_idx - last_avail_idx) > vh->vr.num)) + return -EFAULT; + + /* If there's nothing new since last we looked, return invalid. */ + if (vh->avail_idx == last_avail_idx) + return vh->vr.num; + + /* Only get avail ring entries after they have been exposed by guest. */ + smp_rmb(); + + /* Grab the next descriptor number they're advertising, and increment + * the index we've seen. */ + if (unlikely(__get_user(head, + &vh->vr.avail->ring[last_avail_idx % + vh->vr.num]))) { + pr_debug("Failed to read head: idx %d address %p\n", + last_avail_idx, + &vh->vr.avail->ring[last_avail_idx % + vh->vr.num]); + return -EFAULT; + } + + /* If their number is silly, that's an error. */ + if (unlikely(head >= vh->vr.num)) { + pr_debug("Guest says index %u > %u is available", + head, vh->vr.num); + return -EINVAL; + } + + return head; +} +EXPORT_SYMBOL(vring_avail_desc_user); + +/* Each buffer in the virtqueues is actually a chain of descriptors. This + * function returns the next descriptor in the chain, + * or -1U if we're at the end. */ +unsigned vring_next_desc(struct vring_desc *desc) +{ + unsigned int next; + + /* If this descriptor says it doesn't chain, we're done. */ + if (!(desc->flags & VRING_DESC_F_NEXT)) + return -1U; + + /* Check they're not leading us off end of descriptors. */ + next = desc->next; + /* Make sure compiler knows to grab that: we don't want it changing! */ + /* We will use the result as an index in an array, so most + * architectures only need a compiler barrier here. */ + read_barrier_depends(); + + return next; +} +EXPORT_SYMBOL(vring_next_desc); diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index 7917dac..6c9b871 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -34,4 +34,12 @@ void vring_del_virtqueue(struct virtqueue *vq); void vring_transport_features(struct virtio_device *vdev); irqreturn_t vring_interrupt(int irq, void *_vq); + +unsigned vring_next_desc(struct vring_desc *desc); + +int vring_avail_desc_user(struct vring_host *vh); + +struct vring_used_elem *vring_add_used_user(struct vring_host *vh, + unsigned int head, int len); + #endif /* _LINUX_VIRTIO_RING_H */ -- 1.7.5.4 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization