@@ -10,6 +10,43 @@
MODULE_IMPORT_NS(IOMMUFD);
MODULE_IMPORT_NS(IOMMUFD_VFIO);
+static void vfio_noiommu_access_unmap(void *data, unsigned long iova,
+ unsigned long length)
+{
+ WARN_ON(1);
+}
+
+static const struct iommufd_access_ops vfio_user_noiommu_ops = {
+ .needs_pin_pages = 1,
+ .unmap = vfio_noiommu_access_unmap,
+};
+
+static int vfio_iommufd_noiommu_bind(struct vfio_device *vdev,
+ struct iommufd_ctx *ictx,
+ u32 *out_device_id)
+{
+ struct iommufd_access *user;
+
+ lockdep_assert_held(&vdev->dev_set->lock);
+
+ user = iommufd_access_create(ictx, &vfio_user_noiommu_ops,
+ vdev, out_device_id);
+ if (IS_ERR(user))
+ return PTR_ERR(user);
+ vdev->iommufd_access = user;
+ return 0;
+}
+
+static void vfio_iommufd_noiommu_unbind(struct vfio_device *vdev)
+{
+ lockdep_assert_held(&vdev->dev_set->lock);
+
+ if (vdev->iommufd_access) {
+ iommufd_access_destroy(vdev->iommufd_access);
+ vdev->iommufd_access = NULL;
+ }
+}
+
int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
{
u32 ioas_id;
@@ -29,7 +66,8 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
*/
if (!iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id))
return -EPERM;
- return 0;
+
+ return vfio_iommufd_noiommu_bind(vdev, ictx, &device_id);
}
ret = vdev->ops->bind_iommufd(vdev, ictx, &device_id);
@@ -59,8 +97,10 @@ void vfio_iommufd_unbind(struct vfio_device *vdev)
{
lockdep_assert_held(&vdev->dev_set->lock);
- if (vfio_device_is_noiommu(vdev))
+ if (vfio_device_is_noiommu(vdev)) {
+ vfio_iommufd_noiommu_unbind(vdev);
return;
+ }
if (vdev->ops->unbind_iommufd)
vdev->ops->unbind_iommufd(vdev);