Skip to content

Commit

Permalink
iommufd/selftest: Hugepage mock domain support
Browse files Browse the repository at this point in the history
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/20240202133415.23819-8-joao.m.martins@oracle.com
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
  • Loading branch information
jpemartins authored and jgunthorpe committed Feb 6, 2024
1 parent 02a8c61 commit 7db521e
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/iommu/iommufd/iommufd_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum {

enum {
MOCK_FLAGS_DEVICE_NO_DIRTY = 1 << 0,
MOCK_FLAGS_DEVICE_HUGE_IOVA = 1 << 1,
};

enum {
Expand Down
15 changes: 13 additions & 2 deletions drivers/iommu/iommufd/selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static atomic_t mock_dev_num;
enum {
MOCK_DIRTY_TRACK = 1,
MOCK_IO_PAGE_SIZE = PAGE_SIZE / 2,
MOCK_HUGE_PAGE_SIZE = 512 * MOCK_IO_PAGE_SIZE,

/*
* Like a real page table alignment requires the low bits of the address
Expand All @@ -53,6 +54,7 @@ enum {
MOCK_PFN_START_IOVA = _MOCK_PFN_START,
MOCK_PFN_LAST_IOVA = _MOCK_PFN_START,
MOCK_PFN_DIRTY_IOVA = _MOCK_PFN_START << 1,
MOCK_PFN_HUGE_IOVA = _MOCK_PFN_START << 2,
};

/*
Expand Down Expand Up @@ -242,6 +244,8 @@ static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain,
continue;
}

if (xa_to_value(ent) & MOCK_PFN_HUGE_IOVA)
pgsize = MOCK_HUGE_PAGE_SIZE;
head = iova & ~(pgsize - 1);

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

static struct iommu_domain *mock_domain_alloc_paging(struct device *dev)
{
struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
struct mock_iommu_domain *mock;

mock = kzalloc(sizeof(*mock), GFP_KERNEL);
Expand All @@ -268,6 +273,8 @@ static struct iommu_domain *mock_domain_alloc_paging(struct device *dev)
mock->domain.geometry.aperture_start = MOCK_APERTURE_START;
mock->domain.geometry.aperture_end = MOCK_APERTURE_LAST;
mock->domain.pgsize_bitmap = MOCK_IO_PAGE_SIZE;
if (dev && mdev->flags & MOCK_FLAGS_DEVICE_HUGE_IOVA)
mock->domain.pgsize_bitmap |= MOCK_HUGE_PAGE_SIZE;
mock->domain.ops = mock_ops.default_domain_ops;
mock->domain.type = IOMMU_DOMAIN_UNMANAGED;
xa_init(&mock->pfns);
Expand Down Expand Up @@ -313,7 +320,7 @@ mock_domain_alloc_user(struct device *dev, u32 flags,
return ERR_PTR(-EOPNOTSUPP);
if (user_data || (has_dirty_flag && no_dirty_ops))
return ERR_PTR(-EOPNOTSUPP);
domain = mock_domain_alloc_paging(NULL);
domain = mock_domain_alloc_paging(dev);
if (!domain)
return ERR_PTR(-ENOMEM);
if (has_dirty_flag)
Expand Down Expand Up @@ -376,6 +383,9 @@ static int mock_domain_map_pages(struct iommu_domain *domain,

if (pgcount == 1 && cur + MOCK_IO_PAGE_SIZE == pgsize)
flags = MOCK_PFN_LAST_IOVA;
if (pgsize != MOCK_IO_PAGE_SIZE) {
flags |= MOCK_PFN_HUGE_IOVA;
}
old = xa_store(&mock->pfns, iova / MOCK_IO_PAGE_SIZE,
xa_mk_value((paddr / MOCK_IO_PAGE_SIZE) |
flags),
Expand Down Expand Up @@ -630,7 +640,8 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
struct mock_dev *mdev;
int rc;

if (dev_flags & ~(MOCK_FLAGS_DEVICE_NO_DIRTY))
if (dev_flags &
~(MOCK_FLAGS_DEVICE_NO_DIRTY | MOCK_FLAGS_DEVICE_HUGE_IOVA))
return ERR_PTR(-EINVAL);

mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
Expand Down

0 comments on commit 7db521e

Please sign in to comment.