Re: [PATCH] iommu/vt-d: Fix page table level calculation in compute_vasz_lg2_ss()

From: Jason Gunthorpe

Date: Tue Aug 25 2026 - 07:32:49 EST


On Tue, Aug 25, 2026 at 04:00:02PM +0800, Zhenzhong Duan wrote:
> compute_vasz_lg2_ss() finds the optimal Second-Stage page table level by
> intersecting the maximum guest address width (mgaw) with the hardware's
> SAGAW capability register.
>
> The VT-d spec maps the SAGAW bit field positions as:
> - Bit 1: 39-bit AGAW (3-level page table, top_level = 2)
> - Bit 2: 48-bit AGAW (4-level page table, top_level = 3)
> - Bit 3: 57-bit AGAW (5-level page table, top_level = 4)
>
> The fallback paths use bit shifts that are one position too large,
> causing ffs() to select a deeper page table level than the mgaw window
> requires:
>
> - mgaw > 39: "3 + ffs(sagaw >> 3)" evaluates to top_level = 4 (5-level)
> instead of top_level = 3 (4-level) when hardware supports both
> 48-bit (Bit 2) and 57-bit (Bit 3) AGAW.
> - mgaw > 30: "2 + ffs(sagaw >> 2)" evaluates to top_level = 3 (4-level)
> instead of top_level = 2 (3-level) when hardware supports both
> 39-bit (Bit 1) and 48-bit (Bit 2) AGAW.
>
> In both cases the selected level is still one that the hardware advertises
> in its SAGAW capability, so IOVA translation remains functionally correct.
> However, an unnecessarily deep page table may be selected, adding an extra
> level of page walk overhead and reducing TLB and cache efficiency without
> providing any increase in addressable IOVA space beyond what the mgaw
> window already caps.
>
> Fix by decreasing the shift offset by one in each fallback case, ensuring
> ffs() targets the correct SAGAW bit position and selects the smallest
> page table level that fully covers the mgaw range:
>
> - mgaw > 39: "2 + ffs(sagaw >> 2)" correctly yields top_level = 3
> - mgaw > 30: "1 + ffs(sagaw >> 1)" correctly yields top_level = 2
>
> Fixes: d856f9d27885 ("iommupt/vtd: Allow VT-d to have a larger table top than the vasz requires")
> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>
> ---
> drivers/iommu/intel/iommu.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg@xxxxxxxxxx>

Jason