Commit b1a59be8 authored by Yi Liu's avatar Yi Liu Committed by Alex Williamson

vfio: Refine vfio file kAPIs for KVM

This prepares for making the below kAPIs to accept both group file
and device file instead of only vfio group file.

  bool vfio_file_enforced_coherent(struct file *file);
  void vfio_file_set_kvm(struct file *file, struct kvm *kvm);
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarEric Auger <eric.auger@redhat.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-3-yi.l.liu@intel.comSigned-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent b1a3b5c6
...@@ -754,6 +754,15 @@ bool vfio_device_has_container(struct vfio_device *device) ...@@ -754,6 +754,15 @@ bool vfio_device_has_container(struct vfio_device *device)
return device->group->container; return device->group->container;
} }
struct vfio_group *vfio_group_from_file(struct file *file)
{
struct vfio_group *group = file->private_data;
if (file->f_op != &vfio_group_fops)
return NULL;
return group;
}
/** /**
* vfio_file_iommu_group - Return the struct iommu_group for the vfio group file * vfio_file_iommu_group - Return the struct iommu_group for the vfio group file
* @file: VFIO group file * @file: VFIO group file
...@@ -764,13 +773,13 @@ bool vfio_device_has_container(struct vfio_device *device) ...@@ -764,13 +773,13 @@ bool vfio_device_has_container(struct vfio_device *device)
*/ */
struct iommu_group *vfio_file_iommu_group(struct file *file) struct iommu_group *vfio_file_iommu_group(struct file *file)
{ {
struct vfio_group *group = file->private_data; struct vfio_group *group = vfio_group_from_file(file);
struct iommu_group *iommu_group = NULL; struct iommu_group *iommu_group = NULL;
if (!IS_ENABLED(CONFIG_SPAPR_TCE_IOMMU)) if (!IS_ENABLED(CONFIG_SPAPR_TCE_IOMMU))
return NULL; return NULL;
if (!vfio_file_is_group(file)) if (!group)
return NULL; return NULL;
mutex_lock(&group->group_lock); mutex_lock(&group->group_lock);
...@@ -784,33 +793,20 @@ struct iommu_group *vfio_file_iommu_group(struct file *file) ...@@ -784,33 +793,20 @@ struct iommu_group *vfio_file_iommu_group(struct file *file)
EXPORT_SYMBOL_GPL(vfio_file_iommu_group); EXPORT_SYMBOL_GPL(vfio_file_iommu_group);
/** /**
* vfio_file_is_group - True if the file is usable with VFIO aPIS * vfio_file_is_group - True if the file is a vfio group file
* @file: VFIO group file * @file: VFIO group file
*/ */
bool vfio_file_is_group(struct file *file) bool vfio_file_is_group(struct file *file)
{ {
return file->f_op == &vfio_group_fops; return vfio_group_from_file(file);
} }
EXPORT_SYMBOL_GPL(vfio_file_is_group); EXPORT_SYMBOL_GPL(vfio_file_is_group);
/** bool vfio_group_enforced_coherent(struct vfio_group *group)
* vfio_file_enforced_coherent - True if the DMA associated with the VFIO file
* is always CPU cache coherent
* @file: VFIO group file
*
* Enforced coherency means that the IOMMU ignores things like the PCIe no-snoop
* bit in DMA transactions. A return of false indicates that the user has
* rights to access additional instructions such as wbinvd on x86.
*/
bool vfio_file_enforced_coherent(struct file *file)
{ {
struct vfio_group *group = file->private_data;
struct vfio_device *device; struct vfio_device *device;
bool ret = true; bool ret = true;
if (!vfio_file_is_group(file))
return true;
/* /*
* If the device does not have IOMMU_CAP_ENFORCE_CACHE_COHERENCY then * If the device does not have IOMMU_CAP_ENFORCE_CACHE_COHERENCY then
* any domain later attached to it will also not support it. If the cap * any domain later attached to it will also not support it. If the cap
...@@ -828,28 +824,13 @@ bool vfio_file_enforced_coherent(struct file *file) ...@@ -828,28 +824,13 @@ bool vfio_file_enforced_coherent(struct file *file)
mutex_unlock(&group->device_lock); mutex_unlock(&group->device_lock);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
/** void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
* vfio_file_set_kvm - Link a kvm with VFIO drivers
* @file: VFIO group file
* @kvm: KVM to link
*
* When a VFIO device is first opened the KVM will be available in
* device->kvm if one was associated with the group.
*/
void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
{ {
struct vfio_group *group = file->private_data;
if (!vfio_file_is_group(file))
return;
spin_lock(&group->kvm_ref_lock); spin_lock(&group->kvm_ref_lock);
group->kvm = kvm; group->kvm = kvm;
spin_unlock(&group->kvm_ref_lock); spin_unlock(&group->kvm_ref_lock);
} }
EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
/** /**
* vfio_file_has_dev - True if the VFIO file is a handle for device * vfio_file_has_dev - True if the VFIO file is a handle for device
...@@ -860,9 +841,9 @@ EXPORT_SYMBOL_GPL(vfio_file_set_kvm); ...@@ -860,9 +841,9 @@ EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
*/ */
bool vfio_file_has_dev(struct file *file, struct vfio_device *device) bool vfio_file_has_dev(struct file *file, struct vfio_device *device)
{ {
struct vfio_group *group = file->private_data; struct vfio_group *group = vfio_group_from_file(file);
if (!vfio_file_is_group(file)) if (!group)
return false; return false;
return group == device->group; return group == device->group;
......
...@@ -90,6 +90,9 @@ void vfio_device_group_unregister(struct vfio_device *device); ...@@ -90,6 +90,9 @@ void vfio_device_group_unregister(struct vfio_device *device);
int vfio_device_group_use_iommu(struct vfio_device *device); int vfio_device_group_use_iommu(struct vfio_device *device);
void vfio_device_group_unuse_iommu(struct vfio_device *device); void vfio_device_group_unuse_iommu(struct vfio_device *device);
void vfio_device_group_close(struct vfio_device *device); void vfio_device_group_close(struct vfio_device *device);
struct vfio_group *vfio_group_from_file(struct file *file);
bool vfio_group_enforced_coherent(struct vfio_group *group);
void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm);
bool vfio_device_has_container(struct vfio_device *device); bool vfio_device_has_container(struct vfio_device *device);
int __init vfio_group_init(void); int __init vfio_group_init(void);
void vfio_group_cleanup(void); void vfio_group_cleanup(void);
......
...@@ -1190,6 +1190,55 @@ const struct file_operations vfio_device_fops = { ...@@ -1190,6 +1190,55 @@ const struct file_operations vfio_device_fops = {
.mmap = vfio_device_fops_mmap, .mmap = vfio_device_fops_mmap,
}; };
/**
* vfio_file_is_valid - True if the file is valid vfio file
* @file: VFIO group file or VFIO device file
*/
bool vfio_file_is_valid(struct file *file)
{
return vfio_group_from_file(file);
}
EXPORT_SYMBOL_GPL(vfio_file_is_valid);
/**
* vfio_file_enforced_coherent - True if the DMA associated with the VFIO file
* is always CPU cache coherent
* @file: VFIO group file or VFIO device file
*
* Enforced coherency means that the IOMMU ignores things like the PCIe no-snoop
* bit in DMA transactions. A return of false indicates that the user has
* rights to access additional instructions such as wbinvd on x86.
*/
bool vfio_file_enforced_coherent(struct file *file)
{
struct vfio_group *group;
group = vfio_group_from_file(file);
if (group)
return vfio_group_enforced_coherent(group);
return true;
}
EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
/**
* vfio_file_set_kvm - Link a kvm with VFIO drivers
* @file: VFIO group file or VFIO device file
* @kvm: KVM to link
*
* When a VFIO device is first opened the KVM will be available in
* device->kvm if one was associated with the file.
*/
void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
{
struct vfio_group *group;
group = vfio_group_from_file(file);
if (group)
vfio_group_set_kvm(group, kvm);
}
EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
/* /*
* Sub-module support * Sub-module support
*/ */
......
...@@ -272,6 +272,7 @@ int vfio_mig_get_next_state(struct vfio_device *device, ...@@ -272,6 +272,7 @@ int vfio_mig_get_next_state(struct vfio_device *device,
*/ */
struct iommu_group *vfio_file_iommu_group(struct file *file); struct iommu_group *vfio_file_iommu_group(struct file *file);
bool vfio_file_is_group(struct file *file); bool vfio_file_is_group(struct file *file);
bool vfio_file_is_valid(struct file *file);
bool vfio_file_enforced_coherent(struct file *file); bool vfio_file_enforced_coherent(struct file *file);
void vfio_file_set_kvm(struct file *file, struct kvm *kvm); void vfio_file_set_kvm(struct file *file, struct kvm *kvm);
bool vfio_file_has_dev(struct file *file, struct vfio_device *device); bool vfio_file_has_dev(struct file *file, struct vfio_device *device);
......
...@@ -64,18 +64,18 @@ static bool kvm_vfio_file_enforced_coherent(struct file *file) ...@@ -64,18 +64,18 @@ static bool kvm_vfio_file_enforced_coherent(struct file *file)
return ret; return ret;
} }
static bool kvm_vfio_file_is_group(struct file *file) static bool kvm_vfio_file_is_valid(struct file *file)
{ {
bool (*fn)(struct file *file); bool (*fn)(struct file *file);
bool ret; bool ret;
fn = symbol_get(vfio_file_is_group); fn = symbol_get(vfio_file_is_valid);
if (!fn) if (!fn)
return false; return false;
ret = fn(file); ret = fn(file);
symbol_put(vfio_file_is_group); symbol_put(vfio_file_is_valid);
return ret; return ret;
} }
...@@ -154,8 +154,8 @@ static int kvm_vfio_group_add(struct kvm_device *dev, unsigned int fd) ...@@ -154,8 +154,8 @@ static int kvm_vfio_group_add(struct kvm_device *dev, unsigned int fd)
if (!filp) if (!filp)
return -EBADF; return -EBADF;
/* Ensure the FD is a vfio group FD.*/ /* Ensure the FD is a vfio FD. */
if (!kvm_vfio_file_is_group(filp)) { if (!kvm_vfio_file_is_valid(filp)) {
ret = -EINVAL; ret = -EINVAL;
goto err_fput; goto err_fput;
} }
......
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