/* * device access via the fd opened by this function is blocked until * .open_device() is called successfully during BIND_IOMMUFD.
*/ int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep)
{ struct vfio_device *device = container_of(inode->i_cdev, struct vfio_device, cdev); struct vfio_device_file *df; int ret;
/* Paired with the put in vfio_device_fops_release() */ if (!vfio_device_try_get_registration(device)) return -ENODEV;
df = vfio_allocate_device_file(device); if (IS_ERR(df)) {
ret = PTR_ERR(df); goto err_put_registration;
}
filep->private_data = df;
/* * Use the pseudo fs inode on the device to link all mmaps * to the same address space, allowing us to unmap all vmas * associated to this device using unmap_mapping_range().
*/
filep->f_mapping = device->inode->i_mapping;
ret = get_user(user_size, &arg->argsz); if (ret) return ret; if (user_size < minsz) return -EINVAL;
ret = copy_struct_from_user(&bind, minsz, arg, user_size); if (ret) return ret;
if (bind.iommufd < 0 || bind.flags & ~VALID_FLAGS) return -EINVAL;
/* BIND_IOMMUFD only allowed for cdev fds */ if (df->group) return -EINVAL;
ret = vfio_device_block_group(device); if (ret) return ret;
mutex_lock(&device->dev_set->lock); /* one device cannot be bound twice */ if (df->access_granted) {
ret = -EINVAL; goto out_unlock;
}
ret = vfio_df_check_token(device, &bind); if (ret) goto out_unlock;
df->iommufd = iommufd_ctx_from_fd(bind.iommufd); if (IS_ERR(df->iommufd)) {
ret = PTR_ERR(df->iommufd);
df->iommufd = NULL; goto out_unlock;
}
/* * Before the device open, get the KVM pointer currently * associated with the device file (if there is) and obtain * a reference. This reference is held until device closed. * Save the pointer in the device for use by drivers.
*/
vfio_df_get_kvm_safe(df);
ret = vfio_df_open(df); if (ret) goto out_put_kvm;
ret = copy_to_user(&arg->out_devid, &df->devid, sizeof(df->devid)) ? -EFAULT : 0; if (ret) goto out_close_device;
device->cdev_opened = true; /* * Paired with smp_load_acquire() in vfio_device_fops::ioctl/ * read/write/mmap
*/
smp_store_release(&df->access_granted, true);
mutex_unlock(&device->dev_set->lock); return 0;
/* * In the time of close, there is no contention with another one * changing this flag. So read df->access_granted without lock * and no smp_load_acquire() is ok.
*/ if (!df->access_granted) return;
mutex_lock(&device->dev_set->lock); if (attach.flags & VFIO_DEVICE_ATTACH_PASID)
ret = device->ops->pasid_attach_ioas(device,
attach.pasid,
&attach.pt_id); else
ret = device->ops->attach_ioas(device, &attach.pt_id); if (ret) goto out_unlock;
if (copy_to_user(&arg->pt_id, &attach.pt_id, sizeof(attach.pt_id))) {
ret = -EFAULT; goto out_detach;
}
mutex_unlock(&device->dev_set->lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.