forked from Minki/linux
VFIO fixes for v5.18-rc3
- Fix VF token checking for vfio-pci variant drivers (Jason Gunthorpe) -----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEEQvbATlQL0amee4qQI5ubbjuwiyIFAmJYeycbHGFsZXgud2ls bGlhbXNvbkByZWRoYXQuY29tAAoJECObm247sIsi7J8QAJSuFZvnYNG5MJ6mlUwU iYtCojDdzKloFFcbZU1J1v2dyLuYsaQb0YRwOFJdMOAteFHCjOJzyKCaek4JTK6x uk4MPJWWb3EHP7kNgFsH/EqXJiyjQGJpD3gJNtGNDGjEvAbtBpy/cYoDqPxy3mhx fLHox4O1eWVsBh2Kzgf2GikrDOrK+Xd0zT+7x4SbCRimbRaLQxtndIOuSIEBbGmZ zH4dz5RZ0/1zRLupDfj9voGGIRSxgWjSAvUXBhCxeQKGgHL7zoDkSHbxCmIZN1B5 6RzjbeJPnUSno4QM6WU7hl3lv6qq+VHAb58F7SJCaQGueV6wRGrym1RAxeZQPO0R SmW7s7lPgWG5qXX9glAgha9Nv0gTs1+TEQprYG9pJShvSFGffpo/LHiMcvJDoiND jqnbY5smFKGE/uBDeamESUwotPFiFR9yLug2kZ8qgFRXfYS91/omDlyvii6wOtd/ R9IAtqpQgnpCk7+gH/y8Cf2SlYnffKY3d+dSii67dOcyJoH8KwrRqYp8SWBFir6L VX7n2/zIjxfIiuMjE/YzpW2StZnytxsHS6KT5lJVSbIz4KwnWu0kbBU0SP/i8Tti nGI7QdN4itjN6aYXb2WRbT1RTJZbslIiwlJR1ouO+nn9SGBo9X92ZTGDeMNdIZ6Q BNxxOFN0EgcPu+h9c0Spb8ui =Gif3 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
38a5e3fb17
@ -36,6 +36,10 @@ static bool nointxmask;
|
||||
static bool disable_vga;
|
||||
static bool disable_idle_d3;
|
||||
|
||||
/* List of PF's that vfio_pci_core_sriov_configure() has been called on */
|
||||
static DEFINE_MUTEX(vfio_pci_sriov_pfs_mutex);
|
||||
static LIST_HEAD(vfio_pci_sriov_pfs);
|
||||
|
||||
static inline bool vfio_vga_disabled(void)
|
||||
{
|
||||
#ifdef CONFIG_VFIO_PCI_VGA
|
||||
@ -434,47 +438,17 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfio_pci_core_disable);
|
||||
|
||||
static struct vfio_pci_core_device *get_pf_vdev(struct vfio_pci_core_device *vdev)
|
||||
{
|
||||
struct pci_dev *physfn = pci_physfn(vdev->pdev);
|
||||
struct vfio_device *pf_dev;
|
||||
|
||||
if (!vdev->pdev->is_virtfn)
|
||||
return NULL;
|
||||
|
||||
pf_dev = vfio_device_get_from_dev(&physfn->dev);
|
||||
if (!pf_dev)
|
||||
return NULL;
|
||||
|
||||
if (pci_dev_driver(physfn) != pci_dev_driver(vdev->pdev)) {
|
||||
vfio_device_put(pf_dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return container_of(pf_dev, struct vfio_pci_core_device, vdev);
|
||||
}
|
||||
|
||||
static void vfio_pci_vf_token_user_add(struct vfio_pci_core_device *vdev, int val)
|
||||
{
|
||||
struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
|
||||
|
||||
if (!pf_vdev)
|
||||
return;
|
||||
|
||||
mutex_lock(&pf_vdev->vf_token->lock);
|
||||
pf_vdev->vf_token->users += val;
|
||||
WARN_ON(pf_vdev->vf_token->users < 0);
|
||||
mutex_unlock(&pf_vdev->vf_token->lock);
|
||||
|
||||
vfio_device_put(&pf_vdev->vdev);
|
||||
}
|
||||
|
||||
void vfio_pci_core_close_device(struct vfio_device *core_vdev)
|
||||
{
|
||||
struct vfio_pci_core_device *vdev =
|
||||
container_of(core_vdev, struct vfio_pci_core_device, vdev);
|
||||
|
||||
vfio_pci_vf_token_user_add(vdev, -1);
|
||||
if (vdev->sriov_pf_core_dev) {
|
||||
mutex_lock(&vdev->sriov_pf_core_dev->vf_token->lock);
|
||||
WARN_ON(!vdev->sriov_pf_core_dev->vf_token->users);
|
||||
vdev->sriov_pf_core_dev->vf_token->users--;
|
||||
mutex_unlock(&vdev->sriov_pf_core_dev->vf_token->lock);
|
||||
}
|
||||
vfio_spapr_pci_eeh_release(vdev->pdev);
|
||||
vfio_pci_core_disable(vdev);
|
||||
|
||||
@ -495,7 +469,12 @@ void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev)
|
||||
{
|
||||
vfio_pci_probe_mmaps(vdev);
|
||||
vfio_spapr_pci_eeh_open(vdev->pdev);
|
||||
vfio_pci_vf_token_user_add(vdev, 1);
|
||||
|
||||
if (vdev->sriov_pf_core_dev) {
|
||||
mutex_lock(&vdev->sriov_pf_core_dev->vf_token->lock);
|
||||
vdev->sriov_pf_core_dev->vf_token->users++;
|
||||
mutex_unlock(&vdev->sriov_pf_core_dev->vf_token->lock);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable);
|
||||
|
||||
@ -1583,11 +1562,8 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
|
||||
*
|
||||
* If the VF token is provided but unused, an error is generated.
|
||||
*/
|
||||
if (!vdev->pdev->is_virtfn && !vdev->vf_token && !vf_token)
|
||||
return 0; /* No VF token provided or required */
|
||||
|
||||
if (vdev->pdev->is_virtfn) {
|
||||
struct vfio_pci_core_device *pf_vdev = get_pf_vdev(vdev);
|
||||
struct vfio_pci_core_device *pf_vdev = vdev->sriov_pf_core_dev;
|
||||
bool match;
|
||||
|
||||
if (!pf_vdev) {
|
||||
@ -1600,7 +1576,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
|
||||
}
|
||||
|
||||
if (!vf_token) {
|
||||
vfio_device_put(&pf_vdev->vdev);
|
||||
pci_info_ratelimited(vdev->pdev,
|
||||
"VF token required to access device\n");
|
||||
return -EACCES;
|
||||
@ -1610,8 +1585,6 @@ static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev,
|
||||
match = uuid_equal(uuid, &pf_vdev->vf_token->uuid);
|
||||
mutex_unlock(&pf_vdev->vf_token->lock);
|
||||
|
||||
vfio_device_put(&pf_vdev->vdev);
|
||||
|
||||
if (!match) {
|
||||
pci_info_ratelimited(vdev->pdev,
|
||||
"Incorrect VF token provided for device\n");
|
||||
@ -1732,8 +1705,30 @@ static int vfio_pci_bus_notifier(struct notifier_block *nb,
|
||||
static int vfio_pci_vf_init(struct vfio_pci_core_device *vdev)
|
||||
{
|
||||
struct pci_dev *pdev = vdev->pdev;
|
||||
struct vfio_pci_core_device *cur;
|
||||
struct pci_dev *physfn;
|
||||
int ret;
|
||||
|
||||
if (pdev->is_virtfn) {
|
||||
/*
|
||||
* If this VF was created by our vfio_pci_core_sriov_configure()
|
||||
* then we can find the PF vfio_pci_core_device now, and due to
|
||||
* the locking in pci_disable_sriov() it cannot change until
|
||||
* this VF device driver is removed.
|
||||
*/
|
||||
physfn = pci_physfn(vdev->pdev);
|
||||
mutex_lock(&vfio_pci_sriov_pfs_mutex);
|
||||
list_for_each_entry(cur, &vfio_pci_sriov_pfs, sriov_pfs_item) {
|
||||
if (cur->pdev == physfn) {
|
||||
vdev->sriov_pf_core_dev = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&vfio_pci_sriov_pfs_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not a SRIOV PF */
|
||||
if (!pdev->is_physfn)
|
||||
return 0;
|
||||
|
||||
@ -1805,6 +1800,7 @@ void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
|
||||
INIT_LIST_HEAD(&vdev->ioeventfds_list);
|
||||
mutex_init(&vdev->vma_lock);
|
||||
INIT_LIST_HEAD(&vdev->vma_list);
|
||||
INIT_LIST_HEAD(&vdev->sriov_pfs_item);
|
||||
init_rwsem(&vdev->memory_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfio_pci_core_init_device);
|
||||
@ -1896,7 +1892,7 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev)
|
||||
{
|
||||
struct pci_dev *pdev = vdev->pdev;
|
||||
|
||||
pci_disable_sriov(pdev);
|
||||
vfio_pci_core_sriov_configure(pdev, 0);
|
||||
|
||||
vfio_unregister_group_dev(&vdev->vdev);
|
||||
|
||||
@ -1935,21 +1931,49 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_aer_err_detected);
|
||||
|
||||
int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn)
|
||||
{
|
||||
struct vfio_pci_core_device *vdev;
|
||||
struct vfio_device *device;
|
||||
int ret = 0;
|
||||
|
||||
device_lock_assert(&pdev->dev);
|
||||
|
||||
device = vfio_device_get_from_dev(&pdev->dev);
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
if (nr_virtfn == 0)
|
||||
pci_disable_sriov(pdev);
|
||||
else
|
||||
vdev = container_of(device, struct vfio_pci_core_device, vdev);
|
||||
|
||||
if (nr_virtfn) {
|
||||
mutex_lock(&vfio_pci_sriov_pfs_mutex);
|
||||
/*
|
||||
* The thread that adds the vdev to the list is the only thread
|
||||
* that gets to call pci_enable_sriov() and we will only allow
|
||||
* it to be called once without going through
|
||||
* pci_disable_sriov()
|
||||
*/
|
||||
if (!list_empty(&vdev->sriov_pfs_item)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
list_add_tail(&vdev->sriov_pfs_item, &vfio_pci_sriov_pfs);
|
||||
mutex_unlock(&vfio_pci_sriov_pfs_mutex);
|
||||
ret = pci_enable_sriov(pdev, nr_virtfn);
|
||||
if (ret)
|
||||
goto out_del;
|
||||
ret = nr_virtfn;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
pci_disable_sriov(pdev);
|
||||
|
||||
out_del:
|
||||
mutex_lock(&vfio_pci_sriov_pfs_mutex);
|
||||
list_del_init(&vdev->sriov_pfs_item);
|
||||
out_unlock:
|
||||
mutex_unlock(&vfio_pci_sriov_pfs_mutex);
|
||||
out_put:
|
||||
vfio_device_put(device);
|
||||
|
||||
return ret < 0 ? ret : nr_virtfn;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfio_pci_core_sriov_configure);
|
||||
|
||||
|
@ -133,6 +133,8 @@ struct vfio_pci_core_device {
|
||||
struct mutex ioeventfds_lock;
|
||||
struct list_head ioeventfds_list;
|
||||
struct vfio_pci_vf_token *vf_token;
|
||||
struct list_head sriov_pfs_item;
|
||||
struct vfio_pci_core_device *sriov_pf_core_dev;
|
||||
struct notifier_block nb;
|
||||
struct mutex vma_lock;
|
||||
struct list_head vma_list;
|
||||
|
Loading…
Reference in New Issue
Block a user