Skip to content

Commit b25f62c

Browse files
committed
Merge tag 'vfio-v6.5-rc1' of https://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson: - Adjust log levels for common messages (Oleksandr Natalenko, Alex Williamson) - Support for dynamic MSI-X allocation (Reinette Chatre) - Enable and report PCIe AtomicOp Completer capabilities (Alex Williamson) - Cleanup Kconfigs for vfio bus drivers (Alex Williamson) - Add support for CDX bus based devices (Nipun Gupta) - Fix race with concurrent mdev initialization (Eric Farman) * tag 'vfio-v6.5-rc1' of https://github.com/awilliam/linux-vfio: vfio/mdev: Move the compat_class initialization to module init vfio/cdx: add support for CDX bus vfio/fsl: Create Kconfig sub-menu vfio/platform: Cleanup Kconfig vfio/pci: Cleanup Kconfig vfio/pci-core: Add capability for AtomicOp completer support vfio/pci: Also demote hiding standard cap messages vfio/pci: Clear VFIO_IRQ_INFO_NORESIZE for MSI-X vfio/pci: Support dynamic MSI-X vfio/pci: Probe and store ability to support dynamic MSI-X vfio/pci: Use bitfield for struct vfio_pci_core_device flags vfio/pci: Update stale comment vfio/pci: Remove interrupt context counter vfio/pci: Use xarray for interrupt context storage vfio/pci: Move to single error path vfio/pci: Prepare for dynamic interrupt context storage vfio/pci: Remove negative check on unsigned vector vfio/pci: Consolidate irq cleanup on MSI/MSI-X disable vfio/pci: demote hiding ecap messages to debug level
2 parents 9070577 + ff59808 commit b25f62c

File tree

24 files changed

+654
-146
lines changed

24 files changed

+654
-146
lines changed

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22254,6 +22254,13 @@ F: Documentation/filesystems/vfat.rst
2225422254
F: fs/fat/
2225522255
F: tools/testing/selftests/filesystems/fat/
2225622256

