Skip to content

Commit df7bf83

Browse files
committed
Merge tag 'vfio-v7.1-rc1-pt2' of https://github.com/awilliam/linux-vfio
Pull more VFIO updates from Alex Williamson: - Fix ordering of dma-buf cleanup versus device disabling in vfio-pci (Matt Evans) - Resolve an inconsistent and incorrect use of spinlock-irq in the virtio vfio-pci variant by conversion to mutex and proceed to modernize and simplify driver with use of guards (Alex Williamson) - Resurrect the removal of the remaining class_create() call in vfio, replacing with const struct class and class_register() (Jori Koolstra, Alex Williamson) - Fix NULL pointer dereference, properly serialize interrupt setup, and cleanup interrupt state tracking in the cdx vfio bus driver (Prasanna Kumar T S M, Alex Williamson) * tag 'vfio-v7.1-rc1-pt2' of https://github.com/awilliam/linux-vfio: vfio/cdx: Consolidate MSI configured state onto cdx_irqs vfio/cdx: Serialize VFIO_DEVICE_SET_IRQS with a per-device mutex vfio/cdx: Fix NULL pointer dereference in interrupt trigger path vfio: replace vfio->device_class with a const struct class vfio/virtio: Use guard() for bar_mutex in legacy I/O vfio/virtio: Use guard() for migf->lock where applicable vfio/virtio: Use guard() for list_lock where applicable vfio/virtio: Convert list_lock from spinlock to mutex vfio/pci: Clean up DMABUFs before disabling function
2 parents 429e6c7 + 3047198 commit df7bf83

10 files changed

Lines changed: 107 additions & 106 deletions

File tree

drivers/vfio/cdx/intr.c

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,27 @@ static int vfio_cdx_msi_enable(struct vfio_cdx_device *vdev, int nvec)
3232
return -ENOMEM;
3333

3434
ret = cdx_enable_msi(cdx_dev);
35-
if (ret) {
36-
kfree(vdev->cdx_irqs);
37-
return ret;
38-
}
35+
if (ret)
36+
goto err_free;
3937

4038
/* Allocate cdx MSIs */
4139
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-
}
40+
if (ret)
41+
goto err_disable;
4742

4843
for (msi_idx = 0; msi_idx < nvec; msi_idx++)
4944
vdev->cdx_irqs[msi_idx].irq_no = msi_get_virq(dev, msi_idx);
5045

5146
vdev->msi_count = nvec;
52-
vdev->config_msi = 1;
5347

5448
return 0;
49+
50+
err_disable:
51+
cdx_disable_msi(cdx_dev);
52+
err_free:
53+
kfree(vdev->cdx_irqs);
54+
vdev->cdx_irqs = NULL;
55+
return ret;
5556
}
5657

5758
static int vfio_cdx_msi_set_vector_signal(struct vfio_cdx_device *vdev,
@@ -129,7 +130,7 @@ static void vfio_cdx_msi_disable(struct vfio_cdx_device *vdev)
129130

130131
vfio_cdx_msi_set_block(vdev, 0, vdev->msi_count, NULL);
131132

132-
if (!vdev->config_msi)
133+
if (!vdev->cdx_irqs)
133134
return;
134135

135136
msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
@@ -138,7 +139,6 @@ static void vfio_cdx_msi_disable(struct vfio_cdx_device *vdev)
138139

139140
vdev->cdx_irqs = NULL;
140141
vdev->msi_count = 0;
141-
vdev->config_msi = 0;
142142
}
143143

144144
static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
@@ -152,6 +152,8 @@ static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
152152
if (start + count > cdx_dev->num_msi)
153153
return -EINVAL;
154154

