RE: [PATCH RFC 02/19] iommufd: Dirty tracking for io_pagetable

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

 




> -----Original Message-----
> From: Joao Martins [mailto:joao.m.martins@xxxxxxxxxx]
> Sent: 28 April 2022 22:09
> To: iommu@xxxxxxxxxxxxxxxxxxxxxxxxxx
> Cc: Joao Martins <joao.m.martins@xxxxxxxxxx>; Joerg Roedel
> <joro@xxxxxxxxxx>; Suravee Suthikulpanit
> <suravee.suthikulpanit@xxxxxxx>; Will Deacon <will@xxxxxxxxxx>; Robin
> Murphy <robin.murphy@xxxxxxx>; Jean-Philippe Brucker
> <jean-philippe@xxxxxxxxxx>; zhukeqian <zhukeqian1@xxxxxxxxxx>;
> Shameerali Kolothum Thodi <shameerali.kolothum.thodi@xxxxxxxxxx>;
> David Woodhouse <dwmw2@xxxxxxxxxxxxx>; Lu Baolu
> <baolu.lu@xxxxxxxxxxxxxxx>; Jason Gunthorpe <jgg@xxxxxxxxxx>; Nicolin
> Chen <nicolinc@xxxxxxxxxx>; Yishai Hadas <yishaih@xxxxxxxxxx>; Kevin Tian
> <kevin.tian@xxxxxxxxx>; Eric Auger <eric.auger@xxxxxxxxxx>; Yi Liu
> <yi.l.liu@xxxxxxxxx>; Alex Williamson <alex.williamson@xxxxxxxxxx>;
> Cornelia Huck <cohuck@xxxxxxxxxx>; kvm@xxxxxxxxxxxxxxx
> Subject: [PATCH RFC 02/19] iommufd: Dirty tracking for io_pagetable
> 
> Add an io_pagetable kernel API to toggle dirty tracking:
> 
> * iopt_set_dirty_tracking(iopt, [domain], state)
> 
> It receives either NULL (which means all domains) or an
> iommu_domain. The intended caller of this is via the hw_pagetable
> object that is created on device attach, which passes an
> iommu_domain. For now, the all-domains is left for vfio-compat.
> 
> The hw protection domain dirty control is favored over the IOVA-range
> alternative. For the latter, it iterates over all IOVA areas and calls
> iommu domain op to enable/disable for the range.
> 
> Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx>
> ---
>  drivers/iommu/iommufd/io_pagetable.c    | 71
> +++++++++++++++++++++++++
>  drivers/iommu/iommufd/iommufd_private.h |  3 ++
>  2 files changed, 74 insertions(+)
> 
> diff --git a/drivers/iommu/iommufd/io_pagetable.c
> b/drivers/iommu/iommufd/io_pagetable.c
> index f9f3b06946bf..f4609ef369e0 100644
> --- a/drivers/iommu/iommufd/io_pagetable.c
> +++ b/drivers/iommu/iommufd/io_pagetable.c
> @@ -276,6 +276,77 @@ int iopt_map_user_pages(struct io_pagetable *iopt,
> unsigned long *iova,
>  	return 0;
>  }
> 
> +static int __set_dirty_tracking_range_locked(struct iommu_domain
> *domain,
> +					     struct io_pagetable *iopt,
> +					     bool enable)
> +{
> +	const struct iommu_domain_ops *ops = domain->ops;
> +	struct iommu_iotlb_gather gather;
> +	struct iopt_area *area;
> +	int ret = -EOPNOTSUPP;
> +	unsigned long iova;
> +	size_t size;
> +
> +	iommu_iotlb_gather_init(&gather);
> +
> +	for (area = iopt_area_iter_first(iopt, 0, ULONG_MAX); area;
> +	     area = iopt_area_iter_next(area, 0, ULONG_MAX)) {
> +		iova = iopt_area_iova(area);
> +		size = iopt_area_last_iova(area) - iova;

   size = iopt_area_last_iova(area) - iova + 1;  ?

Thanks,
Shameer
> +
> +		if (ops->set_dirty_tracking_range) {
> +			ret = ops->set_dirty_tracking_range(domain, iova,
> +							    size, &gather,
> +							    enable);
> +			if (ret < 0)
> +				break;
> +		}
> +	}
> +
> +	iommu_iotlb_sync(domain, &gather);
> +
> +	return ret;
> +}
> +
> +static int iommu_set_dirty_tracking(struct iommu_domain *domain,
> +				    struct io_pagetable *iopt, bool enable)
> +{
> +	const struct iommu_domain_ops *ops = domain->ops;
> +	int ret = -EOPNOTSUPP;
> +
> +	if (ops->set_dirty_tracking)
> +		ret = ops->set_dirty_tracking(domain, enable);
> +	else if (ops->set_dirty_tracking_range)
> +		ret = __set_dirty_tracking_range_locked(domain, iopt,
> +							enable);
> +
> +	return ret;
> +}
> +
> +int iopt_set_dirty_tracking(struct io_pagetable *iopt,
> +			    struct iommu_domain *domain, bool enable)
> +{
> +	struct iommu_domain *dom;
> +	unsigned long index;
> +	int ret = -EOPNOTSUPP;
> +
> +	down_write(&iopt->iova_rwsem);
> +	if (!domain) {
> +		down_write(&iopt->domains_rwsem);
> +		xa_for_each(&iopt->domains, index, dom) {
> +			ret = iommu_set_dirty_tracking(dom, iopt, enable);
> +			if (ret < 0)
> +				break;
> +		}
> +		up_write(&iopt->domains_rwsem);
> +	} else {
> +		ret = iommu_set_dirty_tracking(domain, iopt, enable);
> +	}
> +
> +	up_write(&iopt->iova_rwsem);
> +	return ret;
> +}
> +
>  struct iopt_pages *iopt_get_pages(struct io_pagetable *iopt, unsigned long
> iova,
>  				  unsigned long *start_byte,
>  				  unsigned long length)
> diff --git a/drivers/iommu/iommufd/iommufd_private.h
> b/drivers/iommu/iommufd/iommufd_private.h
> index f55654278ac4..d00ef3b785c5 100644
> --- a/drivers/iommu/iommufd/iommufd_private.h
> +++ b/drivers/iommu/iommufd/iommufd_private.h
> @@ -49,6 +49,9 @@ int iopt_unmap_iova(struct io_pagetable *iopt,
> unsigned long iova,
>  		    unsigned long length);
>  int iopt_unmap_all(struct io_pagetable *iopt);
> 
> +int iopt_set_dirty_tracking(struct io_pagetable *iopt,
> +			    struct iommu_domain *domain, bool enable);
> +
>  int iopt_access_pages(struct io_pagetable *iopt, unsigned long iova,
>  		      unsigned long npages, struct page **out_pages, bool write);
>  void iopt_unaccess_pages(struct io_pagetable *iopt, unsigned long iova,
> --
> 2.17.2




[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