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 > >
