Skip to content

Commit 38a5e3f

Browse files
committed
Merge tag 'vfio-v5.18-rc3' of https://github.com/awilliam/linux-vfio
Pull vfio fix from Alex Williamson: - Fix VF token checking for vfio-pci variant drivers (Jason Gunthorpe) * tag 'vfio-v5.18-rc3' of https://github.com/awilliam/linux-vfio: vfio/pci: Fix vf_token mechanism when device-specific VF drivers are used
2 parents 62345e4 + 1ef3342 commit 38a5e3f

2 files changed

Lines changed: 76 additions & 50 deletions

File tree

drivers/vfio/pci/vfio_pci_core.c

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ static bool nointxmask;
3636
static bool disable_vga;
3737
static bool disable_idle_d3;
3838

39+
/* List of PF's that vfio_pci_core_sriov_configure() has been called on */
40+
static DEFINE_MUTEX(vfio_pci_sriov_pfs_mutex);
41+
static LIST_HEAD(vfio_pci_sriov_pfs);
42+
3943
static inline bool vfio_vga_disabled(void)
4044
{
4145
#ifdef CONFIG_VFIO_PCI_VGA
@@ -434,47 +438,17 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
434438
}
435439
EXPORT_SYMBOL_GPL(vfio_pci_core_disable);
436440

437-
static struct vfio_pci_core_device *get_pf_vdev(struct vfio_pci_core_device *vdev)
438-
{
439-
struct pci_dev *physfn = pci_physfn(vdev->pdev);
440-
struct vfio_device *pf_dev;
441-
442-
if (!vdev->pdev->is_virtfn)
443-
return NULL;
444-
445-
pf_dev = vfio_device_get_from_dev(&physfn->dev);
446-
if (!pf_dev)
447-
return NULL;
448-
449-
if (pci_dev_driver(physfn) != pci_dev_driver(vdev->pdev)) {
450-
vfio_device_put(pf_dev);
451-
return NULL;
452-
}
453-
454-
return container_of(pf_dev, struct vfio_pci_core_device, vdev);
455-
}
456-
457-
static void vfio_pci_vf_token_user_add(struct vfio_pci_core_device *vdev, int val)
458-
{
459-
struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
460-
461-
if (!pf_vdev)
462-
return;
463-
464-
mutex_lock(&pf_vdev->vf_token->lock);
465-
pf_vdev->vf_token->users += val;
466-
WARN_ON(pf_vdev->vf_token->users < 0);
467-
mutex_unlock(&pf_vdev->vf_token->lock);
468-
469-
vfio_device_put(&pf_vdev->vdev);
470-
}
471-
472441
void vfio_pci_core_close_device(struct vfio_device *core_vdev)
473442
{
474443
struct vfio_pci_core_device *vdev =
475444
container_of(core_vdev, struct vfio_pci_core_device, vdev);
476445

477-
vfio_pci_vf_token_user_add(vdev, -1);
446+
if (vdev->sriov_pf_core_dev) {
447+
mutex_lock(&vdev->sriov_pf_core_dev->vf_token->lock);
448+
WARN_ON(!vdev->sriov_pf_core_dev->vf_token->users);
449+
vdev->sriov_pf_core_dev->vf_token->users--;
450+
mutex_unlock(&vdev->sriov_pf_core_dev->vf_token->lock);
451+
}
478452
vfio_spapr_pci_eeh_release(vdev->pdev);
479453
vfio_pci_core_disable(vdev);
480454

@@ -495,7 +469,12 @@ void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev)
495469
{
496470
vfio_pci_probe_mmaps(vdev);
497471
vfio_spapr_pci_eeh_open(vdev->pdev);
498-
vfio_pci_vf_token_user_add(vdev, 1);
472+
473+
if (vdev->sriov_pf_core_dev) {
474+
mutex_lock(&vdev->sriov_pf_core_dev->vf_token->lock);
475+
vdev->sriov_pf_core_dev->vf_token->users++;
476+
mutex_unlock(&vdev->sriov_pf_core_dev->vf_token->lock);
477+
}
499478
}
500479
EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable);
501480

