aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-01 16:18:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-01 16:18:25 -0500
commit34b1cf60abb06fa79d5f8e56f1def843dbf91888 (patch)
tree2b6145709fa3c5900957cc0f625fad85f9378c7b
parent27529c891b132f4fc65711334e885f466138ea2a (diff)
parent46ed90f157f42d956ffed17c003f089a59b76e3e (diff)
Merge tag 'vfio-v4.16-rc1' of git://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson: - Mask INTx from user if pdev->irq is zero (Alexey Kardashevskiy) - Capability helper cleanup (Alex Williamson) - Allow mmaps overlapping MSI-X vector table with region capability exposing this feature (Alexey Kardashevskiy) - mdev static cleanups (Xiongwei Song) * tag 'vfio-v4.16-rc1' of git://github.com/awilliam/linux-vfio: vfio: mdev: make a couple of functions and structure vfio_mdev_driver static vfio-pci: Allow mapping MSIX BAR vfio: Simplify capability helper vfio-pci: Mask INTx if a device is not capabable of enabling it
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c15
-rw-r--r--drivers/vfio/mdev/vfio_mdev.c6
-rw-r--r--drivers/vfio/pci/vfio_pci.c75
-rw-r--r--drivers/vfio/vfio.c52
-rw-r--r--include/linux/vfio.h3
-rw-r--r--include/uapi/linux/vfio.h10
6 files changed, 45 insertions, 116 deletions
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 96060920a6fe..0a7d084da1a2 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1012,6 +1012,8 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
1012 if (!sparse) 1012 if (!sparse)
1013 return -ENOMEM; 1013 return -ENOMEM;
1014 1014
1015 sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
1016 sparse->header.version = 1;
1015 sparse->nr_areas = nr_areas; 1017 sparse->nr_areas = nr_areas;
1016 cap_type_id = VFIO_REGION_INFO_CAP_SPARSE_MMAP; 1018 cap_type_id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
1017 sparse->areas[0].offset = 1019 sparse->areas[0].offset =
@@ -1033,7 +1035,9 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
1033 break; 1035 break;
1034 default: 1036 default:
1035 { 1037 {
1036 struct vfio_region_info_cap_type cap_type; 1038 struct vfio_region_info_cap_type cap_type = {
1039 .header.id = VFIO_REGION_INFO_CAP_TYPE,
1040 .header.version = 1 };
1037 1041
1038 if (info.index >= VFIO_PCI_NUM_REGIONS + 1042 if (info.index >= VFIO_PCI_NUM_REGIONS +
1039 vgpu->vdev.num_regions) 1043 vgpu->vdev.num_regions)
@@ -1050,8 +1054,8 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
1050 cap_type.subtype = vgpu->vdev.region[i].subtype; 1054 cap_type.subtype = vgpu->vdev.region[i].subtype;
1051 1055
1052 ret = vfio_info_add_capability(&caps, 1056 ret = vfio_info_add_capability(&caps,
1053 VFIO_REGION_INFO_CAP_TYPE, 1057 &cap_type.header,
1054 &cap_type); 1058 sizeof(cap_type));
1055 if (ret) 1059 if (ret)
1056 return ret; 1060 return ret;
1057 } 1061 }
@@ -1061,8 +1065,9 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
1061 switch (cap_type_id) { 1065 switch (cap_type_id) {
1062 case VFIO_REGION_INFO_CAP_SPARSE_MMAP: 1066 case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
1063 ret = vfio_info_add_capability(&caps, 1067 ret = vfio_info_add_capability(&caps,
1064 VFIO_REGION_INFO_CAP_SPARSE_MMAP, 1068 &sparse->header, sizeof(*sparse) +
1065 sparse); 1069 (sparse->nr_areas *
1070 sizeof(*sparse->areas)));
1066 kfree(sparse); 1071 kfree(sparse);
1067 if (ret) 1072 if (ret)
1068 return ret; 1073 return ret;
diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
index fa848a701b8b..d230620fe02d 100644
--- a/drivers/vfio/mdev/vfio_mdev.c
+++ b/drivers/vfio/mdev/vfio_mdev.c
@@ -111,19 +111,19 @@ static const struct vfio_device_ops vfio_mdev_dev_ops = {
111 .mmap = vfio_mdev_mmap, 111 .mmap = vfio_mdev_mmap,
112}; 112};
113 113
114int vfio_mdev_probe(struct device *dev) 114static int vfio_mdev_probe(struct device *dev)
115{ 115{
116 struct mdev_device *mdev = to_mdev_device(dev); 116 struct mdev_device *mdev = to_mdev_device(dev);
117 117
118 return vfio_add_group_dev(dev, &vfio_mdev_dev_ops, mdev); 118 return vfio_add_group_dev(dev, &vfio_mdev_dev_ops, mdev);
119} 119}
120 120
121void vfio_mdev_remove(struct device *dev) 121static void vfio_mdev_remove(struct device *dev)
122{ 122{
123 vfio_del_group_dev(dev); 123 vfio_del_group_dev(dev);
124} 124}
125 125
126struct mdev_driver vfio_mdev_driver = { 126static struct mdev_driver vfio_mdev_driver = {
127 .name = "vfio_mdev", 127 .name = "vfio_mdev",
128 .probe = vfio_mdev_probe, 128 .probe = vfio_mdev_probe,
129 .remove = vfio_mdev_remove, 129 .remove = vfio_mdev_remove,
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index f041b1a6cf66..b0f759476900 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -207,6 +207,9 @@ static bool vfio_pci_nointx(struct pci_dev *pdev)
207 } 207 }
208 } 208 }
209 209
210 if (!pdev->irq)
211 return true;
212
210 return false; 213 return false;
211} 214}
212 215
@@ -562,46 +565,15 @@ static int vfio_pci_for_each_slot_or_bus(struct pci_dev *pdev,
562 return walk.ret; 565 return walk.ret;
563} 566}
564 567
565static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev, 568static int msix_mmappable_cap(struct vfio_pci_device *vdev,
566 struct vfio_info_cap *caps) 569 struct vfio_info_cap *caps)
567{ 570{
568 struct vfio_region_info_cap_sparse_mmap *sparse; 571 struct vfio_info_cap_header header = {
569 size_t end, size; 572 .id = VFIO_REGION_INFO_CAP_MSIX_MAPPABLE,
570 int nr_areas = 2, i = 0, ret; 573 .version = 1
571 574 };
572 end = pci_resource_len(vdev->pdev, vdev->msix_bar);
573
574 /* If MSI-X table is aligned to the start or end, only one area */
575 if (((vdev->msix_offset & PAGE_MASK) == 0) ||
576 (PAGE_ALIGN(vdev->msix_offset + vdev->msix_size) >= end))
577 nr_areas = 1;
578
579 size = sizeof(*sparse) + (nr_areas * sizeof(*sparse->areas));
580
581 sparse = kzalloc(size, GFP_KERNEL);
582 if (!sparse)
583 return -ENOMEM;
584
585 sparse->nr_areas = nr_areas;
586
587 if (vdev->msix_offset & PAGE_MASK) {
588 sparse->areas[i].offset = 0;
589 sparse->areas[i].size = vdev->msix_offset & PAGE_MASK;
590 i++;
591 }
592
593 if (PAGE_ALIGN(vdev->msix_offset + vdev->msix_size) < end) {
594 sparse->areas[i].offset = PAGE_ALIGN(vdev->msix_offset +
595 vdev->msix_size);
596 sparse->areas[i].size = end - sparse->areas[i].offset;
597 i++;
598 }
599
600 ret = vfio_info_add_capability(caps, VFIO_REGION_INFO_CAP_SPARSE_MMAP,
601 sparse);
602 kfree(sparse);
603 575
604 return ret; 576 return vfio_info_add_capability(caps, &header, sizeof(header));
605} 577}
606 578
607int vfio_pci_register_dev_region(struct vfio_pci_device *vdev, 579int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
@@ -692,7 +664,7 @@ static long vfio_pci_ioctl(void *device_data,
692 if (vdev->bar_mmap_supported[info.index]) { 664 if (vdev->bar_mmap_supported[info.index]) {
693 info.flags |= VFIO_REGION_INFO_FLAG_MMAP; 665 info.flags |= VFIO_REGION_INFO_FLAG_MMAP;
694 if (info.index == vdev->msix_bar) { 666 if (info.index == vdev->msix_bar) {
695 ret = msix_sparse_mmap_cap(vdev, &caps); 667 ret = msix_mmappable_cap(vdev, &caps);
696 if (ret) 668 if (ret)
697 return ret; 669 return ret;
698 } 670 }
@@ -741,7 +713,9 @@ static long vfio_pci_ioctl(void *device_data,
741 break; 713 break;
742 default: 714 default:
743 { 715 {
744 struct vfio_region_info_cap_type cap_type; 716 struct vfio_region_info_cap_type cap_type = {
717 .header.id = VFIO_REGION_INFO_CAP_TYPE,
718 .header.version = 1 };
745 719
746 if (info.index >= 720 if (info.index >=
747 VFIO_PCI_NUM_REGIONS + vdev->num_regions) 721 VFIO_PCI_NUM_REGIONS + vdev->num_regions)
@@ -756,9 +730,8 @@ static long vfio_pci_ioctl(void *device_data,
756 cap_type.type = vdev->region[i].type; 730 cap_type.type = vdev->region[i].type;
757 cap_type.subtype = vdev->region[i].subtype; 731 cap_type.subtype = vdev->region[i].subtype;
758 732
759 ret = vfio_info_add_capability(&caps, 733 ret = vfio_info_add_capability(&caps, &cap_type.header,
760 VFIO_REGION_INFO_CAP_TYPE, 734 sizeof(cap_type));
761 &cap_type);
762 if (ret) 735 if (ret)
763 return ret; 736 return ret;
764 737
@@ -1122,22 +1095,6 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
1122 if (req_start + req_len > phys_len) 1095 if (req_start + req_len > phys_len)
1123 return -EINVAL; 1096 return -EINVAL;
1124 1097
1125 if (index == vdev->msix_bar) {
1126 /*
1127 * Disallow mmaps overlapping the MSI-X table; users don't
1128 * get to touch this directly. We could find somewhere
1129 * else to map the overlap, but page granularity is only
1130 * a recommendation, not a requirement, so the user needs
1131 * to know which bits are real. Requiring them to mmap
1132 * around the table makes that clear.
1133 */
1134
1135 /* If neither entirely above nor below, then it overlaps */
1136 if (!(req_start >= vdev->msix_offset + vdev->msix_size ||
1137 req_start + req_len <= vdev->msix_offset))
1138 return -EINVAL;
1139 }
1140
1141 /* 1098 /*
1142 * Even though we don't make use of the barmap for the mmap, 1099 * Even though we don't make use of the barmap for the mmap,
1143 * we need to request the region and the barmap tracks that. 1100 * we need to request the region and the barmap tracks that.
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 2bc3705a99bd..721f97f8dac1 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1857,63 +1857,19 @@ void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset)
1857} 1857}
1858EXPORT_SYMBOL(vfio_info_cap_shift); 1858EXPORT_SYMBOL(vfio_info_cap_shift);
1859 1859
1860static int sparse_mmap_cap(struct vfio_info_cap *caps, void *cap_type) 1860int vfio_info_add_capability(struct vfio_info_cap *caps,
1861 struct vfio_info_cap_header *cap, size_t size)
1861{ 1862{
1862 struct vfio_info_cap_header *header; 1863 struct vfio_info_cap_header *header;
1863 struct vfio_region_info_cap_sparse_mmap *sparse_cap, *sparse = cap_type;
1864 size_t size;
1865 1864
1866 size = sizeof(*sparse) + sparse->nr_areas * sizeof(*sparse->areas); 1865 header = vfio_info_cap_add(caps, size, cap->id, cap->version);
1867 header = vfio_info_cap_add(caps, size,
1868 VFIO_REGION_INFO_CAP_SPARSE_MMAP, 1);
1869 if (IS_ERR(header)) 1866 if (IS_ERR(header))
1870 return PTR_ERR(header); 1867 return PTR_ERR(header);
1871 1868
1872 sparse_cap = container_of(header, 1869 memcpy(header + 1, cap + 1, size - sizeof(*header));
1873 struct vfio_region_info_cap_sparse_mmap, header);
1874 sparse_cap->nr_areas = sparse->nr_areas;
1875 memcpy(sparse_cap->areas, sparse->areas,
1876 sparse->nr_areas * sizeof(*sparse->areas));
1877 return 0;
1878}
1879
1880static int region_type_cap(struct vfio_info_cap *caps, void *cap_type)
1881{
1882 struct vfio_info_cap_header *header;
1883 struct vfio_region_info_cap_type *type_cap, *cap = cap_type;
1884 1870
1885 header = vfio_info_cap_add(caps, sizeof(*cap),
1886 VFIO_REGION_INFO_CAP_TYPE, 1);
1887 if (IS_ERR(header))
1888 return PTR_ERR(header);
1889
1890 type_cap = container_of(header, struct vfio_region_info_cap_type,
1891 header);
1892 type_cap->type = cap->type;
1893 type_cap->subtype = cap->subtype;
1894 return 0; 1871 return 0;
1895} 1872}
1896
1897int vfio_info_add_capability(struct vfio_info_cap *caps, int cap_type_id,
1898 void *cap_type)
1899{
1900 int ret = -EINVAL;
1901
1902 if (!cap_type)
1903 return 0;
1904
1905 switch (cap_type_id) {
1906 case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
1907 ret = sparse_mmap_cap(caps, cap_type);
1908 break;
1909
1910 case VFIO_REGION_INFO_CAP_TYPE:
1911 ret = region_type_cap(caps, cap_type);
1912 break;
1913 }
1914
1915 return ret;
1916}
1917EXPORT_SYMBOL(vfio_info_add_capability); 1873EXPORT_SYMBOL(vfio_info_add_capability);
1918 1874
1919int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, int num_irqs, 1875int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, int num_irqs,
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index a47b985341d1..66741ab087c1 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -145,7 +145,8 @@ extern struct vfio_info_cap_header *vfio_info_cap_add(
145extern void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset); 145extern void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset);
146 146
147extern int vfio_info_add_capability(struct vfio_info_cap *caps, 147extern int vfio_info_add_capability(struct vfio_info_cap *caps,
148 int cap_type_id, void *cap_type); 148 struct vfio_info_cap_header *cap,
149 size_t size);
149 150
150extern int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, 151extern int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr,
151 int num_irqs, int max_irq_type, 152 int num_irqs, int max_irq_type,
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index e3301dbd27d4..0d914350f7bf 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -301,6 +301,16 @@ struct vfio_region_info_cap_type {
301#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2) 301#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
302#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3) 302#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
303 303
304/*
305 * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped
306 * which allows direct access to non-MSIX registers which happened to be within
307 * the same system page.
308 *
309 * Even though the userspace gets direct access to the MSIX data, the existing
310 * VFIO_DEVICE_SET_IRQS interface must still be used for MSIX configuration.
311 */
312#define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
313
304/** 314/**
305 * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9, 315 * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
306 * struct vfio_irq_info) 316 * struct vfio_irq_info)