22257+
VFIO CDX DRIVER
22258+
M: Nipun Gupta <[email protected]>
22259+
M: Nikhil Agarwal <[email protected]>
22260+
22261+
S: Maintained
22262+
F: drivers/vfio/cdx/*
22263+
2225722264
VFIO DRIVER
2225822265
M: Alex Williamson <[email protected]>
2225922266

drivers/vfio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ source "drivers/vfio/pci/Kconfig"
5757
source "drivers/vfio/platform/Kconfig"
5858
source "drivers/vfio/mdev/Kconfig"
5959
source "drivers/vfio/fsl-mc/Kconfig"
60+
source "drivers/vfio/cdx/Kconfig"
6061
endif
6162

6263
source "virt/lib/Kconfig"

drivers/vfio/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ vfio-$(CONFIG_VFIO_VIRQFD) += virqfd.o
1010

1111
obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
1212
obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
13-
obj-$(CONFIG_VFIO_PCI) += pci/
14-
obj-$(CONFIG_VFIO_PLATFORM) += platform/
13+
obj-$(CONFIG_VFIO_PCI_CORE) += pci/
14+
obj-$(CONFIG_VFIO_PLATFORM_BASE) += platform/
1515
obj-$(CONFIG_VFIO_MDEV) += mdev/
1616
obj-$(CONFIG_VFIO_FSL_MC) += fsl-mc/
17+
obj-$(CONFIG_VFIO_CDX) += cdx/

drivers/vfio/cdx/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
#
3+
# VFIO CDX configuration
4+
#
5+
# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
6+
#
7+
8+
config VFIO_CDX
9+
tristate "VFIO support for CDX bus devices"
10+
depends on CDX_BUS
11+
select EVENTFD
12+
help
13+
Driver to enable VFIO support for the devices on CDX bus.
14+
This is required to make use of CDX devices present in
15+
the system using the VFIO framework.
16+
17+
If you don't know what to do here, say N.

drivers/vfio/cdx/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
#
3+
# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
4+
#
5+
6+
obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o
7+
8+
vfio-cdx-objs := main.o

drivers/vfio/cdx/main.c

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
4+
*/
5+
6+
#include <linux/vfio.h>
7+
#include <linux/cdx/cdx_bus.h>
8+
9+
#include "private.h"
10+
11+
static int vfio_cdx_open_device(struct vfio_device *core_vdev)
12+
{
13+
struct vfio_cdx_device *vdev =
14+
container_of(core_vdev, struct vfio_cdx_device, vdev);
15+
struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
16+
int count = cdx_dev->res_count;
17+
int i;
18+
19+
vdev->regions = kcalloc(count, sizeof(struct vfio_cdx_region),
20+
GFP_KERNEL_ACCOUNT);
21+
if (!vdev->regions)
22+
return -ENOMEM;
23+
24+
for (i = 0; i < count; i++) {
25+
struct resource *res = &cdx_dev->res[i];
26+
27+
vdev->regions[i].addr = res->start;
28+
vdev->regions[i].size = resource_size(res);
29+
vdev->regions[i].type = res->flags;
30+
/*
31+
* Only regions addressed with PAGE granularity may be
32+
* MMAP'ed securely.
33+
*/
34+
if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
35+
!(vdev->regions[i].size & ~PAGE_MASK))
36+
vdev->regions[i].flags |=
37+
VFIO_REGION_INFO_FLAG_MMAP;
38+
vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
39+
if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY))
40+
vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE;
41+
}
42+
43+
return 0;
44+
}
45+
46+
static void vfio_cdx_close_device(struct vfio_device *core_vdev)
47+
{
48+
struct vfio_cdx_device *vdev =
49+
container_of(core_vdev, struct vfio_cdx_device, vdev);
50+
51+
kfree(vdev->regions);
52+
cdx_dev_reset(core_vdev->dev);
53+
}
54+
55+
static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev,
56+
struct vfio_device_info __user *arg)
57+
{
58+
unsigned long minsz = offsetofend(struct vfio_device_info, num_irqs);
59+
struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
60+
struct vfio_device_info info;
61+
62+
if (copy_from_user(&info, arg, minsz))
63+
return -EFAULT;
64+
65+
if (info.argsz < minsz)
66+
return -EINVAL;
67+
68+
info.flags = VFIO_DEVICE_FLAGS_CDX;
69+
info.flags |= VFIO_DEVICE_FLAGS_RESET;
70+
71+
info.num_regions = cdx_dev->res_count;
72+
info.num_irqs = 0;
73+
74+
return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
75+
}
76+
77+
static int vfio_cdx_ioctl_get_region_info(struct vfio_cdx_device *vdev,
78+
struct vfio_region_info __user *arg)
79+
{
80+
unsigned long minsz = offsetofend(struct vfio_region_info, offset);
81+
struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
82+
struct vfio_region_info info;
83+
84+
if (copy_from_user(&info, arg, minsz))
85+
return -EFAULT;
86+
87+
if (info.argsz < minsz)
88+
return -EINVAL;
89+
90+
if (info.index >= cdx_dev->res_count)
91+
return -EINVAL;
92+
93+
/* map offset to the physical address */
94+
info.offset = vfio_cdx_index_to_offset(info.index);
95+
info.size = vdev->regions[info.index].size;
96+
info.flags = vdev->regions[info.index].flags;
97+
98+
return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
99+
}
100+
101+
static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
102+
unsigned int cmd, unsigned long arg)
103+
{
104+
struct vfio_cdx_device *vdev =
105+
container_of(core_vdev, struct vfio_cdx_device, vdev);
106+
void __user *uarg = (void __user *)arg;
107+
108+
switch (cmd) {
109+
case VFIO_DEVICE_GET_INFO:
110+
return vfio_cdx_ioctl_get_info(vdev, uarg);
111+
case VFIO_DEVICE_GET_REGION_INFO:
112+
return vfio_cdx_ioctl_get_region_info(vdev, uarg);
113+
case VFIO_DEVICE_RESET:
114+
return cdx_dev_reset(core_vdev->dev);
115+
default:
116+
return -ENOTTY;
117+
}
118+
}
119+
120+
static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region,
121+
struct vm_area_struct *vma)
122+
{
123+
u64 size = vma->vm_end - vma->vm_start;
124+
u64 pgoff, base;
125+
126+
pgoff = vma->vm_pgoff &
127+
((1U << (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
128+
base = pgoff << PAGE_SHIFT;
129+
130+
if (base + size > region.size)
131+
return -EINVAL;
132+
133+
vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
134+
vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
135+
136+
return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
137+
size, vma->vm_page_prot);
138+
}
139+
140+
static int vfio_cdx_mmap(struct vfio_device *core_vdev,
141+
struct vm_area_struct *vma)
142+
{
143+
struct vfio_cdx_device *vdev =
144+
container_of(core_vdev, struct vfio_cdx_device, vdev);
145+
struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
146+
unsigned int index;
147+
148+
index = vma->vm_pgoff >> (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT);
149+
150+
if (index >= cdx_dev->res_count)
151+
return -EINVAL;
152+
153+
if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
154+
return -EINVAL;
155+
156+
if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ) &&
157+
(vma->vm_flags & VM_READ))
158+
return -EPERM;
159+
160+
if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE) &&
161+
(vma->vm_flags & VM_WRITE))
162+
return -EPERM;
163+
164+
return vfio_cdx_mmap_mmio(vdev->regions[index], vma);
165+
}
166+
167+
static const struct vfio_device_ops vfio_cdx_ops = {
168+
.name = "vfio-cdx",
169+
.open_device = vfio_cdx_open_device,
170+
.close_device = vfio_cdx_close_device,
171+
.ioctl = vfio_cdx_ioctl,
172+
.mmap = vfio_cdx_mmap,
173+
.bind_iommufd = vfio_iommufd_physical_bind,
174+
.unbind_iommufd = vfio_iommufd_physical_unbind,
175+
.attach_ioas = vfio_iommufd_physical_attach_ioas,
176+
};
177+
178+
static int vfio_cdx_probe(struct cdx_device *cdx_dev)
179+
{
180+
struct vfio_cdx_device *vdev;
181+
struct device *dev = &cdx_dev->dev;
182+
int ret;
183+
184+
vdev = vfio_alloc_device(vfio_cdx_device, vdev, dev,
185+
&vfio_cdx_ops);
186+
if (IS_ERR(vdev))
187+
return PTR_ERR(vdev);
188+
189+
ret = vfio_register_group_dev(&vdev->vdev);
190+
if (ret)
191+
goto out_uninit;
192+
193+
dev_set_drvdata(dev, vdev);
194+
return 0;
195+
196+
out_uninit:
197+
vfio_put_device(&vdev->vdev);
198+
return ret;
199+
}
200+
201+
static int vfio_cdx_remove(struct cdx_device *cdx_dev)
202+
{
203+
struct device *dev = &cdx_dev->dev;
204+
struct vfio_cdx_device *vdev = dev_get_drvdata(dev);
205+
206+
vfio_unregister_group_dev(&vdev->vdev);
207+
vfio_put_device(&vdev->vdev);
208+
209+
return 0;
210+
}
211+
212+
static const struct cdx_device_id vfio_cdx_table[] = {
213+
{ CDX_DEVICE_DRIVER_OVERRIDE(CDX_ANY_ID, CDX_ANY_ID,
214+
CDX_ID_F_VFIO_DRIVER_OVERRIDE) }, /* match all by default */
215+
{}
216+
};
217+
218+
MODULE_DEVICE_TABLE(cdx, vfio_cdx_table);
219+
220+
static struct cdx_driver vfio_cdx_driver = {
221+
.probe = vfio_cdx_probe,
222+
.remove = vfio_cdx_remove,
223+
.match_id_table = vfio_cdx_table,
224+
.driver = {
225+
.name = "vfio-cdx",
226+
.owner = THIS_MODULE,
227+
},
228+
.driver_managed_dma = true,
229+
};
230+
231+
module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister);
232+
233+
MODULE_LICENSE("GPL");
234+
MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver");

drivers/vfio/cdx/private.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
4+
*/
5+
6+
#ifndef VFIO_CDX_PRIVATE_H
7+
#define VFIO_CDX_PRIVATE_H
8+
9+
#define VFIO_CDX_OFFSET_SHIFT 40
10+
11+
static inline u64 vfio_cdx_index_to_offset(u32 index)
12+
{
13+
return ((u64)(index) << VFIO_CDX_OFFSET_SHIFT);
14+
}
15+
16+
struct vfio_cdx_region {
17+
u32 flags;
18+
u32 type;
19+
u64 addr;
20+
resource_size_t size;
21+
};
22+
23+
struct vfio_cdx_device {
24+
struct vfio_device vdev;
25+
struct vfio_cdx_region *regions;
26+
};
27+
28+
#endif /* VFIO_CDX_PRIVATE_H */

drivers/vfio/fsl-mc/Kconfig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
menu "VFIO support for FSL_MC bus devices"
2+
depends on FSL_MC_BUS
3+
14
config VFIO_FSL_MC
25
tristate "VFIO support for QorIQ DPAA2 fsl-mc bus devices"
3-
depends on FSL_MC_BUS
46
select EVENTFD
57
help
68
Driver to enable support for the VFIO QorIQ DPAA2 fsl-mc
79
(Management Complex) devices. This is required to passthrough
810
fsl-mc bus devices using the VFIO framework.
911

1012
If you don't know what to do here, say N.
13+
14+
endmenu

drivers/vfio/mdev/mdev_core.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,6 @@ int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
7272
parent->nr_types = nr_types;
7373
atomic_set(&parent->available_instances, mdev_driver->max_instances);
7474

75-
if (!mdev_bus_compat_class) {
76-
mdev_bus_compat_class = class_compat_register("mdev_bus");
77-
if (!mdev_bus_compat_class)
78-
return -ENOMEM;
79-
}
80-
8175
ret = parent_create_sysfs_files(parent);
8276
if (ret)
8377
return ret;
@@ -251,13 +245,24 @@ int mdev_device_remove(struct mdev_device *mdev)
251245

252246
static int __init mdev_init(void)
253247
{
254-
return bus_register(&mdev_bus_type);
248+
int ret;
249+
250+
ret = bus_register(&mdev_bus_type);
251+
if (ret)
252+
return ret;
253+
254+
mdev_bus_compat_class = class_compat_register("mdev_bus");
255+
if (!mdev_bus_compat_class) {
256+
bus_unregister(&mdev_bus_type);
257+
return -ENOMEM;
258+
}
259+
260+
return 0;
255261
}
256262

257263
static void __exit mdev_exit(void)
258264
{
259-
if (mdev_bus_compat_class)
260-
class_compat_unregister(mdev_bus_compat_class);
265+
class_compat_unregister(mdev_bus_compat_class);
261266
bus_unregister(&mdev_bus_type);
262267
}
263268

0 commit comments

Comments
 (0)