Commit 9048c734 authored by Yi Liu's avatar Yi Liu Committed by Alex Williamson

vfio-iommufd: Add detach_ioas support for physical VFIO devices

This prepares for adding DETACH ioctl for physical VFIO devices.
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Tested-by: default avatarTerrence Xu <terrence.xu@intel.com>
Tested-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Tested-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Tested-by: default avatarYanting Jiang <yanting.jiang@intel.com>
Tested-by: default avatarShameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Tested-by: default avatarZhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: default avatarYi Liu <yi.l.liu@intel.com>
Link: https://lore.kernel.org/r/20230718135551.6592-14-yi.l.liu@intel.comSigned-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 31014aef
...@@ -279,6 +279,7 @@ similar to a file operations structure:: ...@@ -279,6 +279,7 @@ similar to a file operations structure::
struct iommufd_ctx *ictx, u32 *out_device_id); struct iommufd_ctx *ictx, u32 *out_device_id);
void (*unbind_iommufd)(struct vfio_device *vdev); void (*unbind_iommufd)(struct vfio_device *vdev);
int (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id); int (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id);
void (*detach_ioas)(struct vfio_device *vdev);
int (*open_device)(struct vfio_device *vdev); int (*open_device)(struct vfio_device *vdev);
void (*close_device)(struct vfio_device *vdev); void (*close_device)(struct vfio_device *vdev);
ssize_t (*read)(struct vfio_device *vdev, char __user *buf, ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
...@@ -315,9 +316,10 @@ container_of(). ...@@ -315,9 +316,10 @@ container_of().
- The [un]bind_iommufd callbacks are issued when the device is bound to - The [un]bind_iommufd callbacks are issued when the device is bound to
and unbound from iommufd. and unbound from iommufd.
- The attach_ioas callback is issued when the device is attached to an - The [de]attach_ioas callback is issued when the device is attached to
IOAS managed by the bound iommufd. The attached IOAS is automatically and detached from an IOAS managed by the bound iommufd. However, the
detached when the device is unbound from iommufd. attached IOAS can also be automatically detached when the device is
unbound from iommufd.
- The read/write/mmap callbacks implement the device region access defined - The read/write/mmap callbacks implement the device region access defined
by the device's own VFIO_DEVICE_GET_REGION_INFO ioctl. by the device's own VFIO_DEVICE_GET_REGION_INFO ioctl.
......
...@@ -593,6 +593,7 @@ static const struct vfio_device_ops vfio_fsl_mc_ops = { ...@@ -593,6 +593,7 @@ static const struct vfio_device_ops vfio_fsl_mc_ops = {
.bind_iommufd = vfio_iommufd_physical_bind, .bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind, .unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas, .attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
}; };
static struct fsl_mc_driver vfio_fsl_mc_driver = { static struct fsl_mc_driver vfio_fsl_mc_driver = {
......
...@@ -140,6 +140,14 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id) ...@@ -140,6 +140,14 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
{ {
int rc; int rc;
lockdep_assert_held(&vdev->dev_set->lock);
if (WARN_ON(!vdev->iommufd_device))
return -EINVAL;
if (vdev->iommufd_attached)
return -EBUSY;
rc = iommufd_device_attach(vdev->iommufd_device, pt_id); rc = iommufd_device_attach(vdev->iommufd_device, pt_id);
if (rc) if (rc)
return rc; return rc;
...@@ -148,6 +156,18 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id) ...@@ -148,6 +156,18 @@ int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
} }
EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas); EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas);
void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev)
{
lockdep_assert_held(&vdev->dev_set->lock);
if (WARN_ON(!vdev->iommufd_device) || !vdev->iommufd_attached)
return;
iommufd_device_detach(vdev->iommufd_device);
vdev->iommufd_attached = false;
}
EXPORT_SYMBOL_GPL(vfio_iommufd_physical_detach_ioas);
/* /*
* The emulated standard ops mean that vfio_device is going to use the * The emulated standard ops mean that vfio_device is going to use the
* "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this * "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this
......
...@@ -1373,6 +1373,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_migrn_ops = { ...@@ -1373,6 +1373,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_migrn_ops = {
.bind_iommufd = vfio_iommufd_physical_bind, .bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind, .unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas, .attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
}; };
static const struct vfio_device_ops hisi_acc_vfio_pci_ops = { static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
...@@ -1391,6 +1392,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_ops = { ...@@ -1391,6 +1392,7 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
.bind_iommufd = vfio_iommufd_physical_bind, .bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind, .unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas, .attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
}; };
static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
......
...@@ -1320,6 +1320,7 @@ static const struct vfio_device_ops mlx5vf_pci_ops = { ...@@ -1320,6 +1320,7 @@ static const struct vfio_device_ops mlx5vf_pci_ops = {
.bind_iommufd = vfio_iommufd_physical_bind, .bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind, .unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas, .attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
}; };
static int mlx5vf_pci_probe(struct pci_dev *pdev, static int mlx5vf_pci_probe(struct pci_dev *pdev,
......
...@@ -141,6 +141,7 @@ static const struct vfio_device_ops vfio_pci_ops = { ...@@ -141,6 +141,7 @@ static const struct vfio_device_ops vfio_pci_ops = {
.bind_iommufd = vfio_iommufd_physical_bind, .bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind, .unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas, .attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
}; };
static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
......
...@@ -119,6 +119,7 @@ static const struct vfio_device_ops vfio_amba_ops = { ...@@ -119,6 +119,7 @@ static const struct vfio_device_ops vfio_amba_ops = {
.bind_iommufd = vfio_iommufd_physical_bind, .bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind, .unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas, .attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
}; };
static const struct amba_id pl330_ids[] = { static const struct amba_id pl330_ids[] = {
......
...@@ -108,6 +108,7 @@ static const struct vfio_device_ops vfio_platform_ops = { ...@@ -108,6 +108,7 @@ static const struct vfio_device_ops vfio_platform_ops = {
.bind_iommufd = vfio_iommufd_physical_bind, .bind_iommufd = vfio_iommufd_physical_bind,
.unbind_iommufd = vfio_iommufd_physical_unbind, .unbind_iommufd = vfio_iommufd_physical_unbind,
.attach_ioas = vfio_iommufd_physical_attach_ioas, .attach_ioas = vfio_iommufd_physical_attach_ioas,
.detach_ioas = vfio_iommufd_physical_detach_ioas,
}; };
static struct platform_driver vfio_platform_driver = { static struct platform_driver vfio_platform_driver = {
......
...@@ -273,7 +273,8 @@ static int __vfio_register_dev(struct vfio_device *device, ...@@ -273,7 +273,8 @@ static int __vfio_register_dev(struct vfio_device *device,
if (WARN_ON(IS_ENABLED(CONFIG_IOMMUFD) && if (WARN_ON(IS_ENABLED(CONFIG_IOMMUFD) &&
(!device->ops->bind_iommufd || (!device->ops->bind_iommufd ||
!device->ops->unbind_iommufd || !device->ops->unbind_iommufd ||
!device->ops->attach_ioas))) !device->ops->attach_ioas ||
!device->ops->detach_ioas)))
return -EINVAL; return -EINVAL;
/* /*
......
...@@ -73,7 +73,9 @@ struct vfio_device { ...@@ -73,7 +73,9 @@ struct vfio_device {
* @bind_iommufd: Called when binding the device to an iommufd * @bind_iommufd: Called when binding the device to an iommufd
* @unbind_iommufd: Opposite of bind_iommufd * @unbind_iommufd: Opposite of bind_iommufd
* @attach_ioas: Called when attaching device to an IOAS/HWPT managed by the * @attach_ioas: Called when attaching device to an IOAS/HWPT managed by the
* bound iommufd. Undo in unbind_iommufd. * bound iommufd. Undo in unbind_iommufd if @detach_ioas is not
* called.
* @detach_ioas: Opposite of attach_ioas
* @open_device: Called when the first file descriptor is opened for this device * @open_device: Called when the first file descriptor is opened for this device
* @close_device: Opposite of open_device * @close_device: Opposite of open_device
* @read: Perform read(2) on device file descriptor * @read: Perform read(2) on device file descriptor
...@@ -97,6 +99,7 @@ struct vfio_device_ops { ...@@ -97,6 +99,7 @@ struct vfio_device_ops {
struct iommufd_ctx *ictx, u32 *out_device_id); struct iommufd_ctx *ictx, u32 *out_device_id);
void (*unbind_iommufd)(struct vfio_device *vdev); void (*unbind_iommufd)(struct vfio_device *vdev);
int (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id); int (*attach_ioas)(struct vfio_device *vdev, u32 *pt_id);
void (*detach_ioas)(struct vfio_device *vdev);
int (*open_device)(struct vfio_device *vdev); int (*open_device)(struct vfio_device *vdev);
void (*close_device)(struct vfio_device *vdev); void (*close_device)(struct vfio_device *vdev);
ssize_t (*read)(struct vfio_device *vdev, char __user *buf, ssize_t (*read)(struct vfio_device *vdev, char __user *buf,
...@@ -120,6 +123,7 @@ int vfio_iommufd_physical_bind(struct vfio_device *vdev, ...@@ -120,6 +123,7 @@ int vfio_iommufd_physical_bind(struct vfio_device *vdev,
struct iommufd_ctx *ictx, u32 *out_device_id); struct iommufd_ctx *ictx, u32 *out_device_id);
void vfio_iommufd_physical_unbind(struct vfio_device *vdev); void vfio_iommufd_physical_unbind(struct vfio_device *vdev);
int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id); int vfio_iommufd_physical_attach_ioas(struct vfio_device *vdev, u32 *pt_id);
void vfio_iommufd_physical_detach_ioas(struct vfio_device *vdev);
int vfio_iommufd_emulated_bind(struct vfio_device *vdev, int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
struct iommufd_ctx *ictx, u32 *out_device_id); struct iommufd_ctx *ictx, u32 *out_device_id);
void vfio_iommufd_emulated_unbind(struct vfio_device *vdev); void vfio_iommufd_emulated_unbind(struct vfio_device *vdev);
...@@ -144,6 +148,8 @@ vfio_iommufd_get_dev_id(struct vfio_device *vdev, struct iommufd_ctx *ictx) ...@@ -144,6 +148,8 @@ vfio_iommufd_get_dev_id(struct vfio_device *vdev, struct iommufd_ctx *ictx)
((void (*)(struct vfio_device *vdev)) NULL) ((void (*)(struct vfio_device *vdev)) NULL)
#define vfio_iommufd_physical_attach_ioas \ #define vfio_iommufd_physical_attach_ioas \
((int (*)(struct vfio_device *vdev, u32 *pt_id)) NULL) ((int (*)(struct vfio_device *vdev, u32 *pt_id)) NULL)
#define vfio_iommufd_physical_detach_ioas \
((void (*)(struct vfio_device *vdev)) NULL)
#define vfio_iommufd_emulated_bind \ #define vfio_iommufd_emulated_bind \
((int (*)(struct vfio_device *vdev, struct iommufd_ctx *ictx, \ ((int (*)(struct vfio_device *vdev, struct iommufd_ctx *ictx, \
u32 *out_device_id)) NULL) u32 *out_device_id)) NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment