This is meant to address the MMU faults reported in
https://gitlab.freedesktop.org/mesa/mesa/-/issues/14610 ?

With this patch I still see faults when running the test script I posted
there.

On Thu, Jan 22, 2026 at 3:35 PM Dave Airlie <[email protected]> wrote:

> From: Dave Airlie <[email protected]>
>
> When NVK enabled large pages userspace tests were seeing fault
> reports at a valid address.
>
> There was a case where an address moving from 64k page to 4k pages
> could expose a race between unmapping the 4k page, mapping the 64k
> page and unref the 4k pages.
>
> Unref 4k pages would cause the dual-page table handling to always
> set the LPTE entry to SPARSE or INVALID, but if we'd mapped a valid
> LPTE in the meantime, it would get trashed. Keep track of when
> a valid LPTE has been referenced, and don't reset in that case.
>
> The SPTES field is fine at 31 limit, so just steal a bit from it.
>
> Cc: [email protected]
> Link: https://gitlab.freedesktop.org/mesa/mesa/-/issues/14610
> Signed-off-by: Dave Airlie <[email protected]>
> ---
>  drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 33 ++++++++++++++-----
>  drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h |  3 +-
>  2 files changed, 27 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
> b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
> index f95c58b67633..73141dda4728 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
> @@ -242,14 +242,17 @@ nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it,
> struct nvkm_vmm_pt *pgt,
>                 if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) {
>                         TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes);
>                         pair->func->sparse(vmm, pgt->pt[0], pteb, ptes);
> -               } else
> -               if (pair->func->invalid) {
> -                       /* If the MMU supports it, restore the LPTE to the
> -                        * INVALID state to tell the MMU there is no point
> -                        * trying to fetch the corresponding SPTEs.
> -                        */
> -                       TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes);
> -                       pair->func->invalid(vmm, pgt->pt[0], pteb, ptes);
> +               } else if (!(pgt->pte[pteb] & NVKM_VMM_PTE_BIG_VALID)) {
> +                       if (pair->func->invalid) {
> +                               /* If the MMU supports it, restore the
> LPTE to the
> +                                * INVALID state to tell the MMU there is
> no point
> +                                * trying to fetch the corresponding SPTEs.
> +                                */
> +                               TRA(it, "LPTE %05x: U -> I %d PTEs", pteb,
> ptes);
> +                               pair->func->invalid(vmm, pgt->pt[0], pteb,
> ptes);
> +                       }
> +               } else {
> +                       TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes);
>                 }
>         }
>  }
> @@ -280,6 +283,13 @@ nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, bool
> pfn, u32 ptei, u32 ptes)
>         if (desc->type == SPT && (pgt->refs[0] || pgt->refs[1]))
>                 nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes);
>
> +       if (desc->type == LPT && (pgt->refs[0] || pgt->refs[1])) {
> +               for (u32 lpti = ptei; ptes; lpti++) {
> +                       pgt->pte[lpti] &= ~NVKM_VMM_PTE_BIG_VALID;
> +                       ptes--;
> +               }
> +       }
> +
>         /* PT no longer needed? Destroy it. */
>         if (!pgt->refs[type]) {
>                 it->lvl++;
> @@ -374,6 +384,13 @@ nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, bool pfn,
> u32 ptei, u32 ptes)
>         if (desc->type == SPT)
>                 nvkm_vmm_ref_sptes(it, pgt, desc, ptei, ptes);
>
> +       if (desc->type == LPT) {
> +               for (u32 lpti = ptei; ptes; lpti++) {
> +                       pgt->pte[lpti] |= NVKM_VMM_PTE_BIG_VALID;
> +                       ptes--;
> +               }
> +       }
> +
>         return true;
>  }
>
> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
> b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
> index 4586a425dbe4..1fe7915b8e87 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
> +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
> @@ -46,7 +46,8 @@ struct nvkm_vmm_pt {
>          */
>  #define NVKM_VMM_PTE_SPARSE 0x80
>  #define NVKM_VMM_PTE_VALID  0x40
> -#define NVKM_VMM_PTE_SPTES  0x3f
> +#define NVKM_VMM_PTE_BIG_VALID 0x20
> +#define NVKM_VMM_PTE_SPTES  0x1f
>         u8 pte[];
>  };
>
> --
> 2.52.0
>
>

Reply via email to