155+
guard(mutex)(&vdev->cdx_irqs_lock);
156+
155157
if (!count && (flags & VFIO_IRQ_SET_DATA_NONE)) {
156158
vfio_cdx_msi_disable(vdev);
157159
return 0;
@@ -161,7 +163,7 @@ static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
161163
s32 *fds = data;
162164
int ret;
163165

164-
if (vdev->config_msi)
166+
if (vdev->cdx_irqs)
165167
return vfio_cdx_msi_set_block(vdev, start, count,
166168
fds);
167169
ret = vfio_cdx_msi_enable(vdev, cdx_dev->num_msi);
@@ -175,6 +177,9 @@ static int vfio_cdx_set_msi_trigger(struct vfio_cdx_device *vdev,
175177
return ret;
176178
}
177179

180+
if (!vdev->cdx_irqs)
181+
return -EINVAL;
182+
178183
for (i = start; i < start + count; i++) {
179184
if (!vdev->cdx_irqs[i].trigger)
180185
continue;
@@ -206,12 +211,5 @@ int vfio_cdx_set_irqs_ioctl(struct vfio_cdx_device *vdev,
206211
/* Free All IRQs for the given device */
207212
void vfio_cdx_irqs_cleanup(struct vfio_cdx_device *vdev)
208213
{
209-
/*
210-
* Device does not support any interrupt or the interrupts
211-
* were not configured
212-
*/
213-
if (!vdev->cdx_irqs)
214-
return;
215-
216214
vfio_cdx_set_msi_trigger(vdev, 0, 0, 0, VFIO_IRQ_SET_DATA_NONE, NULL);
217215
}

drivers/vfio/cdx/main.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,23 @@
88

99
#include "private.h"
1010

11+
static int vfio_cdx_init_dev(struct vfio_device *core_vdev)
12+
{
13+
struct vfio_cdx_device *vdev =
14+
container_of(core_vdev, struct vfio_cdx_device, vdev);
15+
16+
mutex_init(&vdev->cdx_irqs_lock);
17+
return 0;
18+
}
19+
20+
static void vfio_cdx_release_dev(struct vfio_device *core_vdev)
21+
{
22+
struct vfio_cdx_device *vdev =
23+
container_of(core_vdev, struct vfio_cdx_device, vdev);
24+
25+
mutex_destroy(&vdev->cdx_irqs_lock);
26+
}
27+
1128
static int vfio_cdx_open_device(struct vfio_device *core_vdev)
1229
{
1330
struct vfio_cdx_device *vdev =
@@ -273,6 +290,8 @@ static int vfio_cdx_mmap(struct vfio_device *core_vdev,
273290

274291
static const struct vfio_device_ops vfio_cdx_ops = {
275292
.name = "vfio-cdx",
293+
.init = vfio_cdx_init_dev,
294+
.release = vfio_cdx_release_dev,
276295
.open_device = vfio_cdx_open_device,
277296
.close_device = vfio_cdx_close_device,
278297
.ioctl = vfio_cdx_ioctl,

drivers/vfio/cdx/private.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef VFIO_CDX_PRIVATE_H
77
#define VFIO_CDX_PRIVATE_H
88

9+
#include <linux/mutex.h>
10+
911
#define VFIO_CDX_OFFSET_SHIFT 40
1012

1113
static inline u64 vfio_cdx_index_to_offset(u32 index)
@@ -31,11 +33,11 @@ struct vfio_cdx_region {
3133
struct vfio_cdx_device {
3234
struct vfio_device vdev;
3335
struct vfio_cdx_region *regions;
36+
struct mutex cdx_irqs_lock;
3437
struct vfio_cdx_irq *cdx_irqs;
3538
u32 flags;
3639
#define BME_SUPPORT BIT(0)
3740
u32 msi_count;
38-
u8 config_msi;
3941
};
4042

4143
#ifdef CONFIG_GENERIC_MSI_IRQ

drivers/vfio/device_cdev.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,8 @@ int vfio_df_ioctl_detach_pt(struct vfio_device_file *df,
293293
return 0;
294294
}
295295

296-
static char *vfio_device_devnode(const struct device *dev, umode_t *mode)
296+
int vfio_cdev_init(void)
297297
{
298-
return kasprintf(GFP_KERNEL, "vfio/devices/%s", dev_name(dev));
299-
}
300-
301-
int vfio_cdev_init(struct class *device_class)
302-
{
303-
device_class->devnode = vfio_device_devnode;
304298
return alloc_chrdev_region(&device_devt, 0,
305299
MINORMASK + 1, "vfio-dev");
306300
}

drivers/vfio/pci/vfio_pci_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,10 +734,10 @@ void vfio_pci_core_close_device(struct vfio_device *core_vdev)
734734
#if IS_ENABLED(CONFIG_EEH)
735735
eeh_dev_release(vdev->pdev);
736736
#endif
737-
vfio_pci_core_disable(vdev);
738-
739737
vfio_pci_dma_buf_cleanup(vdev);
740738

739+
vfio_pci_core_disable(vdev);
740+
741741
mutex_lock(&vdev->igate);
742742
vfio_pci_eventfd_replace_locked(vdev, &vdev->err_trigger, NULL);
743743
vfio_pci_eventfd_replace_locked(vdev, &vdev->req_trigger, NULL);

drivers/vfio/pci/virtio/common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ struct virtiovf_migration_file {
6868
enum virtiovf_migf_state state;
6969
enum virtiovf_load_state load_state;
7070
/* synchronize access to the lists */
71-
spinlock_t list_lock;
71+
struct mutex list_lock;
7272
struct list_head buf_list;
7373
struct list_head avail_list;
7474
struct virtiovf_data_buffer *buf;

drivers/vfio/pci/virtio/legacy_io.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
3434
common = pos < VIRTIO_PCI_CONFIG_OFF(msix_enabled);
3535
/* offset within the relevant configuration area */
3636
offset = common ? pos : pos - VIRTIO_PCI_CONFIG_OFF(msix_enabled);
37-
mutex_lock(&virtvdev->bar_mutex);
37+
38+
guard(mutex)(&virtvdev->bar_mutex);
39+
3840
if (read) {
3941
if (common)
4042
ret = virtio_pci_admin_legacy_common_io_read(pdev, offset,
@@ -43,14 +45,12 @@ virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
4345
ret = virtio_pci_admin_legacy_device_io_read(pdev, offset,
4446
count, bar0_buf + pos);
4547
if (ret)
46-
goto out;
48+
return ret;
4749
if (copy_to_user(buf, bar0_buf + pos, count))
48-
ret = -EFAULT;
50+
return -EFAULT;
4951
} else {
50-
if (copy_from_user(bar0_buf + pos, buf, count)) {
51-
ret = -EFAULT;
52-
goto out;
53-
}
52+
if (copy_from_user(bar0_buf + pos, buf, count))
53+
return -EFAULT;
5454

5555
if (common)
5656
ret = virtio_pci_admin_legacy_common_io_write(pdev, offset,
@@ -59,8 +59,7 @@ virtiovf_issue_legacy_rw_cmd(struct virtiovf_pci_core_device *virtvdev,
5959
ret = virtio_pci_admin_legacy_device_io_write(pdev, offset,
6060
count, bar0_buf + pos);
6161
}
62-
out:
63-
mutex_unlock(&virtvdev->bar_mutex);
62+
6463
return ret;
6564
}
6665

0 commit comments

Comments
 (0)