Skip to content

Commit 30aec6e

Browse files
committed
Merge tag 'vfio-v6.10-rc1' of https://github.com/awilliam/linux-vfio
Pull vfio updates from Alex Williamson: - The vfio fsl-mc bus driver has become orphaned. We'll consider removing it in future releases if a new maintainer isn't found (Alex Williamson) - Improved usage of opaque data in vfio-pci INTx handling, avoiding lookups of the eventfd through the interrupt and irqfd runtime paths (Alex Williamson) - Resolve an error path memory leak introduced in vfio-pci interrupt code (Ye Bin) - Addition of interrupt support for vfio devices exposed on the CDX bus, including a new MSI allocation helper and export of existing helpers for MSI alloc and free (Nipun Gupta) - A new vfio-pci variant driver supporting migration of Intel QAT VF devices for the GEN4 PFs (Xin Zeng & Yahui Cao) - Resolve a possibly circular locking dependency in vfio-pci by avoiding copy_to_user() from a PCI bus walk callback (Alex Williamson) - Trivial docs update to remove a duplicate semicolon (Foryun Ma) * tag 'vfio-v6.10-rc1' of https://github.com/awilliam/linux-vfio: vfio/pci: Restore zero affected bus reset devices warning vfio: remove an extra semicolon vfio/pci: Collect hot-reset devices to local buffer vfio/qat: Add vfio_pci driver for Intel QAT SR-IOV VF devices vfio/cdx: add interrupt support genirq/msi: Add MSI allocation helper and export MSI functions vfio/pci: fix potential memory leak in vfio_intx_enable() vfio/pci: Pass eventfd context object through irqfd vfio/pci: Pass eventfd context to IRQ handler MAINTAINERS: Orphan vfio fsl-mc bus driver
2 parents 70ec81c + cbb325e commit 30aec6e

File tree

15 files changed

+1116
-68
lines changed

15 files changed

+1116
-68
lines changed

Documentation/driver-api/vfio.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ IOMMUFD IOAS/HWPT to enable userspace DMA::
364364
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
365365
map.iova = 0; /* 1MB starting at 0x0 from device view */
366366
map.length = 1024 * 1024;
367-
map.ioas_id = alloc_data.out_ioas_id;;
367+
map.ioas_id = alloc_data.out_ioas_id;
368368

369369
ioctl(iommufd, IOMMU_IOAS_MAP, &map);
370370

MAINTAINERS

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23512,9 +23512,8 @@ F: include/linux/vfio_pci_core.h
2351223512
F: include/uapi/linux/vfio.h
2351323513

2351423514
VFIO FSL-MC DRIVER
23515-
M: Diana Craciun <diana.craciun@oss.nxp.com>
2351623515
L: kvm@vger.kernel.org
23517-
S: Maintained
23516+
S: Orphan
2351823517
F: drivers/vfio/fsl-mc/
2351923518

2352023519
VFIO HISILICON PCI DRIVER
@@ -23568,6 +23567,14 @@ L: kvm@vger.kernel.org
2356823567
S: Maintained
2356923568
F: drivers/vfio/platform/
2357023569

23570+
VFIO QAT PCI DRIVER
23571+
M: Xin Zeng <xin.zeng@intel.com>
23572+
M: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
23573+
L: kvm@vger.kernel.org
23574+
L: qat-linux@intel.com
23575+
S: Supported
23576+
F: drivers/vfio/pci/qat/
23577+
2357123578
VFIO VIRTIO PCI DRIVER
2357223579
M: Yishai Hadas <yishaih@nvidia.com>
2357323580
L: kvm@vger.kernel.org

drivers/vfio/cdx/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55

66
obj-$(CONFIG_VFIO_CDX) += vfio-cdx.o
77

8-
vfio-cdx-objs := main.o
8+
vfio-cdx-objs := main.o intr.o

