Commit d1a343a0 authored by Linus Torvalds's avatar Linus Torvalds

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
parents b681268c c9ce42f7
...@@ -5899,7 +5899,6 @@ S: Supported ...@@ -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 ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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); ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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, ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment