RE: [PATCH v2 5/8] vfio: Change vfio_external_check_extension() to vfio_file_enforced_coherent()

Tian, Kevin
2022-04-20T23:49:20Z

> From: Jason Gunthorpe <jgg@nvidia.com>
> Sent: Thursday, April 21, 2022 3:23 AM
>
> 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.
>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
> drivers/vfio/vfio.c | 30 +++++++++++++++++++++++++++---
> include/linux/vfio.h | 3 +--
> virt/kvm/vfio.c | 16 ++++++++--------
> 3 files changed, 36 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
> index c9122c84583aa1..ae3e802991edf2 100644
> --- a/drivers/vfio/vfio.c
> +++ b/drivers/vfio/vfio.c
> @@ -2005,11 +2005,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;

IMHO I still think returning an error here is better for 'user must
do so' than telling inaccurate info and leading to a situation
where lacking of wbinvd may incur various cache problem which
is hard to debug. Yes, it's user's own problem but having a place
to capture this problem early is still a nice thing to do.

> + 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
> diff --git a/include/linux/vfio.h b/include/linux/vfio.h
> index 132cf3e7cda8db..7f022ae126a392 100644
> --- a/include/linux/vfio.h
> +++ b/include/linux/vfio.h
> @@ -143,8 +143,7 @@ extern void vfio_group_put_external_user(struct
> vfio_group *group);
> extern struct vfio_group *vfio_group_get_external_user_from_dev(struct
> device
> *dev);
> 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))
>
> diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
> index 50193ae270faca..2330b0c272e671 100644
> --- a/virt/kvm/vfio.c
> +++ b/virt/kvm/vfio.c
> @@ -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
> @@ -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;
> }
> --
> 2.36.0