[PATCH 2/6] iommupt: allow full-table contiguous leaves in unit tests
From: Daniel Drake <hidden>
Date: 2026-07-12 21:19:42
Also in:
linux-devicetree, linux-iommu, lkml
Subsystem:
iommu subsystem, the rest · Maintainers:
Joerg Roedel, Will Deacon, Linus Torvalds
The generic_pt tests currently assume that a format should never support a contiguous page size that spans the entire mapping range of the table it resides in. This assumption breaks for BCM2712, which has a 2-level page table. Level 1 entries cover 4MB of memory via their corresponding Level 0 table pages. There is a concept of a 4MB largepage, but that is represented as a Level 1 entry pointing at a Level 0 table with the 1024 usual PTEs with an additional largepage hint applied (for TLB optimization purposes). Unlike typical IOMMUs, it is not possible to have the Level 1 entry point directly at a 4MB chunk without the need for Level 0 mapping. This BCM2712 format is well supported by generic_pt: SZ_4M can be advertised as a possible size at Level 0 (so that the iommu core feeds it 4MB-aligned mapping requests where possible), and drivers can also advertise that *all* leaf entries are installed at Level 0. This indicates that the tests are overly strict. Transform the test to become a validation of the driver's routing intent: for every advertised page size, check that pt_pgsz_lg2_to_level() maps that size back to the table level under test. This is roughly what the original tests were doing, but also allows the BCM2712 case to pass. Signed-off-by: Daniel Drake <redacted> --- drivers/iommu/generic_pt/kunit_generic_pt.h | 39 +++++++++++------------------ 1 file changed, 14 insertions(+), 25 deletions(-)
diff --git a/drivers/iommu/generic_pt/kunit_generic_pt.h b/drivers/iommu/generic_pt/kunit_generic_pt.h
index ef2c90b6d6af..7f4e172ef08b 100644
--- a/drivers/iommu/generic_pt/kunit_generic_pt.h
+++ b/drivers/iommu/generic_pt/kunit_generic_pt.h@@ -419,40 +419,35 @@ static void test_table_radix(struct kunit *test) } } -static unsigned int safe_pt_num_items_lg2(const struct pt_state *pts) -{ - struct pt_range top_range = pt_top_range(pts->range->common); - struct pt_state top_pts = pt_init_top(&top_range); - - /* - * Avoid calling pt_num_items_lg2() on the top, instead we can derive - * the size of the top table from the top range. - */ - if (pts->level == top_range.top_level) - return ilog2(pt_range_to_end_index(&top_pts)); - return pt_num_items_lg2(pts); -} - static void test_lvl_possible_sizes(struct kunit *test, struct pt_state *pts, void *arg) { - unsigned int num_items_lg2 = safe_pt_num_items_lg2(pts); pt_vaddr_t pgsize_bitmap = pt_possible_sizes(pts); /* Matches get_info() */ pt_vaddr_t limited_pgsize_bitmap = log2_mod(pgsize_bitmap, pts->range->common->max_vasz_lg2 - 1); unsigned int isz_lg2 = pt_table_item_lg2sz(pts); + unsigned int sz_lg2; if (!pt_can_have_leaf(pts)) { KUNIT_ASSERT_EQ(test, pgsize_bitmap, 0); return; } - /* No bits for sizes that would be outside this table */ + /* A page size cannot be smaller than the span of a single entry. */ KUNIT_ASSERT_EQ(test, log2_mod(pgsize_bitmap, isz_lg2), 0); - KUNIT_ASSERT_EQ( - test, - fvalog2_div(limited_pgsize_bitmap, num_items_lg2 + isz_lg2), 0); + + /* + * Ensure every page size claimed to be supported at this level + * actually routes back to this level + */ + for (sz_lg2 = 0; sz_lg2 < PT_VADDR_MAX_LG2; sz_lg2++) { + if (limited_pgsize_bitmap & log2_to_int(sz_lg2)) { + KUNIT_ASSERT_EQ(test, + pt_pgsz_lg2_to_level(pts->range->common, sz_lg2), + pts->level); + } + } /* * Non contiguous must be supported. AMDv1 has a HW bug where it does
@@ -463,12 +458,6 @@ static void test_lvl_possible_sizes(struct kunit *test, struct pt_state *pts, KUNIT_ASSERT_TRUE(test, pgsize_bitmap & log2_to_int(isz_lg2)); else KUNIT_ASSERT_NE(test, pgsize_bitmap, 0); - - /* A contiguous entry should not span the whole table */ - if (num_items_lg2 + isz_lg2 != PT_VADDR_MAX_LG2) - KUNIT_ASSERT_FALSE( - test, limited_pgsize_bitmap & - log2_to_int(num_items_lg2 + isz_lg2)); } static void test_entry_possible_sizes(struct kunit *test)
--
2.55.0