virtio/vhost: fixes for 4.2
Bugfixes and documentation fixes. Igor's patch that allows users to tweak memory table size is borderline, but it does fix known crashes, so I merged it. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVpBzpAAoJECgfDbjSjVRpQXEIAMEqetqPuRduynjIw2HNktle fe/UUhvipwTsAM4R2pmcEl5tW04A/M54RkXN4iVy0rPshAfG3Fh4XTjLmzSGU0fI KD6qX8/Zc/+DUWnfe3aUC6jOOrjb7c4xRKOlQ9X8lZgi2M6AzrPeoZHFTtbX34CU 2kcnv5Sb1SaI/t2SaCc2CaKilQalEOcd59gGjje2QXjidZnIVHwONrOyjBiINUy6 GzfTgvAje8ZiG6951W3HDwwSfcqXezin27LJqnZgaLCwTCKt2gdQ2MAKjrfP2aVF +gX2B4XxcFLutMVx/obsjvA1ceipubyUauRLB3mnO3P5VOj1qbofa2lj4pzQ80k= =EKPr -----END PGP SIGNATURE----- Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost Pull virtio/vhost fixes from Michael Tsirkin: "Bugfixes and documentation fixes. Igor's patch that allows users to tweak memory table size is borderline, but it does fix known crashes, so I merged it" * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: vhost: add max_mem_regions module parameter vhost: extend memory regions allocation to vmalloc 9p/trans_virtio: reset virtio device on remove virtio/s390: rename drivers/s390/kvm -> drivers/s390/virtio MAINTAINERS: separate section for s390 virtio drivers virtio: define virtio_pci_cfg_cap in header. virtio: Fix typecast of pointer in vring_init() virtio scsi: fix unused variable warning vhost: use binary search instead of linear in find_region() virtio_net: document VIRTIO_NET_CTRL_GUEST_OFFLOADS
This commit is contained in:
		
				commit
				
					
						d1a343a023
					
				
			
		
					 11 changed files with 91 additions and 20 deletions
				
			
		
							
								
								
									
										10
									
								
								MAINTAINERS
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								MAINTAINERS
									
										
									
									
									
								
							|  | @ -5899,7 +5899,6 @@ S:	Supported | ||||||
| F:	Documentation/s390/kvm.txt | F:	Documentation/s390/kvm.txt | ||||||
| F:	arch/s390/include/asm/kvm* | F:	arch/s390/include/asm/kvm* | ||||||
| F:	arch/s390/kvm/ | F:	arch/s390/kvm/ | ||||||
| F:	drivers/s390/kvm/ |  | ||||||
| 
 | 
 | ||||||
| KERNEL VIRTUAL MACHINE (KVM) FOR ARM | KERNEL VIRTUAL MACHINE (KVM) FOR ARM | ||||||
| M:	Christoffer Dall <christoffer.dall@linaro.org> | M:	Christoffer Dall <christoffer.dall@linaro.org> | ||||||
|  | @ -10896,6 +10895,15 @@ F:	drivers/block/virtio_blk.c | ||||||
| F:	include/linux/virtio_*.h | F:	include/linux/virtio_*.h | ||||||
| F:	include/uapi/linux/virtio_*.h | F:	include/uapi/linux/virtio_*.h | ||||||
| 
 | 
 | ||||||
|  | VIRTIO DRIVERS FOR S390 | ||||||
|  | M:	Christian Borntraeger <borntraeger@de.ibm.com> | ||||||
|  | M:	Cornelia Huck <cornelia.huck@de.ibm.com> | ||||||
|  | L:	linux-s390@vger.kernel.org | ||||||
|  | L:	virtualization@lists.linux-foundation.org | ||||||
|  | L:	kvm@vger.kernel.org | ||||||
|  | S:	Supported | ||||||
|  | F:	drivers/s390/virtio/ | ||||||
|  | 
 | ||||||
| VIRTIO GPU DRIVER | VIRTIO GPU DRIVER | ||||||
| M:	David Airlie <airlied@linux.ie> | M:	David Airlie <airlied@linux.ie> | ||||||
| M:	Gerd Hoffmann <kraxel@redhat.com> | M:	Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| # Makefile for the S/390 specific device drivers
 | # Makefile for the S/390 specific device drivers
 | ||||||
| #
 | #
 | ||||||
| 
 | 
 | ||||||
| obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ | obj-y += cio/ block/ char/ crypto/ net/ scsi/ virtio/ | ||||||
| 
 | 
 | ||||||
| drivers-y += drivers/s390/built-in.o | drivers-y += drivers/s390/built-in.o | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -949,7 +949,7 @@ static int virtscsi_probe(struct virtio_device *vdev) | ||||||
| { | { | ||||||
| 	struct Scsi_Host *shost; | 	struct Scsi_Host *shost; | ||||||
| 	struct virtio_scsi *vscsi; | 	struct virtio_scsi *vscsi; | ||||||
| 	int err, host_prot; | 	int err; | ||||||
| 	u32 sg_elems, num_targets; | 	u32 sg_elems, num_targets; | ||||||
| 	u32 cmd_per_lun; | 	u32 cmd_per_lun; | ||||||
| 	u32 num_queues; | 	u32 num_queues; | ||||||
|  | @ -1009,6 +1009,8 @@ static int virtscsi_probe(struct virtio_device *vdev) | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_BLK_DEV_INTEGRITY | #ifdef CONFIG_BLK_DEV_INTEGRITY | ||||||
| 	if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) { | 	if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) { | ||||||
|  | 		int host_prot; | ||||||
|  | 
 | ||||||
| 		host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | | 		host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | | ||||||
| 			    SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | | 			    SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | | ||||||
| 			    SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; | 			    SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; | ||||||
|  |  | ||||||
|  | @ -22,14 +22,20 @@ | ||||||
| #include <linux/file.h> | #include <linux/file.h> | ||||||
| #include <linux/highmem.h> | #include <linux/highmem.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
|  | #include <linux/vmalloc.h> | ||||||
| #include <linux/kthread.h> | #include <linux/kthread.h> | ||||||
| #include <linux/cgroup.h> | #include <linux/cgroup.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
|  | #include <linux/sort.h> | ||||||
| 
 | 
 | ||||||
| #include "vhost.h" | #include "vhost.h" | ||||||
| 
 | 
 | ||||||
|  | static ushort max_mem_regions = 64; | ||||||
|  | module_param(max_mem_regions, ushort, 0444); | ||||||
|  | MODULE_PARM_DESC(max_mem_regions, | ||||||
|  | 	"Maximum number of memory regions in memory map. (default: 64)"); | ||||||
|  | 
 | ||||||
| enum { | enum { | ||||||
| 	VHOST_MEMORY_MAX_NREGIONS = 64, |  | ||||||
| 	VHOST_MEMORY_F_LOG = 0x1, | 	VHOST_MEMORY_F_LOG = 0x1, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -543,7 +549,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked) | ||||||
| 		fput(dev->log_file); | 		fput(dev->log_file); | ||||||
| 	dev->log_file = NULL; | 	dev->log_file = NULL; | ||||||
| 	/* No one will access memory at this point */ | 	/* No one will access memory at this point */ | ||||||
| 	kfree(dev->memory); | 	kvfree(dev->memory); | ||||||
| 	dev->memory = NULL; | 	dev->memory = NULL; | ||||||
| 	WARN_ON(!list_empty(&dev->work_list)); | 	WARN_ON(!list_empty(&dev->work_list)); | ||||||
| 	if (dev->worker) { | 	if (dev->worker) { | ||||||
|  | @ -663,6 +669,28 @@ int vhost_vq_access_ok(struct vhost_virtqueue *vq) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(vhost_vq_access_ok); | EXPORT_SYMBOL_GPL(vhost_vq_access_ok); | ||||||
| 
 | 
 | ||||||
|  | static int vhost_memory_reg_sort_cmp(const void *p1, const void *p2) | ||||||
|  | { | ||||||
|  | 	const struct vhost_memory_region *r1 = p1, *r2 = p2; | ||||||
|  | 	if (r1->guest_phys_addr < r2->guest_phys_addr) | ||||||
|  | 		return 1; | ||||||
|  | 	if (r1->guest_phys_addr > r2->guest_phys_addr) | ||||||
|  | 		return -1; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void *vhost_kvzalloc(unsigned long size) | ||||||
|  | { | ||||||
|  | 	void *n = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); | ||||||
|  | 
 | ||||||
|  | 	if (!n) { | ||||||
|  | 		n = vzalloc(size); | ||||||
|  | 		if (!n) | ||||||
|  | 			return ERR_PTR(-ENOMEM); | ||||||
|  | 	} | ||||||
|  | 	return n; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | ||||||
| { | { | ||||||
| 	struct vhost_memory mem, *newmem, *oldmem; | 	struct vhost_memory mem, *newmem, *oldmem; | ||||||
|  | @ -673,21 +701,23 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 	if (mem.padding) | 	if (mem.padding) | ||||||
| 		return -EOPNOTSUPP; | 		return -EOPNOTSUPP; | ||||||
| 	if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) | 	if (mem.nregions > max_mem_regions) | ||||||
| 		return -E2BIG; | 		return -E2BIG; | ||||||
| 	newmem = kmalloc(size + mem.nregions * sizeof *m->regions, GFP_KERNEL); | 	newmem = vhost_kvzalloc(size + mem.nregions * sizeof(*m->regions)); | ||||||
| 	if (!newmem) | 	if (!newmem) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	memcpy(newmem, &mem, size); | 	memcpy(newmem, &mem, size); | ||||||
| 	if (copy_from_user(newmem->regions, m->regions, | 	if (copy_from_user(newmem->regions, m->regions, | ||||||
| 			   mem.nregions * sizeof *m->regions)) { | 			   mem.nregions * sizeof *m->regions)) { | ||||||
| 		kfree(newmem); | 		kvfree(newmem); | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 	} | 	} | ||||||
|  | 	sort(newmem->regions, newmem->nregions, sizeof(*newmem->regions), | ||||||
|  | 		vhost_memory_reg_sort_cmp, NULL); | ||||||
| 
 | 
 | ||||||
| 	if (!memory_access_ok(d, newmem, 0)) { | 	if (!memory_access_ok(d, newmem, 0)) { | ||||||
| 		kfree(newmem); | 		kvfree(newmem); | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 	} | 	} | ||||||
| 	oldmem = d->memory; | 	oldmem = d->memory; | ||||||
|  | @ -699,7 +729,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | ||||||
| 		d->vqs[i]->memory = newmem; | 		d->vqs[i]->memory = newmem; | ||||||
| 		mutex_unlock(&d->vqs[i]->mutex); | 		mutex_unlock(&d->vqs[i]->mutex); | ||||||
| 	} | 	} | ||||||
| 	kfree(oldmem); | 	kvfree(oldmem); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -992,17 +1022,22 @@ EXPORT_SYMBOL_GPL(vhost_dev_ioctl); | ||||||
| static const struct vhost_memory_region *find_region(struct vhost_memory *mem, | static const struct vhost_memory_region *find_region(struct vhost_memory *mem, | ||||||
| 						     __u64 addr, __u32 len) | 						     __u64 addr, __u32 len) | ||||||
| { | { | ||||||
| 	struct vhost_memory_region *reg; | 	const struct vhost_memory_region *reg; | ||||||
| 	int i; | 	int start = 0, end = mem->nregions; | ||||||
| 
 | 
 | ||||||
| 	/* linear search is not brilliant, but we really have on the order of 6
 | 	while (start < end) { | ||||||
| 	 * regions in practice */ | 		int slot = start + (end - start) / 2; | ||||||
| 	for (i = 0; i < mem->nregions; ++i) { | 		reg = mem->regions + slot; | ||||||
| 		reg = mem->regions + i; | 		if (addr >= reg->guest_phys_addr) | ||||||
| 		if (reg->guest_phys_addr <= addr && | 			end = slot; | ||||||
| 		    reg->guest_phys_addr + reg->memory_size - 1 >= addr) | 		else | ||||||
| 			return reg; | 			start = slot + 1; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	reg = mem->regions + start; | ||||||
|  | 	if (addr >= reg->guest_phys_addr && | ||||||
|  | 		reg->guest_phys_addr + reg->memory_size > addr) | ||||||
|  | 		return reg; | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ | ||||||
| /* The feature bitmap for virtio net */ | /* The feature bitmap for virtio net */ | ||||||
| #define VIRTIO_NET_F_CSUM	0	/* Host handles pkts w/ partial csum */ | #define VIRTIO_NET_F_CSUM	0	/* Host handles pkts w/ partial csum */ | ||||||
| #define VIRTIO_NET_F_GUEST_CSUM	1	/* Guest handles pkts w/ partial csum */ | #define VIRTIO_NET_F_GUEST_CSUM	1	/* Guest handles pkts w/ partial csum */ | ||||||
|  | #define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Dynamic offload configuration. */ | ||||||
| #define VIRTIO_NET_F_MAC	5	/* Host has given MAC address. */ | #define VIRTIO_NET_F_MAC	5	/* Host has given MAC address. */ | ||||||
| #define VIRTIO_NET_F_GUEST_TSO4	7	/* Guest can handle TSOv4 in. */ | #define VIRTIO_NET_F_GUEST_TSO4	7	/* Guest can handle TSOv4 in. */ | ||||||
| #define VIRTIO_NET_F_GUEST_TSO6	8	/* Guest can handle TSOv6 in. */ | #define VIRTIO_NET_F_GUEST_TSO6	8	/* Guest can handle TSOv6 in. */ | ||||||
|  | @ -226,4 +227,19 @@ struct virtio_net_ctrl_mq { | ||||||
|  #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1 |  #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1 | ||||||
|  #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000 |  #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000 | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Control network offloads | ||||||
|  |  * | ||||||
|  |  * Reconfigures the network offloads that Guest can handle. | ||||||
|  |  * | ||||||
|  |  * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit. | ||||||
|  |  * | ||||||
|  |  * Command data format matches the feature bit mask exactly. | ||||||
|  |  * | ||||||
|  |  * See VIRTIO_NET_F_GUEST_* for the list of offloads | ||||||
|  |  * that can be enabled/disabled. | ||||||
|  |  */ | ||||||
|  | #define VIRTIO_NET_CTRL_GUEST_OFFLOADS   5 | ||||||
|  | #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET        0 | ||||||
|  | 
 | ||||||
| #endif /* _LINUX_VIRTIO_NET_H */ | #endif /* _LINUX_VIRTIO_NET_H */ | ||||||
|  |  | ||||||
|  | @ -157,6 +157,12 @@ struct virtio_pci_common_cfg { | ||||||
| 	__le32 queue_used_hi;		/* read-write */ | 	__le32 queue_used_hi;		/* read-write */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */ | ||||||
|  | struct virtio_pci_cfg_cap { | ||||||
|  | 	struct virtio_pci_cap cap; | ||||||
|  | 	__u8 pci_cfg_data[4]; /* Data for BAR access. */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /* Macro versions of offsets for the Old Timers! */ | /* Macro versions of offsets for the Old Timers! */ | ||||||
| #define VIRTIO_PCI_CAP_VNDR		0 | #define VIRTIO_PCI_CAP_VNDR		0 | ||||||
| #define VIRTIO_PCI_CAP_NEXT		1 | #define VIRTIO_PCI_CAP_NEXT		1 | ||||||
|  |  | ||||||
|  | @ -31,6 +31,9 @@ | ||||||
|  * SUCH DAMAGE. |  * SUCH DAMAGE. | ||||||
|  * |  * | ||||||
|  * Copyright Rusty Russell IBM Corporation 2007. */ |  * Copyright Rusty Russell IBM Corporation 2007. */ | ||||||
|  | #ifndef __KERNEL__ | ||||||
|  | #include <stdint.h> | ||||||
|  | #endif | ||||||
| #include <linux/types.h> | #include <linux/types.h> | ||||||
| #include <linux/virtio_types.h> | #include <linux/virtio_types.h> | ||||||
| 
 | 
 | ||||||
|  | @ -143,7 +146,7 @@ static inline void vring_init(struct vring *vr, unsigned int num, void *p, | ||||||
| 	vr->num = num; | 	vr->num = num; | ||||||
| 	vr->desc = p; | 	vr->desc = p; | ||||||
| 	vr->avail = p + num*sizeof(struct vring_desc); | 	vr->avail = p + num*sizeof(struct vring_desc); | ||||||
| 	vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__virtio16) | 	vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(__virtio16) | ||||||
| 		+ align-1) & ~(align - 1)); | 		+ align-1) & ~(align - 1)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -704,6 +704,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) | ||||||
| 
 | 
 | ||||||
| 	mutex_unlock(&virtio_9p_lock); | 	mutex_unlock(&virtio_9p_lock); | ||||||
| 
 | 
 | ||||||
|  | 	vdev->config->reset(vdev); | ||||||
| 	vdev->config->del_vqs(vdev); | 	vdev->config->del_vqs(vdev); | ||||||
| 
 | 
 | ||||||
| 	sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | 	sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Linus Torvalds
				Linus Torvalds