mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
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/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>
This commit is contained in:
parent
02a8c61a8b
commit
7db521e23f
@ -45,6 +45,7 @@ enum {
|
||||
|
||||
enum {
|
||||
MOCK_FLAGS_DEVICE_NO_DIRTY = 1 << 0,
|
||||
MOCK_FLAGS_DEVICE_HUGE_IOVA = 1 << 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -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
|
||||
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -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 */
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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)
|
||||
@ -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),
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user