kvm/vfio: Move KVM_DEV_VFIO_GROUP_* ioctls into functions

To make it easier to read and change in following patches.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/1-v3-f7729924a7ea+25e33-vfio_kvm_no_group_jgg@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
Jason Gunthorpe 2022-05-04 16:14:39 -03:00 коммит произвёл Alex Williamson
Родитель dc15f82f53
Коммит 73b0565f19
1 изменённых файлов: 149 добавлений и 126 удалений

Просмотреть файл

@ -181,21 +181,14 @@ static void kvm_vfio_update_coherency(struct kvm_device *dev)
mutex_unlock(&kv->lock); mutex_unlock(&kv->lock);
} }
static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg) static int kvm_vfio_group_add(struct kvm_device *dev, unsigned int fd)
{ {
struct kvm_vfio *kv = dev->private; struct kvm_vfio *kv = dev->private;
struct vfio_group *vfio_group; struct vfio_group *vfio_group;
struct kvm_vfio_group *kvg; struct kvm_vfio_group *kvg;
int32_t __user *argp = (int32_t __user *)(unsigned long)arg;
struct fd f; struct fd f;
int32_t fd;
int ret; int ret;
switch (attr) {
case KVM_DEV_VFIO_GROUP_ADD:
if (get_user(fd, argp))
return -EFAULT;
f = fdget(fd); f = fdget(fd);
if (!f.file) if (!f.file)
return -EBADF; return -EBADF;
@ -210,17 +203,15 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
list_for_each_entry(kvg, &kv->group_list, node) { list_for_each_entry(kvg, &kv->group_list, node) {
if (kvg->vfio_group == vfio_group) { if (kvg->vfio_group == vfio_group) {
mutex_unlock(&kv->lock); ret = -EEXIST;
kvm_vfio_group_put_external_user(vfio_group); goto err_unlock;
return -EEXIST;
} }
} }
kvg = kzalloc(sizeof(*kvg), GFP_KERNEL_ACCOUNT); kvg = kzalloc(sizeof(*kvg), GFP_KERNEL_ACCOUNT);
if (!kvg) { if (!kvg) {
mutex_unlock(&kv->lock); ret = -ENOMEM;
kvm_vfio_group_put_external_user(vfio_group); goto err_unlock;
return -ENOMEM;
} }
list_add_tail(&kvg->node, &kv->group_list); list_add_tail(&kvg->node, &kv->group_list);
@ -231,14 +222,21 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
mutex_unlock(&kv->lock); mutex_unlock(&kv->lock);
kvm_vfio_group_set_kvm(vfio_group, dev->kvm); kvm_vfio_group_set_kvm(vfio_group, dev->kvm);
kvm_vfio_update_coherency(dev); kvm_vfio_update_coherency(dev);
return 0; return 0;
err_unlock:
mutex_unlock(&kv->lock);
kvm_vfio_group_put_external_user(vfio_group);
return ret;
}
case KVM_DEV_VFIO_GROUP_DEL: static int kvm_vfio_group_del(struct kvm_device *dev, unsigned int fd)
if (get_user(fd, argp)) {
return -EFAULT; struct kvm_vfio *kv = dev->private;
struct kvm_vfio_group *kvg;
struct fd f;
int ret;
f = fdget(fd); f = fdget(fd);
if (!f.file) if (!f.file)
@ -256,8 +254,7 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
list_del(&kvg->node); list_del(&kvg->node);
kvm_arch_end_assignment(dev->kvm); kvm_arch_end_assignment(dev->kvm);
#ifdef CONFIG_SPAPR_TCE_IOMMU #ifdef CONFIG_SPAPR_TCE_IOMMU
kvm_spapr_tce_release_vfio_group(dev->kvm, kvm_spapr_tce_release_vfio_group(dev->kvm, kvg->vfio_group);
kvg->vfio_group);
#endif #endif
kvm_vfio_group_set_kvm(kvg->vfio_group, NULL); kvm_vfio_group_set_kvm(kvg->vfio_group, NULL);
kvm_vfio_group_put_external_user(kvg->vfio_group); kvm_vfio_group_put_external_user(kvg->vfio_group);
@ -273,18 +270,21 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
kvm_vfio_update_coherency(dev); kvm_vfio_update_coherency(dev);
return ret; return ret;
}
#ifdef CONFIG_SPAPR_TCE_IOMMU #ifdef CONFIG_SPAPR_TCE_IOMMU
case KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE: { static int kvm_vfio_group_set_spapr_tce(struct kvm_device *dev,
void __user *arg)
{
struct kvm_vfio_spapr_tce param; struct kvm_vfio_spapr_tce param;
struct kvm_vfio *kv = dev->private; struct kvm_vfio *kv = dev->private;
struct vfio_group *vfio_group; struct vfio_group *vfio_group;
struct kvm_vfio_group *kvg; struct kvm_vfio_group *kvg;
struct fd f; struct fd f;
struct iommu_group *grp; struct iommu_group *grp;
int ret;
if (copy_from_user(&param, (void __user *)arg, if (copy_from_user(&param, arg, sizeof(struct kvm_vfio_spapr_tce)))
sizeof(struct kvm_vfio_spapr_tce)))
return -EFAULT; return -EFAULT;
f = fdget(param.groupfd); f = fdget(param.groupfd);
@ -299,8 +299,8 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
grp = kvm_vfio_group_get_iommu_group(vfio_group); grp = kvm_vfio_group_get_iommu_group(vfio_group);
if (WARN_ON_ONCE(!grp)) { if (WARN_ON_ONCE(!grp)) {
kvm_vfio_group_put_external_user(vfio_group); ret = -EIO;
return -EIO; goto err_put_external;
} }
ret = -ENOENT; ret = -ENOENT;
@ -311,19 +311,41 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
if (kvg->vfio_group != vfio_group) if (kvg->vfio_group != vfio_group)
continue; continue;
ret = kvm_spapr_tce_attach_iommu_group(dev->kvm, ret = kvm_spapr_tce_attach_iommu_group(dev->kvm, param.tablefd,
param.tablefd, grp); grp);
break; break;
} }
mutex_unlock(&kv->lock); mutex_unlock(&kv->lock);
iommu_group_put(grp); iommu_group_put(grp);
err_put_external:
kvm_vfio_group_put_external_user(vfio_group); kvm_vfio_group_put_external_user(vfio_group);
return ret; return ret;
} }
#endif /* CONFIG_SPAPR_TCE_IOMMU */ #endif
static int kvm_vfio_set_group(struct kvm_device *dev, long attr,
void __user *arg)
{
int32_t __user *argp = arg;
int32_t fd;
switch (attr) {
case KVM_DEV_VFIO_GROUP_ADD:
if (get_user(fd, argp))
return -EFAULT;
return kvm_vfio_group_add(dev, fd);
case KVM_DEV_VFIO_GROUP_DEL:
if (get_user(fd, argp))
return -EFAULT;
return kvm_vfio_group_del(dev, fd);
#ifdef CONFIG_SPAPR_TCE_IOMMU
case KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE:
return kvm_vfio_group_set_spapr_tce(dev, arg);
#endif
} }
return -ENXIO; return -ENXIO;
@ -334,7 +356,8 @@ static int kvm_vfio_set_attr(struct kvm_device *dev,
{ {
switch (attr->group) { switch (attr->group) {
case KVM_DEV_VFIO_GROUP: case KVM_DEV_VFIO_GROUP:
return kvm_vfio_set_group(dev, attr->attr, attr->addr); return kvm_vfio_set_group(dev, attr->attr,
u64_to_user_ptr(attr->addr));
} }
return -ENXIO; return -ENXIO;