drivers/vfio/cdx/intr.c

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
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/slab.h>
8+
#include <linux/types.h>
9+
#include <linux/eventfd.h>
10+
#include <linux/msi.h>
11+
#include <linux/interrupt.h>
12+
13+
#include "linux/cdx/cdx_bus.h"
14+
#include "private.h"
15+
16+
static irqreturn_t vfio_cdx_msihandler(int irq_no, void *arg)
17+
{
18+
struct eventfd_ctx *trigger = arg;
19+
20+
eventfd_signal(trigger);
21+
return IRQ_HANDLED;
22+
}
23+
24+
static int vfio_cdx_msi_enable(struct vfio_cdx_device *vdev, int nvec)
25+
{
26+
struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
27+
struct device *dev = vdev->vdev.dev;
28+
int msi_idx, ret;
29+
30+
vdev->cdx_irqs = kcalloc(nvec, sizeof(struct vfio_cdx_irq), GFP_KERNEL);
31+
if (!vdev->cdx_irqs)
32+
return -ENOMEM;
33+
34+
ret = cdx_enable_msi(cdx_dev);
35+
if (ret) {
36+
kfree(vdev->cdx_irqs);
37+
return ret;
38+
}
39+
40+
/* Allocate cdx MSIs */
41+
ret = msi_domain_alloc_irqs(dev, MSI_DEFAULT_DOMAIN, nvec);
42+
if (ret) {
43+
cdx_disable_msi(cdx_dev);
44+
kfree(vdev->cdx_irqs);
45+
return ret;
46+
}
47+
48+
for (msi_idx = 0; msi_idx < nvec; msi_idx++)
49+
vdev->cdx_irqs[msi_idx].irq_no = msi_get_virq(dev, msi_idx);
50+
51+
vdev->msi_count = nvec;
52+
vdev->config_msi = 1;
53+
54+
return 0;
55+
}
56+
57+
static int vfio_cdx_msi_set_vector_signal(struct vfio_cdx_device *vdev,
58+
int vector, int fd)
59+
{
60+
struct eventfd_ctx *trigger;
61+
int irq_no, ret;
62+
63+
if (vector < 0 || vector >= vdev->msi_count)
64+
return -EINVAL;
65+
66+
irq_no = vdev->cdx_irqs[vector].irq_no;
67+
68+
if (vdev->cdx_irqs[vector].trigger) {
69+
free_irq(irq_no, vdev->cdx_irqs[vector].trigger);
70+
kfree(vdev->cdx_irqs[vector].name);
71+
eventfd_ctx_put(vdev->cdx_irqs[vector].trigger);
72+
vdev->cdx_irqs[vector].trigger = NULL;
73+
}
74+
75+
if (fd < 0)
76+
return 0;
77+
78+
vdev->cdx_irqs[vector].name = kasprintf(GFP_KERNEL, "vfio-msi[%d](%s)",
79+
vector, dev_name(vdev->vdev.dev));
80+
if (!vdev->cdx_irqs[vector].name)
81+
return -ENOMEM;
82+
83+
trigger = eventfd_ctx_fdget(fd);
84+
if (IS_ERR(trigger)) {
85+
kfree(vdev->cdx_irqs[vector].name);
86+
return PTR_ERR(trigger);
87+
}
88+
89+
ret = request_irq(irq_no, vfio_cdx_msihandler, 0,
90+
vdev->cdx_irqs[vector].name, trigger);
91+
if (ret) {
92+
kfree(vdev->cdx_irqs[vector].name);
93+
eventfd_ctx_put(trigger);
94+
return ret;
95+
}
96+
97+
vdev->cdx_irqs[vector].trigger = trigger;
98+
99+
return 0;
100+
}
101+
102+
static int vfio_cdx_msi_set_block(struct vfio_cdx_device *vdev,
103+
unsigned int start, unsigned int count,
104+
int32_t *fds)
105+
{
106+
int i, j, ret = 0;
107+
108+
if (start >= vdev->msi_count || start + count > vdev->msi_count)
109+
return -EINVAL;
110+
111+
for (i = 0, j = start; i < count && !ret; i++, j++) {
112+
int fd = fds ? fds[i] : -1;
113+
114+
ret = vfio_cdx_msi_set_vector_signal(vdev, j, fd);
115+
}
116+
117+
if (ret) {
118+
for (--j; j >= (int)start; j--)
119+
vfio_cdx_msi_set_vector_signal(vdev, j, -1);
120+
}
121+
122+
return ret;
123+
}
124+
125+
static void vfio_cdx_msi_disable(struct vfio_cdx_device *vdev)
126+
{
127+
struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
128+
struct device *dev = vdev->vdev.dev;
129+
130+
vfio_cdx_msi_set_block(vdev, 0, vdev->msi_count, NULL);
131+
132+
if (!vdev->config_msi)
133+
return;
134+
135+
msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
136+
cdx_disable_msi(cdx_dev);
137+
kfree(vdev->cdx_irqs);
138+
139+
vdev->cdx_irqs = NULL;
140+
vdev->msi_count = 0;
141+
vdev->config_msi = 0;
142+
}
143+
144+
static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
145+
unsigned int index, unsigned int start,
146+
unsigned int count, u32 flags,
147+
void *data)
148+
{
149+
struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
150+
int i;
151+
152+
if (start + count > cdx_dev->num_msi)
153+
return -EINVAL;
154+
155+
if (!count && (flags & VFIO_IRQ_SET_DATA_NONE)) {
156+
vfio_cdx_msi_disable(vdev);
157+
return 0;
158+
}
159+
160+
if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
161+
s32 *fds = data;
162+
int ret;
163+
164+
if (vdev->config_msi)
165+
return vfio_cdx_msi_set_block(vdev, start, count,
166+
fds);
167+
ret = vfio_cdx_msi_enable(vdev, cdx_dev->num_msi);
168+
if (ret)
169+
return ret;
170+
171+
ret = vfio_cdx_msi_set_block(vdev, start, count, fds);
172+
if (ret)
173+
vfio_cdx_msi_disable(vdev);
174+
175+
return ret;
176+
}
177+
178+
for (i = start; i < start + count; i++) {
179+
if (!vdev->cdx_irqs[i].trigger)
180+
continue;
181+
if (flags & VFIO_IRQ_SET_DATA_NONE) {
182+
eventfd_signal(vdev->cdx_irqs[i].trigger);
183+
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
184+
u8 *bools = data;
185+
186+
if (bools[i - start])
187+
eventfd_signal(vdev->cdx_irqs[i].trigger);
188+
}
189+
}
190+
191+
return 0;
192+
}
193+
194+
int vfio_cdx_set_irqs_ioctl(struct vfio_cdx_device *vdev,
195+
u32 flags, unsigned int index,
196+
unsigned int start, unsigned int count,
197+
void *data)
198+
{
199+
if (flags & VFIO_IRQ_SET_ACTION_TRIGGER)
200+
return vfio_cdx_set_msi_trigger(vdev, index, start,
201+
count, flags, data);
202+
else
203+
return -EINVAL;
204+
}
205+
206+
/* Free All IRQs for the given device */
207+
void vfio_cdx_irqs_cleanup(struct vfio_cdx_device *vdev)
208+
{
209+
/*
210+
* Device does not support any interrupt or the interrupts
211+
* were not configured
212+
*/
213+
if (!vdev->cdx_irqs)
214+
return;
215+
216+
vfio_cdx_set_msi_trigger(vdev, 0, 0, 0, VFIO_IRQ_SET_DATA_NONE, NULL);
217+
}

