Commit 02a8c61a authored by Joao Martins's avatar Joao Martins Committed by Jason Gunthorpe

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/20240202133415.23819-7-joao.m.martins@oracle.comSigned-off-by: default avatarJoao Martins <joao.m.martins@oracle.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 407fc184
...@@ -191,39 +191,65 @@ static int mock_domain_set_dirty_tracking(struct iommu_domain *domain, ...@@ -191,39 +191,65 @@ static int mock_domain_set_dirty_tracking(struct iommu_domain *domain,
return 0; return 0;
} }
static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain, static bool mock_test_and_clear_dirty(struct mock_iommu_domain *mock,
unsigned long iova, size_t size, unsigned long iova, size_t page_size,
unsigned long flags, unsigned long flags)
struct iommu_dirty_bitmap *dirty)
{ {
struct mock_iommu_domain *mock = unsigned long cur, end = iova + page_size - 1;
container_of(domain, struct mock_iommu_domain, domain); bool dirty = false;
unsigned long i, max = size / MOCK_IO_PAGE_SIZE;
void *ent, *old; void *ent, *old;
if (!(mock->flags & MOCK_DIRTY_TRACK) && dirty->bitmap) for (cur = iova; cur < end; cur += MOCK_IO_PAGE_SIZE) {
return -EINVAL;
for (i = 0; i < max; i++) {
unsigned long cur = iova + i * MOCK_IO_PAGE_SIZE;
ent = xa_load(&mock->pfns, cur / MOCK_IO_PAGE_SIZE); ent = xa_load(&mock->pfns, cur / MOCK_IO_PAGE_SIZE);
if (ent && (xa_to_value(ent) & MOCK_PFN_DIRTY_IOVA)) { if (!ent || !(xa_to_value(ent) & MOCK_PFN_DIRTY_IOVA))
continue;
dirty = true;
/* Clear dirty */ /* Clear dirty */
if (!(flags & IOMMU_DIRTY_NO_CLEAR)) { if (!(flags & IOMMU_DIRTY_NO_CLEAR)) {
unsigned long val; unsigned long val;
val = xa_to_value(ent) & ~MOCK_PFN_DIRTY_IOVA; val = xa_to_value(ent) & ~MOCK_PFN_DIRTY_IOVA;
old = xa_store(&mock->pfns, old = xa_store(&mock->pfns, cur / MOCK_IO_PAGE_SIZE,
cur / MOCK_IO_PAGE_SIZE,
xa_mk_value(val), GFP_KERNEL); xa_mk_value(val), GFP_KERNEL);
WARN_ON_ONCE(ent != old); WARN_ON_ONCE(ent != old);
} }
iommu_dirty_bitmap_record(dirty, cur,
MOCK_IO_PAGE_SIZE);
} }
return dirty;
}
static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain,
unsigned long iova, size_t size,
unsigned long flags,
struct iommu_dirty_bitmap *dirty)
{
struct mock_iommu_domain *mock =
container_of(domain, struct mock_iommu_domain, domain);
unsigned long end = iova + size;
void *ent;
if (!(mock->flags & MOCK_DIRTY_TRACK) && dirty->bitmap)
return -EINVAL;
do {
unsigned long pgsize = MOCK_IO_PAGE_SIZE;
unsigned long head;
ent = xa_load(&mock->pfns, iova / MOCK_IO_PAGE_SIZE);
if (!ent) {
iova += pgsize;
continue;
} }
head = iova & ~(pgsize - 1);
/* Clear dirty */
if (mock_test_and_clear_dirty(mock, head, pgsize, flags))
iommu_dirty_bitmap_record(dirty, head, pgsize);
iova = head + pgsize;
} while (iova < end);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment