Commit 9fdf7916 authored by Jason Gunthorpe's avatar Jason Gunthorpe

Merge branch 'vfio_mdev_ops' into iommufd.git for-next

Yi Liu says

===================
The .bind_iommufd op of vfio emulated devices are either empty or does
nothing. This is different with the vfio physical devices, to add vfio
device cdev, need to make them act the same.

This series first makes the .bind_iommufd op of vfio emulated devices to
create iommufd_access, this introduces a new iommufd API. Then let the
driver that does not provide .bind_iommufd op to use the vfio emulated
iommufd op set. This makes all vfio device drivers have consistent iommufd
operations, which is good for adding new device uAPIs in the device cdev
===================

* branch 'vfio_mdev_ops':
  vfio: Check the presence for iommufd callbacks in __vfio_register_dev()
  vfio/mdev: Uses the vfio emulated iommufd ops set in the mdev sample drivers
  vfio-iommufd: Make vfio_iommufd_emulated_bind() return iommufd_access ID
  vfio-iommufd: No need to record iommufd_ctx in vfio_device
  iommufd: Create access in vfio_iommufd_emulated_bind()
  iommu/iommufd: Pass iommufd_ctx pointer in iommufd_get_ioas()
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parents fd8c1a4a 7d12578c
...@@ -395,17 +395,20 @@ void iommufd_access_destroy_object(struct iommufd_object *obj) ...@@ -395,17 +395,20 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
struct iommufd_access *access = struct iommufd_access *access =
container_of(obj, struct iommufd_access, obj); container_of(obj, struct iommufd_access, obj);
if (access->ioas) {
iopt_remove_access(&access->ioas->iopt, access); iopt_remove_access(&access->ioas->iopt, access);
iommufd_ctx_put(access->ictx);
refcount_dec(&access->ioas->obj.users); refcount_dec(&access->ioas->obj.users);
access->ioas = NULL;
}
iommufd_ctx_put(access->ictx);
} }
/** /**
* iommufd_access_create - Create an iommufd_access * iommufd_access_create - Create an iommufd_access
* @ictx: iommufd file descriptor * @ictx: iommufd file descriptor
* @ioas_id: ID for a IOMMUFD_OBJ_IOAS
* @ops: Driver's ops to associate with the access * @ops: Driver's ops to associate with the access
* @data: Opaque data to pass into ops functions * @data: Opaque data to pass into ops functions
* @id: Output ID number to return to userspace for this access
* *
* An iommufd_access allows a driver to read/write to the IOAS without using * An iommufd_access allows a driver to read/write to the IOAS without using
* DMA. The underlying CPU memory can be accessed using the * DMA. The underlying CPU memory can be accessed using the
...@@ -414,12 +417,10 @@ void iommufd_access_destroy_object(struct iommufd_object *obj) ...@@ -414,12 +417,10 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
* The provided ops are required to use iommufd_access_pin_pages(). * The provided ops are required to use iommufd_access_pin_pages().
*/ */
struct iommufd_access * struct iommufd_access *
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id, iommufd_access_create(struct iommufd_ctx *ictx,
const struct iommufd_access_ops *ops, void *data) const struct iommufd_access_ops *ops, void *data, u32 *id)
{ {
struct iommufd_access *access; struct iommufd_access *access;
struct iommufd_object *obj;
int rc;
/* /*
* There is no uAPI for the access object, but to keep things symmetric * There is no uAPI for the access object, but to keep things symmetric
...@@ -432,33 +433,18 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id, ...@@ -432,33 +433,18 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
access->data = data; access->data = data;
access->ops = ops; access->ops = ops;
obj = iommufd_get_object(ictx, ioas_id, IOMMUFD_OBJ_IOAS);
if (IS_ERR(obj)) {
rc = PTR_ERR(obj);
goto out_abort;
}
access->ioas = container_of(obj, struct iommufd_ioas, obj);
iommufd_ref_to_users(obj);
if (ops->needs_pin_pages) if (ops->needs_pin_pages)
access->iova_alignment = PAGE_SIZE; access->iova_alignment = PAGE_SIZE;
else else
access->iova_alignment = 1; access->iova_alignment = 1;
rc = iopt_add_access(&access->ioas->iopt, access);
if (rc)
goto out_put_ioas;
/* The calling driver is a user until iommufd_access_destroy() */ /* The calling driver is a user until iommufd_access_destroy() */
refcount_inc(&access->obj.users); refcount_inc(&access->obj.users);
access->ictx = ictx; access->ictx = ictx;
iommufd_ctx_get(ictx); iommufd_ctx_get(ictx);
iommufd_object_finalize(ictx, &access->obj); iommufd_object_finalize(ictx, &access->obj);
*id = access->obj.id;
return access; return access;
out_put_ioas:
refcount_dec(&access->ioas->obj.users);
out_abort:
iommufd_object_abort(ictx, &access->obj);
return ERR_PTR(rc);
} }
EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD); EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
...@@ -477,6 +463,30 @@ void iommufd_access_destroy(struct iommufd_access *access) ...@@ -477,6 +463,30 @@ void iommufd_access_destroy(struct iommufd_access *access)
} }
EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD); EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
{
struct iommufd_ioas *new_ioas;
int rc = 0;
if (access->ioas)
return -EINVAL;
new_ioas = iommufd_get_ioas(access->ictx, ioas_id);
if (IS_ERR(new_ioas))
return PTR_ERR(new_ioas);
rc = iopt_add_access(&new_ioas->iopt, access);
if (rc) {
iommufd_put_object(&new_ioas->obj);
return rc;
}
iommufd_ref_to_users(&new_ioas->obj);
access->ioas = new_ioas;
return 0;
}
EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, IOMMUFD);
/** /**
* iommufd_access_notify_unmap - Notify users of an iopt to stop using it * iommufd_access_notify_unmap - Notify users of an iopt to stop using it
* @iopt: iopt to work on * @iopt: iopt to work on
......
...@@ -71,7 +71,7 @@ int iommufd_ioas_iova_ranges(struct iommufd_ucmd *ucmd) ...@@ -71,7 +71,7 @@ int iommufd_ioas_iova_ranges(struct iommufd_ucmd *ucmd)
if (cmd->__reserved) if (cmd->__reserved)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id); ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return PTR_ERR(ioas); return PTR_ERR(ioas);
...@@ -151,7 +151,7 @@ int iommufd_ioas_allow_iovas(struct iommufd_ucmd *ucmd) ...@@ -151,7 +151,7 @@ int iommufd_ioas_allow_iovas(struct iommufd_ucmd *ucmd)
if (cmd->__reserved) if (cmd->__reserved)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id); ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return PTR_ERR(ioas); return PTR_ERR(ioas);
iopt = &ioas->iopt; iopt = &ioas->iopt;
...@@ -213,7 +213,7 @@ int iommufd_ioas_map(struct iommufd_ucmd *ucmd) ...@@ -213,7 +213,7 @@ int iommufd_ioas_map(struct iommufd_ucmd *ucmd)
if (cmd->iova >= ULONG_MAX || cmd->length >= ULONG_MAX) if (cmd->iova >= ULONG_MAX || cmd->length >= ULONG_MAX)
return -EOVERFLOW; return -EOVERFLOW;
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id); ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return PTR_ERR(ioas); return PTR_ERR(ioas);
...@@ -253,7 +253,7 @@ int iommufd_ioas_copy(struct iommufd_ucmd *ucmd) ...@@ -253,7 +253,7 @@ int iommufd_ioas_copy(struct iommufd_ucmd *ucmd)
cmd->dst_iova >= ULONG_MAX) cmd->dst_iova >= ULONG_MAX)
return -EOVERFLOW; return -EOVERFLOW;
src_ioas = iommufd_get_ioas(ucmd, cmd->src_ioas_id); src_ioas = iommufd_get_ioas(ucmd->ictx, cmd->src_ioas_id);
if (IS_ERR(src_ioas)) if (IS_ERR(src_ioas))
return PTR_ERR(src_ioas); return PTR_ERR(src_ioas);
rc = iopt_get_pages(&src_ioas->iopt, cmd->src_iova, cmd->length, rc = iopt_get_pages(&src_ioas->iopt, cmd->src_iova, cmd->length,
...@@ -262,7 +262,7 @@ int iommufd_ioas_copy(struct iommufd_ucmd *ucmd) ...@@ -262,7 +262,7 @@ int iommufd_ioas_copy(struct iommufd_ucmd *ucmd)
if (rc) if (rc)
return rc; return rc;
dst_ioas = iommufd_get_ioas(ucmd, cmd->dst_ioas_id); dst_ioas = iommufd_get_ioas(ucmd->ictx, cmd->dst_ioas_id);
if (IS_ERR(dst_ioas)) { if (IS_ERR(dst_ioas)) {
rc = PTR_ERR(dst_ioas); rc = PTR_ERR(dst_ioas);
goto out_pages; goto out_pages;
...@@ -292,7 +292,7 @@ int iommufd_ioas_unmap(struct iommufd_ucmd *ucmd) ...@@ -292,7 +292,7 @@ int iommufd_ioas_unmap(struct iommufd_ucmd *ucmd)
unsigned long unmapped = 0; unsigned long unmapped = 0;
int rc; int rc;
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id); ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return PTR_ERR(ioas); return PTR_ERR(ioas);
...@@ -381,7 +381,7 @@ int iommufd_ioas_option(struct iommufd_ucmd *ucmd) ...@@ -381,7 +381,7 @@ int iommufd_ioas_option(struct iommufd_ucmd *ucmd)
if (cmd->__reserved) if (cmd->__reserved)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ioas = iommufd_get_ioas(ucmd, cmd->object_id); ioas = iommufd_get_ioas(ucmd->ictx, cmd->object_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return PTR_ERR(ioas); return PTR_ERR(ioas);
......
...@@ -212,10 +212,10 @@ struct iommufd_ioas { ...@@ -212,10 +212,10 @@ struct iommufd_ioas {
struct list_head hwpt_list; struct list_head hwpt_list;
}; };
static inline struct iommufd_ioas *iommufd_get_ioas(struct iommufd_ucmd *ucmd, static inline struct iommufd_ioas *iommufd_get_ioas(struct iommufd_ctx *ictx,
u32 id) u32 id)
{ {
return container_of(iommufd_get_object(ucmd->ictx, id, return container_of(iommufd_get_object(ictx, id,
IOMMUFD_OBJ_IOAS), IOMMUFD_OBJ_IOAS),
struct iommufd_ioas, obj); struct iommufd_ioas, obj);
} }
......
...@@ -75,7 +75,7 @@ void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd, ...@@ -75,7 +75,7 @@ void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd,
return; return;
*flags &= ~(u32)MOCK_FLAGS_ACCESS_SYZ; *flags &= ~(u32)MOCK_FLAGS_ACCESS_SYZ;
ioas = iommufd_get_ioas(ucmd, ioas_id); ioas = iommufd_get_ioas(ucmd->ictx, ioas_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return; return;
*iova = iommufd_test_syz_conv_iova(&ioas->iopt, iova); *iova = iommufd_test_syz_conv_iova(&ioas->iopt, iova);
...@@ -463,7 +463,7 @@ static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd, ...@@ -463,7 +463,7 @@ static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd,
struct iommufd_ioas *ioas; struct iommufd_ioas *ioas;
int rc; int rc;
ioas = iommufd_get_ioas(ucmd, mockpt_id); ioas = iommufd_get_ioas(ucmd->ictx, mockpt_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return PTR_ERR(ioas); return PTR_ERR(ioas);
down_write(&ioas->iopt.iova_rwsem); down_write(&ioas->iopt.iova_rwsem);
...@@ -700,6 +700,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd, ...@@ -700,6 +700,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
struct iommu_test_cmd *cmd = ucmd->cmd; struct iommu_test_cmd *cmd = ucmd->cmd;
struct selftest_access *staccess; struct selftest_access *staccess;
struct iommufd_access *access; struct iommufd_access *access;
u32 id;
int fdno; int fdno;
int rc; int rc;
...@@ -717,15 +718,18 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd, ...@@ -717,15 +718,18 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
} }
access = iommufd_access_create( access = iommufd_access_create(
ucmd->ictx, ioas_id, ucmd->ictx,
(flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ? (flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ?
&selftest_access_ops_pin : &selftest_access_ops_pin :
&selftest_access_ops, &selftest_access_ops,
staccess); staccess, &id);
if (IS_ERR(access)) { if (IS_ERR(access)) {
rc = PTR_ERR(access); rc = PTR_ERR(access);
goto out_put_fdno; goto out_put_fdno;
} }
rc = iommufd_access_attach(access, ioas_id);
if (rc)
goto out_destroy;
cmd->create_access.out_access_fd = fdno; cmd->create_access.out_access_fd = fdno;
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
if (rc) if (rc)
......
...@@ -137,7 +137,7 @@ int iommufd_vfio_ioas(struct iommufd_ucmd *ucmd) ...@@ -137,7 +137,7 @@ int iommufd_vfio_ioas(struct iommufd_ucmd *ucmd)
return iommufd_ucmd_respond(ucmd, sizeof(*cmd)); return iommufd_ucmd_respond(ucmd, sizeof(*cmd));
case IOMMU_VFIO_IOAS_SET: case IOMMU_VFIO_IOAS_SET:
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id); ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
if (IS_ERR(ioas)) if (IS_ERR(ioas))
return PTR_ERR(ioas); return PTR_ERR(ioas);
xa_lock(&ucmd->ictx->objects); xa_lock(&ucmd->ictx->objects);
......
...@@ -32,13 +32,6 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx) ...@@ -32,13 +32,6 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
return 0; return 0;
} }
/*
* If the driver doesn't provide this op then it means the device does
* not do DMA at all. So nothing to do.
*/
if (!vdev->ops->bind_iommufd)
return 0;
ret = vdev->ops->bind_iommufd(vdev, ictx, &device_id); ret = vdev->ops->bind_iommufd(vdev, ictx, &device_id);
if (ret) if (ret)
return ret; return ret;
...@@ -119,7 +112,8 @@ EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas); ...@@ -119,7 +112,8 @@ EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_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
* ops set should call vfio_register_emulated_iommu_dev(). * ops set should call vfio_register_emulated_iommu_dev(). Drivers that do
* not call vfio_pin_pages()/vfio_dma_rw() have no need to provide dma_unmap.
*/ */
static void vfio_emulated_unmap(void *data, unsigned long iova, static void vfio_emulated_unmap(void *data, unsigned long iova,
...@@ -127,6 +121,7 @@ static void vfio_emulated_unmap(void *data, unsigned long iova, ...@@ -127,6 +121,7 @@ static void vfio_emulated_unmap(void *data, unsigned long iova,
{ {
struct vfio_device *vdev = data; struct vfio_device *vdev = data;
if (vdev->ops->dma_unmap)
vdev->ops->dma_unmap(vdev, iova, length); vdev->ops->dma_unmap(vdev, iova, length);
} }
...@@ -138,10 +133,14 @@ static const struct iommufd_access_ops vfio_user_ops = { ...@@ -138,10 +133,14 @@ static const struct iommufd_access_ops vfio_user_ops = {
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)
{ {
struct iommufd_access *user;
lockdep_assert_held(&vdev->dev_set->lock); lockdep_assert_held(&vdev->dev_set->lock);
vdev->iommufd_ictx = ictx; user = iommufd_access_create(ictx, &vfio_user_ops, vdev, out_device_id);
iommufd_ctx_get(ictx); if (IS_ERR(user))
return PTR_ERR(user);
vdev->iommufd_access = user;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind); EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
...@@ -152,24 +151,24 @@ void vfio_iommufd_emulated_unbind(struct vfio_device *vdev) ...@@ -152,24 +151,24 @@ void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)
if (vdev->iommufd_access) { if (vdev->iommufd_access) {
iommufd_access_destroy(vdev->iommufd_access); iommufd_access_destroy(vdev->iommufd_access);
vdev->iommufd_attached = false;
vdev->iommufd_access = NULL; vdev->iommufd_access = NULL;
} }
iommufd_ctx_put(vdev->iommufd_ictx);
vdev->iommufd_ictx = NULL;
} }
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind); EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);
int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id) int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
{ {
struct iommufd_access *user; int rc;
lockdep_assert_held(&vdev->dev_set->lock); lockdep_assert_held(&vdev->dev_set->lock);
user = iommufd_access_create(vdev->iommufd_ictx, *pt_id, &vfio_user_ops, if (vdev->iommufd_attached)
vdev); return -EBUSY;
if (IS_ERR(user)) rc = iommufd_access_attach(vdev->iommufd_access, *pt_id);
return PTR_ERR(user); if (rc)
vdev->iommufd_access = user; return rc;
vdev->iommufd_attached = true;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas); EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);
...@@ -255,8 +255,9 @@ static int __vfio_register_dev(struct vfio_device *device, ...@@ -255,8 +255,9 @@ static int __vfio_register_dev(struct vfio_device *device,
{ {
int ret; int ret;
if (WARN_ON(device->ops->bind_iommufd && if (WARN_ON(IS_ENABLED(CONFIG_IOMMUFD) &&
(!device->ops->unbind_iommufd || (!device->ops->bind_iommufd ||
!device->ops->unbind_iommufd ||
!device->ops->attach_ioas))) !device->ops->attach_ioas)))
return -EINVAL; return -EINVAL;
......
...@@ -40,9 +40,10 @@ enum { ...@@ -40,9 +40,10 @@ enum {
}; };
struct iommufd_access * struct iommufd_access *
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id, iommufd_access_create(struct iommufd_ctx *ictx,
const struct iommufd_access_ops *ops, void *data); const struct iommufd_access_ops *ops, void *data, u32 *id);
void iommufd_access_destroy(struct iommufd_access *access); void iommufd_access_destroy(struct iommufd_access *access);
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id);
void iommufd_ctx_get(struct iommufd_ctx *ictx); void iommufd_ctx_get(struct iommufd_ctx *ictx);
......
...@@ -60,7 +60,6 @@ struct vfio_device { ...@@ -60,7 +60,6 @@ struct vfio_device {
void (*put_kvm)(struct kvm *kvm); void (*put_kvm)(struct kvm *kvm);
#if IS_ENABLED(CONFIG_IOMMUFD) #if IS_ENABLED(CONFIG_IOMMUFD)
struct iommufd_device *iommufd_device; struct iommufd_device *iommufd_device;
struct iommufd_ctx *iommufd_ictx;
bool iommufd_attached; bool iommufd_attached;
#endif #endif
}; };
......
...@@ -1374,6 +1374,9 @@ static const struct vfio_device_ops mbochs_dev_ops = { ...@@ -1374,6 +1374,9 @@ static const struct vfio_device_ops mbochs_dev_ops = {
.write = mbochs_write, .write = mbochs_write,
.ioctl = mbochs_ioctl, .ioctl = mbochs_ioctl,
.mmap = mbochs_mmap, .mmap = mbochs_mmap,
.bind_iommufd = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas = vfio_iommufd_emulated_attach_ioas,
}; };
static struct mdev_driver mbochs_driver = { static struct mdev_driver mbochs_driver = {
......
...@@ -663,6 +663,9 @@ static const struct vfio_device_ops mdpy_dev_ops = { ...@@ -663,6 +663,9 @@ static const struct vfio_device_ops mdpy_dev_ops = {
.write = mdpy_write, .write = mdpy_write,
.ioctl = mdpy_ioctl, .ioctl = mdpy_ioctl,
.mmap = mdpy_mmap, .mmap = mdpy_mmap,
.bind_iommufd = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas = vfio_iommufd_emulated_attach_ioas,
}; };
static struct mdev_driver mdpy_driver = { static struct mdev_driver mdpy_driver = {
......
...@@ -1269,6 +1269,9 @@ static const struct vfio_device_ops mtty_dev_ops = { ...@@ -1269,6 +1269,9 @@ static const struct vfio_device_ops mtty_dev_ops = {
.read = mtty_read, .read = mtty_read,
.write = mtty_write, .write = mtty_write,
.ioctl = mtty_ioctl, .ioctl = mtty_ioctl,
.bind_iommufd = vfio_iommufd_emulated_bind,
.unbind_iommufd = vfio_iommufd_emulated_unbind,
.attach_ioas = vfio_iommufd_emulated_attach_ioas,
}; };
static struct mdev_driver mtty_driver = { static struct mdev_driver mtty_driver = {
......
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