Re: [PATCH 13/14] vfio/iommu_type1: remove the "external" domain

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 26 Aug 2021 15:34:23 +0200
Christoph Hellwig <hch@xxxxxx> wrote:

> The external_domain concept rather misleading and not actually needed.
> Replace it with a list of emulated groups in struct vfio_iommu and
> document the purpose.
> 
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>
> Reviewed-by: Jason Gunthorpe <jgg@xxxxxxxxxx>
> Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx>
> ---
>  drivers/vfio/vfio_iommu_type1.c | 121 ++++++++++++++------------------
>  1 file changed, 54 insertions(+), 67 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index ca3c995c84166f..1ef98d4e2abecf 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -65,7 +65,6 @@ MODULE_PARM_DESC(dma_entry_limit,
>  struct vfio_iommu {
>  	struct list_head	domain_list;
>  	struct list_head	iova_list;
> -	struct vfio_domain	*external_domain; /* domain for external user */
>  	struct mutex		lock;
>  	struct rb_root		dma_list;
>  	struct blocking_notifier_head notifier;
> @@ -78,6 +77,7 @@ struct vfio_iommu {
>  	bool			nesting;
>  	bool			dirty_page_tracking;
>  	bool			container_open;
> +	struct list_head	emulated_iommu_groups;
>  };
>  
>  struct vfio_domain {
> @@ -1892,8 +1892,8 @@ static struct vfio_iommu_group*
>  vfio_iommu_find_iommu_group(struct vfio_iommu *iommu,
>  			    struct iommu_group *iommu_group)
>  {
> +	struct vfio_iommu_group *group;
>  	struct vfio_domain *domain;
> -	struct vfio_iommu_group *group = NULL;
>  
>  	list_for_each_entry(domain, &iommu->domain_list, next) {
>  		group = find_iommu_group(domain, iommu_group);
> @@ -1901,10 +1901,10 @@ vfio_iommu_find_iommu_group(struct vfio_iommu *iommu,
>  			return group;
>  	}
>  
> -	if (iommu->external_domain)
> -		group = find_iommu_group(iommu->external_domain, iommu_group);
> -
> -	return group;
> +	list_for_each_entry(group, &iommu->emulated_iommu_groups, next)
> +		if (group->iommu_group == iommu_group)
> +			return group;
> +	return NULL;
>  }
>  
>  static bool vfio_iommu_has_sw_msi(struct list_head *group_resv_regions,
> @@ -2163,62 +2163,52 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>  	struct vfio_iommu_group *group;
>  	struct vfio_domain *domain, *d;
>  	struct bus_type *bus = NULL;
> -	int ret;
>  	bool resv_msi, msi_remap;
>  	phys_addr_t resv_msi_base = 0;
>  	struct iommu_domain_geometry *geo;
>  	LIST_HEAD(iova_copy);
>  	LIST_HEAD(group_resv_regions);
> +	int ret = -EINVAL;
>  
>  	mutex_lock(&iommu->lock);
>  
>  	/* Check for duplicates */
> -	if (vfio_iommu_find_iommu_group(iommu, iommu_group)) {
> -		mutex_unlock(&iommu->lock);
> -		return -EINVAL;
> -	}
> +	if (vfio_iommu_find_iommu_group(iommu, iommu_group))
> +		goto out_unlock;
>  
> +	ret = -ENOMEM;
>  	group = kzalloc(sizeof(*group), GFP_KERNEL);
> -	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
> -	if (!group || !domain) {
> -		ret = -ENOMEM;
> -		goto out_free;
> -	}
> -
> +	if (!group)
> +		goto out_unlock;
>  	group->iommu_group = iommu_group;
>  
> -	/* Determine bus_type in order to allocate a domain */
> -	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
> -	if (ret)
> -		goto out_free;
> -
>  	if (flags & VFIO_EMULATED_IOMMU) {
> -		if (!iommu->external_domain) {
> -			INIT_LIST_HEAD(&domain->group_list);
> -			iommu->external_domain = domain;
> -			vfio_update_pgsize_bitmap(iommu);
> -		} else {
> -			kfree(domain);
> -		}
> -
> -		list_add(&group->next, &iommu->external_domain->group_list);
> +		list_add(&group->next, &iommu->emulated_iommu_groups);
>  		/*
> -		 * Non-iommu backed group cannot dirty memory directly, it can
> +		 * An emulated IOMMU group cannot dirty memory directly, it can
>  		 * only use interfaces that provide dirty tracking.
>  		 * The iommu scope can only be promoted with the addition of a
>  		 * dirty tracking group.
>  		 */


I didn't actually spot the additional documentation noted in the commit
log, is this it?  Thanks,

Alex


>  		group->pinned_page_dirty_scope = true;
> -		mutex_unlock(&iommu->lock);
> -
> -		return 0;
> +		ret = 0;
> +		goto out_unlock;
>  	}
>  
> +	/* Determine bus_type in order to allocate a domain */
> +	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
> +	if (ret)
> +		goto out_free_group;
> +
> +	ret = -ENOMEM;
> +	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
> +	if (!domain)
> +		goto out_free_group;
> +
> +	ret = -EIO;
>  	domain->domain = iommu_domain_alloc(bus);
> -	if (!domain->domain) {
> -		ret = -EIO;
> -		goto out_free;
> -	}
> +	if (!domain->domain)
> +		goto out_free_domain;
>  
>  	if (iommu->nesting) {
>  		ret = iommu_enable_nesting(domain->domain);
> @@ -2345,9 +2335,11 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>  	iommu_domain_free(domain->domain);
>  	vfio_iommu_iova_free(&iova_copy);
>  	vfio_iommu_resv_free(&group_resv_regions);
> -out_free:
> +out_free_domain:
>  	kfree(domain);
> +out_free_group:
>  	kfree(group);
> +out_unlock:
>  	mutex_unlock(&iommu->lock);
>  	return ret;
>  }
> @@ -2472,25 +2464,19 @@ static void vfio_iommu_type1_detach_group(void *iommu_data,
>  	LIST_HEAD(iova_copy);
>  
>  	mutex_lock(&iommu->lock);
> +	list_for_each_entry(group, &iommu->emulated_iommu_groups, next) {
> +		if (group->iommu_group != iommu_group)
> +			continue;
> +		update_dirty_scope = !group->pinned_page_dirty_scope;
> +		list_del(&group->next);
> +		kfree(group);
>  
> -	if (iommu->external_domain) {
> -		group = find_iommu_group(iommu->external_domain, iommu_group);
> -		if (group) {
> -			update_dirty_scope = !group->pinned_page_dirty_scope;
> -			list_del(&group->next);
> -			kfree(group);
> -
> -			if (list_empty(&iommu->external_domain->group_list)) {
> -				if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) {
> -					WARN_ON(iommu->notifier.head);
> -					vfio_iommu_unmap_unpin_all(iommu);
> -				}
> -
> -				kfree(iommu->external_domain);
> -				iommu->external_domain = NULL;
> -			}
> -			goto detach_group_done;
> +		if (list_empty(&iommu->emulated_iommu_groups) &&
> +		    !IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) {
> +			WARN_ON(iommu->notifier.head);
> +			vfio_iommu_unmap_unpin_all(iommu);
>  		}
> +		goto detach_group_done;
>  	}
>  
>  	/*
> @@ -2518,7 +2504,7 @@ static void vfio_iommu_type1_detach_group(void *iommu_data,
>  		 */
>  		if (list_empty(&domain->group_list)) {
>  			if (list_is_singular(&iommu->domain_list)) {
> -				if (!iommu->external_domain) {
> +				if (list_empty(&iommu->emulated_iommu_groups)) {
>  					WARN_ON(iommu->notifier.head);
>  					vfio_iommu_unmap_unpin_all(iommu);
>  				} else {
> @@ -2582,41 +2568,42 @@ static void *vfio_iommu_type1_open(unsigned long arg)
>  	mutex_init(&iommu->lock);
>  	BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier);
>  	init_waitqueue_head(&iommu->vaddr_wait);
> +	INIT_LIST_HEAD(&iommu->emulated_iommu_groups);
>  
>  	return iommu;
>  }
>  
> -static void vfio_release_domain(struct vfio_domain *domain, bool external)
> +static void vfio_release_domain(struct vfio_domain *domain)
>  {
>  	struct vfio_iommu_group *group, *group_tmp;
>  
>  	list_for_each_entry_safe(group, group_tmp,
>  				 &domain->group_list, next) {
> -		if (!external)
> -			iommu_detach_group(domain->domain, group->iommu_group);
> +		iommu_detach_group(domain->domain, group->iommu_group);
>  		list_del(&group->next);
>  		kfree(group);
>  	}
>  
> -	if (!external)
> -		iommu_domain_free(domain->domain);
> +	iommu_domain_free(domain->domain);
>  }
>  
>  static void vfio_iommu_type1_release(void *iommu_data)
>  {
>  	struct vfio_iommu *iommu = iommu_data;
>  	struct vfio_domain *domain, *domain_tmp;
> +	struct vfio_iommu_group *group, *next_group;
>  
> -	if (iommu->external_domain) {
> -		vfio_release_domain(iommu->external_domain, true);
> -		kfree(iommu->external_domain);
> +	list_for_each_entry_safe(group, next_group,
> +			&iommu->emulated_iommu_groups, next) {
> +		list_del(&group->next);
> +		kfree(group);
>  	}
>  
>  	vfio_iommu_unmap_unpin_all(iommu);
>  
>  	list_for_each_entry_safe(domain, domain_tmp,
>  				 &iommu->domain_list, next) {
> -		vfio_release_domain(domain, false);
> +		vfio_release_domain(domain);
>  		list_del(&domain->next);
>  		kfree(domain);
>  	}




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux