On Wed, Nov 19, 2025 at 09:31:50AM +0000, Tian, Kevin wrote:

> old way:
> 
>       if (first_stage)
>               domain->domain.geometry.aperture_end = 
> __DOMAIN_MAX_ADDR(domain->gaw - 1);
>       else
>               domain->domain.geometry.aperture_end = 
> __DOMAIN_MAX_ADDR(domain->gaw);
> 
> i.e. both are initialized around domain->gaw.
> 
> but the new way has difference between first-stage and second-stage as
> Jason pointed out already.
> 
> Baolu, what is the number in "Using xxx-bit DMA addresses" when
> using second-stage?

He said 42.

Indeed Chaitanya's dmesg has this:

[    0.079787] DMAR: Host address width 42

Which I think explains the bug. The dmar->width is being ignored by
the driver except for that print.

> my  understanding of various 'gaw' fields are only about second stage, but
> maybe there is something we overlooked...

That is what the spec says:

  MGAW: Maximum Guest Address Width

  This field indicates the maximum guest physical address width
  supported by second-stage translation in remapping hardware. The
  Maximum Guest Address Width (MGAW) is computed as (N+1),
  where N is the valued reported in this field. For example, a hardware
  implementation supporting 48-bit MGAW reports a value of 47
  (101111b) in this fiel

Seems very clear it is related to the second stage in that paragraph..

So, I think what has happened here is the old driver mis-used mgaw for
the first stage:

        addr_width = agaw_to_width(iommu->agaw);
        if (addr_width > cap_mgaw(iommu->cap))
                addr_width = cap_mgaw(iommu->cap);
        domain->gaw = addr_width;

And fully ignored dmar->width, which happened to work because mgaw < dmar->width

So we should be using dmar->width to constrain the first stage and
expect that mgaw is less than dmar->width ?

Jason

Reply via email to