From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2BBACE83052 for ; Tue, 3 Feb 2026 05:28:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 78EDD10E552; Tue, 3 Feb 2026 05:28:43 +0000 (UTC) Received: from us-smtp-delivery-44.mimecast.com (us-smtp-delivery-44.mimecast.com [205.139.111.44]) by gabe.freedesktop.org (Postfix) with ESMTPS id EEFD010E546 for ; Tue, 3 Feb 2026 05:28:41 +0000 (UTC) Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-658-oPoglKlVOzCt7N2e4nHesA-1; Tue, 03 Feb 2026 00:28:39 -0500 X-MC-Unique: oPoglKlVOzCt7N2e4nHesA-1 X-Mimecast-MFC-AGG-ID: oPoglKlVOzCt7N2e4nHesA_1770096518 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AD1BD195606D; Tue, 3 Feb 2026 05:28:38 +0000 (UTC) Received: from dreadlord.redhat.com (unknown [10.67.32.75]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AEAF51955F16; Tue, 3 Feb 2026 05:28:36 +0000 (UTC) From: Dave Airlie To: dri-devel@lists.freedesktop.org Cc: nouveau@lists.freedesktop.org Subject: [PATCH 3/3] nouveau/vmm: start tracking if the LPT PTE is valid. (v6) Date: Tue, 3 Feb 2026 15:25:27 +1000 Message-ID: <20260203052823.2220053-4-airlied@gmail.com> In-Reply-To: <20260203052823.2220053-1-airlied@gmail.com> References: <20260203052823.2220053-1-airlied@gmail.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: RS3045hEHRnAijVg1XNPFDYb987tgRL_Sfo8JQ8PKpE_1770096518 X-Mimecast-Originator: gmail.com Content-Transfer-Encoding: quoted-printable content-type: text/plain; charset=WINDOWS-1252; x-default=true X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Dave Airlie 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. This adds an lpte valid tracker and lpte reference count. Whenever an lpte is referenced, it gets made valid and the ref count increases, whenever it gets unreference the refcount is tracked. Link: https://gitlab.freedesktop.org/mesa/mesa/-/issues/14610 Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 39 +++++++++++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h | 3 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/dr= m/nouveau/nvkm/subdev/mmu/vmm.c index 8b8f4b85e315..ea1191386c6e 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, =09=09if (pgt->pte[pteb].s.sparse) { =09=09=09TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes); =09=09=09pair->func->sparse(vmm, pgt->pt[0], pteb, ptes); -=09=09} else -=09=09if (pair->func->invalid) { -=09=09=09/* If the MMU supports it, restore the LPTE to the -=09=09=09 * INVALID state to tell the MMU there is no point -=09=09=09 * trying to fetch the corresponding SPTEs. -=09=09=09 */ -=09=09=09TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes); -=09=09=09pair->func->invalid(vmm, pgt->pt[0], pteb, ptes); +=09=09} else if (!pgt->pte[pteb].s.lpte_valid) { +=09=09=09if (pair->func->invalid) { +=09=09=09=09/* If the MMU supports it, restore the LPTE to the +=09=09=09=09 * INVALID state to tell the MMU there is no point +=09=09=09=09 * trying to fetch the corresponding SPTEs. +=09=09=09=09 */ +=09=09=09=09TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes); +=09=09=09=09pair->func->invalid(vmm, pgt->pt[0], pteb, ptes); +=09=09=09} +=09=09} else { +=09=09=09TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes); =09=09} =09} } @@ -280,6 +283,15 @@ nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, bool pfn= , u32 ptei, u32 ptes) =09if (desc->type =3D=3D SPT && (pgt->refs[0] || pgt->refs[1])) =09=09nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes); =20 +=09if (desc->type =3D=3D LPT && (pgt->refs[0] || pgt->refs[1])) { +=09=09for (u32 lpti =3D ptei; ptes; lpti++) { +=09=09=09pgt->pte[lpti].s.lptes--; +=09=09=09if (pgt->pte[lpti].s.lptes =3D=3D 0) +=09=09=09=09pgt->pte[lpti].s.lpte_valid =3D false; +=09=09=09ptes--; +=09=09} +=09} + =09/* PT no longer needed? Destroy it. */ =09if (!pgt->refs[type]) { =09=09it->lvl++; @@ -332,10 +344,12 @@ nvkm_vmm_ref_sptes(struct nvkm_vmm_iter *it, struct n= vkm_vmm_pt *pgt, =09=09 * Determine how many LPTEs need to transition state. =09=09 */ =09=09pgt->pte[ptei].s.spte_valid =3D true; +=09=09pgt->pte[ptei].s.lpte_valid =3D false; =09=09for (ptes =3D 1, ptei++; ptei < lpti; ptes++, ptei++) { =09=09=09if (pgt->pte[ptei].s.spte_valid) =09=09=09=09break; =09=09=09pgt->pte[ptei].s.spte_valid =3D true; +=09=09=09pgt->pte[ptei].s.lpte_valid =3D false; =09=09} =20 =09=09if (pgt->pte[pteb].s.sparse) { @@ -374,6 +388,15 @@ nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, bool pfn, = u32 ptei, u32 ptes) =09if (desc->type =3D=3D SPT) =09=09nvkm_vmm_ref_sptes(it, pgt, desc, ptei, ptes); =20 +=09if (desc->type =3D=3D LPT) { +=09=09for (u32 lpti =3D ptei; ptes; lpti++) { +=09=09=09pgt->pte[lpti].s.spte_valid =3D false; +=09=09=09pgt->pte[lpti].s.lpte_valid =3D true; +=09=09=09pgt->pte[lpti].s.lptes++; +=09=09=09ptes--; +=09=09} +=09} + =09return true; } =20 diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h b/drivers/gpu/dr= m/nouveau/nvkm/subdev/mmu/vmm.h index a8b08126e8dc..4ec0a3a21169 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h @@ -9,7 +9,8 @@ union nvkm_pte_tracker { =09struct { =09=09u32 sparse:1; =09=09u32 spte_valid:1; -=09=09u32 padding:14; +=09=09u32 lpte_valid:1; +=09=09u32 lptes:13; =09=09u32 sptes:16; =09} s; }; --=20 2.52.0