Skip to content

Commit 02a8c61

Browse files
jpemartinsjgunthorpe
authored andcommitted
iommufd/selftest: Refactor mock_domain_read_and_clear_dirty()
Move the clearing of the dirty bit of the mock domain into mock_domain_test_and_clear_dirty() helper, simplifying the caller function. Additionally, rework the mock_domain_read_and_clear_dirty() loop to iterate over a potentially variable IO page size. No functional change intended with the loop refactor. This is in preparation for dirty tracking support for IOMMU hugepage mock domains. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joao Martins <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 407fc18 commit 02a8c61

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

drivers/iommu/iommufd/selftest.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,38 +191,64 @@ static int mock_domain_set_dirty_tracking(struct iommu_domain *domain,
191191
return 0;
192192
}
193193

194+
static bool mock_test_and_clear_dirty(struct mock_iommu_domain *mock,
195+
unsigned long iova, size_t page_size,
196+
unsigned long flags)
197+
{
198+
unsigned long cur, end = iova + page_size - 1;
199+
bool dirty = false;
200+
void *ent, *old;
201+
202+
for (cur = iova; cur < end; cur += MOCK_IO_PAGE_SIZE) {
203+
ent = xa_load(&mock->pfns, cur / MOCK_IO_PAGE_SIZE);
204+
if (!ent || !(xa_to_value(ent) & MOCK_PFN_DIRTY_IOVA))
205+
continue;
206+
207+
dirty = true;
208+
/* Clear dirty */
209+
if (!(flags & IOMMU_DIRTY_NO_CLEAR)) {
210+
unsigned long val;
211+
212+
val = xa_to_value(ent) & ~MOCK_PFN_DIRTY_IOVA;
213+
old = xa_store(&mock->pfns, cur / MOCK_IO_PAGE_SIZE,
214+
xa_mk_value(val), GFP_KERNEL);
215+
WARN_ON_ONCE(ent != old);
216+
}
217+
}
218+
219+
return dirty;
220+
}
221+
194222
static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain,
195223
unsigned long iova, size_t size,
196224
unsigned long flags,
197225
struct iommu_dirty_bitmap *dirty)
198226
{
199227
struct mock_iommu_domain *mock =
200228
container_of(domain, struct mock_iommu_domain, domain);
201-
unsigned long i, max = size / MOCK_IO_PAGE_SIZE;
202-
void *ent, *old;
229+
unsigned long end = iova + size;
230+
void *ent;
203231

204232
if (!(mock->flags & MOCK_DIRTY_TRACK) && dirty->bitmap)
205233
return -EINVAL;
206234

207-
for (i = 0; i < max; i++) {
208-
unsigned long cur = iova + i * MOCK_IO_PAGE_SIZE;
235+
do {
236+
unsigned long pgsize = MOCK_IO_PAGE_SIZE;
237+
unsigned long head;
209238

210-
ent = xa_load(&mock->pfns, cur / MOCK_IO_PAGE_SIZE);
211-
if (ent && (xa_to_value(ent) & MOCK_PFN_DIRTY_IOVA)) {
212-
/* Clear dirty */
213-
if (!(flags & IOMMU_DIRTY_NO_CLEAR)) {
214-
unsigned long val;
215-
216-
val = xa_to_value(ent) & ~MOCK_PFN_DIRTY_IOVA;
217-
old = xa_store(&mock->pfns,
218-
cur / MOCK_IO_PAGE_SIZE,
219-
xa_mk_value(val), GFP_KERNEL);
220-
WARN_ON_ONCE(ent != old);
221-
}
222-
iommu_dirty_bitmap_record(dirty, cur,
223-
MOCK_IO_PAGE_SIZE);
239+
ent = xa_load(&mock->pfns, iova / MOCK_IO_PAGE_SIZE);
240+
if (!ent) {
241+
iova += pgsize;
242+
continue;
224243
}
225-
}
244+
245+
head = iova & ~(pgsize - 1);
246+
247+
/* Clear dirty */
248+
if (mock_test_and_clear_dirty(mock, head, pgsize, flags))
249+
iommu_dirty_bitmap_record(dirty, head, pgsize);
250+
iova = head + pgsize;
251+
} while (iova < end);
226252

227253
return 0;
228254
}

0 commit comments

Comments
 (0)