mirror of
https://github.com/lkl/linux.git
synced 2025-12-19 16:13:19 +09:00
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:
@@ -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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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);
|
|||||||
*/
|
*/
|
||||||
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);
|
|||||||
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 = {
|
|||||||
.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,
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user