Skip to content

Commit

Permalink
vfio: Change vfio_external_check_extension() to vfio_file_enforced_co…
Browse files Browse the repository at this point in the history
…herent()

Instead of a general extension check change the function into a limited
test if the iommu_domain has enforced coherency, which is the only thing
kvm needs to query.

Make the new op self contained by properly refcounting the container
before touching it.

Reviewed-by: Christoph Hellwig <[email protected]>
Signed-off-by: Jason Gunthorpe <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alex Williamson <[email protected]>
  • Loading branch information
jgunthorpe authored and awilliam committed May 13, 2022
1 parent c38ff5b commit a905ad0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
30 changes: 27 additions & 3 deletions drivers/vfio/vfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1701,11 +1701,35 @@ struct iommu_group *vfio_file_iommu_group(struct file *file)
}
EXPORT_SYMBOL_GPL(vfio_file_iommu_group);

long vfio_external_check_extension(struct vfio_group *group, unsigned long arg)
/**
* 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)
{
return vfio_ioctl_check_extension(group->container, arg);
struct vfio_group *group = file->private_data;
bool ret;

if (file->f_op != &vfio_group_fops)
return true;

/*
* Since the coherency state is determined only once a container is
* attached the user must do so before they can prove they have
* permission.
*/
if (vfio_group_add_container_user(group))
return true;
ret = vfio_ioctl_check_extension(group->container, VFIO_DMA_CC_IOMMU);
vfio_group_try_dissolve_container(group);
return ret;
}
EXPORT_SYMBOL_GPL(vfio_external_check_extension);
EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);

/*
* Sub-module support
Expand Down
3 changes: 1 addition & 2 deletions include/linux/vfio.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ int vfio_mig_get_next_state(struct vfio_device *device,
extern struct vfio_group *vfio_group_get_external_user(struct file *filep);
extern void vfio_group_put_external_user(struct vfio_group *group);
extern struct iommu_group *vfio_file_iommu_group(struct file *file);
extern long vfio_external_check_extension(struct vfio_group *group,
unsigned long arg);
extern bool vfio_file_enforced_coherent(struct file *file);

#define VFIO_PIN_PAGES_MAX_ENTRIES (PAGE_SIZE/sizeof(unsigned long))

Expand Down
16 changes: 8 additions & 8 deletions virt/kvm/vfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,20 @@ static void kvm_vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
symbol_put(vfio_group_set_kvm);
}

static bool kvm_vfio_group_is_coherent(struct vfio_group *vfio_group)
static bool kvm_vfio_file_enforced_coherent(struct file *file)
{
long (*fn)(struct vfio_group *, unsigned long);
long ret;
bool (*fn)(struct file *file);
bool ret;

fn = symbol_get(vfio_external_check_extension);
fn = symbol_get(vfio_file_enforced_coherent);
if (!fn)
return false;

ret = fn(vfio_group, VFIO_DMA_CC_IOMMU);
ret = fn(file);

symbol_put(vfio_external_check_extension);
symbol_put(vfio_file_enforced_coherent);

return ret > 0;
return ret;
}

#ifdef CONFIG_SPAPR_TCE_IOMMU
Expand Down Expand Up @@ -136,7 +136,7 @@ static void kvm_vfio_update_coherency(struct kvm_device *dev)
mutex_lock(&kv->lock);

list_for_each_entry(kvg, &kv->group_list, node) {
if (!kvm_vfio_group_is_coherent(kvg->vfio_group)) {
if (!kvm_vfio_file_enforced_coherent(kvg->file)) {
noncoherent = true;
break;
}
Expand Down

0 comments on commit a905ad0

Please sign in to comment.