aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/vfio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio/vfio.c')
-rw-r--r--drivers/vfio/vfio.c117
1 files changed, 90 insertions, 27 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index fcc12f3e60a3..acb7121a9316 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -24,8 +24,10 @@
24#include <linux/list.h> 24#include <linux/list.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/mutex.h> 26#include <linux/mutex.h>
27#include <linux/rwsem.h>
27#include <linux/sched.h> 28#include <linux/sched.h>
28#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/stat.h>
29#include <linux/string.h> 31#include <linux/string.h>
30#include <linux/uaccess.h> 32#include <linux/uaccess.h>
31#include <linux/vfio.h> 33#include <linux/vfio.h>
@@ -57,7 +59,7 @@ struct vfio_iommu_driver {
57struct vfio_container { 59struct vfio_container {
58 struct kref kref; 60 struct kref kref;
59 struct list_head group_list; 61 struct list_head group_list;
60 struct mutex group_lock; 62 struct rw_semaphore group_lock;
61 struct vfio_iommu_driver *iommu_driver; 63 struct vfio_iommu_driver *iommu_driver;
62 void *iommu_data; 64 void *iommu_data;
63}; 65};
@@ -392,12 +394,13 @@ static void vfio_device_release(struct kref *kref)
392} 394}
393 395
394/* Device reference always implies a group reference */ 396/* Device reference always implies a group reference */
395static void vfio_device_put(struct vfio_device *device) 397void vfio_device_put(struct vfio_device *device)
396{ 398{
397 struct vfio_group *group = device->group; 399 struct vfio_group *group = device->group;
398 kref_put_mutex(&device->kref, vfio_device_release, &group->device_lock); 400 kref_put_mutex(&device->kref, vfio_device_release, &group->device_lock);
399 vfio_group_put(group); 401 vfio_group_put(group);
400} 402}
403EXPORT_SYMBOL_GPL(vfio_device_put);
401 404
402static void vfio_device_get(struct vfio_device *device) 405static void vfio_device_get(struct vfio_device *device)
403{ 406{
@@ -627,6 +630,33 @@ int vfio_add_group_dev(struct device *dev,
627} 630}
628EXPORT_SYMBOL_GPL(vfio_add_group_dev); 631EXPORT_SYMBOL_GPL(vfio_add_group_dev);
629 632
633/**
634 * Get a reference to the vfio_device for a device that is known to
635 * be bound to a vfio driver. The driver implicitly holds a
636 * vfio_device reference between vfio_add_group_dev and
637 * vfio_del_group_dev. We can therefore use drvdata to increment
638 * that reference from the struct device. This additional
639 * reference must be released by calling vfio_device_put.
640 */
641struct vfio_device *vfio_device_get_from_dev(struct device *dev)
642{
643 struct vfio_device *device = dev_get_drvdata(dev);
644
645 vfio_device_get(device);
646
647 return device;
648}
649EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
650
651/*
652 * Caller must hold a reference to the vfio_device
653 */
654void *vfio_device_data(struct vfio_device *device)
655{
656 return device->device_data;
657}
658EXPORT_SYMBOL_GPL(vfio_device_data);
659
630/* Given a referenced group, check if it contains the device */ 660/* Given a referenced group, check if it contains the device */
631static bool vfio_dev_present(struct vfio_group *group, struct device *dev) 661static bool vfio_dev_present(struct vfio_group *group, struct device *dev)
632{ 662{
@@ -675,9 +705,13 @@ EXPORT_SYMBOL_GPL(vfio_del_group_dev);
675static long vfio_ioctl_check_extension(struct vfio_container *container, 705static long vfio_ioctl_check_extension(struct vfio_container *container,
676 unsigned long arg) 706 unsigned long arg)
677{ 707{
678 struct vfio_iommu_driver *driver = container->iommu_driver; 708 struct vfio_iommu_driver *driver;
679 long ret = 0; 709 long ret = 0;
680 710
711 down_read(&container->group_lock);
712
713 driver = container->iommu_driver;
714
681 switch (arg) { 715 switch (arg) {
682 /* No base extensions yet */ 716 /* No base extensions yet */
683 default: 717 default:
@@ -707,10 +741,12 @@ static long vfio_ioctl_check_extension(struct vfio_container *container,
707 VFIO_CHECK_EXTENSION, arg); 741 VFIO_CHECK_EXTENSION, arg);
708 } 742 }
709 743
744 up_read(&container->group_lock);
745
710 return ret; 746 return ret;
711} 747}
712 748
713/* hold container->group_lock */ 749/* hold write lock on container->group_lock */
714static int __vfio_container_attach_groups(struct vfio_container *container, 750static int __vfio_container_attach_groups(struct vfio_container *container,
715 struct vfio_iommu_driver *driver, 751 struct vfio_iommu_driver *driver,
716 void *data) 752 void *data)
@@ -741,7 +777,7 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container,
741 struct vfio_iommu_driver *driver; 777 struct vfio_iommu_driver *driver;
742 long ret = -ENODEV; 778 long ret = -ENODEV;
743 779
744 mutex_lock(&container->group_lock); 780 down_write(&container->group_lock);
745 781
746 /* 782 /*
747 * The container is designed to be an unprivileged interface while 783 * The container is designed to be an unprivileged interface while
@@ -752,7 +788,7 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container,
752 * the container is deprivileged and returns to an unset state. 788 * the container is deprivileged and returns to an unset state.
753 */ 789 */
754 if (list_empty(&container->group_list) || container->iommu_driver) { 790 if (list_empty(&container->group_list) || container->iommu_driver) {
755 mutex_unlock(&container->group_lock); 791 up_write(&container->group_lock);
756 return -EINVAL; 792 return -EINVAL;
757 } 793 }
758 794
@@ -799,7 +835,7 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container,
799 835
800 mutex_unlock(&vfio.iommu_drivers_lock); 836 mutex_unlock(&vfio.iommu_drivers_lock);
801skip_drivers_unlock: 837skip_drivers_unlock:
802 mutex_unlock(&container->group_lock); 838 up_write(&container->group_lock);
803 839
804 return ret; 840 return ret;
805} 841}
@@ -815,9 +851,6 @@ static long vfio_fops_unl_ioctl(struct file *filep,
815 if (!container) 851 if (!container)
816 return ret; 852 return ret;
817 853
818 driver = container->iommu_driver;
819 data = container->iommu_data;
820
821 switch (cmd) { 854 switch (cmd) {
822 case VFIO_GET_API_VERSION: 855 case VFIO_GET_API_VERSION:
823 ret = VFIO_API_VERSION; 856 ret = VFIO_API_VERSION;
@@ -829,8 +862,15 @@ static long vfio_fops_unl_ioctl(struct file *filep,
829 ret = vfio_ioctl_set_iommu(container, arg); 862 ret = vfio_ioctl_set_iommu(container, arg);
830 break; 863 break;
831 default: 864 default:
865 down_read(&container->group_lock);
866
867 driver = container->iommu_driver;
868 data = container->iommu_data;
869
832 if (driver) /* passthrough all unrecognized ioctls */ 870 if (driver) /* passthrough all unrecognized ioctls */
833 ret = driver->ops->ioctl(data, cmd, arg); 871 ret = driver->ops->ioctl(data, cmd, arg);
872
873 up_read(&container->group_lock);
834 } 874 }
835 875
836 return ret; 876 return ret;
@@ -854,7 +894,7 @@ static int vfio_fops_open(struct inode *inode, struct file *filep)
854 return -ENOMEM; 894 return -ENOMEM;
855 895
856 INIT_LIST_HEAD(&container->group_list); 896 INIT_LIST_HEAD(&container->group_list);
857 mutex_init(&container->group_lock); 897 init_rwsem(&container->group_lock);
858 kref_init(&container->kref); 898 kref_init(&container->kref);
859 899
860 filep->private_data = container; 900 filep->private_data = container;
@@ -881,35 +921,55 @@ static ssize_t vfio_fops_read(struct file *filep, char __user *buf,
881 size_t count, loff_t *ppos) 921 size_t count, loff_t *ppos)
882{ 922{
883 struct vfio_container *container = filep->private_data; 923 struct vfio_container *container = filep->private_data;
884 struct vfio_iommu_driver *driver = container->iommu_driver; 924 struct vfio_iommu_driver *driver;
925 ssize_t ret = -EINVAL;
885 926
886 if (unlikely(!driver || !driver->ops->read)) 927 down_read(&container->group_lock);
887 return -EINVAL;
888 928
889 return driver->ops->read(container->iommu_data, buf, count, ppos); 929 driver = container->iommu_driver;
930 if (likely(driver && driver->ops->read))
931 ret = driver->ops->read(container->iommu_data,
932 buf, count, ppos);
933
934 up_read(&container->group_lock);
935
936 return ret;
890} 937}
891 938
892static ssize_t vfio_fops_write(struct file *filep, const char __user *buf, 939static ssize_t vfio_fops_write(struct file *filep, const char __user *buf,
893 size_t count, loff_t *ppos) 940 size_t count, loff_t *ppos)
894{ 941{
895 struct vfio_container *container = filep->private_data; 942 struct vfio_container *container = filep->private_data;
896 struct vfio_iommu_driver *driver = container->iommu_driver; 943 struct vfio_iommu_driver *driver;
944 ssize_t ret = -EINVAL;
897 945
898 if (unlikely(!driver || !driver->ops->write)) 946 down_read(&container->group_lock);
899 return -EINVAL;
900 947
901 return driver->ops->write(container->iommu_data, buf, count, ppos); 948 driver = container->iommu_driver;
949 if (likely(driver && driver->ops->write))
950 ret = driver->ops->write(container->iommu_data,
951 buf, count, ppos);
952
953 up_read(&container->group_lock);
954
955 return ret;
902} 956}
903 957
904static int vfio_fops_mmap(struct file *filep, struct vm_area_struct *vma) 958static int vfio_fops_mmap(struct file *filep, struct vm_area_struct *vma)
905{ 959{
906 struct vfio_container *container = filep->private_data; 960 struct vfio_container *container = filep->private_data;
907 struct vfio_iommu_driver *driver = container->iommu_driver; 961 struct vfio_iommu_driver *driver;
962 int ret = -EINVAL;
908 963
909 if (unlikely(!driver || !driver->ops->mmap)) 964 down_read(&container->group_lock);
910 return -EINVAL;
911 965
912 return driver->ops->mmap(container->iommu_data, vma); 966 driver = container->iommu_driver;
967 if (likely(driver && driver->ops->mmap))
968 ret = driver->ops->mmap(container->iommu_data, vma);
969
970 up_read(&container->group_lock);
971
972 return ret;
913} 973}
914 974
915static const struct file_operations vfio_fops = { 975static const struct file_operations vfio_fops = {
@@ -933,7 +993,7 @@ static void __vfio_group_unset_container(struct vfio_group *group)
933 struct vfio_container *container = group->container; 993 struct vfio_container *container = group->container;
934 struct vfio_iommu_driver *driver; 994 struct vfio_iommu_driver *driver;
935 995
936 mutex_lock(&container->group_lock); 996 down_write(&container->group_lock);
937 997
938 driver = container->iommu_driver; 998 driver = container->iommu_driver;
939 if (driver) 999 if (driver)
@@ -951,7 +1011,7 @@ static void __vfio_group_unset_container(struct vfio_group *group)
951 container->iommu_data = NULL; 1011 container->iommu_data = NULL;
952 } 1012 }
953 1013
954 mutex_unlock(&container->group_lock); 1014 up_write(&container->group_lock);
955 1015
956 vfio_container_put(container); 1016 vfio_container_put(container);
957} 1017}
@@ -1011,7 +1071,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
1011 container = f.file->private_data; 1071 container = f.file->private_data;
1012 WARN_ON(!container); /* fget ensures we don't race vfio_release */ 1072 WARN_ON(!container); /* fget ensures we don't race vfio_release */
1013 1073
1014 mutex_lock(&container->group_lock); 1074 down_write(&container->group_lock);
1015 1075
1016 driver = container->iommu_driver; 1076 driver = container->iommu_driver;
1017 if (driver) { 1077 if (driver) {
@@ -1029,7 +1089,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
1029 atomic_inc(&group->container_users); 1089 atomic_inc(&group->container_users);
1030 1090
1031unlock_out: 1091unlock_out:
1032 mutex_unlock(&container->group_lock); 1092 up_write(&container->group_lock);
1033 fdput(f); 1093 fdput(f);
1034 return ret; 1094 return ret;
1035} 1095}
@@ -1300,6 +1360,9 @@ static const struct file_operations vfio_device_fops = {
1300 */ 1360 */
1301static char *vfio_devnode(struct device *dev, umode_t *mode) 1361static char *vfio_devnode(struct device *dev, umode_t *mode)
1302{ 1362{
1363 if (MINOR(dev->devt) == 0)
1364 *mode = S_IRUGO | S_IWUGO;
1365
1303 return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev)); 1366 return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev));
1304} 1367}
1305 1368