drivers/vfio/cdx/main.c

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ static void vfio_cdx_close_device(struct vfio_device *core_vdev)
6161

6262
kfree(vdev->regions);
6363
cdx_dev_reset(core_vdev->dev);
64+
vfio_cdx_irqs_cleanup(vdev);
6465
}
6566

6667
static int vfio_cdx_bm_ctrl(struct vfio_device *core_vdev, u32 flags,
@@ -123,7 +124,7 @@ static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev,
123124
info.flags |= VFIO_DEVICE_FLAGS_RESET;
124125

125126
info.num_regions = cdx_dev->res_count;
126-
info.num_irqs = 0;
127+
info.num_irqs = cdx_dev->num_msi ? 1 : 0;
127128

128129
return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
129130
}
@@ -152,6 +153,62 @@ static int vfio_cdx_ioctl_get_region_info(struct vfio_cdx_device *vdev,
152153
return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
153154
}
154155

156+
static int vfio_cdx_ioctl_get_irq_info(struct vfio_cdx_device *vdev,
157+
struct vfio_irq_info __user *arg)
158+
{
159+
unsigned long minsz = offsetofend(struct vfio_irq_info, count);
160+
struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
161+
struct vfio_irq_info info;
162+
163+
if (copy_from_user(&info, arg, minsz))
164+
return -EFAULT;
165+
166+
if (info.argsz < minsz)
167+
return -EINVAL;
168+
169+
if (info.index >= 1)
170+
return -EINVAL;
171+
172+
if (!cdx_dev->num_msi)
173+
return -EINVAL;
174+
175+
info.flags = VFIO_IRQ_INFO_EVENTFD | VFIO_IRQ_INFO_NORESIZE;
176+
info.count = cdx_dev->num_msi;
177+
178+
return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
179+
}
180+
181+
static int vfio_cdx_ioctl_set_irqs(struct vfio_cdx_device *vdev,
182+
struct vfio_irq_set __user *arg)
183+
{
184+
unsigned long minsz = offsetofend(struct vfio_irq_set, count);
185+
struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
186+
struct vfio_irq_set hdr;
187+
size_t data_size = 0;
188+
u8 *data = NULL;
189+
int ret = 0;
190+
191+
if (copy_from_user(&hdr, arg, minsz))
192+
return -EFAULT;
193+
194+
ret = vfio_set_irqs_validate_and_prepare(&hdr, cdx_dev->num_msi,
195+
1, &data_size);
196+
if (ret)
197+
return ret;
198+
199+
if (data_size) {
200+
data = memdup_user(arg->data, data_size);
201+
if (IS_ERR(data))
202+
return PTR_ERR(data);
203+
}
204+
205+
ret = vfio_cdx_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
206+
hdr.start, hdr.count, data);
207+
kfree(data);
208+
209+
return ret;
210+
}
211+
155212
static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
156213
unsigned int cmd, unsigned long arg)
157214
{
@@ -164,6 +221,10 @@ static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
164221
return vfio_cdx_ioctl_get_info(vdev, uarg);
165222
case VFIO_DEVICE_GET_REGION_INFO:
166223
return vfio_cdx_ioctl_get_region_info(vdev, uarg);
224+
case VFIO_DEVICE_GET_IRQ_INFO:
225+
return vfio_cdx_ioctl_get_irq_info(vdev, uarg);
226+
case VFIO_DEVICE_SET_IRQS:
227+
return vfio_cdx_ioctl_set_irqs(vdev, uarg);
167228
case VFIO_DEVICE_RESET:
168229
return cdx_dev_reset(core_vdev->dev);
169230
default:

drivers/vfio/cdx/private.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ static inline u64 vfio_cdx_index_to_offset(u32 index)
1313
return ((u64)(index) << VFIO_CDX_OFFSET_SHIFT);
1414
}
1515

