Signed-off-by: jiaqingtong jiaqingtong@huawei.com --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 8 ++--- drivers/iommu/iommu.c | 13 ++++--- drivers/vfio/vfio_iommu_type1.c | 5 ++- include/linux/iommu.h | 39 +++++++++++---------- 4 files changed, 32 insertions(+), 33 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index f024093e5e4f..326bd2ed5541 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3101,10 +3101,6 @@ static struct iommu_ops arm_smmu_ops = { .probe_device = arm_smmu_probe_device, .release_device = arm_smmu_release_device, .device_group = arm_smmu_device_group, - .support_dirty_log = arm_smmu_support_dirty_log, - .switch_dirty_log = arm_smmu_switch_dirty_log, - .sync_dirty_log = arm_smmu_sync_dirty_log, - .clear_dirty_log = arm_smmu_clear_dirty_log, .of_xlate = arm_smmu_of_xlate, .get_resv_regions = arm_smmu_get_resv_regions, .remove_dev_pasid = arm_smmu_remove_dev_pasid, @@ -3125,6 +3121,10 @@ static struct iommu_ops arm_smmu_ops = { #endif .iova_to_phys = arm_smmu_iova_to_phys, .enable_nesting = arm_smmu_enable_nesting, + .support_dirty_log = arm_smmu_support_dirty_log, + .switch_dirty_log = arm_smmu_switch_dirty_log, + .sync_dirty_log = arm_smmu_sync_dirty_log, + .clear_dirty_log = arm_smmu_clear_dirty_log, .free = arm_smmu_domain_free, } }; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 0ebea4808212..dbae8a71c0f0 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2750,7 +2750,7 @@ EXPORT_SYMBOL_GPL(iommu_set_pgtable_quirks);
bool iommu_support_dirty_log(struct iommu_domain *domain) { - const struct iommu_ops *ops = domain->ops; + const struct iommu_domain_ops *ops = domain->ops;
return ops->support_dirty_log && ops->support_dirty_log(domain); } @@ -2759,7 +2759,7 @@ EXPORT_SYMBOL_GPL(iommu_support_dirty_log); int iommu_switch_dirty_log(struct iommu_domain *domain, bool enable, unsigned long iova, size_t size, int prot) { - const struct iommu_ops *ops = domain->ops; + const struct iommu_domain_ops *ops = domain->ops; unsigned long orig_iova = iova; unsigned int min_pagesz; size_t orig_size = size; @@ -2820,7 +2820,7 @@ int iommu_sync_dirty_log(struct iommu_domain *domain, unsigned long iova, size_t size, unsigned long *bitmap, unsigned long base_iova, unsigned long bitmap_pgshift) { - const struct iommu_ops *ops = domain->ops; + const struct iommu_domain_ops *ops = domain->ops; unsigned long orig_iova = iova; unsigned int min_pagesz; size_t orig_size = size; @@ -2873,7 +2873,7 @@ static int __iommu_clear_dirty_log(struct iommu_domain *domain, unsigned long base_iova, unsigned long bitmap_pgshift) { - const struct iommu_ops *ops = domain->ops; + const struct iommu_domain_ops *ops = domain->ops; unsigned long orig_iova = iova; size_t orig_size = size; int ret = 0; @@ -2927,9 +2927,8 @@ int iommu_clear_dirty_log(struct iommu_domain *domain, goto out; }
- start = (iova - base_iova) >> bitmap_pgshift; - end = start + (size >> bitmap_pgshift); - bitmap_for_each_set_region(bitmap, rs, re, start, end) { + rs = (iova - base_iova) >> bitmap_pgshift; + for_each_set_bitrange_from(rs, re, bitmap, (size >> bitmap_pgshift)) { flush = true; riova = base_iova + ((unsigned long)rs << bitmap_pgshift); rsize = (unsigned long)(re - rs) << bitmap_pgshift; diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index b7c9f4f3b796..cb7957a6dcb4 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -1238,9 +1238,8 @@ static int vfio_iova_dirty_log_clear(u64 __user *bitmap, /* Similar logic as the tail of vfio_iova_dirty_bitmap */
clear_valid = false; - start = (start_iova - iova) >> pgshift; - end = (end_iova - iova) >> pgshift; - bitmap_for_each_set_region(bitmap_buffer, rs, re, start, end) { + rs = (start_iova - iova) >> pgshift; + for_each_set_bitrange(rs, re, bitmap_buffer, (end_iova - iova) >> pgshift) { clear_valid = true; riova = iova + ((unsigned long)rs << pgshift); dma_offset = (riova - dma->iova) >> pgshift; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 5413160ebbfb..45734fd9cfd4 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -245,10 +245,6 @@ struct iommu_iotlb_gather { * is to support old IOMMU drivers, new drivers should use * default domains, and the common IOMMU DMA ops. * @device_group: find iommu group for a particular device - * @support_dirty_log: Check whether domain supports dirty log tracking - * @switch_dirty_log: Perform actions to start|stop dirty log tracking - * @sync_dirty_log: Sync dirty log from IOMMU into a dirty bitmap - * @clear_dirty_log: Clear dirty log of IOMMU by a mask bitmap * @get_resv_regions: Request list of reserved regions for a device * @of_xlate: add OF master IDs to iommu grouping * @is_attach_deferred: Check if domain attach should be deferred from iommu @@ -280,21 +276,6 @@ struct iommu_ops { void (*set_platform_dma_ops)(struct device *dev); struct iommu_group *(*device_group)(struct device *dev);
- /* - * Track dirty log. Note: Don't concurrently call these interfaces with - * other ops that access underlying page table. - */ - bool (*support_dirty_log)(struct iommu_domain *domain); - int (*switch_dirty_log)(struct iommu_domain *domain, bool enable, - unsigned long iova, size_t size, int prot); - int (*sync_dirty_log)(struct iommu_domain *domain, - unsigned long iova, size_t size, - unsigned long *bitmap, unsigned long base_iova, - unsigned long bitmap_pgshift); - int (*clear_dirty_log)(struct iommu_domain *domain, - unsigned long iova, size_t size, - unsigned long *bitmap, unsigned long base_iova, - unsigned long bitmap_pgshift);
/* Request/Free a list of reserved regions for a device */ void (*get_resv_regions)(struct device *dev, struct list_head *list); @@ -349,6 +330,10 @@ struct iommu_ops { * specific mechanisms. * @enable_nesting: Enable nesting * @set_pgtable_quirks: Set io page table quirks (IO_PGTABLE_QUIRK_*) + * @support_dirty_log: Check whether domain supports dirty log tracking + * @switch_dirty_log: Perform actions to start|stop dirty log tracking + * @sync_dirty_log: Sync dirty log from IOMMU into a dirty bitmap + * @clear_dirty_log: Clear dirty log of IOMMU by a mask bitmap * @free: Release the domain after use. */ struct iommu_domain_ops { @@ -381,6 +366,22 @@ struct iommu_domain_ops { int (*set_pgtable_quirks)(struct iommu_domain *domain, unsigned long quirks);
+ /* + * Track dirty log. Note: Don't concurrently call these interfaces with + * other ops that access underlying page table. + */ + bool (*support_dirty_log)(struct iommu_domain *domain); + int (*switch_dirty_log)(struct iommu_domain *domain, bool enable, + unsigned long iova, size_t size, int prot); + int (*sync_dirty_log)(struct iommu_domain *domain, + unsigned long iova, size_t size, + unsigned long *bitmap, unsigned long base_iova, + unsigned long bitmap_pgshift); + int (*clear_dirty_log)(struct iommu_domain *domain, + unsigned long iova, size_t size, + unsigned long *bitmap, unsigned long base_iova, + unsigned long bitmap_pgshift); + void (*free)(struct iommu_domain *domain); };