lkml.org 
[lkml]   [2021]   [Feb]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[RFC PATCH 06/10] vfio: Add a device notifier interface
    From
    Date
    Using a vfio device, a notifier block can be registered to receive
    select device events. Notifiers can only be registered for contained
    devices, ie. they are available through a user context. Registration
    of a notifier increments the reference to that container context
    therefore notifiers must minimally respond to the release event by
    asynchronously removing notifiers.

    Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
    ---
    drivers/vfio/Kconfig | 1 +
    drivers/vfio/vfio.c | 35 +++++++++++++++++++++++++++++++++++
    include/linux/vfio.h | 9 +++++++++
    3 files changed, 45 insertions(+)

    diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
    index 5533df91b257..8ac1601b681b 100644
    --- a/drivers/vfio/Kconfig
    +++ b/drivers/vfio/Kconfig
    @@ -23,6 +23,7 @@ menuconfig VFIO
    tristate "VFIO Non-Privileged userspace driver framework"
    depends on IOMMU_API
    select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM || ARM64)
    + select SRCU
    help
    VFIO provides a framework for secure userspace device drivers.
    See Documentation/driver-api/vfio.rst for more details.
    diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
    index 399c42b77fbb..1a1b46215ac4 100644
    --- a/drivers/vfio/vfio.c
    +++ b/drivers/vfio/vfio.c
    @@ -105,6 +105,7 @@ struct vfio_device {
    struct list_head group_next;
    void *device_data;
    struct inode *inode;
    + struct srcu_notifier_head notifier;
    };

    #ifdef CONFIG_VFIO_NOIOMMU
    @@ -610,6 +611,7 @@ struct vfio_device *vfio_group_create_device(struct vfio_group *group,
    device->ops = ops;
    device->device_data = device_data;
    dev_set_drvdata(dev, device);
    + srcu_init_notifier_head(&device->notifier);

    /* No need to get group_lock, caller has group reference */
    vfio_group_get(group);
    @@ -1778,6 +1780,39 @@ static const struct file_operations vfio_device_fops = {
    .mmap = vfio_device_fops_mmap,
    };

    +int vfio_device_register_notifier(struct vfio_device *device,
    + struct notifier_block *nb)
    +{
    + int ret;
    +
    + /* Container ref persists until unregister on success */
    + ret = vfio_group_add_container_user(device->group);
    + if (ret)
    + return ret;
    +
    + ret = srcu_notifier_chain_register(&device->notifier, nb);
    + if (ret)
    + vfio_group_try_dissolve_container(device->group);
    +
    + return ret;
    +}
    +EXPORT_SYMBOL_GPL(vfio_device_register_notifier);
    +
    +void vfio_device_unregister_notifier(struct vfio_device *device,
    + struct notifier_block *nb)
    +{
    + if (!srcu_notifier_chain_unregister(&device->notifier, nb))
    + vfio_group_try_dissolve_container(device->group);
    +}
    +EXPORT_SYMBOL_GPL(vfio_device_unregister_notifier);
    +
    +int vfio_device_notifier_call(struct vfio_device *device,
    + enum vfio_device_notify_type event)
    +{
    + return srcu_notifier_call_chain(&device->notifier, event, NULL);
    +}
    +EXPORT_SYMBOL_GPL(vfio_device_notifier_call);
    +
    /**
    * External user API, exported by symbols to be linked dynamically.
    *
    diff --git a/include/linux/vfio.h b/include/linux/vfio.h
    index 188c2f3feed9..8217cd4ea53d 100644
    --- a/include/linux/vfio.h
    +++ b/include/linux/vfio.h
    @@ -60,6 +60,15 @@ extern void vfio_device_unmap_mapping_range(struct vfio_device *device,
    loff_t start, loff_t len);
    extern void vfio_device_vma_open(struct vm_area_struct *vma);
    extern struct vfio_device *vfio_device_get_from_vma(struct vm_area_struct *vma);
    +extern int vfio_device_register_notifier(struct vfio_device *device,
    + struct notifier_block *nb);
    +extern void vfio_device_unregister_notifier(struct vfio_device *device,
    + struct notifier_block *nb);
    +enum vfio_device_notify_type {
    + VFIO_DEVICE_RELEASE = 0,
    +};
    +int vfio_device_notifier_call(struct vfio_device *device,
    + enum vfio_device_notify_type event);

    /* events for the backend driver notify callback */
    enum vfio_iommu_notify_type {
    \
     
     \ /
      Last update: 2021-02-22 17:56    [W:5.829 / U:0.736 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site