vfio: Remove iommu group notifier
The iommu core and driver core have been enhanced to avoid unsafe driver binding to a live group after iommu_group_set_dma_owner(PRIVATE_USER) has been called. There's no need to register iommu group notifier. This removes the iommu group notifer which contains BUG_ON() and WARN(). Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Acked-by: Alex Williamson <alex.williamson@redhat.com> Link: https://lore.kernel.org/r/20220418005000.897664-11-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
93219ea943
commit
3b86f317c9
@ -71,7 +71,6 @@ struct vfio_group {
|
|||||||
struct vfio_container *container;
|
struct vfio_container *container;
|
||||||
struct list_head device_list;
|
struct list_head device_list;
|
||||||
struct mutex device_lock;
|
struct mutex device_lock;
|
||||||
struct notifier_block nb;
|
|
||||||
struct list_head vfio_next;
|
struct list_head vfio_next;
|
||||||
struct list_head container_next;
|
struct list_head container_next;
|
||||||
atomic_t opened;
|
atomic_t opened;
|
||||||
@ -274,8 +273,6 @@ void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver);
|
EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver);
|
||||||
|
|
||||||
static int vfio_iommu_group_notifier(struct notifier_block *nb,
|
|
||||||
unsigned long action, void *data);
|
|
||||||
static void vfio_group_get(struct vfio_group *group);
|
static void vfio_group_get(struct vfio_group *group);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -395,13 +392,6 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
|
|||||||
goto err_put;
|
goto err_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
group->nb.notifier_call = vfio_iommu_group_notifier;
|
|
||||||
err = iommu_group_register_notifier(iommu_group, &group->nb);
|
|
||||||
if (err) {
|
|
||||||
ret = ERR_PTR(err);
|
|
||||||
goto err_put;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&vfio.group_lock);
|
mutex_lock(&vfio.group_lock);
|
||||||
|
|
||||||
/* Did we race creating this group? */
|
/* Did we race creating this group? */
|
||||||
@ -422,7 +412,6 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
|
|||||||
|
|
||||||
err_unlock:
|
err_unlock:
|
||||||
mutex_unlock(&vfio.group_lock);
|
mutex_unlock(&vfio.group_lock);
|
||||||
iommu_group_unregister_notifier(group->iommu_group, &group->nb);
|
|
||||||
err_put:
|
err_put:
|
||||||
put_device(&group->dev);
|
put_device(&group->dev);
|
||||||
return ret;
|
return ret;
|
||||||
@ -447,7 +436,6 @@ static void vfio_group_put(struct vfio_group *group)
|
|||||||
cdev_device_del(&group->cdev, &group->dev);
|
cdev_device_del(&group->cdev, &group->dev);
|
||||||
mutex_unlock(&vfio.group_lock);
|
mutex_unlock(&vfio.group_lock);
|
||||||
|
|
||||||
iommu_group_unregister_notifier(group->iommu_group, &group->nb);
|
|
||||||
put_device(&group->dev);
|
put_device(&group->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,141 +491,6 @@ static struct vfio_device *vfio_group_get_device(struct vfio_group *group,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Some drivers, like pci-stub, are only used to prevent other drivers from
|
|
||||||
* claiming a device and are therefore perfectly legitimate for a user owned
|
|
||||||
* group. The pci-stub driver has no dependencies on DMA or the IOVA mapping
|
|
||||||
* of the device, but it does prevent the user from having direct access to
|
|
||||||
* the device, which is useful in some circumstances.
|
|
||||||
*
|
|
||||||
* We also assume that we can include PCI interconnect devices, ie. bridges.
|
|
||||||
* IOMMU grouping on PCI necessitates that if we lack isolation on a bridge
|
|
||||||
* then all of the downstream devices will be part of the same IOMMU group as
|
|
||||||
* the bridge. Thus, if placing the bridge into the user owned IOVA space
|
|
||||||
* breaks anything, it only does so for user owned devices downstream. Note
|
|
||||||
* that error notification via MSI can be affected for platforms that handle
|
|
||||||
* MSI within the same IOVA space as DMA.
|
|
||||||
*/
|
|
||||||
static const char * const vfio_driver_allowed[] = { "pci-stub" };
|
|
||||||
|
|
||||||
static bool vfio_dev_driver_allowed(struct device *dev,
|
|
||||||
struct device_driver *drv)
|
|
||||||
{
|
|
||||||
if (dev_is_pci(dev)) {
|
|
||||||
struct pci_dev *pdev = to_pci_dev(dev);
|
|
||||||
|
|
||||||
if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return match_string(vfio_driver_allowed,
|
|
||||||
ARRAY_SIZE(vfio_driver_allowed),
|
|
||||||
drv->name) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A vfio group is viable for use by userspace if all devices are in
|
|
||||||
* one of the following states:
|
|
||||||
* - driver-less
|
|
||||||
* - bound to a vfio driver
|
|
||||||
* - bound to an otherwise allowed driver
|
|
||||||
* - a PCI interconnect device
|
|
||||||
*
|
|
||||||
* We use two methods to determine whether a device is bound to a vfio
|
|
||||||
* driver. The first is to test whether the device exists in the vfio
|
|
||||||
* group. The second is to test if the device exists on the group
|
|
||||||
* unbound_list, indicating it's in the middle of transitioning from
|
|
||||||
* a vfio driver to driver-less.
|
|
||||||
*/
|
|
||||||
static int vfio_dev_viable(struct device *dev, void *data)
|
|
||||||
{
|
|
||||||
struct vfio_group *group = data;
|
|
||||||
struct vfio_device *device;
|
|
||||||
struct device_driver *drv = READ_ONCE(dev->driver);
|
|
||||||
|
|
||||||
if (!drv || vfio_dev_driver_allowed(dev, drv))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
device = vfio_group_get_device(group, dev);
|
|
||||||
if (device) {
|
|
||||||
vfio_device_put(device);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Async device support
|
|
||||||
*/
|
|
||||||
static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev)
|
|
||||||
{
|
|
||||||
struct vfio_device *device;
|
|
||||||
|
|
||||||
/* Do we already know about it? We shouldn't */
|
|
||||||
device = vfio_group_get_device(group, dev);
|
|
||||||
if (WARN_ON_ONCE(device)) {
|
|
||||||
vfio_device_put(device);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nothing to do for idle groups */
|
|
||||||
if (!atomic_read(&group->container_users))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* TODO Prevent device auto probing */
|
|
||||||
dev_WARN(dev, "Device added to live group %d!\n",
|
|
||||||
iommu_group_id(group->iommu_group));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vfio_group_nb_verify(struct vfio_group *group, struct device *dev)
|
|
||||||
{
|
|
||||||
/* We don't care what happens when the group isn't in use */
|
|
||||||
if (!atomic_read(&group->container_users))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return vfio_dev_viable(dev, group);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vfio_iommu_group_notifier(struct notifier_block *nb,
|
|
||||||
unsigned long action, void *data)
|
|
||||||
{
|
|
||||||
struct vfio_group *group = container_of(nb, struct vfio_group, nb);
|
|
||||||
struct device *dev = data;
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case IOMMU_GROUP_NOTIFY_ADD_DEVICE:
|
|
||||||
vfio_group_nb_add_dev(group, dev);
|
|
||||||
break;
|
|
||||||
case IOMMU_GROUP_NOTIFY_DEL_DEVICE:
|
|
||||||
/*
|
|
||||||
* Nothing to do here. If the device is in use, then the
|
|
||||||
* vfio sub-driver should block the remove callback until
|
|
||||||
* it is unused. If the device is unused or attached to a
|
|
||||||
* stub driver, then it should be released and we don't
|
|
||||||
* care that it will be going away.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
case IOMMU_GROUP_NOTIFY_BIND_DRIVER:
|
|
||||||
dev_dbg(dev, "%s: group %d binding to driver\n", __func__,
|
|
||||||
iommu_group_id(group->iommu_group));
|
|
||||||
break;
|
|
||||||
case IOMMU_GROUP_NOTIFY_BOUND_DRIVER:
|
|
||||||
dev_dbg(dev, "%s: group %d bound to driver %s\n", __func__,
|
|
||||||
iommu_group_id(group->iommu_group), dev->driver->name);
|
|
||||||
BUG_ON(vfio_group_nb_verify(group, dev));
|
|
||||||
break;
|
|
||||||
case IOMMU_GROUP_NOTIFY_UNBIND_DRIVER:
|
|
||||||
dev_dbg(dev, "%s: group %d unbinding from driver %s\n",
|
|
||||||
__func__, iommu_group_id(group->iommu_group),
|
|
||||||
dev->driver->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NOTIFY_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VFIO driver API
|
* VFIO driver API
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user