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: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Tested-by: Terrence Xu <terrence.xu@intel.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
Tested-by: Yanting Jiang <yanting.jiang@intel.com>
Tested-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Tested-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Link: https://lore.kernel.org/r/20230718135551.6592-3-yi.l.liu@intel.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
Yi Liu 2023-07-18 06:55:27 -07:00 committed by Alex Williamson
parent b1a3b5c61d
commit b1a59be8a2
5 changed files with 75 additions and 41 deletions

View file

@ -754,6 +754,15 @@ bool vfio_device_has_container(struct vfio_device *device)
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
* @file: VFIO group file
@ -764,13 +773,13 @@ bool vfio_device_has_container(struct vfio_device *device)
*/
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;
if (!IS_ENABLED(CONFIG_SPAPR_TCE_IOMMU))
return NULL;
if (!vfio_file_is_group(file))
if (!group)
return NULL;
mutex_lock(&group->group_lock);
@ -784,33 +793,20 @@ struct iommu_group *vfio_file_iommu_group(struct file *file)
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
*/
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);
/**
* 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)
bool vfio_group_enforced_coherent(struct vfio_group *group)
{
struct vfio_group *group = file->private_data;
struct vfio_device *device;
bool ret = true;
if (!vfio_file_is_group(file))
return true;
/*
* 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
@ -828,28 +824,13 @@ bool vfio_file_enforced_coherent(struct file *file)
mutex_unlock(&group->device_lock);
return ret;
}
EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
/**
* 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)
void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
{
struct vfio_group *group = file->private_data;
if (!vfio_file_is_group(file))
return;
spin_lock(&group->kvm_ref_lock);
group->kvm = kvm;
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
@ -860,9 +841,9 @@ EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
*/
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 group == device->group;

View file

@ -90,6 +90,9 @@ void vfio_device_group_unregister(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_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);
int __init vfio_group_init(void);
void vfio_group_cleanup(void);

View file

@ -1190,6 +1190,55 @@ const struct file_operations vfio_device_fops = {
.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
*/

View file

@ -272,6 +272,7 @@ int vfio_mig_get_next_state(struct vfio_device *device,
*/
struct iommu_group *vfio_file_iommu_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);
void vfio_file_set_kvm(struct file *file, struct kvm *kvm);
bool vfio_file_has_dev(struct file *file, struct vfio_device *device);

View file

@ -64,18 +64,18 @@ static bool kvm_vfio_file_enforced_coherent(struct file *file)
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 ret;
fn = symbol_get(vfio_file_is_group);
fn = symbol_get(vfio_file_is_valid);
if (!fn)
return false;
ret = fn(file);
symbol_put(vfio_file_is_group);
symbol_put(vfio_file_is_valid);
return ret;
}
@ -154,8 +154,8 @@ static int kvm_vfio_group_add(struct kvm_device *dev, unsigned int fd)
if (!filp)
return -EBADF;
/* Ensure the FD is a vfio group FD.*/
if (!kvm_vfio_file_is_group(filp)) {
/* Ensure the FD is a vfio FD. */
if (!kvm_vfio_file_is_valid(filp)) {
ret = -EINVAL;
goto err_fput;
}