Messages in this thread Patches in this message |  | | Date | Mon, 6 Apr 2026 10:28:12 -0300 | | From | Jason Gunthorpe <> | | Subject | Re: [PATCH v4 1/3] iommu_pt: support small VA for AMDv1 |
| |
On Wed, Apr 01, 2026 at 02:43:55PM +0000, Ankit Soni wrote: > When hardware/VM request a small VA limit, the generic page table code > clears PT_FEAT_DYNAMIC_TOP. This later causes domain initialization to > fail with -EOPNOTSUPP. > To properly enforce the domain VA limit, clamp amdv1pt_possible_sizes > using the requested max_vasz_lg2. > > Signed-off-by: Ankit Soni <Ankit.Soni@amd.com> > --- > drivers/iommu/generic_pt/fmt/amdv1.h | 4 +++- > drivers/iommu/generic_pt/iommu_pt.h | 4 ---- > 2 files changed, 3 insertions(+), 5 deletions(-) > > diff --git a/drivers/iommu/generic_pt/fmt/amdv1.h b/drivers/iommu/generic_pt/fmt/amdv1.h > index 3b2c41d9654d..bc04d482c12f 100644 > --- a/drivers/iommu/generic_pt/fmt/amdv1.h > +++ b/drivers/iommu/generic_pt/fmt/amdv1.h > @@ -156,6 +156,7 @@ static inline unsigned int amdv1pt_num_items_lg2(const struct pt_state *pts) > static inline pt_vaddr_t amdv1pt_possible_sizes(const struct pt_state *pts) > { > unsigned int isz_lg2 = pt_table_item_lg2sz(pts); > + pt_vaddr_t raw; > > if (!amdv1pt_can_have_leaf(pts)) > return 0; > @@ -168,8 +169,9 @@ static inline pt_vaddr_t amdv1pt_possible_sizes(const struct pt_state *pts) > * 512GB Pages are not supported due to a hardware bug. > * Otherwise every power of two size is supported. > */ > - return GENMASK_ULL(min(51, isz_lg2 + amdv1pt_num_items_lg2(pts) - 1), > + raw = GENMASK_ULL(min(51, isz_lg2 + amdv1pt_num_items_lg2(pts) - 1), > isz_lg2) & ~SZ_512G; > + return fvalog2_mod(raw, pts->range->common->max_vasz_lg2); > } > #define pt_possible_sizes amdv1pt_possible_sizes
This is a generic issue, I think it should be fixed like this instead:
@@ -1153,8 +1153,12 @@ static void NS(get_info)(struct pt_iommu *iommu_table, pgsize_bitmap |= pt_possible_sizes(&pts); } - /* Hide page sizes larger than the maximum OA */ - info->pgsize_bitmap = oalog2_mod(pgsize_bitmap, common->max_oasz_lg2); + /* + * Hide page sizes larger than the maximum. -1 because a whole table + * pgsize is not allowed + */ + info->pgsize_bitmap = log2_mod(pgsize_bitmap, common->max_vasz_lg2 - 1); + info->pgsize_bitmap = oalog2_mod(info->pgsize_bitmap, common->max_oasz_lg2); } pt_possible_sizes() always has to be masked with the pgsize_bitmap, so fixing it here is enough to remove those sizes from all the other places..
Then one of the tests isn't following that rule, so it needs a fix too: @@ -438,6 +440,9 @@ static void test_lvl_possible_sizes(struct kunit *test, struct pt_state *pts, { 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); if (!pt_can_have_leaf(pts)) { @@ -448,7 +453,8 @@ static void test_lvl_possible_sizes(struct kunit *test, struct pt_state *pts, /* No bits for sizes that would be outside this table */ KUNIT_ASSERT_EQ(test, log2_mod(pgsize_bitmap, isz_lg2), 0); KUNIT_ASSERT_EQ( - test, fvalog2_div(pgsize_bitmap, num_items_lg2 + isz_lg2), 0); + test, + fvalog2_div(limited_pgsize_bitmap, num_items_lg2 + isz_lg2), 0); /* * Non contiguous must be supported. AMDv1 has a HW bug where it does @@ -463,8 +469,8 @@ static void test_lvl_possible_sizes(struct kunit *test, struct pt_state *pts, /* A contiguous entry should not span the whole table */ if (num_items_lg2 + isz_lg2 != PT_VADDR_MAX_LG2) KUNIT_ASSERT_FALSE( - test, - pgsize_bitmap & log2_to_int(num_items_lg2 + isz_lg2)); + test, limited_pgsize_bitmap & + log2_to_int(num_items_lg2 + isz_lg2)); }
And it should go in its own patch: "fix pgsize_bitmap calculation in get_info for smaller vasz's"
Jason
|  |