Hi, On 10/06/2017 00:00, Alex Williamson wrote: > Generally we don't know about vfio bus drivers until a device is > added to the vfio-core with vfio_add_group_dev(), this optional > registration with vfio_register_bus_driver() allows vfio-core to > track known drivers. Our current use for this information is to > know whether a driver is vfio compatible during a bind operation. > For devices on buses with driver_override support, we can use this > linkage to block non-vfio drivers from binding to devices where > the iommu group state would trigger a BUG to avoid host/user > integrity issues. > > Signed-off-by: Alex Williamson <alex.williamson@xxxxxxxxxx> Reviewed-by: Eric Auger <eric.auger@xxxxxxxxxx> Thanks Eric > --- > drivers/vfio/vfio.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/vfio.h | 3 +++ > 2 files changed, 58 insertions(+) > > diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c > index e6117de60f87..a25ee4930200 100644 > --- a/drivers/vfio/vfio.c > +++ b/drivers/vfio/vfio.c > @@ -43,6 +43,8 @@ > struct class *class; > struct list_head iommu_drivers_list; > struct mutex iommu_drivers_lock; > + struct list_head bus_drivers_list; > + struct mutex bus_drivers_lock; > struct list_head group_list; > struct idr group_idr; > struct mutex group_lock; > @@ -51,6 +53,11 @@ > wait_queue_head_t release_q; > } vfio; > > +struct vfio_bus_driver { > + struct device_driver *drv; > + struct list_head vfio_next; > +}; > + > struct vfio_iommu_driver { > const struct vfio_iommu_driver_ops *ops; > struct list_head vfio_next; > @@ -2243,6 +2250,52 @@ int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type, > } > EXPORT_SYMBOL(vfio_unregister_notifier); > > +int vfio_register_bus_driver(struct device_driver *drv) > +{ > + struct vfio_bus_driver *driver, *tmp; > + > + driver = kzalloc(sizeof(*driver), GFP_KERNEL); > + if (!driver) > + return -ENOMEM; > + > + driver->drv = drv; > + > + mutex_lock(&vfio.bus_drivers_lock); > + > + /* Check for duplicates */ > + list_for_each_entry(tmp, &vfio.bus_drivers_list, vfio_next) { > + if (tmp->drv == drv) { > + mutex_unlock(&vfio.bus_drivers_lock); > + kfree(driver); > + return -EINVAL; > + } > + } > + > + list_add(&driver->vfio_next, &vfio.bus_drivers_list); > + > + mutex_unlock(&vfio.bus_drivers_lock); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(vfio_register_bus_driver); > + > +void vfio_unregister_bus_driver(struct device_driver *drv) > +{ > + struct vfio_bus_driver *driver; > + > + mutex_lock(&vfio.bus_drivers_lock); > + list_for_each_entry(driver, &vfio.bus_drivers_list, vfio_next) { > + if (driver->drv == drv) { > + list_del(&driver->vfio_next); > + mutex_unlock(&vfio.bus_drivers_lock); > + kfree(driver); > + return; > + } > + } > + mutex_unlock(&vfio.bus_drivers_lock); > +} > +EXPORT_SYMBOL_GPL(vfio_unregister_bus_driver); > + > /** > * Module/class support > */ > @@ -2266,8 +2319,10 @@ static int __init vfio_init(void) > idr_init(&vfio.group_idr); > mutex_init(&vfio.group_lock); > mutex_init(&vfio.iommu_drivers_lock); > + mutex_init(&vfio.bus_drivers_lock); > INIT_LIST_HEAD(&vfio.group_list); > INIT_LIST_HEAD(&vfio.iommu_drivers_list); > + INIT_LIST_HEAD(&vfio.bus_drivers_list); > init_waitqueue_head(&vfio.release_q); > > ret = misc_register(&vfio_dev); > diff --git a/include/linux/vfio.h b/include/linux/vfio.h > index 9b34d0af5d27..dab0f8105e4a 100644 > --- a/include/linux/vfio.h > +++ b/include/linux/vfio.h > @@ -92,6 +92,9 @@ struct vfio_iommu_driver_ops { > extern void vfio_unregister_iommu_driver( > const struct vfio_iommu_driver_ops *ops); > > +extern int vfio_register_bus_driver(struct device_driver *drv); > +extern void vfio_unregister_bus_driver(struct device_driver *drv); > + > /* > * External user API > */ >