16+
struct vfio_cdx_irq {
17+
u32 flags;
18+
u32 count;
19+
int irq_no;
20+
struct eventfd_ctx *trigger;
21+
char *name;
22+
};
23+
1624
struct vfio_cdx_region {
1725
u32 flags;
1826
u32 type;
@@ -23,8 +31,18 @@ struct vfio_cdx_region {
2331
struct vfio_cdx_device {
2432
struct vfio_device vdev;
2533
struct vfio_cdx_region *regions;
34+
struct vfio_cdx_irq *cdx_irqs;
2635
u32 flags;
2736
#define BME_SUPPORT BIT(0)
37+
u32 msi_count;
38+
u8 config_msi;
2839
};
2940

41+
int vfio_cdx_set_irqs_ioctl(struct vfio_cdx_device *vdev,
42+
u32 flags, unsigned int index,
43+
unsigned int start, unsigned int count,
44+
void *data);
45+
46+
void vfio_cdx_irqs_cleanup(struct vfio_cdx_device *vdev);
47+
3048
#endif /* VFIO_CDX_PRIVATE_H */

drivers/vfio/pci/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,6 @@ source "drivers/vfio/pci/virtio/Kconfig"
6969

7070
source "drivers/vfio/pci/nvgrace-gpu/Kconfig"
7171

72+
source "drivers/vfio/pci/qat/Kconfig"
73+
7274
endmenu

drivers/vfio/pci/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ obj-$(CONFIG_PDS_VFIO_PCI) += pds/
1717
obj-$(CONFIG_VIRTIO_VFIO_PCI) += virtio/
1818

1919
obj-$(CONFIG_NVGRACE_GPU_VFIO_PCI) += nvgrace-gpu/
20+
21+
obj-$(CONFIG_QAT_VFIO_PCI) += qat/

0 commit comments

Comments
 (0)