Re: [PATCH v4 1/3] iommu_pt: support small VA for AMDv1

From: Ankit Soni

Date: Tue Apr 07 2026 - 10:59:00 EST


On Mon, Apr 06, 2026 at 10:28:12AM -0300, Jason Gunthorpe wrote:
> 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@xxxxxxx>
> > ---
> > 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

Got it, Thanks for the Heads-up, I'll test and send this.

Ankit