···1010#include <linux/eventfd.h>1111#include <linux/vhost.h>1212#include <linux/virtio_net.h>1313-#include <linux/mmu_context.h>1413#include <linux/miscdevice.h>1514#include <linux/module.h>1615#include <linux/mutex.h>···142143 return;143144 }144145145145- use_mm(net->dev.mm);146146 mutex_lock(&vq->mutex);147147 vhost_disable_notify(vq);148148···206208 }207209208210 mutex_unlock(&vq->mutex);209209- unuse_mm(net->dev.mm);210211}211212212213static int peek_head_len(struct sock *sk)···310313 if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))311314 return;312315313313- use_mm(net->dev.mm);314316 mutex_lock(&vq->mutex);315317 vhost_disable_notify(vq);316318 hdr_size = vq->vhost_hlen;···388392 }389393390394 mutex_unlock(&vq->mutex);391391- unuse_mm(net->dev.mm);392395}393396394397/* Expects to be always run from workqueue - which acts as···419424 if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))420425 return;421426422422- use_mm(net->dev.mm);423427 mutex_lock(&vq->mutex);424428 vhost_disable_notify(vq);425429 vhost_hlen = vq->vhost_hlen;···453459 move_iovec_hdr(vq->iov, vq->hdr, vhost_hlen, in);454460 else455461 /* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF:456456- * needed because sendmsg can modify msg_iov. */462462+ * needed because recvmsg can modify msg_iov. */457463 copy_iovec_hdr(vq->iov, vq->hdr, sock_hlen, in);458464 msg.msg_iovlen = in;459465 err = sock->ops->recvmsg(NULL, sock, &msg,···495501 }496502497503 mutex_unlock(&vq->mutex);498498- unuse_mm(net->dev.mm);499504}500505501506static void handle_rx(struct vhost_net *net)
+320
drivers/vhost/test.c
···11+/* Copyright (C) 2009 Red Hat, Inc.22+ * Author: Michael S. Tsirkin <mst@redhat.com>33+ *44+ * This work is licensed under the terms of the GNU GPL, version 2.55+ *66+ * test virtio server in host kernel.77+ */88+99+#include <linux/compat.h>1010+#include <linux/eventfd.h>1111+#include <linux/vhost.h>1212+#include <linux/miscdevice.h>1313+#include <linux/module.h>1414+#include <linux/mutex.h>1515+#include <linux/workqueue.h>1616+#include <linux/rcupdate.h>1717+#include <linux/file.h>1818+#include <linux/slab.h>1919+2020+#include "test.h"2121+#include "vhost.c"2222+2323+/* Max number of bytes transferred before requeueing the job.2424+ * Using this limit prevents one virtqueue from starving others. */2525+#define VHOST_TEST_WEIGHT 0x800002626+2727+enum {2828+ VHOST_TEST_VQ = 0,2929+ VHOST_TEST_VQ_MAX = 1,3030+};3131+3232+struct vhost_test {3333+ struct vhost_dev dev;3434+ struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];3535+};3636+3737+/* Expects to be always run from workqueue - which acts as3838+ * read-size critical section for our kind of RCU. */3939+static void handle_vq(struct vhost_test *n)4040+{4141+ struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];4242+ unsigned out, in;4343+ int head;4444+ size_t len, total_len = 0;4545+ void *private;4646+4747+ private = rcu_dereference_check(vq->private_data, 1);4848+ if (!private)4949+ return;5050+5151+ mutex_lock(&vq->mutex);5252+ vhost_disable_notify(vq);5353+5454+ for (;;) {5555+ head = vhost_get_vq_desc(&n->dev, vq, vq->iov,5656+ ARRAY_SIZE(vq->iov),5757+ &out, &in,5858+ NULL, NULL);5959+ /* On error, stop handling until the next kick. */6060+ if (unlikely(head < 0))6161+ break;6262+ /* Nothing new? Wait for eventfd to tell us they refilled. */6363+ if (head == vq->num) {6464+ if (unlikely(vhost_enable_notify(vq))) {6565+ vhost_disable_notify(vq);6666+ continue;6767+ }6868+ break;6969+ }7070+ if (in) {7171+ vq_err(vq, "Unexpected descriptor format for TX: "7272+ "out %d, int %d\n", out, in);7373+ break;7474+ }7575+ len = iov_length(vq->iov, out);7676+ /* Sanity check */7777+ if (!len) {7878+ vq_err(vq, "Unexpected 0 len for TX\n");7979+ break;8080+ }8181+ vhost_add_used_and_signal(&n->dev, vq, head, 0);8282+ total_len += len;8383+ if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {8484+ vhost_poll_queue(&vq->poll);8585+ break;8686+ }8787+ }8888+8989+ mutex_unlock(&vq->mutex);9090+}9191+9292+static void handle_vq_kick(struct vhost_work *work)9393+{9494+ struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,9595+ poll.work);9696+ struct vhost_test *n = container_of(vq->dev, struct vhost_test, dev);9797+9898+ handle_vq(n);9999+}100100+101101+static int vhost_test_open(struct inode *inode, struct file *f)102102+{103103+ struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);104104+ struct vhost_dev *dev;105105+ int r;106106+107107+ if (!n)108108+ return -ENOMEM;109109+110110+ dev = &n->dev;111111+ n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;112112+ r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX);113113+ if (r < 0) {114114+ kfree(n);115115+ return r;116116+ }117117+118118+ f->private_data = n;119119+120120+ return 0;121121+}122122+123123+static void *vhost_test_stop_vq(struct vhost_test *n,124124+ struct vhost_virtqueue *vq)125125+{126126+ void *private;127127+128128+ mutex_lock(&vq->mutex);129129+ private = rcu_dereference_protected(vq->private_data,130130+ lockdep_is_held(&vq->mutex));131131+ rcu_assign_pointer(vq->private_data, NULL);132132+ mutex_unlock(&vq->mutex);133133+ return private;134134+}135135+136136+static void vhost_test_stop(struct vhost_test *n, void **privatep)137137+{138138+ *privatep = vhost_test_stop_vq(n, n->vqs + VHOST_TEST_VQ);139139+}140140+141141+static void vhost_test_flush_vq(struct vhost_test *n, int index)142142+{143143+ vhost_poll_flush(&n->dev.vqs[index].poll);144144+}145145+146146+static void vhost_test_flush(struct vhost_test *n)147147+{148148+ vhost_test_flush_vq(n, VHOST_TEST_VQ);149149+}150150+151151+static int vhost_test_release(struct inode *inode, struct file *f)152152+{153153+ struct vhost_test *n = f->private_data;154154+ void *private;155155+156156+ vhost_test_stop(n, &private);157157+ vhost_test_flush(n);158158+ vhost_dev_cleanup(&n->dev);159159+ /* We do an extra flush before freeing memory,160160+ * since jobs can re-queue themselves. */161161+ vhost_test_flush(n);162162+ kfree(n);163163+ return 0;164164+}165165+166166+static long vhost_test_run(struct vhost_test *n, int test)167167+{168168+ void *priv, *oldpriv;169169+ struct vhost_virtqueue *vq;170170+ int r, index;171171+172172+ if (test < 0 || test > 1)173173+ return -EINVAL;174174+175175+ mutex_lock(&n->dev.mutex);176176+ r = vhost_dev_check_owner(&n->dev);177177+ if (r)178178+ goto err;179179+180180+ for (index = 0; index < n->dev.nvqs; ++index) {181181+ /* Verify that ring has been setup correctly. */182182+ if (!vhost_vq_access_ok(&n->vqs[index])) {183183+ r = -EFAULT;184184+ goto err;185185+ }186186+ }187187+188188+ for (index = 0; index < n->dev.nvqs; ++index) {189189+ vq = n->vqs + index;190190+ mutex_lock(&vq->mutex);191191+ priv = test ? n : NULL;192192+193193+ /* start polling new socket */194194+ oldpriv = rcu_dereference_protected(vq->private_data,195195+ lockdep_is_held(&vq->mutex));196196+ rcu_assign_pointer(vq->private_data, priv);197197+198198+ mutex_unlock(&vq->mutex);199199+200200+ if (oldpriv) {201201+ vhost_test_flush_vq(n, index);202202+ }203203+ }204204+205205+ mutex_unlock(&n->dev.mutex);206206+ return 0;207207+208208+err:209209+ mutex_unlock(&n->dev.mutex);210210+ return r;211211+}212212+213213+static long vhost_test_reset_owner(struct vhost_test *n)214214+{215215+ void *priv = NULL;216216+ long err;217217+ mutex_lock(&n->dev.mutex);218218+ err = vhost_dev_check_owner(&n->dev);219219+ if (err)220220+ goto done;221221+ vhost_test_stop(n, &priv);222222+ vhost_test_flush(n);223223+ err = vhost_dev_reset_owner(&n->dev);224224+done:225225+ mutex_unlock(&n->dev.mutex);226226+ return err;227227+}228228+229229+static int vhost_test_set_features(struct vhost_test *n, u64 features)230230+{231231+ mutex_lock(&n->dev.mutex);232232+ if ((features & (1 << VHOST_F_LOG_ALL)) &&233233+ !vhost_log_access_ok(&n->dev)) {234234+ mutex_unlock(&n->dev.mutex);235235+ return -EFAULT;236236+ }237237+ n->dev.acked_features = features;238238+ smp_wmb();239239+ vhost_test_flush(n);240240+ mutex_unlock(&n->dev.mutex);241241+ return 0;242242+}243243+244244+static long vhost_test_ioctl(struct file *f, unsigned int ioctl,245245+ unsigned long arg)246246+{247247+ struct vhost_test *n = f->private_data;248248+ void __user *argp = (void __user *)arg;249249+ u64 __user *featurep = argp;250250+ int test;251251+ u64 features;252252+ int r;253253+ switch (ioctl) {254254+ case VHOST_TEST_RUN:255255+ if (copy_from_user(&test, argp, sizeof test))256256+ return -EFAULT;257257+ return vhost_test_run(n, test);258258+ case VHOST_GET_FEATURES:259259+ features = VHOST_FEATURES;260260+ if (copy_to_user(featurep, &features, sizeof features))261261+ return -EFAULT;262262+ return 0;263263+ case VHOST_SET_FEATURES:264264+ if (copy_from_user(&features, featurep, sizeof features))265265+ return -EFAULT;266266+ if (features & ~VHOST_FEATURES)267267+ return -EOPNOTSUPP;268268+ return vhost_test_set_features(n, features);269269+ case VHOST_RESET_OWNER:270270+ return vhost_test_reset_owner(n);271271+ default:272272+ mutex_lock(&n->dev.mutex);273273+ r = vhost_dev_ioctl(&n->dev, ioctl, arg);274274+ vhost_test_flush(n);275275+ mutex_unlock(&n->dev.mutex);276276+ return r;277277+ }278278+}279279+280280+#ifdef CONFIG_COMPAT281281+static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl,282282+ unsigned long arg)283283+{284284+ return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));285285+}286286+#endif287287+288288+static const struct file_operations vhost_test_fops = {289289+ .owner = THIS_MODULE,290290+ .release = vhost_test_release,291291+ .unlocked_ioctl = vhost_test_ioctl,292292+#ifdef CONFIG_COMPAT293293+ .compat_ioctl = vhost_test_compat_ioctl,294294+#endif295295+ .open = vhost_test_open,296296+ .llseek = noop_llseek,297297+};298298+299299+static struct miscdevice vhost_test_misc = {300300+ MISC_DYNAMIC_MINOR,301301+ "vhost-test",302302+ &vhost_test_fops,303303+};304304+305305+static int vhost_test_init(void)306306+{307307+ return misc_register(&vhost_test_misc);308308+}309309+module_init(vhost_test_init);310310+311311+static void vhost_test_exit(void)312312+{313313+ misc_deregister(&vhost_test_misc);314314+}315315+module_exit(vhost_test_exit);316316+317317+MODULE_VERSION("0.0.1");318318+MODULE_LICENSE("GPL v2");319319+MODULE_AUTHOR("Michael S. Tsirkin");320320+MODULE_DESCRIPTION("Host kernel side for virtio simulator");
+7
drivers/vhost/test.h
···11+#ifndef LINUX_VHOST_TEST_H22+#define LINUX_VHOST_TEST_H33+44+/* Start a given test on the virtio null device. 0 stops all tests. */55+#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)66+77+#endif
+23-21
drivers/vhost/vhost.c
···1515#include <linux/vhost.h>1616#include <linux/virtio_net.h>1717#include <linux/mm.h>1818+#include <linux/mmu_context.h>1819#include <linux/miscdevice.h>1920#include <linux/mutex.h>2021#include <linux/rcupdate.h>···2928#include <linux/net.h>3029#include <linux/if_packet.h>3130#include <linux/if_arp.h>3232-3333-#include <net/sock.h>34313532#include "vhost.h"3633···156157 vq->avail_idx = 0;157158 vq->last_used_idx = 0;158159 vq->used_flags = 0;159159- vq->used_flags = 0;160160 vq->log_used = false;161161 vq->log_addr = -1ull;162162 vq->vhost_hlen = 0;···176178 struct vhost_work *work = NULL;177179 unsigned uninitialized_var(seq);178180181181+ use_mm(dev->mm);182182+179183 for (;;) {180184 /* mb paired w/ kthread_stop */181185 set_current_state(TASK_INTERRUPTIBLE);···192192 if (kthread_should_stop()) {193193 spin_unlock_irq(&dev->work_lock);194194 __set_current_state(TASK_RUNNING);195195- return 0;195195+ break;196196 }197197 if (!list_empty(&dev->work_list)) {198198 work = list_first_entry(&dev->work_list,···210210 schedule();211211212212 }213213+ unuse_mm(dev->mm);214214+ return 0;213215}214216215217/* Helper to allocate iovec buffers for all vqs. */···404402 kfree(rcu_dereference_protected(dev->memory,405403 lockdep_is_held(&dev->mutex)));406404 RCU_INIT_POINTER(dev->memory, NULL);407407- if (dev->mm)408408- mmput(dev->mm);409409- dev->mm = NULL;410410-411405 WARN_ON(!list_empty(&dev->work_list));412406 if (dev->worker) {413407 kthread_stop(dev->worker);414408 dev->worker = NULL;415409 }410410+ if (dev->mm)411411+ mmput(dev->mm);412412+ dev->mm = NULL;416413}417414418415static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz)···882881static int log_write(void __user *log_base,883882 u64 write_address, u64 write_length)884883{884884+ u64 write_page = write_address / VHOST_PAGE_SIZE;885885 int r;886886 if (!write_length)887887 return 0;888888- write_address /= VHOST_PAGE_SIZE;888888+ write_length += write_address % VHOST_PAGE_SIZE;889889 for (;;) {890890 u64 base = (u64)(unsigned long)log_base;891891- u64 log = base + write_address / 8;892892- int bit = write_address % 8;891891+ u64 log = base + write_page / 8;892892+ int bit = write_page % 8;893893 if ((u64)(unsigned long)log != log)894894 return -EFAULT;895895 r = set_bit_to_user(bit, (void __user *)(unsigned long)log);···899897 if (write_length <= VHOST_PAGE_SIZE)900898 break;901899 write_length -= VHOST_PAGE_SIZE;902902- write_address += VHOST_PAGE_SIZE;900900+ write_page += 1;903901 }904902 return r;905903}···1094109210951093 /* Check it isn't doing very strange things with descriptor numbers. */10961094 last_avail_idx = vq->last_avail_idx;10971097- if (unlikely(get_user(vq->avail_idx, &vq->avail->idx))) {10951095+ if (unlikely(__get_user(vq->avail_idx, &vq->avail->idx))) {10981096 vq_err(vq, "Failed to access avail idx at %p\n",10991097 &vq->avail->idx);11001098 return -EFAULT;···1115111311161114 /* Grab the next descriptor number they're advertising, and increment11171115 * the index we've seen. */11181118- if (unlikely(get_user(head,11191119- &vq->avail->ring[last_avail_idx % vq->num]))) {11161116+ if (unlikely(__get_user(head,11171117+ &vq->avail->ring[last_avail_idx % vq->num]))) {11201118 vq_err(vq, "Failed to read head: idx %d address %p\n",11211119 last_avail_idx,11221120 &vq->avail->ring[last_avail_idx % vq->num]);···12151213 /* The virtqueue contains a ring of used buffers. Get a pointer to the12161214 * next entry in that used ring. */12171215 used = &vq->used->ring[vq->last_used_idx % vq->num];12181218- if (put_user(head, &used->id)) {12161216+ if (__put_user(head, &used->id)) {12191217 vq_err(vq, "Failed to write used id");12201218 return -EFAULT;12211219 }12221222- if (put_user(len, &used->len)) {12201220+ if (__put_user(len, &used->len)) {12231221 vq_err(vq, "Failed to write used len");12241222 return -EFAULT;12251223 }12261224 /* Make sure buffer is written before we update index. */12271225 smp_wmb();12281228- if (put_user(vq->last_used_idx + 1, &vq->used->idx)) {12261226+ if (__put_user(vq->last_used_idx + 1, &vq->used->idx)) {12291227 vq_err(vq, "Failed to increment used idx");12301228 return -EFAULT;12311229 }···1257125512581256 start = vq->last_used_idx % vq->num;12591257 used = vq->used->ring + start;12601260- if (copy_to_user(used, heads, count * sizeof *used)) {12581258+ if (__copy_to_user(used, heads, count * sizeof *used)) {12611259 vq_err(vq, "Failed to write used");12621260 return -EFAULT;12631261 }···13181316 * interrupts. */13191317 smp_mb();1320131813211321- if (get_user(flags, &vq->avail->flags)) {13191319+ if (__get_user(flags, &vq->avail->flags)) {13221320 vq_err(vq, "Failed to get flags");13231321 return;13241322 }···13691367 /* They could have slipped one in as we were doing that: make13701368 * sure it's written, then check again. */13711369 smp_mb();13721372- r = get_user(avail_idx, &vq->avail->idx);13701370+ r = __get_user(avail_idx, &vq->avail->idx);13731371 if (r) {13741372 vq_err(vq, "Failed to check avail idx at %p: %d\n",13751373 &vq->avail->idx, r);
+1-1
drivers/vhost/vhost.h
···102102 * flush the vhost_work instead of synchronize_rcu. Therefore readers do103103 * not need to call rcu_read_lock/rcu_read_unlock: the beginning of104104 * vhost_work execution acts instead of rcu_read_lock() and the end of105105- * vhost_work execution acts instead of rcu_read_lock().105105+ * vhost_work execution acts instead of rcu_read_unlock().106106 * Writers use virtqueue mutex. */107107 void __rcu *private_data;108108 /* Log write descriptors */
+12
tools/virtio/Makefile
···11+all: test mod22+test: virtio_test33+virtio_test: virtio_ring.o virtio_test.o44+CFLAGS += -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -MMD55+vpath %.c ../../drivers/virtio66+mod:77+ ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test88+.PHONY: all test mod clean99+clean:1010+ ${RM} *.o vhost_test/*.o vhost_test/.*.cmd \1111+ vhost_test/Module.symvers vhost_test/modules.order *.d1212+-include *.d