@@ -1583,11 +1562,8 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
15831562
*
15841563
* If the VF token is provided but unused, an error is generated.
15851564
*/
1586-
if (!vdev->pdev->is_virtfn && !vdev->vf_token && !vf_token)
1587-
return 0; /* No VF token provided or required */
1588-
15891565
if (vdev->pdev->is_virtfn) {
1590-
struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
1566+
struct vfio_pci_core_device *pf_vdev = vdev->sriov_pf_core_dev;
15911567
bool match;
15921568

15931569
if (!pf_vdev) {
@@ -1600,7 +1576,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
16001576
}
16011577

16021578
if (!vf_token) {
1603-
vfio_device_put(&pf_vdev->vdev);
16041579
pci_info_ratelimited(vdev->pdev,
16051580
"VF token required to access device\n");
16061581
return -EACCES;
@@ -1610,8 +1585,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
16101585
match = uuid_equal(uuid, &pf_vdev->vf_token->uuid);
16111586
mutex_unlock(&pf_vdev->vf_token->lock);
16121587

1613-
vfio_device_put(&pf_vdev->vdev);
1614-
16151588
if (!match) {
16161589
pci_info_ratelimited(vdev->pdev,
16171590
"Incorrect VF token provided for device\n");
@@ -1732,8 +1705,30 @@ static int vfio_pci_bus_notifier(struct notifier_block *nb,
17321705
static int vfio_pci_vf_init(struct vfio_pci_core_device *vdev)
17331706
{
17341707
struct pci_dev *pdev = vdev->pdev;
1708+
struct vfio_pci_core_device *cur;
1709+
struct pci_dev *physfn;
17351710
int ret;
17361711

1712+
if (pdev->is_virtfn) {
1713+
/*
1714+
* If this VF was created by our vfio_pci_core_sriov_configure()
1715+
* then we can find the PF vfio_pci_core_device now, and due to
1716+
* the locking in pci_disable_sriov() it cannot change until
1717+
* this VF device driver is removed.
1718+
*/
1719+
physfn = pci_physfn(vdev->pdev);
1720+
mutex_lock(&vfio_pci_sriov_pfs_mutex);
1721+
list_for_each_entry(cur, &vfio_pci_sriov_pfs, sriov_pfs_item) {
1722+
if (cur->pdev == physfn) {
1723+
vdev->sriov_pf_core_dev = cur;
1724+
break;
1725+
}
1726+
}
1727+
mutex_unlock(&vfio_pci_sriov_pfs_mutex);
1728+
return 0;
1729+
}
1730+
1731+
/* Not a SRIOV PF */
17371732
if (!pdev->is_physfn)
17381733
return 0;
17391734

@@ -1805,6 +1800,7 @@ void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
18051800
INIT_LIST_HEAD(&vdev->ioeventfds_list);
18061801
mutex_init(&vdev->vma_lock);
18071802
INIT_LIST_HEAD(&vdev->vma_list);
1803+
INIT_LIST_HEAD(&vdev->sriov_pfs_item);
18081804
init_rwsem(&vdev->memory_lock);
18091805
}
18101806
EXPORT_SYMBOL_GPL(vfio_pci_core_init_device);
@@ -1896,7 +1892,7 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev)
18961892
{
18971893
struct pci_dev *pdev = vdev->pdev;
18981894

1899-
pci_disable_sriov(pdev);
1895+
vfio_pci_core_sriov_configure(pdev, 0);
19001896

19011897
vfio_unregister_group_dev(&vdev->vdev);
19021898

@@ -1935,21 +1931,49 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_aer_err_detected);
19351931

19361932
int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn)
19371933
{
1934+
struct vfio_pci_core_device *vdev;
19381935
struct vfio_device *device;
19391936
int ret = 0;
19401937

1938+
device_lock_assert(&pdev->dev);
1939+
19411940
device = vfio_device_get_from_dev(&pdev->dev);
19421941
if (!device)
19431942
return -ENODEV;
19441943

1945-
if (nr_virtfn == 0)
1946-
pci_disable_sriov(pdev);
1947-
else
1944+
vdev = container_of(device, struct vfio_pci_core_device, vdev);
1945+
1946+
if (nr_virtfn) {
1947+
mutex_lock(&vfio_pci_sriov_pfs_mutex);
1948+
/*
1949+
* The thread that adds the vdev to the list is the only thread
1950+
* that gets to call pci_enable_sriov() and we will only allow
1951+
* it to be called once without going through
1952+
* pci_disable_sriov()
1953+
*/
1954+
if (!list_empty(&vdev->sriov_pfs_item)) {
1955+
ret = -EINVAL;
1956+
goto out_unlock;
1957+
}
1958+
list_add_tail(&vdev->sriov_pfs_item, &vfio_pci_sriov_pfs);
1959+
mutex_unlock(&vfio_pci_sriov_pfs_mutex);
19481960
ret = pci_enable_sriov(pdev, nr_virtfn);
1961+
if (ret)
1962+
goto out_del;
1963+
ret = nr_virtfn;
1964+
goto out_put;
1965+
}
19491966

1950-
vfio_device_put(device);
1967+
pci_disable_sriov(pdev);
19511968

1952-
return ret < 0 ? ret : nr_virtfn;
1969+
out_del:
1970+
mutex_lock(&vfio_pci_sriov_pfs_mutex);
1971+
list_del_init(&vdev->sriov_pfs_item);
1972+
out_unlock:
1973+
mutex_unlock(&vfio_pci_sriov_pfs_mutex);
1974+
out_put:
1975+
vfio_device_put(device);
1976+
return ret;
19531977
}
19541978
EXPORT_SYMBOL_GPL(vfio_pci_core_sriov_configure);
19551979

include/linux/vfio_pci_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ struct vfio_pci_core_device {
133133
struct mutex ioeventfds_lock;
134134
struct list_head ioeventfds_list;
135135
struct vfio_pci_vf_token *vf_token;
136+
struct list_head sriov_pfs_item;
137+
struct vfio_pci_core_device *sriov_pf_core_dev;
136138
struct notifier_block nb;
137139
struct mutex vma_lock;
138140
struct list_head vma_list;

0 commit comments

Comments
 (0)