mm: export use_mm/unuse_mm to modules
Subsystems (11)
A message that is not in the archive (sent off-list or not yet received): [email protected]
Michael S. Tsirkin
maintainerPATCH v4 1/2 mm: export use_mm/unuse_mm to modules
vhost net module wants to do copy to/from user from a kernel thread, which needs use_mm (like what fs/aio has). Move that into mm/ and export to modules.
--- fs/aio.c | 47 +---------------------------------- include/linux/mmu_context.h | 9 ++++++ mm/Makefile | 2 +- mm/mmu_context.c | 58 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 47 deletions(-) create mode 100644 include/linux/mmu_context.h create mode 100644 mm/mmu_context.c
fs/aio.c +1 -46
@@ -24,6 +24,7 @@#include <linux/file.h> #include <linux/mm.h> #include <linux/mman.h> +#include <linux/mmu_context.h> #include <linux/slab.h> #include <linux/timer.h> #include <linux/aio.h>
@@ -34,7 +35,6 @@#include <asm/kmap_types.h> #include <asm/uaccess.h> -#include <asm/mmu_context.h> #if DEBUG >1 #define dprintk printk
@@ -595,51 +595,6 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) }/* -* use_mm -* Makes the calling kernel thread take on the specified -* mm context. -* Called by the retry thread execute retries within the -* iocb issuer's mm context, so that copy_from/to_user -* operations work seamlessly for aio. -* (Note: this routine is intended to be called only -* from a kernel thread context) -*/ -static void use_mm (struct mm_struct *mm) -{ -struct mm_struct *active_mm; -struct task_struct *tsk = current; - -task_lock (tsk); - active_mm = tsk->active_mm; -atomic_inc (&mm->mm_count); - tsk->mm = mm; - tsk->active_mm = mm; -switch_mm (active_mm, mm, tsk); -task_unlock (tsk); - -mmdrop (active_mm); -} - -/* -* unuse_mm -* Reverses the effect of use_mm, i.e. releases the -* specified mm context which was earlier taken on -* by the calling kernel thread -* (Note: this routine is intended to be called only -* from a kernel thread context) -*/ -static void unuse_mm (struct mm_struct *mm) -{ -struct task_struct *tsk = current; - -task_lock (tsk); - tsk->mm =NULL ; -/* active_mm is still 'mm' */ -enter_lazy_tlb (mm, tsk); -task_unlock (tsk); -} - -/* * Queue up a kiocb to be retried. Assumes that the kiocb * has already been marked as kicked, and places it on * the retry run list for the corresponding ioctx, if it
include/linux/mmu_context.h new file +9 -0
@@ -0,0 +1,9 @@ +#ifndef _LINUX_MMU_CONTEXT_H +#define _LINUX_MMU_CONTEXT_H + +struct mm_struct ; + +void use_mm (struct mm_struct *mm); +void unuse_mm (struct mm_struct *mm); + +#endif
mm/Makefile +1 -1
@@ -11,7 +11,7 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ maccess.o page_alloc.o page-writeback.o pdflush.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ - page_isolation.o mm_init.o $(mmu-y) + page_isolation.o mm_init.o mmu_context.o $(mmu-y) obj-y += init-mm.o obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o
mm/mmu_context.c new file +58 -0
58 lines not on this page · raw message
Signature · 7 lines
1.6.2.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michael S. Tsirkin
maintainerPATCH v4 1/2 mm: export use_mm/unuse_mm to modules
In reply to a message not in the archivevhost net module wants to do copy to/from user from a kernel thread, which needs use_mm (like what fs/aio has). Move that into mm/ and export to modules.
--- fs/aio.c | 47 +---------------------------------- include/linux/mmu_context.h | 9 ++++++ mm/Makefile | 2 +- mm/mmu_context.c | 58 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 47 deletions(-) create mode 100644 include/linux/mmu_context.h create mode 100644 mm/mmu_context.c
fs/aio.c +1 -46
@@ -24,6 +24,7 @@#include <linux/file.h> #include <linux/mm.h> #include <linux/mman.h> +#include <linux/mmu_context.h> #include <linux/slab.h> #include <linux/timer.h> #include <linux/aio.h>
@@ -34,7 +35,6 @@#include <asm/kmap_types.h> #include <asm/uaccess.h> -#include <asm/mmu_context.h> #if DEBUG >1 #define dprintk printk
@@ -595,51 +595,6 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) }/* -* use_mm -* Makes the calling kernel thread take on the specified -* mm context. -* Called by the retry thread execute retries within the -* iocb issuer's mm context, so that copy_from/to_user -* operations work seamlessly for aio. -* (Note: this routine is intended to be called only -* from a kernel thread context) -*/ -static void use_mm (struct mm_struct *mm) -{ -struct mm_struct *active_mm; -struct task_struct *tsk = current; - -task_lock (tsk); - active_mm = tsk->active_mm; -atomic_inc (&mm->mm_count); - tsk->mm = mm; - tsk->active_mm = mm; -switch_mm (active_mm, mm, tsk); -task_unlock (tsk); - -mmdrop (active_mm); -} - -/* -* unuse_mm -* Reverses the effect of use_mm, i.e. releases the -* specified mm context which was earlier taken on -* by the calling kernel thread -* (Note: this routine is intended to be called only -* from a kernel thread context) -*/ -static void unuse_mm (struct mm_struct *mm) -{ -struct task_struct *tsk = current; - -task_lock (tsk); - tsk->mm =NULL ; -/* active_mm is still 'mm' */ -enter_lazy_tlb (mm, tsk); -task_unlock (tsk); -} - -/* * Queue up a kiocb to be retried. Assumes that the kiocb * has already been marked as kicked, and places it on * the retry run list for the corresponding ioctx, if it
include/linux/mmu_context.h new file +9 -0
@@ -0,0 +1,9 @@ +#ifndef _LINUX_MMU_CONTEXT_H +#define _LINUX_MMU_CONTEXT_H + +struct mm_struct ; + +void use_mm (struct mm_struct *mm); +void unuse_mm (struct mm_struct *mm); + +#endif
mm/Makefile +1 -1
@@ -11,7 +11,7 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ maccess.o page_alloc.o page-writeback.o pdflush.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ - page_isolation.o mm_init.o $(mmu-y) + page_isolation.o mm_init.o mmu_context.o $(mmu-y) obj-y += init-mm.o obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o
mm/mmu_context.c new file +58 -0
58 lines not on this page · raw message
Signature · 1 line
1.6.2.5
Michael S. Tsirkin
maintainerPATCH v4 2/2 vhost_net: a kernel-level virtio server
In reply to a message not in the archiveWhat it is: vhost net is a character device that can be used to reduce the number of system calls involved in virtio networking. Existing virtio net code is used in the guest without modification.
There's similarity with vringfd, with some differences and reduced scope
- uses eventfd for signalling
- structures can be moved around in memory at any time (good for migration)
- support memory table and not just an offset (needed for kvm)
common virtio related code has been put in a separate file vhost.c and can be made into a separate module if/when more backends appear. I used Rusty's lguest.c as the source for developing this part : this supplied me with witty comments I wouldn't be able to write myself.
What it is not: vhost net is not a bus, and not a generic new system call. No assumptions are made on how guest performs hypercalls. Userspace hypervisors are supported as well as kvm.
How it works: Basically, we connect virtio frontend (configured by userspace) to a backend. The backend could be a network device, or a tun-like device. In this version I only support raw socket as a backend, which can be bound to e.g. SR IOV, or to macvlan device. Backend is also configured by userspace, including vlan/mac etc.
Status:
This works for me, and I haven't see any crashes.
I have not run any benchmarks yet, compared to userspace, I expect to see improved latency (as I save up to 4 system calls per packet) but not bandwidth/CPU (as TSO and interrupt mitigation are not supported).
Features that I plan to look at in the future:
- TSO
- interrupt mitigation
- zero copy
--- MAINTAINERS | 10 + arch/x86/kvm/Kconfig | 1 + drivers/Makefile | 1 + drivers/vhost/Kconfig | 11 + drivers/vhost/Makefile | 2 + drivers/vhost/net.c | 429 ++++++++++++++++++++++++++++ drivers/vhost/vhost.c | 664 ++++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 108 +++++++ include/linux/Kbuild | 1 + include/linux/miscdevice.h | 1 + include/linux/vhost.h | 100 +++++++ 11 files changed, 1328 insertions(+), 0 deletions(-) create mode 100644 drivers/vhost/Kconfig create mode 100644 drivers/vhost/Makefile create mode 100644 drivers/vhost/net.c create mode 100644 drivers/vhost/vhost.c create mode 100644 drivers/vhost/vhost.h create mode 100644 include/linux/vhost.h
MAINTAINERS +10 -0
@@ -5431,6 +5431,16 @@ S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ +VIRTIO HOST (VHOST) +P: Michael S. Tsirkin +M: [email protected] +L: [email protected] +L: [email protected] +L: [email protected] +S: Maintained +F: drivers/vhost/ +F: include/linux/vhost.h + VIA RHINE NETWORK DRIVER M: Roger Luethi <[email protected]> S: Maintained
arch/x86/kvm/Kconfig +1 -0
@@ -64,6 +64,7 @@ config KVM_AMD # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. +source drivers/vhost/Kconfig source drivers/lguest/Kconfig source drivers/virtio/Kconfig
drivers/Makefile +1 -0
@@ -105,6 +105,7 @@ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ obj-$(CONFIG_SSB) += ssb/ +obj-$(CONFIG_VHOST_NET) += vhost/ obj-$(CONFIG_VIRTIO) += virtio/ obj-$(CONFIG_VLYNQ) += vlynq/ obj-$(CONFIG_STAGING) += staging/
drivers/vhost/Kconfig new file +11 -0
@@ -0,0 +1,11 @@ +config VHOST_NET + tristate "Host kernel accelerator for virtio net" + depends on NET && EVENTFD + ---help--- + This kernel module can be loaded in host kernel to accelerate + guest networking with virtio_net. Not to be confused with virtio_net + module itself which needs to be loaded in guest kernel. + + To compile this driver as a module, choose M here: the module will + be called vhost_net. +
drivers/vhost/Makefile new file +2 -0
@@ -0,0 +1,2 @@ +obj-$(CONFIG_VHOST_NET) += vhost_net.o +vhost_net-y := vhost.o net.o
drivers/vhost/net.c new file +429 -0
429 lines not on this page · raw message
drivers/vhost/vhost.c new file +664 -0
664 lines not on this page · raw message
drivers/vhost/vhost.h new file +108 -0
108 lines not on this page · raw message
include/linux/Kbuild +1 -0
@@ -360,6 +360,7 @@ unifdef-y += uio.h unifdef-y += unistd.h unifdef-y += usbdevice_fs.h unifdef-y += utsname.h +unifdef-y += vhost.h unifdef-y += videodev2.h unifdef-y += videodev.h unifdef-y += virtio_config.h
include/linux/miscdevice.h +1 -0
@@ -30,6 +30,7 @@#define HPET_MINOR 228#define FUSE_MINOR 229#define KVM_MINOR 232 +#define VHOST_NET_MINOR 233#define MISC_DYNAMIC_MINOR 255struct device ;
include/linux/vhost.h new file +100 -0
100 lines not on this page · raw message
Signature · 7 lines
1.6.2.5 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 3 lines · Michael S. Tsirkin
What it is: vhost net is a character device that can be used to reduce the number of system calls involved in virtio networking. Existing virtio net code is used in the guest without modification.
...
drivers/vhost/Kconfig line 10
Quoted 10 lines
drivers/vhost/Kconfig new file +10
-0+config VHOST_NET + tristate "Host kernel accelerator for virtio net" + depends on NET && EVENTFD + ---help--- + This kernel module can be loaded in host kernel to accelerate + guest networking with virtio_net. Not to be confused with virtio_net + module itself which needs to be loaded in guest kernel. + + To compile this driver as a module, choose M here: the module will + be called vhost_net.
Just want to note that the patch explanation and the Kconfig help text are exceptional examples of reader-oriented text. Nice!
drivers/vhost/net.c line 87
Quoted 7 lines
drivers/vhost/net.c new file +7
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for TX: " +"%ld expected %zd\n" , vq->iov->iov_len, +sizeof (struct virtio_net_hdr )); +break ; + }
OK, this check, which is in the qemu version, is *wrong*. There should be no assumption on sg boundaries. For example, the guest should be able to put the virtio_net_hdr in the front of the skbuf data if there is room.
You should try to explicitly "consume" sizeof(struct virtio_net_hdr) of the iov, and if fail, do this message. You can skip the out <= 1 test then, too.
Anyway, I really prefer vq->iov[0]. to vq->iov-> here.
drivers/vhost/net.c line 152
Quoted 6 lines
drivers/vhost/net.c new file +6
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for RX: " +"%ld expected %zd\n" , + vq->iov->iov_len,sizeof (struct virtio_net_hdr )); +break ;
Here too.
Quoted 4 lines
drivers/vhost/net.c new file +4
-0+u32 __user *featurep = argp; +int __user *fdp = argp; +u32 features; +int fd, r;
drivers/vhost/net.c line 362
Quoted 10 lines
drivers/vhost/net.c new file +10
-0+switch (ioctl) { +case VHOST_NET_SET_SOCKET : + r =get_user (fd, fdp); +if (r <0 ) +return r; +return vhost_net_set_socket (n, fd); +case VHOST_GET_FEATURES : +/* No features for now */ + features =0 ; +return put_user (features, featurep);
We may well get more than 32 feature bits, at least for virtio_net, which will force us to do some trickery in virtio_pci. I'd like to avoid that here, though it's kind of ugly. We'd need VHOST_GET_FEATURES (and ACK) to take a struct like:
u32 feature_size; u32 features[];
Quoted 1 line
+int
vhost_net_init(void)
static?
Quoted 1 line
+void
vhost_net_exit(void)
static?
Quoted 2 lines
+/* Start polling a file. We add ourselves to file's wait queue. The user must
+ * keep a reference to a file until aftervhost_poll_stopis called. */
I experienced minor confusion from the comments in this file. Where you said "user" I think "caller". No biggie though.
drivers/vhost/vhost.c line 148
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+ memory->nregions =2 ; + memory->regions[0 ].guest_phys_addr =1 ; + memory->regions[0 ].userspace_addr =1 ; + memory->regions[0 ].memory_size = ~0ULL ; + memory->regions[1 ].guest_phys_addr =0 ; + memory->regions[1 ].userspace_addr =0 ; + memory->regions[1 ].memory_size =1 ;
Not sure I understand why there are two regions to start?
Quoted 5 lines
drivers/vhost/vhost.c new file +5
-0+case VHOST_SET_VRING_BASE : + r =copy_from_user (&s, argp,sizeof s); +if (r <0 ) +break ; +if (s.num >0xffff ) {
drivers/vhost/vhost.c line 273
Quoted 10 lines
drivers/vhost/vhost.c new file +10
-0+ r = -EINVAL ; +break ; + } + vq->last_avail_idx = s.num; +break ; +case VHOST_GET_VRING_BASE : + s.index = idx; + s.num = vq->last_avail_idx; + r =copy_to_user (argp, &s,sizeof s); +break ;
Ah, this is my fault. I didn't expose the last_avail_idx in the ring because the other side doesn't need it; but without it the ring state is not fully observable from outside (no external save / restore!).
I have a patch which published these indices (we have room), see:
http://ozlabs.org/~rusty/kernel/rr-2009-08-12-1/virtio:ring-publish-indices.patch
Perhaps we should use that mechanism instead? We don't actually have to offer the feature (we don't care about the guest state), but it's nice as documentation. I've been waiting for an excuse to use that patch.
drivers/vhost/vhost.c line 397
Quoted 12 lines
drivers/vhost/vhost.c new file +12
-0+long vhost_dev_ioctl (struct vhost_dev *d,unsigned int ioctl,unsigned long arg) +{ +void __user *argp = (void __user *)arg; +long r; + +mutex_lock (&d->mutex); +if (ioctl ==VHOST_SET_OWNER ) { + r =vhost_dev_set_owner (d); + goto done; + } + + r =vhost_dev_check_owner (d);
You can do a VHOST_SET_OWNER without being the owner? So really, the -EPERM from all the vhost_dev_check_owner() is not a security thing, but a "I don't think you mean to do that" thing?
If so, a comment above it might help?
drivers/vhost/vhost.c line 420
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+static const struct vhost_memory_region *find_region (struct vhost_memory *mem, +__u64 addr,__u32 len) +{ +struct vhost_memory_region *reg; +int i; +/* linear search is not brilliant, but we really have on the order of 6 +* regions in practice */
Ah, you actually mean "this code has been carefully cache-optimized for the common case" :)
drivers/vhost/vhost.c line 440
Quoted 11 lines
drivers/vhost/vhost.c new file +11
-0+/* FIXME: this does not handle a region that spans multiple +* address/len pairs */ +int translate_desc (struct vhost_dev *dev,u64 addr,u32 len, +struct iovec iov[],int iov_count,int iov_size, +unsigned *num) +{ +const struct vhost_memory_region *reg; +struct vhost_memory *mem; +struct iovec *_iov; +u64 s =0 ; +int ret =0 ;
Would this be neater if it returned the num iovecs used? And offsetting iov in the caller, rather than passing iov_count?
drivers/vhost/vhost.c line 542
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+/* If their number is silly, that's a fatal mistake. */ +if (head >= vq->num) { +vq_err (vq,"Guest says index %u > %u is available" , + head, vq->num); +return vq->num; + }
Not a fatal mistake in this code/
drivers/vhost/vhost.c line 587
Quoted 1 line
drivers/vhost/vhost.c new file +1
-0+ vq->inflight++;
vq->inflight was a brain fart in the old lguest code. See commit ebf9a5a99c1a464afe0b4dfa64416fc8b273bc5c.
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious about wmb() in example Launcher code
lguest: clean up length-used value in example launcher
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;
And I wouldn't support notify on empty at all, TBH. It should definitely be conditional on the guest accepting the NOTIFY_ON_EMPTY feature.
Quoted 2 lines
drivers/vhost/vhost.h new file +2
-0+/* The virtqueue structure describes a queue attached to a device. */ +struct vhost_virtqueue {
...
Quoted 1 line
+}
____cacheline_aligned;
Really? I'd want to see numbers on this one. False sharing vs. more cache utilization.
drivers/vhost/vhost.h line 106
Quoted 5 lines
drivers/vhost/vhost.h new file +5
-0+#define vq_err (vq, fmt, ...) do { \ + printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__); \ + if ((vq)->error_ctx) \ + eventfd_signal((vq)->error_ctx, 1);\ + } while (0)
Mmm... guests should not be able to create unlimited printks in the host.
But really, nothing major to object to in here...
Thanks!
Rusty.
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Thanks for the comments, I'll work on them ASAP.
Answers to questions and more comments below.
Quoted 7 lines · Rusty Russell
Quoted 3 lines · Michael S. Tsirkin
What it is: vhost net is a character device that can be used to reduce the number of system calls involved in virtio networking. Existing virtio net code is used in the guest without modification.
...
Quoted 13 lines
drivers/vhost/Kconfig line 10
Quoted 10 lines
drivers/vhost/Kconfig new file +10
-0+config VHOST_NET + tristate "Host kernel accelerator for virtio net" + depends on NET && EVENTFD + ---help--- + This kernel module can be loaded in host kernel to accelerate + guest networking with virtio_net. Not to be confused with virtio_net + module itself which needs to be loaded in guest kernel. + + To compile this driver as a module, choose M here: the module will + be called vhost_net.Just want to note that the patch explanation and the
Kconfighelp text are exceptional examples of reader-oriented text. Nice!
High praise indeed from the author of the lguest Quest :).
Quoted 12 lines
drivers/vhost/net.c line 87
Quoted 7 lines
drivers/vhost/net.c new file +7
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for TX: " +"%ld expected %zd\n" , vq->iov->iov_len, +sizeof (struct virtio_net_hdr )); +break ; + }OK, this check, which is in the qemu version, is *wrong*. There should be no assumption on sg boundaries. For example, the guest should be able to put the
virtio_net_hdrin the front of the skbuf data if there is room.
Quoted 5 lines
You should try to explicitly "consume"
sizeof(struct virtio_net_hdr)of the iov, and if fail, do this message. You can skip the out <= 1 test then, too.Anyway, I really prefer vq->iov[0]. to vq->iov-> here.
I'll fix that. Probably should fix qemu as well.
Quoted 29 lines
drivers/vhost/net.c line 152
Quoted 6 lines
drivers/vhost/net.c new file +6
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for RX: " +"%ld expected %zd\n" , + vq->iov->iov_len,sizeof (struct virtio_net_hdr )); +break ;Here too.
Quoted 4 lines
drivers/vhost/net.c new file +4
-0+u32 __user *featurep = argp; +int __user *fdp = argp; +u32 features; +int fd, r;drivers/vhost/net.c line 362
Quoted 10 lines
drivers/vhost/net.c new file +10
-0+switch (ioctl) { +case VHOST_NET_SET_SOCKET : + r =get_user (fd, fdp); +if (r <0 ) +return r; +return vhost_net_set_socket (n, fd); +case VHOST_GET_FEATURES : +/* No features for now */ + features =0 ; +return put_user (features, featurep);We may well get more than 32 feature bits, at least for
virtio_net, which will force us to do some trickery invirtio_pci. I'd like to avoid that here, though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:
Quoted 2 lines
u32 feature_size; u32 features[];
Do you feel just making it 64 bit won't be enough? How about 128 bit?
Quoted 7 lines
Quoted 1 line
+int
vhost_net_init(void)static?
Quoted 1 line
+void
vhost_net_exit(void)static?
Good catch.
Quoted 6 lines
Quoted 2 lines
+/* Start polling a file. We add ourselves to file's wait queue. The user must
+ * keep a reference to a file until aftervhost_poll_stopis called. */I experienced minor confusion from the comments in this file. Where you said "user" I think "caller". No biggie though.
Quoted 9 lines
drivers/vhost/vhost.c line 148
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+ memory->nregions =2 ; + memory->regions[0 ].guest_phys_addr =1 ; + memory->regions[0 ].userspace_addr =1 ; + memory->regions[0 ].memory_size = ~0ULL ; + memory->regions[1 ].guest_phys_addr =0 ; + memory->regions[1 ].userspace_addr =0 ; + memory->regions[1 ].memory_size =1 ;Not sure I understand why there are two regions to start?
We are trying to cover a whole 2^64 range here. It's size does not fit in a single 64 bit length value. I could special case 0 length to mean 2^64, but decided against it.
Quoted 20 lines
Quoted 5 lines
drivers/vhost/vhost.c new file +5
-0+case VHOST_SET_VRING_BASE : + r =copy_from_user (&s, argp,sizeof s); +if (r <0 ) +break ; +if (s.num >0xffff ) {drivers/vhost/vhost.c line 273
Quoted 10 lines
drivers/vhost/vhost.c new file +10
-0+ r = -EINVAL ; +break ; + } + vq->last_avail_idx = s.num; +break ; +case VHOST_GET_VRING_BASE : + s.index = idx; + s.num = vq->last_avail_idx; + r =copy_to_user (argp, &s,sizeof s); +break ;Ah, this is my fault. I didn't expose the
last_avail_idxin the ring because the other side doesn't need it; but without it the ring state is not fully observable from outside (no external save / restore!).
Quoted 6 lines
I have a patch which published these indices (we have room), see:
http://ozlabs.org/~rusty/kernel/rr-2009-08-12-1/virtio:ring-publish-indices.patchPerhaps we should use that mechanism instead? We don't actually have to offer the feature (we don't care about the guest state), but it's nice as documentation. I've been waiting for an excuse to use that patch.
Good idea and might be handy for optimizations as well, and I would have used it if it was there. I'd like to support existing guests in vhost though, so I think we need to support this ioctl for now.
Quoted 6 lines
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+long vhost_dev_ioctl (struct vhost_dev *d,unsigned int ioctl,unsigned long arg) +{ +void __user *argp = (void __user *)arg; +long r; + +mutex_lock (&d->mutex);
Quoted 8 lines
drivers/vhost/vhost.c line 397
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+if (ioctl ==VHOST_SET_OWNER ) { + r =vhost_dev_set_owner (d); + goto done; + } + + r =vhost_dev_check_owner (d);You can do a
VHOST_SET_OWNERwithout being the owner?
Only if no one else is the owner. It has a mutual exclusion mechanism.
Quoted 3 lines
So really,
the-EPERMfrom all thevhost_dev_check_owner()is not a security thing, but a "I don't think you mean to do that" thing?
Mostly that. I started by assuming that an open fd can't be passed around at all, but talking with management guys here, they really like being able to open fds and pass them around through unix domain sockets.
Since using this fd from multiple processes does not work well, I decided to make this explicit in the interface. I find it quite possible that there's no security thing here, but this is just a simpler model to think about than guessing whether some crash is exploitable or not.
Quoted 1 line
If so, a comment above it might help?
Yes.
Quoted 11 lines
drivers/vhost/vhost.c line 420
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+static const struct vhost_memory_region *find_region (struct vhost_memory *mem, +__u64 addr,__u32 len) +{ +struct vhost_memory_region *reg; +int i; +/* linear search is not brilliant, but we really have on the order of 6 +* regions in practice */ Ah, you actually mean "this code has been carefully cache-optimized for the common case" :)
Quoted 14 lines
drivers/vhost/vhost.c line 440
Quoted 11 lines
drivers/vhost/vhost.c new file +11
-0+/* FIXME: this does not handle a region that spans multiple +* address/len pairs */ +int translate_desc (struct vhost_dev *dev,u64 addr,u32 len, +struct iovec iov[],int iov_count,int iov_size, +unsigned *num) +{ +const struct vhost_memory_region *reg; +struct vhost_memory *mem; +struct iovec *_iov; +u64 s =0 ; +int ret =0 ;Would this be neater if it returned the num iovecs used? And offsetting iov in the caller, rather than passing
iov_count?
iov_size would have to be tweaked instead as well.
Quoted 9 lines
drivers/vhost/vhost.c line 542
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+/* If their number is silly, that's a fatal mistake. */ +if (head >= vq->num) { +vq_err (vq,"Guest says index %u > %u is available" , + head, vq->num); +return vq->num; + }Not a fatal mistake in this code/
Quoted 4 lines
drivers/vhost/vhost.c line 587
Quoted 1 line
drivers/vhost/vhost.c new file +1
-0+ vq->inflight++;
vq->inflightwas a brain fart in the old lguest code. See commitebf9a5a99c1a464afe0b4dfa64416fc8b273bc5c.
I wondered about that. OK.
Quoted 4 lines
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher code
lguest: clean up length-used value in example launcher
I'll go over them, thanks!
I did look over barriers, but this is tricky stuff.
Quoted 5 lines
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;And I wouldn't support notify on empty at all, TBH.
If I don't, virtio net in guest uses a timer, which might be expensive. Will need to check what this does.
Quoted 3 lines
It should
definitely be conditional on the guest accepting theNOTIFY_ON_EMPTYfeature.
Good point.
Quoted 7 lines
Quoted 2 lines
drivers/vhost/vhost.h new file +2
-0+/* The virtqueue structure describes a queue attached to a device. */ +struct vhost_virtqueue {...
Quoted 1 line
+}
____cacheline_aligned;Really? I'd want to see numbers on this one. False sharing vs. more cache utilization.
I don't yet want to focus on micro optimizations. What's your guess? That it's better without? I'll kill it then ...
Quoted 7 lines
drivers/vhost/vhost.h line 106
Quoted 5 lines
drivers/vhost/vhost.h new file +5
-0+#define vq_err (vq, fmt, ...) do { \ + printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__); \ + if ((vq)->error_ctx) \ + eventfd_signal((vq)->error_ctx, 1);\ + } while (0)Mmm... guests should not be able to create unlimited printks in the host.
Yes, but handy for debugging :)
I guess I'll just make it use pr_debug instead?
Quoted 4 lines
But really, nothing major to object to in here...
Thanks!
Rusty.
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 6 lines · Michael S. Tsirkin
Quoted 5 lines
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;And I wouldn't support notify on empty at all, TBH.
Quoted 6 lines
If I don't, virtio net in guest uses a timer, which might be expensive. Will need to check what this does.
Quoted 3 lines
It should
definitely be conditional on the guest accepting theNOTIFY_ON_EMPTYfeature.
lguest does not do it this way though, do it?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 7 lines · Michael S. Tsirkin
Quoted 6 lines · Michael S. Tsirkin
Quoted 5 lines
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;And I wouldn't support notify on empty at all, TBH.
Quoted 8 lines
Quoted 6 lines
If I don't, virtio net in guest uses a timer, which might be expensive. Will need to check what this does.
Quoted 3 lines
It should
definitely be conditional on the guest accepting theNOTIFY_ON_EMPTYfeature.lguest does not do it this way though, do it?
Does when a patch in my current queue is applied though.
Thanks,
Rusty.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Michael S. TsirkinQuoted 7 lines · Michael S. Tsirkin
Quoted 6 lines · Michael S. Tsirkin
Quoted 5 lines
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;And I wouldn't support notify on empty at all, TBH.
Quoted 8 lines
Quoted 6 lines
If I don't, virtio net in guest uses a timer, which might be expensive. Will need to check what this does.
Quoted 3 lines
It should
definitely be conditional on the guest accepting theNOTIFY_ON_EMPTYfeature.lguest does not do it this way though, do it?
Does when a patch in my current queue is applied though.
Thanks,
Rusty.
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Michael S. TsirkinQuoted 6 lines · Michael S. Tsirkin
Quoted 5 lines
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;And I wouldn't support notify on empty at all, TBH.
Quoted 6 lines
If I don't, virtio net in guest uses a timer, which might be expensive. Will need to check what this does.
Quoted 3 lines
It should
definitely be conditional on the guest accepting theNOTIFY_ON_EMPTYfeature.
lguest does not do it this way though, do it?
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Rusty RussellThanks for the comments, I'll work on them ASAP.
Answers to questions and more comments below.
Quoted 7 lines · Rusty Russell
Quoted 3 lines · Michael S. Tsirkin
What it is: vhost net is a character device that can be used to reduce the number of system calls involved in virtio networking. Existing virtio net code is used in the guest without modification.
...
Quoted 13 lines
drivers/vhost/Kconfig line 10
Quoted 10 lines
drivers/vhost/Kconfig new file +10
-0+config VHOST_NET + tristate "Host kernel accelerator for virtio net" + depends on NET && EVENTFD + ---help--- + This kernel module can be loaded in host kernel to accelerate + guest networking with virtio_net. Not to be confused with virtio_net + module itself which needs to be loaded in guest kernel. + + To compile this driver as a module, choose M here: the module will + be called vhost_net.Just want to note that the patch explanation and the
Kconfighelp text are exceptional examples of reader-oriented text. Nice!
High praise indeed from the author of the lguest Quest :).
Quoted 12 lines
drivers/vhost/net.c line 87
Quoted 7 lines
drivers/vhost/net.c new file +7
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for TX: " +"%ld expected %zd\n" , vq->iov->iov_len, +sizeof (struct virtio_net_hdr )); +break ; + }OK, this check, which is in the qemu version, is *wrong*. There should be no assumption on sg boundaries. For example, the guest should be able to put the
virtio_net_hdrin the front of the skbuf data if there is room.
Quoted 5 lines
You should try to explicitly "consume"
sizeof(struct virtio_net_hdr)of the iov, and if fail, do this message. You can skip the out <= 1 test then, too.Anyway, I really prefer vq->iov[0]. to vq->iov-> here.
I'll fix that. Probably should fix qemu as well.
Quoted 29 lines
drivers/vhost/net.c line 152
Quoted 6 lines
drivers/vhost/net.c new file +6
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for RX: " +"%ld expected %zd\n" , + vq->iov->iov_len,sizeof (struct virtio_net_hdr )); +break ;Here too.
Quoted 4 lines
drivers/vhost/net.c new file +4
-0+u32 __user *featurep = argp; +int __user *fdp = argp; +u32 features; +int fd, r;drivers/vhost/net.c line 362
Quoted 10 lines
drivers/vhost/net.c new file +10
-0+switch (ioctl) { +case VHOST_NET_SET_SOCKET : + r =get_user (fd, fdp); +if (r <0 ) +return r; +return vhost_net_set_socket (n, fd); +case VHOST_GET_FEATURES : +/* No features for now */ + features =0 ; +return put_user (features, featurep);We may well get more than 32 feature bits, at least for
virtio_net, which will force us to do some trickery invirtio_pci. I'd like to avoid that here, though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:
Quoted 2 lines
u32 feature_size; u32 features[];
Do you feel just making it 64 bit won't be enough? How about 128 bit?
Quoted 7 lines
Quoted 1 line
+int
vhost_net_init(void)static?
Quoted 1 line
+void
vhost_net_exit(void)static?
Good catch.
Quoted 6 lines
Quoted 2 lines
+/* Start polling a file. We add ourselves to file's wait queue. The user must
+ * keep a reference to a file until aftervhost_poll_stopis called. */I experienced minor confusion from the comments in this file. Where you said "user" I think "caller". No biggie though.
Quoted 9 lines
drivers/vhost/vhost.c line 148
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+ memory->nregions =2 ; + memory->regions[0 ].guest_phys_addr =1 ; + memory->regions[0 ].userspace_addr =1 ; + memory->regions[0 ].memory_size = ~0ULL ; + memory->regions[1 ].guest_phys_addr =0 ; + memory->regions[1 ].userspace_addr =0 ; + memory->regions[1 ].memory_size =1 ;Not sure I understand why there are two regions to start?
We are trying to cover a whole 2^64 range here. It's size does not fit in a single 64 bit length value. I could special case 0 length to mean 2^64, but decided against it.
Quoted 20 lines
Quoted 5 lines
drivers/vhost/vhost.c new file +5
-0+case VHOST_SET_VRING_BASE : + r =copy_from_user (&s, argp,sizeof s); +if (r <0 ) +break ; +if (s.num >0xffff ) {drivers/vhost/vhost.c line 273
Quoted 10 lines
drivers/vhost/vhost.c new file +10
-0+ r = -EINVAL ; +break ; + } + vq->last_avail_idx = s.num; +break ; +case VHOST_GET_VRING_BASE : + s.index = idx; + s.num = vq->last_avail_idx; + r =copy_to_user (argp, &s,sizeof s); +break ;Ah, this is my fault. I didn't expose the
last_avail_idxin the ring because the other side doesn't need it; but without it the ring state is not fully observable from outside (no external save / restore!).
Quoted 6 lines
I have a patch which published these indices (we have room), see:
http://ozlabs.org/~rusty/kernel/rr-2009-08-12-1/virtio:ring-publish-indices.patchPerhaps we should use that mechanism instead? We don't actually have to offer the feature (we don't care about the guest state), but it's nice as documentation. I've been waiting for an excuse to use that patch.
Good idea and might be handy for optimizations as well, and I would have used it if it was there. I'd like to support existing guests in vhost though, so I think we need to support this ioctl for now.
Quoted 6 lines
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+long vhost_dev_ioctl (struct vhost_dev *d,unsigned int ioctl,unsigned long arg) +{ +void __user *argp = (void __user *)arg; +long r; + +mutex_lock (&d->mutex);
Quoted 8 lines
drivers/vhost/vhost.c line 397
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+if (ioctl ==VHOST_SET_OWNER ) { + r =vhost_dev_set_owner (d); + goto done; + } + + r =vhost_dev_check_owner (d);You can do a
VHOST_SET_OWNERwithout being the owner?
Only if no one else is the owner. It has a mutual exclusion mechanism.
Quoted 3 lines
So really,
the-EPERMfrom all thevhost_dev_check_owner()is not a security thing, but a "I don't think you mean to do that" thing?
Mostly that. I started by assuming that an open fd can't be passed around at all, but talking with management guys here, they really like being able to open fds and pass them around through unix domain sockets.
Since using this fd from multiple processes does not work well, I decided to make this explicit in the interface. I find it quite possible that there's no security thing here, but this is just a simpler model to think about than guessing whether some crash is exploitable or not.
Quoted 1 line
If so, a comment above it might help?
Yes.
Quoted 11 lines
drivers/vhost/vhost.c line 420
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+static const struct vhost_memory_region *find_region (struct vhost_memory *mem, +__u64 addr,__u32 len) +{ +struct vhost_memory_region *reg; +int i; +/* linear search is not brilliant, but we really have on the order of 6 +* regions in practice */ Ah, you actually mean "this code has been carefully cache-optimized for the common case" :)
Quoted 14 lines
drivers/vhost/vhost.c line 440
Quoted 11 lines
drivers/vhost/vhost.c new file +11
-0+/* FIXME: this does not handle a region that spans multiple +* address/len pairs */ +int translate_desc (struct vhost_dev *dev,u64 addr,u32 len, +struct iovec iov[],int iov_count,int iov_size, +unsigned *num) +{ +const struct vhost_memory_region *reg; +struct vhost_memory *mem; +struct iovec *_iov; +u64 s =0 ; +int ret =0 ;Would this be neater if it returned the num iovecs used? And offsetting iov in the caller, rather than passing
iov_count?
iov_size would have to be tweaked instead as well.
Quoted 9 lines
drivers/vhost/vhost.c line 542
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+/* If their number is silly, that's a fatal mistake. */ +if (head >= vq->num) { +vq_err (vq,"Guest says index %u > %u is available" , + head, vq->num); +return vq->num; + }Not a fatal mistake in this code/
Quoted 4 lines
drivers/vhost/vhost.c line 587
Quoted 1 line
drivers/vhost/vhost.c new file +1
-0+ vq->inflight++;
vq->inflightwas a brain fart in the old lguest code. See commitebf9a5a99c1a464afe0b4dfa64416fc8b273bc5c.
I wondered about that. OK.
Quoted 4 lines
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher code
lguest: clean up length-used value in example launcher
I'll go over them, thanks!
I did look over barriers, but this is tricky stuff.
Quoted 5 lines
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;And I wouldn't support notify on empty at all, TBH.
If I don't, virtio net in guest uses a timer, which might be expensive. Will need to check what this does.
Quoted 3 lines
It should
definitely be conditional on the guest accepting theNOTIFY_ON_EMPTYfeature.
Good point.
Quoted 7 lines
Quoted 2 lines
drivers/vhost/vhost.h new file +2
-0+/* The virtqueue structure describes a queue attached to a device. */ +struct vhost_virtqueue {...
Quoted 1 line
+}
____cacheline_aligned;Really? I'd want to see numbers on this one. False sharing vs. more cache utilization.
I don't yet want to focus on micro optimizations. What's your guess? That it's better without? I'll kill it then ...
Quoted 7 lines
drivers/vhost/vhost.h line 106
Quoted 5 lines
drivers/vhost/vhost.h new file +5
-0+#define vq_err (vq, fmt, ...) do { \ + printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__); \ + if ((vq)->error_ctx) \ + eventfd_signal((vq)->error_ctx, 1);\ + } while (0)Mmm... guests should not be able to create unlimited printks in the host.
Yes, but handy for debugging :)
I guess I'll just make it use pr_debug instead?
Quoted 4 lines
But really, nothing major to object to in here...
Thanks!
Rusty.
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Rusty RussellQuoted 9 lines · Rusty Russell
Quoted 9 lines
drivers/vhost/net.c new file +9
-0+u32 __user *featurep = argp; +int __user *fdp = argp; +u32 features; +int fd, r; +switch (ioctl) { +case VHOST_NET_SET_SOCKET : + r =get_user (fd, fdp); +if (r <0 ) +return r;
Quoted 8 lines
drivers/vhost/net.c line 362
Quoted 5 lines
drivers/vhost/net.c new file +5
-0+return vhost_net_set_socket (n, fd); +case VHOST_GET_FEATURES : +/* No features for now */ + features =0 ; +return put_user (features, featurep);We may well get more than 32 feature bits, at least for
virtio_net, which will force us to do some trickery invirtio_pci.
Unlike PCI, if we ever run out of bits we can just add FEATURES_EXTENDED ioctl, no need for trickery.
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];
Thinking about this proposal some more, how will the guest determine the size to supply the GET_FEATURES ioctl?
Since we are a bit tight in 32 bit space already, let's just use a 64 bit integer and be done with it? Right?
Signature · 1 line
MST
Arnd Bergmann
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];
Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:
struct vhost_get_features2 {
__u64 bits[2];
};#define VHOST_GET_FEATURES2 _IOR(VHOST_VIRTIO, 0x00, \
struct vhost_get_features2)
*/
Quoted 2 lines
Thinking about this proposal some more, how will the guest determine the size to supply the
GET_FEATURESioctl?
Wait, the *guest*?
Maybe I misunderstood something in a major way here, but I expected the features to be negotiated between host user space (qemu) and host kernel, as well as between guest and qemu (as they are already), but never between guest and kernel.
I would certainly expect the bits to be distinct from the virtio-net feature bits. E.g. stuff like TAP frame format opposed to TCP socket frame format (length+date) is something we need to negotiate here but that the guest does not care about.
Quoted 2 lines
Since we are a bit tight in 32 bit space already, let's just use a 64 bit integer and be done with it?
Can't hurt, but don't use a struct unless you think we are going to need more than 64 bits.
Arnd <><
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 20 lines · Arnd Bergmann
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#defineVHOST_GET_FEATURES_IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:struct vhost_get_features2 { __u64 bits[2]; };
Quoted 8 lines
#define
VHOST_GET_FEATURES2_IOR(VHOST_VIRTIO,0x00, \
structvhost_get_features2)
*/Quoted 2 lines
Thinking about this proposal some more, how will the guest determine the size to supply the
GET_FEATURESioctl?Wait, the *guest*?
Sorry. the userspace hypervisor.
Quoted 5 lines
Maybe I misunderstood something in a major way here, but I expected the features to be negotiated between host user space (qemu) and host kernel, as well as between guest and qemu (as they are already), but never between guest and kernel.
Yes.
Quoted 5 lines
I would certainly expect the bits to be distinct from the virtio-net feature bits. E.g. stuff like TAP frame format opposed to TCP socket frame format (length+date) is something we need to negotiate here but that the guest does not care about.
My idea is to use virtio format for things I share with virtio (e.g. mergeable buffers). Since we are a kind of transport, I thought that I will use the transport bits, that is bits 28 and up for vhost things.
Quoted 7 lines
Quoted 2 lines
Since we are a bit tight in 32 bit space already, let's just use a 64 bit integer and be done with it?
Can't hurt, but don't use a struct unless you think we are going to need more than 64 bits.
Arnd <><
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Arnd BergmannQuoted 20 lines · Arnd Bergmann
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#defineVHOST_GET_FEATURES_IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:struct vhost_get_features2 { __u64 bits[2]; };
Quoted 8 lines
#define
VHOST_GET_FEATURES2_IOR(VHOST_VIRTIO,0x00, \
structvhost_get_features2)
*/Quoted 2 lines
Thinking about this proposal some more, how will the guest determine the size to supply the
GET_FEATURESioctl?Wait, the *guest*?
Sorry. the userspace hypervisor.
Quoted 5 lines
Maybe I misunderstood something in a major way here, but I expected the features to be negotiated between host user space (qemu) and host kernel, as well as between guest and qemu (as they are already), but never between guest and kernel.
Yes.
Quoted 5 lines
I would certainly expect the bits to be distinct from the virtio-net feature bits. E.g. stuff like TAP frame format opposed to TCP socket frame format (length+date) is something we need to negotiate here but that the guest does not care about.
My idea is to use virtio format for things I share with virtio (e.g. mergeable buffers). Since we are a kind of transport, I thought that I will use the transport bits, that is bits 28 and up for vhost things.
Quoted 7 lines
Quoted 2 lines
Since we are a bit tight in 32 bit space already, let's just use a 64 bit integer and be done with it?
Can't hurt, but don't use a struct unless you think we are going to need more than 64 bits.
Arnd <><
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Arnd BergmannQuoted 17 lines · Arnd Bergmann
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#defineVHOST_GET_FEATURES_IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:
Quoted 6 lines
struct vhost_get_features2 { __u64 bits[2]; };#define
VHOST_GET_FEATURES2_IOR(VHOST_VIRTIO,0x00, \
structvhost_get_features2)
*/
I thought so, too. Rusty, agree?
Signature · 7 lines
MST -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 26 lines · Michael S. Tsirkin
Quoted 17 lines · Arnd Bergmann
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#defineVHOST_GET_FEATURES_IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:Quoted 6 lines
struct vhost_get_features2 { __u64 bits[2]; };#define
VHOST_GET_FEATURES2_IOR(VHOST_VIRTIO,0x00, \
structvhost_get_features2)
*/
Quoted 1 line
I thought so, too. Rusty, agree?
Yep, am convinced. Make it u64 to stop us having to do this tomorrow, then we can always extend later.
Thanks,
Rusty.
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Michael S. TsirkinQuoted 26 lines · Michael S. Tsirkin
Quoted 17 lines · Arnd Bergmann
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#defineVHOST_GET_FEATURES_IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:Quoted 6 lines
struct vhost_get_features2 { __u64 bits[2]; };#define
VHOST_GET_FEATURES2_IOR(VHOST_VIRTIO,0x00, \
structvhost_get_features2)
*/
Quoted 1 line
I thought so, too. Rusty, agree?
Yep, am convinced. Make it u64 to stop us having to do this tomorrow, then we can always extend later.
Thanks,
Rusty.
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Arnd BergmannQuoted 17 lines · Arnd Bergmann
Quoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#defineVHOST_GET_FEATURES_IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:
Quoted 6 lines
struct vhost_get_features2 { __u64 bits[2]; };#define
VHOST_GET_FEATURES2_IOR(VHOST_VIRTIO,0x00, \
structvhost_get_features2)
*/
I thought so, too. Rusty, agree?
Signature · 1 line
MST
Arnd Bergmann
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Michael S. TsirkinQuoted 6 lines · Michael S. Tsirkin
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];
Hmm, variable length ioctl arguments, I'd rather not go there. The ioctl infrastructure already has a length argument encoded in the ioctl number. We can use that if we need more, e.g.
/* now */
#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
/*
* uncomment if we run out of feature bits:
struct vhost_get_features2 {
__u64 bits[2];
};#define VHOST_GET_FEATURES2 _IOR(VHOST_VIRTIO, 0x00, \
struct vhost_get_features2)
*/
Quoted 2 lines
Thinking about this proposal some more, how will the guest determine the size to supply the
GET_FEATURESioctl?
Wait, the *guest*?
Maybe I misunderstood something in a major way here, but I expected the features to be negotiated between host user space (qemu) and host kernel, as well as between guest and qemu (as they are already), but never between guest and kernel.
I would certainly expect the bits to be distinct from the virtio-net feature bits. E.g. stuff like TAP frame format opposed to TCP socket frame format (length+date) is something we need to negotiate here but that the guest does not care about.
Quoted 2 lines
Since we are a bit tight in 32 bit space already, let's just use a 64 bit integer and be done with it?
Can't hurt, but don't use a struct unless you think we are going to need more than 64 bits.
Arnd <><
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Rusty RussellQuoted 9 lines · Rusty Russell
Quoted 9 lines
drivers/vhost/net.c new file +9
-0+u32 __user *featurep = argp; +int __user *fdp = argp; +u32 features; +int fd, r; +switch (ioctl) { +case VHOST_NET_SET_SOCKET : + r =get_user (fd, fdp); +if (r <0 ) +return r;
Quoted 8 lines
drivers/vhost/net.c line 362
Quoted 5 lines
drivers/vhost/net.c new file +5
-0+return vhost_net_set_socket (n, fd); +case VHOST_GET_FEATURES : +/* No features for now */ + features =0 ; +return put_user (features, featurep);We may well get more than 32 feature bits, at least for
virtio_net, which will force us to do some trickery invirtio_pci.
Unlike PCI, if we ever run out of bits we can just add FEATURES_EXTENDED ioctl, no need for trickery.
Quoted 6 lines
I'd like to avoid that here,
though it's kind of ugly. We'd needVHOST_GET_FEATURES(and ACK) to take a struct like:u32 feature_size; u32 features[];
Thinking about this proposal some more, how will the guest determine the size to supply the GET_FEATURES ioctl?
Since we are a bit tight in 32 bit space already, let's just use a 64 bit integer and be done with it? Right?
Signature · 1 line
MST
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Rusty RussellQuoted 3 lines · Rusty Russell
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher code
Heh, this just gets one step closer to a real wmb. I just used the correct code from linux, so I think nothing needs to be done in vhost. Apropos this change in lguest: why is a compiler barrier sufficient? The comment says devices are run in separate threads (presumably from guest?), if so don't you need to tell CPU that there's a barrier as well?
Quoted 1 line
lguest: clean up length-used value in example launcher
OK, fixing that.
Thanks!
Signature · 7 lines
MST -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 11 lines · Michael S. Tsirkin
Quoted 3 lines · Rusty Russell
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher codeHeh, this just gets one step closer to a real wmb. I just used the correct code from linux, so I think nothing needs to be done in vhost. Apropos this change in lguest: why is a compiler barrier sufficient? The comment says devices are run in separate threads (presumably from guest?), if so don't you need to tell CPU that there's a barrier as well?
Yep, but x86 only :) The kernel uses a real insn if XMM/XMM2, but I don't know if userspace needs that. I just use compiler barriers.
Thanks,
Rusty.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
Quoted 6 lines · Rusty Russell
Quoted 5 lines · Michael S. Tsirkin
Quoted 3 lines · Rusty Russell
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher code
Quoted 8 lines
Quoted 6 lines
Heh, this just gets one step closer to a real wmb. I just used the correct code from linux, so I think nothing needs to be done in vhost. Apropos this change in lguest: why is a compiler barrier sufficient? The comment says devices are run in separate threads (presumably from guest?), if so don't you need to tell CPU that there's a barrier as well?
Yep, but x86 only :)
Okay, writes are ordered them. But mb() orders reads as well, so it'll have to have a real one IMO, even in userspace?
Quoted 5 lines
The kernel uses a real insn if XMM/XMM2, but I don't
know if userspace needs that. I just use compiler barriers.Thanks,
Rusty.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Rusty RussellQuoted 6 lines · Rusty Russell
Quoted 5 lines · Michael S. Tsirkin
Quoted 3 lines · Rusty Russell
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher code
Quoted 8 lines
Quoted 6 lines
Heh, this just gets one step closer to a real wmb. I just used the correct code from linux, so I think nothing needs to be done in vhost. Apropos this change in lguest: why is a compiler barrier sufficient? The comment says devices are run in separate threads (presumably from guest?), if so don't you need to tell CPU that there's a barrier as well?
Yep, but x86 only :)
Okay, writes are ordered them. But mb() orders reads as well, so it'll have to have a real one IMO, even in userspace?
Quoted 5 lines
The kernel uses a real insn if XMM/XMM2, but I don't
know if userspace needs that. I just use compiler barriers.Thanks,
Rusty.
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Michael S. TsirkinQuoted 11 lines · Michael S. Tsirkin
Quoted 3 lines · Rusty Russell
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher codeHeh, this just gets one step closer to a real wmb. I just used the correct code from linux, so I think nothing needs to be done in vhost. Apropos this change in lguest: why is a compiler barrier sufficient? The comment says devices are run in separate threads (presumably from guest?), if so don't you need to tell CPU that there's a barrier as well?
Yep, but x86 only :) The kernel uses a real insn if XMM/XMM2, but I don't know if userspace needs that. I just use compiler barriers.
Thanks,
Rusty.
Michael S. Tsirkin
maintainerRe: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Rusty RussellQuoted 3 lines · Rusty Russell
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious aboutwmb()in example Launcher code
Heh, this just gets one step closer to a real wmb. I just used the correct code from linux, so I think nothing needs to be done in vhost. Apropos this change in lguest: why is a compiler barrier sufficient? The comment says devices are run in separate threads (presumably from guest?), if so don't you need to tell CPU that there's a barrier as well?
Quoted 1 line
lguest: clean up length-used value in example launcher
OK, fixing that.
Thanks!
Signature · 1 line
MST
Re: [PATCHv4 2/2] vhost_net: a kernel-level virtio server
In reply to Michael S. TsirkinQuoted 3 lines · Michael S. Tsirkin
What it is: vhost net is a character device that can be used to reduce the number of system calls involved in virtio networking. Existing virtio net code is used in the guest without modification.
...
drivers/vhost/Kconfig line 10
Quoted 10 lines
drivers/vhost/Kconfig new file +10
-0+config VHOST_NET + tristate "Host kernel accelerator for virtio net" + depends on NET && EVENTFD + ---help--- + This kernel module can be loaded in host kernel to accelerate + guest networking with virtio_net. Not to be confused with virtio_net + module itself which needs to be loaded in guest kernel. + + To compile this driver as a module, choose M here: the module will + be called vhost_net.
Just want to note that the patch explanation and the Kconfig help text are exceptional examples of reader-oriented text. Nice!
drivers/vhost/net.c line 87
Quoted 7 lines
drivers/vhost/net.c new file +7
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for TX: " +"%ld expected %zd\n" , vq->iov->iov_len, +sizeof (struct virtio_net_hdr )); +break ; + }
OK, this check, which is in the qemu version, is *wrong*. There should be no assumption on sg boundaries. For example, the guest should be able to put the virtio_net_hdr in the front of the skbuf data if there is room.
You should try to explicitly "consume" sizeof(struct virtio_net_hdr) of the iov, and if fail, do this message. You can skip the out <= 1 test then, too.
Anyway, I really prefer vq->iov[0]. to vq->iov-> here.
drivers/vhost/net.c line 152
Quoted 6 lines
drivers/vhost/net.c new file +6
-0+/* Sanity check */ +if (vq->iov->iov_len !=sizeof (struct virtio_net_hdr )) { +vq_err (vq,"Unexpected header len for RX: " +"%ld expected %zd\n" , + vq->iov->iov_len,sizeof (struct virtio_net_hdr )); +break ;
Here too.
Quoted 4 lines
drivers/vhost/net.c new file +4
-0+u32 __user *featurep = argp; +int __user *fdp = argp; +u32 features; +int fd, r;
drivers/vhost/net.c line 362
Quoted 10 lines
drivers/vhost/net.c new file +10
-0+switch (ioctl) { +case VHOST_NET_SET_SOCKET : + r =get_user (fd, fdp); +if (r <0 ) +return r; +return vhost_net_set_socket (n, fd); +case VHOST_GET_FEATURES : +/* No features for now */ + features =0 ; +return put_user (features, featurep);
We may well get more than 32 feature bits, at least for virtio_net, which will force us to do some trickery in virtio_pci. I'd like to avoid that here, though it's kind of ugly. We'd need VHOST_GET_FEATURES (and ACK) to take a struct like:
u32 feature_size; u32 features[];
Quoted 1 line
+int
vhost_net_init(void)
static?
Quoted 1 line
+void
vhost_net_exit(void)
static?
Quoted 2 lines
+/* Start polling a file. We add ourselves to file's wait queue. The user must
+ * keep a reference to a file until aftervhost_poll_stopis called. */
I experienced minor confusion from the comments in this file. Where you said "user" I think "caller". No biggie though.
drivers/vhost/vhost.c line 148
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+ memory->nregions =2 ; + memory->regions[0 ].guest_phys_addr =1 ; + memory->regions[0 ].userspace_addr =1 ; + memory->regions[0 ].memory_size = ~0ULL ; + memory->regions[1 ].guest_phys_addr =0 ; + memory->regions[1 ].userspace_addr =0 ; + memory->regions[1 ].memory_size =1 ;
Not sure I understand why there are two regions to start?
Quoted 5 lines
drivers/vhost/vhost.c new file +5
-0+case VHOST_SET_VRING_BASE : + r =copy_from_user (&s, argp,sizeof s); +if (r <0 ) +break ; +if (s.num >0xffff ) {
drivers/vhost/vhost.c line 273
Quoted 10 lines
drivers/vhost/vhost.c new file +10
-0+ r = -EINVAL ; +break ; + } + vq->last_avail_idx = s.num; +break ; +case VHOST_GET_VRING_BASE : + s.index = idx; + s.num = vq->last_avail_idx; + r =copy_to_user (argp, &s,sizeof s); +break ;
Ah, this is my fault. I didn't expose the last_avail_idx in the ring because the other side doesn't need it; but without it the ring state is not fully observable from outside (no external save / restore!).
I have a patch which published these indices (we have room), see:
http://ozlabs.org/~rusty/kernel/rr-2009-08-12-1/virtio:ring-publish-indices.patch
Perhaps we should use that mechanism instead? We don't actually have to offer the feature (we don't care about the guest state), but it's nice as documentation. I've been waiting for an excuse to use that patch.
drivers/vhost/vhost.c line 397
Quoted 12 lines
drivers/vhost/vhost.c new file +12
-0+long vhost_dev_ioctl (struct vhost_dev *d,unsigned int ioctl,unsigned long arg) +{ +void __user *argp = (void __user *)arg; +long r; + +mutex_lock (&d->mutex); +if (ioctl ==VHOST_SET_OWNER ) { + r =vhost_dev_set_owner (d); + goto done; + } + + r =vhost_dev_check_owner (d);
You can do a VHOST_SET_OWNER without being the owner? So really, the -EPERM from all the vhost_dev_check_owner() is not a security thing, but a "I don't think you mean to do that" thing?
If so, a comment above it might help?
drivers/vhost/vhost.c line 420
Quoted 7 lines
drivers/vhost/vhost.c new file +7
-0+static const struct vhost_memory_region *find_region (struct vhost_memory *mem, +__u64 addr,__u32 len) +{ +struct vhost_memory_region *reg; +int i; +/* linear search is not brilliant, but we really have on the order of 6 +* regions in practice */
Ah, you actually mean "this code has been carefully cache-optimized for the common case" :)
drivers/vhost/vhost.c line 440
Quoted 11 lines
drivers/vhost/vhost.c new file +11
-0+/* FIXME: this does not handle a region that spans multiple +* address/len pairs */ +int translate_desc (struct vhost_dev *dev,u64 addr,u32 len, +struct iovec iov[],int iov_count,int iov_size, +unsigned *num) +{ +const struct vhost_memory_region *reg; +struct vhost_memory *mem; +struct iovec *_iov; +u64 s =0 ; +int ret =0 ;
Would this be neater if it returned the num iovecs used? And offsetting iov in the caller, rather than passing iov_count?
drivers/vhost/vhost.c line 542
Quoted 6 lines
drivers/vhost/vhost.c new file +6
-0+/* If their number is silly, that's a fatal mistake. */ +if (head >= vq->num) { +vq_err (vq,"Guest says index %u > %u is available" , + head, vq->num); +return vq->num; + }
Not a fatal mistake in this code/
drivers/vhost/vhost.c line 587
Quoted 1 line
drivers/vhost/vhost.c new file +1
-0+ vq->inflight++;
vq->inflight was a brain fart in the old lguest code. See commit ebf9a5a99c1a464afe0b4dfa64416fc8b273bc5c.
Also, see other fixes to the lguest launcher since then which might be relevant to this code:
lguest: get more serious about wmb() in example Launcher code
lguest: clean up length-used value in example launcher
drivers/vhost/vhost.c line 638
Quoted 3 lines
drivers/vhost/vhost.c new file +3
-0+/* If they don't want an interrupt, don't send one, unless empty. */ +if ((flags &VRING_AVAIL_F_NO_INTERRUPT ) && vq->inflight) +return ;
And I wouldn't support notify on empty at all, TBH. It should definitely be conditional on the guest accepting the NOTIFY_ON_EMPTY feature.
Quoted 2 lines
drivers/vhost/vhost.h new file +2
-0+/* The virtqueue structure describes a queue attached to a device. */ +struct vhost_virtqueue {
...
Quoted 1 line
+}
____cacheline_aligned;
Really? I'd want to see numbers on this one. False sharing vs. more cache utilization.
drivers/vhost/vhost.h line 106
Quoted 5 lines
drivers/vhost/vhost.h new file +5
-0+#define vq_err (vq, fmt, ...) do { \ + printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__); \ + if ((vq)->error_ctx) \ + eventfd_signal((vq)->error_ctx, 1);\ + } while (0)
Mmm... guests should not be able to create unlimited printks in the host.
But really, nothing major to object to in here...
Thanks!
Rusty.
Michael S. Tsirkin
maintainerPATCH v4 2/2 vhost_net: a kernel-level virtio server
In reply to a message not in the archiveWhat it is: vhost net is a character device that can be used to reduce the number of system calls involved in virtio networking. Existing virtio net code is used in the guest without modification.
There's similarity with vringfd, with some differences and reduced scope
- uses eventfd for signalling
- structures can be moved around in memory at any time (good for migration)
- support memory table and not just an offset (needed for kvm)
common virtio related code has been put in a separate file vhost.c and can be made into a separate module if/when more backends appear. I used Rusty's lguest.c as the source for developing this part : this supplied me with witty comments I wouldn't be able to write myself.
What it is not: vhost net is not a bus, and not a generic new system call. No assumptions are made on how guest performs hypercalls. Userspace hypervisors are supported as well as kvm.
How it works: Basically, we connect virtio frontend (configured by userspace) to a backend. The backend could be a network device, or a tun-like device. In this version I only support raw socket as a backend, which can be bound to e.g. SR IOV, or to macvlan device. Backend is also configured by userspace, including vlan/mac etc.
Status:
This works for me, and I haven't see any crashes.
I have not run any benchmarks yet, compared to userspace, I expect to see improved latency (as I save up to 4 system calls per packet) but not bandwidth/CPU (as TSO and interrupt mitigation are not supported).
Features that I plan to look at in the future:
- TSO
- interrupt mitigation
- zero copy
--- MAINTAINERS | 10 + arch/x86/kvm/Kconfig | 1 + drivers/Makefile | 1 + drivers/vhost/Kconfig | 11 + drivers/vhost/Makefile | 2 + drivers/vhost/net.c | 429 ++++++++++++++++++++++++++++ drivers/vhost/vhost.c | 664 ++++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 108 +++++++ include/linux/Kbuild | 1 + include/linux/miscdevice.h | 1 + include/linux/vhost.h | 100 +++++++ 11 files changed, 1328 insertions(+), 0 deletions(-) create mode 100644 drivers/vhost/Kconfig create mode 100644 drivers/vhost/Makefile create mode 100644 drivers/vhost/net.c create mode 100644 drivers/vhost/vhost.c create mode 100644 drivers/vhost/vhost.h create mode 100644 include/linux/vhost.h
MAINTAINERS +10 -0
@@ -5431,6 +5431,16 @@ S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ +VIRTIO HOST (VHOST) +P: Michael S. Tsirkin +M: [email protected] +L: [email protected] +L: [email protected] +L: [email protected] +S: Maintained +F: drivers/vhost/ +F: include/linux/vhost.h + VIA RHINE NETWORK DRIVER M: Roger Luethi <[email protected]> S: Maintained
arch/x86/kvm/Kconfig +1 -0
@@ -64,6 +64,7 @@ config KVM_AMD # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. +source drivers/vhost/Kconfig source drivers/lguest/Kconfig source drivers/virtio/Kconfig
drivers/Makefile +1 -0
@@ -105,6 +105,7 @@ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ obj-$(CONFIG_SSB) += ssb/ +obj-$(CONFIG_VHOST_NET) += vhost/ obj-$(CONFIG_VIRTIO) += virtio/ obj-$(CONFIG_VLYNQ) += vlynq/ obj-$(CONFIG_STAGING) += staging/
drivers/vhost/Kconfig new file +11 -0
@@ -0,0 +1,11 @@ +config VHOST_NET + tristate "Host kernel accelerator for virtio net" + depends on NET && EVENTFD + ---help--- + This kernel module can be loaded in host kernel to accelerate + guest networking with virtio_net. Not to be confused with virtio_net + module itself which needs to be loaded in guest kernel. + + To compile this driver as a module, choose M here: the module will + be called vhost_net. +
drivers/vhost/Makefile new file +2 -0
@@ -0,0 +1,2 @@ +obj-$(CONFIG_VHOST_NET) += vhost_net.o +vhost_net-y := vhost.o net.o
drivers/vhost/net.c new file +429 -0
429 lines not on this page · raw message
drivers/vhost/vhost.c new file +664 -0
664 lines not on this page · raw message
drivers/vhost/vhost.h new file +108 -0
108 lines not on this page · raw message
include/linux/Kbuild +1 -0
@@ -360,6 +360,7 @@ unifdef-y += uio.h unifdef-y += unistd.h unifdef-y += usbdevice_fs.h unifdef-y += utsname.h +unifdef-y += vhost.h unifdef-y += videodev2.h unifdef-y += videodev.h unifdef-y += virtio_config.h
include/linux/miscdevice.h +1 -0
@@ -30,6 +30,7 @@#define HPET_MINOR 228#define FUSE_MINOR 229#define KVM_MINOR 232 +#define VHOST_NET_MINOR 233#define MISC_DYNAMIC_MINOR 255struct device ;
include/linux/vhost.h new file +100 -0
100 lines not on this page · raw message
Signature · 1 line
1.6.2.5