Skip to content

Commit 7db521e

Browse files
jpemartinsjgunthorpe
authored andcommitted
iommufd/selftest: Hugepage mock domain support
Add support to mock iommu hugepages of 1M (for a 2K mock io page size). To avoid breaking test suite defaults, the way this is done is by explicitly creating a iommu mock device which has hugepage support (i.e. through MOCK_FLAGS_DEVICE_HUGE_IOVA). The same scheme is maintained of mock base page index tracking in the XArray, except that an extra bit is added to mark it as a hugepage. One subpage containing the dirty bit, means that the whole hugepage is dirty (similar to AMD IOMMU non-standard page sizes). For clearing, same thing applies, and it must clear all dirty subpages. This is in preparation for dirty tracking to mark mock hugepages as dirty to exercise all the iova-bitmap fixes. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joao Martins <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 02a8c61 commit 7db521e

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

drivers/iommu/iommufd/iommufd_test.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum {
4545

4646
enum {
4747
MOCK_FLAGS_DEVICE_NO_DIRTY = 1 << 0,
48+
MOCK_FLAGS_DEVICE_HUGE_IOVA = 1 << 1,
4849
};
4950

5051
enum {

drivers/iommu/iommufd/selftest.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ static atomic_t mock_dev_num;
4141
enum {
4242
MOCK_DIRTY_TRACK = 1,
4343
MOCK_IO_PAGE_SIZE = PAGE_SIZE / 2,
44+
MOCK_HUGE_PAGE_SIZE = 512 * MOCK_IO_PAGE_SIZE,
4445

4546
/*
4647
* Like a real page table alignment requires the low bits of the address
@@ -53,6 +54,7 @@ enum {
5354
MOCK_PFN_START_IOVA = _MOCK_PFN_START,
5455
MOCK_PFN_LAST_IOVA = _MOCK_PFN_START,
5556
MOCK_PFN_DIRTY_IOVA = _MOCK_PFN_START << 1,
57+
MOCK_PFN_HUGE_IOVA = _MOCK_PFN_START << 2,
5658
};
5759

5860
/*
@@ -242,6 +244,8 @@ static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain,
242244
continue;
243245
}
244246

247+
if (xa_to_value(ent) & MOCK_PFN_HUGE_IOVA)
248+
pgsize = MOCK_HUGE_PAGE_SIZE;
245249
head = iova & ~(pgsize - 1);
246250

247251
/* Clear dirty */
@@ -260,6 +264,7 @@ const struct iommu_dirty_ops dirty_ops = {
260264

261265
static struct iommu_domain *mock_domain_alloc_paging(struct device *dev)
262266
{
267+
struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
263268
struct mock_iommu_domain *mock;
264269

265270
mock = kzalloc(sizeof(*mock), GFP_KERNEL);
@@ -268,6 +273,8 @@ static struct iommu_domain *mock_domain_alloc_paging(struct device *dev)
268273
mock->domain.geometry.aperture_start = MOCK_APERTURE_START;
269274
mock->domain.geometry.aperture_end = MOCK_APERTURE_LAST;
270275
mock->domain.pgsize_bitmap = MOCK_IO_PAGE_SIZE;
276+
if (dev && mdev->flags & MOCK_FLAGS_DEVICE_HUGE_IOVA)
277+
mock->domain.pgsize_bitmap |= MOCK_HUGE_PAGE_SIZE;
271278
mock->domain.ops = mock_ops.default_domain_ops;
272279
mock->domain.type = IOMMU_DOMAIN_UNMANAGED;
273280
xa_init(&mock->pfns);
@@ -313,7 +320,7 @@ mock_domain_alloc_user(struct device *dev, u32 flags,
313320
return ERR_PTR(-EOPNOTSUPP);
314321
if (user_data || (has_dirty_flag && no_dirty_ops))
315322
return ERR_PTR(-EOPNOTSUPP);
316-
domain = mock_domain_alloc_paging(NULL);
323+
domain = mock_domain_alloc_paging(dev);
317324
if (!domain)
318325
return ERR_PTR(-ENOMEM);
319326
if (has_dirty_flag)
@@ -376,6 +383,9 @@ static int mock_domain_map_pages(struct iommu_domain *domain,
376383

377384
if (pgcount == 1 && cur + MOCK_IO_PAGE_SIZE == pgsize)
378385
flags = MOCK_PFN_LAST_IOVA;
386+
if (pgsize != MOCK_IO_PAGE_SIZE) {
387+
flags |= MOCK_PFN_HUGE_IOVA;
388+
}
379389
old = xa_store(&mock->pfns, iova / MOCK_IO_PAGE_SIZE,
380390
xa_mk_value((paddr / MOCK_IO_PAGE_SIZE) |
381391
flags),
@@ -630,7 +640,8 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
630640
struct mock_dev *mdev;
631641
int rc;
632642

633-
if (dev_flags & ~(MOCK_FLAGS_DEVICE_NO_DIRTY))
643+
if (dev_flags &
644+
~(MOCK_FLAGS_DEVICE_NO_DIRTY | MOCK_FLAGS_DEVICE_HUGE_IOVA))
634645
return ERR_PTR(-EINVAL);
635646

636647
mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);

0 commit comments

Comments
 (0)