From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADA9B3BE623 for ; Fri, 10 Jul 2026 21:26:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718795; cv=none; b=ncLL0z+LkQoHU/nfiRuumkuFiPRKXlpdu6FdAujQHt+k56SYWa4roK3tK6ec+S9d9KHZ5YMhqknQYSHyTD1pttMQVtNYOthoeBInvB4tUQ6iU/FPTtIa4Sp2aHBDB4U9/nbBTyalLDmlvg8luffg4zdgQFuduCI/VSd2gtJdqmc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718795; c=relaxed/simple; bh=EkKsxGxbwqoAEVoChmNYdEJ3T6vK01FnBsNC9G9arvg=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Bvsz2zC72UAwWlB47NDNRVPXWGucZMD5tQ9ZwUws6fARgJJAwXmsgkjCsuXv/MW6aLdqiyG6LDqPPlaPJNGnOhHs83afy+y9c4/2m5zjxKtKssRSlsp4WP+tXP1DY6ojzSR2o/erC13389JKBjz+XnlgFT1L7KEuOxotau4Rxkw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=pYM/HePd; arc=none smtp.client-ip=209.85.216.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pYM/HePd" Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-381c51fde6bso1400202a91.2 for ; Fri, 10 Jul 2026 14:26:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718790; x=1784323590; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=8+MHxD8uf0HO8SRBYZIasl4vPo7jNKxT6S73gN/spU8=; b=pYM/HePdkgyz9sRexjpJV2zNuxQ2oEBuxzV6Ka9zhgeN46Z9DKBPNHWs2kZOkzzWG5 s91VJ3OkYi6vnMsRR21zJaJL+o9Y5Cm6SLT/NyxRYH3B/JcOK1C4ZYSEJH797j/O1bl4 /fV0KtTWVZOyi3fzodS2JYUS6s8DiT+hZs73wHgkp7jK8Fvc6cPr0WmDlQ6QOvrZX0dZ G2XKVFWmYC426FW2LgQWoktCarpPPsuZbq5hz1Am7DF82m6kMwTENLsVh8BQt7uh6I52 pM9p+KV1HuO00992Usj8eOmO6NBFI6MA8hMkwrPE228sKQs3ETtFwsg48ATnDo5Utby+ ZxKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718790; x=1784323590; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=8+MHxD8uf0HO8SRBYZIasl4vPo7jNKxT6S73gN/spU8=; b=c8CJM46agDtk8rRrY2+WKJFlbGELBx/uVZ+Kmwg0xoZ8SLxA8VZo1Ca33tRDRwvF3R lh45kA96vDwTrd6lt2QtMq9wrTbfaCGXwJxsnALrm/NwRqVvH2pQGzXSF8jMucqhECB7 /HpbDedsXKtPLc4usYEyhjRZ7QZ+gIjzWkaNhaXzIUnOp4sKxi/QMvC0zuuAdidCwg2J vOZzupdkulPVe57Y731WLKWiOgteeUN5Ez2mY4/IfTileQXUPgLgcV4guDtdLXfd/lUx YvBPQcIDMWwwOG7guqg0a4owZdKg+I+kf+lnuMvNXY2SaNxlaNfiEuQNj/GoyOgbJUN6 G1XA== X-Forwarded-Encrypted: i=1; AHgh+RphM80jIUXmFuujCjKzR4p+lG4gtOlSCMnm8GWkSGVCSYJ+oxwJGSJjPz5tnS6nXbMEB3eSHtT6jZP1sow=@vger.kernel.org X-Gm-Message-State: AOJu0YzB3LPSYKXmkFWZldAUiuPkmCb3OLltv2ELlpiMxEeynINaGNaa DwfWpVhSi+ImmSSxc6WaIUxQEagbxmIgxj7NX8JbkXYhSbIYhOUgohhw X-Gm-Gg: AfdE7ckvi/LAmgFlmXsPqW1NZYsuwpR/wW1mV2JwDiQCeJzkjGYzz0sgR/KFcZKvuRo dDvHLQsJWdw4qkUDmGzH21Z/NTwVRDELl5D4hG1OZBQp0EGsHu3VYlUchIdFn6/TANZE8nNI2YF YmgjH6aEJYjGWugqdHIQ3Mel9VmPdSv6rPKySDFX1eLcZRqMnS0fMLvZRc/n52ANgh9QORS94Ql 9BxA6vngob62L8jv0w6YXG8lrmNxhKr6bgzFCq779Wir/x+wDKjzU9lgFOS+vvVbF4ZfIt2r/4l bkcpO2QxIeAVi64VIZxtKPhpDrGgw05yJqhcknZnvbdLd7sfHpGQLPDyewYYRfe+4TheQd5hft1 Sl8ayjgwKFqFp10JyqSTyTs4u4nZQL/gxt8eaQB3Wkcu0v0NnZQKyB7HlAnv0VnjLWHrxKTId5T jUAQk6i7zD6Bb5TF/sEdW7ad05o47ISMtilrQiGYJwedLuagXmoRKvVn9yT4Q= X-Received: by 2002:a17:90a:e705:b0:38c:e9e9:e7ce with SMTP id 98e67ed59e1d1-38dc74c5007mr567748a91.3.1783718790283; Fri, 10 Jul 2026 14:26:30 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-38a55557f39sm3404785a91.6.2026.07.10.14.26.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:26:29 -0700 (PDT) Subject: [PATCH v8 1/8] mm/hmm: move page fault handling out of walk callbacks From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:26:27 -0700 Message-ID: <178371878774.900500.3975008123082170472.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable hmm_range_fault() currently triggers page faults from inside the page-table walk callbacks: hmm_vma_walk_pmd(), hmm_vma_walk_pud(), hmm_vma_walk_hugetlb_entry() and the pte-level helper all call hmm_vma_fault(), which in turn calls handle_mm_fault() while the walker still holds nested locks. The pte spinlock is dropped explicitly by each caller, and the hugetlb path manually drops and retakes hugetlb_vma_lock_read around the fault to dodge a deadlock against the walk framework's unconditional unlock. This layering does not extend cleanly to fault handlers that may release mmap_lock (VM_FAULT_RETRY, VM_FAULT_COMPLETED). If the lock is dropped while walk_page_range() is mid-traversal, the VMA can be freed before the walk framework's matching hugetlb_vma_unlock_read(), turning that unlock into a use-after-free. Split the responsibilities the way get_user_pages() does. Walk callbacks become inspect-only: when they detect a range that needs to be faulted in, they record it in struct hmm_vma_walk and return a private sentinel (HMM_FAULT_PENDING). The outer loop in hmm_range_fault() then drops out of walk_page_range(), invokes a new helper hmm_do_fault() that calls handle_mm_fault() with only mmap_lock held, and restarts the walk so the now-present entries are collected into hmm_pfns. No functional change for existing callers. As a side effect the hugetlb callback no longer needs the hugetlb_vma_{un}lock_read dance, and every fault-path exit from the callbacks now releases the pte spinlock on a single, common path. This refactor is also a precursor for adding an unlockable variant of hmm_range_fault() in a follow-up patch. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Jason Gunthorpe --- mm/hmm.c | 118 +++++++++++++++++++++++++++++++++++++++-------------------= ---- 1 file changed, 75 insertions(+), 43 deletions(-) diff --git a/mm/hmm.c b/mm/hmm.c index e5c1f4deed24..bc9361a715fa 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -33,8 +33,17 @@ struct hmm_vma_walk { struct hmm_range *range; unsigned long last; + unsigned long end; + unsigned int required_fault; }; =20 +/* + * Internal sentinel returned by walk callbacks when they need a page faul= t. + * The callback stores end/required_fault in hmm_vma_walk; the outer loop + * consumes the sentinel and never propagates it to the caller. + */ +#define HMM_FAULT_PENDING -EAGAIN + enum { HMM_NEED_FAULT =3D 1 << 0, HMM_NEED_WRITE_FAULT =3D 1 << 1, @@ -60,37 +69,25 @@ static int hmm_pfns_fill(unsigned long addr, unsigned l= ong end, } =20 /* - * hmm_vma_fault() - fault in a range lacking valid pmd or pte(s) - * @addr: range virtual start address (inclusive) - * @end: range virtual end address (exclusive) - * @required_fault: HMM_NEED_* flags - * @walk: mm_walk structure - * Return: -EBUSY after page fault, or page fault error + * hmm_record_fault() - record a range that needs to be faulted in * - * This function will be called whenever pmd_none() or pte_none() returns = true, - * or whenever there is no page directory covering the virtual address ran= ge. + * Called by the walk callbacks when they discover that part of the range + * needs a page fault. The callback records what to fault and returns + * HMM_FAULT_PENDING; the outer loop in hmm_range_fault() drops back out of + * walk_page_range() and invokes handle_mm_fault() from a context where no + * page-table or hugetlb_vma_lock is held. */ -static int hmm_vma_fault(unsigned long addr, unsigned long end, - unsigned int required_fault, struct mm_walk *walk) +static int hmm_record_fault(unsigned long addr, unsigned long end, + unsigned int required_fault, + struct mm_walk *walk) { struct hmm_vma_walk *hmm_vma_walk =3D walk->private; - struct vm_area_struct *vma =3D walk->vma; - unsigned int fault_flags =3D FAULT_FLAG_REMOTE; =20 WARN_ON_ONCE(!required_fault); hmm_vma_walk->last =3D addr; - - if (required_fault & HMM_NEED_WRITE_FAULT) { - if (!(vma->vm_flags & VM_WRITE)) - return -EPERM; - fault_flags |=3D FAULT_FLAG_WRITE; - } - - for (; addr < end; addr +=3D PAGE_SIZE) - if (handle_mm_fault(vma, addr, fault_flags, NULL) & - VM_FAULT_ERROR) - return -EFAULT; - return -EBUSY; + hmm_vma_walk->end =3D end; + hmm_vma_walk->required_fault =3D required_fault; + return HMM_FAULT_PENDING; } =20 static unsigned int hmm_pte_need_fault(const struct hmm_vma_walk *hmm_vma_= walk, @@ -174,7 +171,7 @@ static int hmm_vma_walk_hole(unsigned long addr, unsign= ed long end, return hmm_pfns_fill(addr, end, range, HMM_PFN_ERROR); } if (required_fault) - return hmm_vma_fault(addr, end, required_fault, walk); + return hmm_record_fault(addr, end, required_fault, walk); return hmm_pfns_fill(addr, end, range, 0); } =20 @@ -209,7 +206,7 @@ static int hmm_vma_handle_pmd(struct mm_walk *walk, uns= igned long addr, required_fault =3D hmm_range_need_fault(hmm_vma_walk, hmm_pfns, npages, cpu_flags); if (required_fault) - return hmm_vma_fault(addr, end, required_fault, walk); + return hmm_record_fault(addr, end, required_fault, walk); =20 pfn =3D pmd_pfn(pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); for (i =3D 0; addr < end; addr +=3D PAGE_SIZE, i++, pfn++) { @@ -328,7 +325,7 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, uns= igned long addr, fault: pte_unmap(ptep); /* Fault any virtual address we were asked to fault */ - return hmm_vma_fault(addr, end, required_fault, walk); + return hmm_record_fault(addr, end, required_fault, walk); } =20 #ifdef CONFIG_ARCH_HAS_PMD_SOFTLEAVES @@ -371,7 +368,7 @@ static int hmm_vma_handle_absent_pmd(struct mm_walk *wa= lk, unsigned long start, npages, 0); if (required_fault) { if (softleaf_is_device_private(entry)) - return hmm_vma_fault(addr, end, required_fault, walk); + return hmm_record_fault(addr, end, required_fault, walk); else return -EFAULT; } @@ -517,7 +514,7 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long = start, unsigned long end, npages, cpu_flags); if (required_fault) { spin_unlock(ptl); - return hmm_vma_fault(addr, end, required_fault, walk); + return hmm_record_fault(addr, end, required_fault, walk); } =20 pfn =3D pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); @@ -564,21 +561,8 @@ static int hmm_vma_walk_hugetlb_entry(pte_t *pte, unsi= gned long hmask, required_fault =3D hmm_pte_need_fault(hmm_vma_walk, pfn_req_flags, cpu_flags); if (required_fault) { - int ret; - spin_unlock(ptl); - hugetlb_vma_unlock_read(vma); - /* - * Avoid deadlock: drop the vma lock before calling - * hmm_vma_fault(), which will itself potentially take and - * drop the vma lock. This is also correct from a - * protection point of view, because there is no further - * use here of either pte or ptl after dropping the vma - * lock. - */ - ret =3D hmm_vma_fault(addr, end, required_fault, walk); - hugetlb_vma_lock_read(vma); - return ret; + return hmm_record_fault(addr, end, required_fault, walk); } =20 pfn =3D pte_pfn(entry) + ((start & ~hmask) >> PAGE_SHIFT); @@ -637,6 +621,44 @@ static const struct mm_walk_ops hmm_walk_ops =3D { .walk_lock =3D PGWALK_RDLOCK, }; =20 +/* + * hmm_do_fault - fault in a range recorded by a walk callback + * + * Called from the outer loop in hmm_range_fault() after a callback + * returned HMM_FAULT_PENDING. At this point we hold only mmap_lock; + * the page-table spinlock and any hugetlb_vma_lock acquired by the walk + * framework have already been released by the unwind. + * + * Returns -EBUSY on success (all pages faulted, caller should re-walk). + * Returns a negative errno on failure. + */ +static int hmm_do_fault(struct mm_struct *mm, + struct hmm_vma_walk *hmm_vma_walk) +{ + unsigned long addr =3D hmm_vma_walk->last; + unsigned long end =3D hmm_vma_walk->end; + unsigned int required_fault =3D hmm_vma_walk->required_fault; + unsigned int fault_flags =3D FAULT_FLAG_REMOTE; + struct vm_area_struct *vma; + + vma =3D vma_lookup(mm, addr); + if (!vma) + return -EFAULT; + + if (required_fault & HMM_NEED_WRITE_FAULT) { + if (!(vma->vm_flags & VM_WRITE)) + return -EPERM; + fault_flags |=3D FAULT_FLAG_WRITE; + } + + for (; addr < end; addr +=3D PAGE_SIZE) + if (handle_mm_fault(vma, addr, fault_flags, NULL) & + VM_FAULT_ERROR) + return -EFAULT; + + return -EBUSY; +} + /** * hmm_range_fault - try to fault some address in a virtual address range * @range: argument structure @@ -674,6 +696,16 @@ int hmm_range_fault(struct hmm_range *range) return -EBUSY; ret =3D walk_page_range(mm, hmm_vma_walk.last, range->end, &hmm_walk_ops, &hmm_vma_walk); + /* + * When HMM_FAULT_PENDING is returned a walk callback + * recorded a range that needs handle_mm_fault(); + * hmm_do_fault() runs the fault outside walk_page_range() + * (so no page-table or hugetlb_vma_lock is held) and + * returns -EBUSY so the loop re-walks and picks up the + * now-present entries. + */ + if (ret =3D=3D HMM_FAULT_PENDING) + ret =3D hmm_do_fault(mm, &hmm_vma_walk); /* * When -EBUSY is returned the loop restarts with * hmm_vma_walk.last set to an address that has not been stored From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1FAF83BB116 for ; Fri, 10 Jul 2026 21:26:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718804; cv=none; b=iq1eVc1AEm3S7/Bi6Wn44qBfryGR/eHD2+tribTbenCeKkepMKA8i2GOtfzwRYAbnrCzaLiF4IuwfW5V3P5n963ttWc8xKTjU5RsZDlNUD+JDTa3NwYdU38IAhYasaHsfGoS3HWXiQUmh9BUoVI/0wZLE2PEbCbAnGslxhHGwGY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718804; c=relaxed/simple; bh=SGN2zajB7g6F1+FA9RLw2HuWwA1m6Nf7GKGNqJxh1d8=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CS234N4/zoiHhfmrQwTzGzLVxflNTVlR7qNGWrRzesE0Te7omS+pUTsuNZ8m40yJVrQwyxNKXP0wZMLjsROcJ+Qc9BL0tHjlcsouxIGTexoo7O2v3a6cXjnlOwwBC5dxLpMkF6TVZSl+UOTQ61wS9zqyMFvTkzP2LfH+67hupKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=amRmznTv; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="amRmznTv" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2c6b67d5fa1so22994225ad.2 for ; Fri, 10 Jul 2026 14:26:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718797; x=1784323597; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=ZqbwRVP/sfR6Y4F4lzaqregK9IVNqigDowAHMdHoVCE=; b=amRmznTvDLm86N6EINfPvft1zp+yPmNLbHxcAsPXDX8Eh8JQymH1TYs1W89s3YZkkM MBn6s/7TYFAXFZcbxlHqGoX5lli8QzdBbb+NVZfj8Vkw+ubTtjr+84ab4uMPjzHyNgJ2 iXJkt1sPJ0mOuA/yOUHkKhFYPCTjcGb52z8ynv0lCkrJih/dYk8Sdo09a1hY0nlSCP6d PL6iAGjqwxMabgbzB71QXC/3XXUwo1XsVItsCVHpcaSTcCYIE0mTx5zIgKsAPrl9IzoE +MnRK+xjzImzN8JMsK8ZwZu9UcHiOK4Bf0uW9hGAUKFLj4q48qcjAa8+wxjh1pT+u0bY Q9dQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718797; x=1784323597; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=ZqbwRVP/sfR6Y4F4lzaqregK9IVNqigDowAHMdHoVCE=; b=B/Bv6BsSgoY4GnyeKtcVr4XWzhMNrkyIn/EBZB+yY4V+RovJaD2uGAxbRmSfO0nz9y 7xAzQApgMfZ3Xkh+mjXssGNew0IRthtq98fkqU9+n7V/b8yDV4vvhrOinOlO9xlK/AGs 4PRE8YPCfMFLcgo4anQ18aZSQALHSL1PO+RcbhU9WqYFdCtx28uUOLflN71dnDdLK1Az nHLSEcSNiqwCeuju2Jmh0t37Nd8Z5yTSzdtaBGvssorNXpHbfN6cyLPsWMRtLKLJcBRH xME6xdNUqR2IgNeReShslcaoUoFKiOc02OXyXfI5pCw34ElW4hiQkV35ORZJMhFXpy6J HQBQ== X-Forwarded-Encrypted: i=1; AHgh+Rov8Ead5sRBsHor7pPNDE5L6sbKmlKw4ZV5jYrmCrygZllcKLNQ3xk3zGjeFPC2CDVGehKTHjnICw3E+Ug=@vger.kernel.org X-Gm-Message-State: AOJu0YxrElttLZMtSzGydFJP2pPJK2rwLRItpx9zyLGyy0Uon4Ex6H6b EjxNhQaIOicbAtb7GC9Ae/cL/aON7EK0Lfh6c3PZXJMQ3LUjqgDZT1YL X-Gm-Gg: AfdE7cnYxVAGhpV6alZNs17SLLz+fJGKU4xmYZDkrRc6e+Rr2MkQ4X85XRw2FDMUgBX u7ZVuzxprLe9i//gfrPHRxyBmkMSg4v3aPWHyUPO16cZTLlta9iwjSMZzikm/VzZ01PbU80TrSD GR0WpSId19f/EFZjOT4UyEY8cWXrfI557KYKH1aXFOOqvHB61DailoOQlfF+3WYO936qepbbVPE tWkFymKpa3fs7MeK9v1FXwWHiVgxyvB1rpa2/Sg7bjnrZmno0cKhvVgqeY2qqZ0Gvnx9euVkBOz paM/WYDC4yRGkWNYNp6RdPskUPupgKk3O8LNHza2zs6WzB5qJcyyT0nvzcN7MVpsCu5WxJtvhYP jHBCtlPg+wdmT7NfOXa3cJXk+eOCMnymr0/lMLGUR2ppT9bUlnZeLLkQevAXc/w8E3OCmAgp5rH aP/VkMzFutgztttXGfdKJh82DdG9qGIiILMmYzS7ndODeqOKAYRYOI8yJhUpAwc/Fznsb5jA== X-Received: by 2002:a05:6a20:1604:b0:3bb:2200:f67b with SMTP id adf61e73a8af0-3c110cdb319mr625385637.40.1783718797427; Fri, 10 Jul 2026 14:26:37 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-ca5af7d58f3sm5552601a12.1.2026.07.10.14.26.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:26:36 -0700 (PDT) Subject: [PATCH v8 2/8] mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:26:35 -0700 Message-ID: <178371879503.900500.7148019929226548795.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable hmm_range_fault() requires the caller to hold the mmap read lock for the duration of the call. This is incompatible with mappings whose fault handler may release the mmap lock, notably userfaultfd-managed regions, where handle_mm_fault() can return VM_FAULT_RETRY or VM_FAULT_COMPLETED after dropping the lock. Drivers that need to populate device page tables for such mappings have no way to do so today. Add hmm_range_fault_unlocked_timeout() for callers that do not need to hold mmap_lock across any work outside the HMM fault itself. The helper takes mmap_read_lock_killable() internally, calls the common HMM fault implementation, and releases the lock before returning if it is still held. The timeout is specified in jiffies; passing 0 retries indefinitely, while a non-zero timeout makes the helper return -EBUSY when the retry budget expires. When handle_mm_fault() drops mmap_lock, or when the range is invalidated, hmm_range_fault_unlocked_timeout() refreshes range->notifier_seq and retries the walk internally. If the lock was dropped, the retry deadline is also restarted because a lock-dropping fault handler made progress. Ordinary -EBUSY retries keep the existing deadline, preserving the caller's timeout policy for repeated mmu-notifier invalidations. The caller only needs to perform the usual post-success mmu_interval_read_retry() check while holding its update lock before consuming the pfns. If mmap_lock acquisition is interrupted or a fatal signal is pending during retry handling, -EINTR is returned instead. The common implementation conditionally sets FAULT_FLAG_ALLOW_RETRY and FAULT_FLAG_KILLABLE only for hmm_range_fault_unlocked_timeout(). The existing hmm_range_fault() path still passes no locked state, does not allow handle_mm_fault() to drop mmap_lock, and remains a thin wrapper preserving the existing API contract for current callers. The previous refactor that moved page fault handling out of the page-table walk callbacks is what makes this change small. Faults now run after walk_page_range() has unwound, with only mmap_lock held, so dropping it does not interact with the walker's pte spinlock or hugetlb_vma_lock. Hugetlb regions therefore participate in the unlocked path uniformly with PTE- and PMD-level mappings; no special case is required. Documentation/mm/hmm.rst is updated with a description of the new API and the recommended caller pattern. Signed-off-by: Stanislav Kinsburskii --- Documentation/mm/hmm.rst | 76 +++++++++++++++------ include/linux/hmm.h | 2 + mm/hmm.c | 165 ++++++++++++++++++++++++++++++++++++++----= ---- 3 files changed, 192 insertions(+), 51 deletions(-) diff --git a/Documentation/mm/hmm.rst b/Documentation/mm/hmm.rst index 7d61b7a8b65b..4e5a750748ae 100644 --- a/Documentation/mm/hmm.rst +++ b/Documentation/mm/hmm.rst @@ -156,42 +156,57 @@ During the ops->invalidate() callback the device driv= er must perform the update action to the range (mark range read only, or fully unmap, etc.). T= he device must complete the update before the driver callback returns. =20 -When the device driver wants to populate a range of virtual addresses, it = can -use:: +When the device driver wants to populate a range of virtual addresses, the +normal interface is:: =20 - int hmm_range_fault(struct hmm_range *range); + int hmm_range_fault_unlocked_timeout(struct hmm_range *range, + unsigned long timeout); =20 It will trigger a page fault on missing or read-only entries if write acce= ss is requested (see below). Page faults use the generic mm page fault code path= just -like a CPU page fault. The usage pattern is:: +like a CPU page fault. + +The caller must not hold ``mmap_read_lock`` before the call. +``hmm_range_fault_unlocked_timeout()`` takes the mmap read lock internally= and +allows ``handle_mm_fault()`` to drop it during fault handling. This is req= uired +for VMAs whose fault handlers may release the mmap lock, for example regio= ns +managed by ``userfaultfd``. + +If the mmap lock is dropped or the range is invalidated, the function refr= eshes +``range->notifier_seq`` and restarts the walk internally. ``-EINTR`` is re= turned +if mmap lock acquisition is interrupted or a fatal signal is pending during +retry handling. + +The timeout is specified in jiffies; passing ``0`` means retry indefinitel= y. The +timeout exists to preserve caller policy for repeated mmu-notifier invalid= ation +and is checked between retry attempts. HMM does not interrupt page fault +handling when the timeout expires, but returns ``-EBUSY`` if the retry bud= get is +exhausted before a stable range is obtained. + +The usage pattern is:: =20 int driver_populate_range(...) { struct hmm_range range; + unsigned long timeout; ... =20 + timeout =3D msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); range.notifier =3D &interval_sub; range.start =3D ...; range.end =3D ...; range.hmm_pfns =3D ...; =20 - if (!mmget_not_zero(interval_sub->notifier.mm)) + if (!mmget_not_zero(interval_sub.mm)) return -EFAULT; =20 again: - range.notifier_seq =3D mmu_interval_read_begin(&interval_sub); - mmap_read_lock(mm); - ret =3D hmm_range_fault(&range); - if (ret) { - mmap_read_unlock(mm); - if (ret =3D=3D -EBUSY) - goto again; - return ret; - } - mmap_read_unlock(mm); + ret =3D hmm_range_fault_unlocked_timeout(&range, timeout); + if (ret) + goto out_put; =20 take_lock(driver->update); - if (mmu_interval_read_retry(&ni, range.notifier_seq) { + if (mmu_interval_read_retry(&interval_sub, range.notifier_seq)) { release_lock(driver->update); goto again; } @@ -200,7 +215,11 @@ like a CPU page fault. The usage pattern is:: * under the update lock */ =20 release_lock(driver->update); - return 0; + ret =3D 0; + + out_put: + mmput(interval_sub.mm); + return ret; } =20 The driver->update lock is the same lock that the driver takes inside its @@ -208,6 +227,19 @@ invalidate() callback. That lock must be held before c= alling mmu_interval_read_retry() to avoid any race with a concurrent CPU page tab= le update. =20 +Holding the mmap lock across HMM faults +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Most callers should use ``hmm_range_fault_unlocked_timeout()``. If a driver +really needs to hold the mmap lock across work outside HMM, it can use:: + + int hmm_range_fault(struct hmm_range *range); + +The mmap lock must be held by the caller and will remain held on return. T= his +interface cannot support VMAs whose fault handlers need to drop the mmap l= ock. +New callers should prefer ``hmm_range_fault_unlocked_timeout()`` unless th= ey +have a specific requirement to keep the mmap lock held across the call. + Leverage default_flags and pfn_flags_mask =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 @@ -221,8 +253,8 @@ permission, it sets:: range->default_flags =3D HMM_PFN_REQ_FAULT; range->pfn_flags_mask =3D 0; =20 -and calls hmm_range_fault() as described above. This will fill fault all p= ages -in the range with at least read permission. +and calls the HMM range fault helper as described above. This will fault +all pages in the range with at least read permission. =20 Now let's say the driver wants to do the same except for one page in the r= ange for which it wants to have write permission. Now driver set:: @@ -236,9 +268,9 @@ address =3D=3D range->start + (index_of_write << PAGE_S= HIFT) it will fault with write permission i.e., if the CPU pte does not have write permission set t= hen HMM will call handle_mm_fault(). =20 -After hmm_range_fault completes the flag bits are set to the current state= of -the page tables, ie HMM_PFN_VALID | HMM_PFN_WRITE will be set if the page = is -writable. +After the HMM range fault helper completes the flag bits are set to the +current state of the page tables, ie HMM_PFN_VALID | HMM_PFN_WRITE will be +set if the page is writable. =20 =20 Represent and manage device memory from core kernel point of view diff --git a/include/linux/hmm.h b/include/linux/hmm.h index db75ffc949a7..6f04e3932f5b 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h @@ -123,6 +123,8 @@ struct hmm_range { * Please see Documentation/mm/hmm.rst for how to use the range API. */ int hmm_range_fault(struct hmm_range *range); +int hmm_range_fault_unlocked_timeout(struct hmm_range *range, + unsigned long timeout); =20 /* * HMM_RANGE_DEFAULT_TIMEOUT - default timeout (ms) when waiting for a ran= ge diff --git a/mm/hmm.c b/mm/hmm.c index bc9361a715fa..fc2e1cd0cb22 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -32,6 +32,7 @@ =20 struct hmm_vma_walk { struct hmm_range *range; + bool *locked; unsigned long last; unsigned long end; unsigned int required_fault; @@ -44,6 +45,14 @@ struct hmm_vma_walk { */ #define HMM_FAULT_PENDING -EAGAIN =20 +/* + * Internal sentinel returned by hmm_do_fault() when handle_mm_fault() + * completes a page fault with the mmap lock dropped. hmm_do_fault() sets + * *locked =3D false; the outer loop consumes the sentinel and never propa= gates + * it to the caller. + */ +#define HMM_FAULT_UNLOCKED -ENOLCK + enum { HMM_NEED_FAULT =3D 1 << 0, HMM_NEED_WRITE_FAULT =3D 1 << 1, @@ -73,9 +82,9 @@ static int hmm_pfns_fill(unsigned long addr, unsigned lon= g end, * * Called by the walk callbacks when they discover that part of the range * needs a page fault. The callback records what to fault and returns - * HMM_FAULT_PENDING; the outer loop in hmm_range_fault() drops back out of - * walk_page_range() and invokes handle_mm_fault() from a context where no - * page-table or hugetlb_vma_lock is held. + * HMM_FAULT_PENDING; the outer loop in hmm_range_fault_locked() drops + * back out of walk_page_range() and invokes handle_mm_fault() from a cont= ext + * where no page-table or hugetlb_vma_lock is held. */ static int hmm_record_fault(unsigned long addr, unsigned long end, unsigned int required_fault, @@ -624,7 +633,7 @@ static const struct mm_walk_ops hmm_walk_ops =3D { /* * hmm_do_fault - fault in a range recorded by a walk callback * - * Called from the outer loop in hmm_range_fault() after a callback + * Called from the outer loop in hmm_range_fault_locked() after a callback * returned HMM_FAULT_PENDING. At this point we hold only mmap_lock; * the page-table spinlock and any hugetlb_vma_lock acquired by the walk * framework have already been released by the unwind. @@ -641,6 +650,9 @@ static int hmm_do_fault(struct mm_struct *mm, unsigned int fault_flags =3D FAULT_FLAG_REMOTE; struct vm_area_struct *vma; =20 + if (hmm_vma_walk->locked) + fault_flags |=3D FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; + vma =3D vma_lookup(mm, addr); if (!vma) return -EFAULT; @@ -651,37 +663,34 @@ static int hmm_do_fault(struct mm_struct *mm, fault_flags |=3D FAULT_FLAG_WRITE; } =20 - for (; addr < end; addr +=3D PAGE_SIZE) - if (handle_mm_fault(vma, addr, fault_flags, NULL) & - VM_FAULT_ERROR) - return -EFAULT; + for (; addr < end; addr +=3D PAGE_SIZE) { + vm_fault_t ret; + + ret =3D handle_mm_fault(vma, addr, fault_flags, NULL); + + if (ret & (VM_FAULT_COMPLETED | VM_FAULT_RETRY)) { + *hmm_vma_walk->locked =3D false; + return HMM_FAULT_UNLOCKED; + } + + if (ret & VM_FAULT_ERROR) { + int err =3D vm_fault_to_errno(ret, 0); + + if (WARN_ON(!err)) + err =3D -EINVAL; + + return err; + } + } =20 return -EBUSY; } =20 -/** - * hmm_range_fault - try to fault some address in a virtual address range - * @range: argument structure - * - * Returns 0 on success or one of the following error codes: - * - * -EINVAL: Invalid arguments or mm or virtual address is in an invalid vma - * (e.g., device file vma). - * -ENOMEM: Out of memory. - * -EPERM: Invalid permission (e.g., asking for write and range is read - * only). - * -EBUSY: The range has been invalidated and the caller needs to wait for - * the invalidation to finish. - * -EFAULT: A page was requested to be valid and could not be made val= id - * ie it has no backing VMA or it is illegal to access - * - * This is similar to get_user_pages(), except that it can read the page t= ables - * without mutating them (ie causing faults). - */ -int hmm_range_fault(struct hmm_range *range) +static int hmm_range_fault_locked(struct hmm_range *range, bool *locked) { struct hmm_vma_walk hmm_vma_walk =3D { .range =3D range, + .locked =3D locked, .last =3D range->start, }; struct mm_struct *mm =3D range->notifier->mm; @@ -704,8 +713,14 @@ int hmm_range_fault(struct hmm_range *range) * returns -EBUSY so the loop re-walks and picks up the * now-present entries. */ - if (ret =3D=3D HMM_FAULT_PENDING) + if (ret =3D=3D HMM_FAULT_PENDING) { ret =3D hmm_do_fault(mm, &hmm_vma_walk); + if (ret =3D=3D HMM_FAULT_UNLOCKED) { + if (fatal_signal_pending(current)) + return -EINTR; + return -EBUSY; + } + } /* * When -EBUSY is returned the loop restarts with * hmm_vma_walk.last set to an address that has not been stored @@ -715,8 +730,100 @@ int hmm_range_fault(struct hmm_range *range) } while (ret =3D=3D -EBUSY); return ret; } + +/** + * hmm_range_fault - try to fault some address in a virtual address range + * @range: argument structure + * + * Returns 0 on success or one of the following error codes: + * + * -EINVAL: Invalid arguments or mm or virtual address is in an invalid vma + * (e.g., device file vma). + * -ENOMEM: Out of memory. + * -EPERM: Invalid permission (e.g., asking for write and range is read + * only). + * -EBUSY: The range has been invalidated and the caller needs to wait for + * the invalidation to finish. + * -EFAULT: A page was requested to be valid and could not be made val= id + * ie it has no backing VMA or it is illegal to access + * + * This is similar to get_user_pages(), except that it can read the page t= ables + * without mutating them (ie causing faults). + * + * The mmap lock must be held by the caller and will remain held on return. + * New users should prefer hmm_range_fault_unlocked_timeout() unless they + * specifically need to keep the mmap lock held across the call. This help= er + * cannot support VMAs whose fault handlers need to drop the mmap lock. + */ +int hmm_range_fault(struct hmm_range *range) +{ + return hmm_range_fault_locked(range, NULL); +} EXPORT_SYMBOL(hmm_range_fault); =20 +/** + * hmm_range_fault_unlocked_timeout - fault in a range with a retry timeout + * @range: argument structure + * @timeout: timeout in jiffies for internal -EBUSY retries, or 0 to retry + * indefinitely + * + * The caller must not hold the mmap lock. The function takes the mmap read + * lock internally and allows handle_mm_fault() to drop it during faults. = If + * the mmap lock is dropped or the range is invalidated, the function refr= eshes + * range->notifier_seq and restarts the walk internally. + * + * Passing 0 for @timeout retries indefinitely. A non-zero @timeout is a c= aller + * policy limit for repeated mmu-notifier invalidation retries. HMM does n= ot + * interrupt page fault handling when the timeout expires, but returns -EB= USY + * if the retry budget is exhausted before a stable range is obtained. + * + * Returns 0 on success or one of the error codes documented for + * hmm_range_fault(). -EINTR is returned if mmap_lock acquisition is + * interrupted or a fatal signal is pending during retry handling. + */ +int hmm_range_fault_unlocked_timeout(struct hmm_range *range, + unsigned long timeout) +{ + struct mm_struct *mm =3D range->notifier->mm; + unsigned long deadline =3D 0; + bool locked =3D false; + int ret; + + do { + if (fatal_signal_pending(current)) + return -EINTR; + + if (timeout) { + /* + * If the previous fault dropped mmap_lock, then the fault + * handler made progress. Restart the retry timeout in that + * case, but keep the existing deadline for ordinary -EBUSY + * retries. + */ + if (!locked) + deadline =3D jiffies + timeout; + + if (time_after(jiffies, deadline)) + return -EBUSY; + } + + range->notifier_seq =3D + mmu_interval_read_begin(range->notifier); + + ret =3D mmap_read_lock_killable(mm); + if (ret) + return ret; + + locked =3D true; + ret =3D hmm_range_fault_locked(range, &locked); + if (locked) + mmap_read_unlock(mm); + } while (ret =3D=3D -EBUSY); + + return ret; +} +EXPORT_SYMBOL(hmm_range_fault_unlocked_timeout); + /** * hmm_dma_map_alloc - Allocate HMM map structure * @dev: device to allocate structure for From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C8A33E2AB6 for ; Fri, 10 Jul 2026 21:26:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718809; cv=none; b=DoUOyu8pJmwkJPbSZqdO+jQCiLttJuGF1hTIX1q/xZbDmuYc38gxKAW74fHQRcuGOA+RNnadB0fMwT4II7Bt8CiTS/wAQenAm6kWhARbyIlgVPAZ/9er/nLPbHZYmVOGiEyEzmEFpV4fkmBAnZeilF7IlnmNk4CWL5iuBbC+cd0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718809; c=relaxed/simple; bh=a5vRcLyCKSKmKjk3x4G/kwnSbNGO0aDPFY7NNkdnxw0=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eT32RtTFlA1I+uF35aYWqb9eBEsUIjITfsys7TswdhPbADrb/bHhFBhbk8HhbnEIstKlL/vBAF3hYIJH3+wDcNWPn66NzA9mvKvNEnUx8slsZkRNXTgvr+7kg0Pw93tc2haj6894tzu2KjOL6R9ILdETiUAfDeFomqRajX6lH4s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=NzgkxNv2; arc=none smtp.client-ip=209.85.214.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NzgkxNv2" Received: by mail-pl1-f182.google.com with SMTP id d9443c01a7336-2cc73e322dbso14239075ad.1 for ; Fri, 10 Jul 2026 14:26:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718805; x=1784323605; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=RipBZIycyhdDriy0xY08qbrpkk/gJ3+/YM3pixpsFXk=; b=NzgkxNv24u2eGvKMLd4ZICD4UVYsf5GzlBveEUnE6rhfAb2RhJQbHHw+K7W7NQwPAS Lmga7rFMQkXa7oA+D9xEqjxal4HQFScw0TlaB8QyTL4OeQvWoJGu8vJSYpEtodd7WBnF JPFSg7BhYBBFJsdKZPgq/8V/NR+hdLJfGBf2XtdkHDo13evN1N+Zg7Lkp5ZPooqol664 79bUMym8cqW8jRhNBkhVDCv5jx4KD9r65c6Yqw/+ZqgWmB18tTLTx1BIN1fw2iqZ3XrP A0UYR7mdR3tia/VKSfmIeH8P2l8PKd16PCo4CyYjMCU4E/GUJjLqQRtdXAcEL1CORHiK JawQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718805; x=1784323605; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=RipBZIycyhdDriy0xY08qbrpkk/gJ3+/YM3pixpsFXk=; b=UXmFKJUH2e6ZGQ4AQZcPRpBx+AUlCBbqaM0HSdZ0g91wyQ1Cfim8filb1AjWgm7L21 L1Ww9Dvbhe8dfAHqODT2J9DXKIKW20ZdMZYa0bsQKLN4YeHJsfFR8ofC8Hyt5ahipeqS KTpdWimD8m5aQn4n/55DVVGoo2kz1I7Sbs1S+N8cHwn8J6fsNCpkGxdIVj+tyvPEynKW cOFtkHD79DstWOpTQ3idZ1R4a3DDezMGG6I2mGaajFW/GHmRljOpo35duFLemeM5n3c1 51OHqqHLm1UdU7xxx6SQa4A2+Uf7u6N/eLLCKQrMepvC0PAmz+AzHqFRBPqAxgaIHGG+ gQng== X-Forwarded-Encrypted: i=1; AHgh+Ro5j4IS3ht4GT8uVbRXM2SzItjN802W3cyDdX0cVkdvLRDXdjwsSQWSbex7guiztmzItgrk6b08bMAgKeI=@vger.kernel.org X-Gm-Message-State: AOJu0YwMn7iWSwnhSOHQx3TzDLo4bGwbjgjK3hPwyarfjVzWlQMEdY5+ SVbwwk2cpbJdY0z/K4ao3CeQsTgtBoeqJnO6gn89tz5ZsiRiw3Hy/KeI X-Gm-Gg: AfdE7clMNEHUomGVmGw6x35oZvLO2MVP1sKRZXjjofJHZ1WJFyBpXrPZiRH7xA2mH9u LmzC9K4LxII5WBdeimI6S8PvbO5tZ+yrYSaMY6lQeDywk8L1gBehNI8xLU+0IO60xm3cFEOJ0EX 5v4PKQpzY/FyT2x1kBeZTDDAWgWZj5XoDLtFuFb3us8V2RWnvfC3rZxhoTVuu2VmCO5tReuqEA1 vWnsQdiO0+3CUgNhXxUMuvFASYZil7vMkjA14tQBU903FYiEFQbenuVVmSpzNZRDcZdvW6rqq5Z 0iD9Zwklh3sfYqciE93kRIwGoasM1pXDZkneU1JCLRXXE9BMUJhXvc6+PbNayMUJtb6uBRT7szW LTSq506hmQhj1QSnbJ/UwHcxLlNf6fAVMeCsHBQau7DQHH1CAS/48fV9e0FHS0AqPB/Ed6Urq1b /5BxJ/uQZmHRoa66Q1Fuw3IN3LPKNVVZ4vqjHGzQo8Go/ZbQX0nklyRv7nfyU= X-Received: by 2002:a17:902:d483:b0:2c9:e261:95c4 with SMTP id d9443c01a7336-2ce9f01d298mr7642895ad.30.1783718805605; Fri, 10 Jul 2026 14:26:45 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ccc9bdb75fsm65281555ad.8.2026.07.10.14.26.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:26:45 -0700 (PDT) Subject: [PATCH v8 3/8] selftests/mm: add HMM test for mmap lock-dropping faults From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:26:42 -0700 Message-ID: <178371880218.900500.12093463712908415421.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add test_hmm coverage for the HMM lock-dropping fault path. The test module gets a new HMM_DMIRROR_READ_UNLOCKED ioctl that calls hmm_range_fault_unlocked_timeout() with a timeout of 0, exercising the unbounded retry mode while allowing the mmap lock to be dropped during fault handling. Add a userfaultfd_read selftest that registers an anonymous mapping with UFFDIO_REGISTER_MODE_MISSING, services the faults from a handler thread with UFFDIO_COPY, and verifies that HMM can read back the data supplied by the handler. This exercises the path where handle_mm_fault() drops mmap_lock and hmm_range_fault_unlocked_timeout() restarts the walk internally. Assisted-by: GitHub-Copilot:claude-opus-4.6 Signed-off-by: Stanislav Kinsburskii --- lib/test_hmm.c | 107 +++++++++++++++++++++++ lib/test_hmm_uapi.h | 1=20 tools/testing/selftests/mm/hmm-tests.c | 150 ++++++++++++++++++++++++++++= ++++ 3 files changed, 257 insertions(+), 1 deletion(-) diff --git a/lib/test_hmm.c b/lib/test_hmm.c index 45c0cb992218..6205fb313bd0 100644 --- a/lib/test_hmm.c +++ b/lib/test_hmm.c @@ -389,6 +389,67 @@ static int dmirror_range_fault(struct dmirror *dmirror, return ret; } =20 +static int dmirror_range_fault_unlocked(struct dmirror *dmirror, + struct hmm_range *range, + unsigned long timeout) +{ + int ret; + + while (true) { + ret =3D hmm_range_fault_unlocked_timeout(range, timeout); + if (ret) + goto out; + + mutex_lock(&dmirror->mutex); + if (mmu_interval_read_retry(range->notifier, + range->notifier_seq)) { + mutex_unlock(&dmirror->mutex); + continue; + } + break; + } + + ret =3D dmirror_do_fault(dmirror, range); + + mutex_unlock(&dmirror->mutex); +out: + return ret; +} + +static int dmirror_fault_unlocked(struct dmirror *dmirror, + unsigned long start, + unsigned long end, bool write, + unsigned long timeout) +{ + struct mm_struct *mm =3D dmirror->notifier.mm; + unsigned long addr; + unsigned long pfns[32]; + struct hmm_range range =3D { + .notifier =3D &dmirror->notifier, + .hmm_pfns =3D pfns, + .pfn_flags_mask =3D 0, + .default_flags =3D + HMM_PFN_REQ_FAULT | (write ? HMM_PFN_REQ_WRITE : 0), + .dev_private_owner =3D dmirror->mdevice, + }; + int ret =3D 0; + + if (!mmget_not_zero(mm)) + return -EFAULT; + + for (addr =3D start; addr < end; addr =3D range.end) { + range.start =3D addr; + range.end =3D min(addr + (ARRAY_SIZE(pfns) << PAGE_SHIFT), end); + + ret =3D dmirror_range_fault_unlocked(dmirror, &range, timeout); + if (ret) + break; + } + + mmput(mm); + return ret; +} + static int dmirror_fault(struct dmirror *dmirror, unsigned long start, unsigned long end, bool write) { @@ -488,6 +549,48 @@ static int dmirror_read(struct dmirror *dmirror, struc= t hmm_dmirror_cmd *cmd) return ret; } =20 +static int dmirror_read_unlocked(struct dmirror *dmirror, + struct hmm_dmirror_cmd *cmd, + unsigned long timeout) +{ + struct dmirror_bounce bounce; + unsigned long start, end; + unsigned long size =3D cmd->npages << PAGE_SHIFT; + int ret; + + start =3D cmd->addr; + end =3D start + size; + if (end < start) + return -EINVAL; + + ret =3D dmirror_bounce_init(&bounce, start, size); + if (ret) + return ret; + + while (1) { + mutex_lock(&dmirror->mutex); + ret =3D dmirror_do_read(dmirror, start, end, &bounce); + mutex_unlock(&dmirror->mutex); + if (ret !=3D -ENOENT) + break; + + start =3D cmd->addr + (bounce.cpages << PAGE_SHIFT); + ret =3D dmirror_fault_unlocked(dmirror, start, end, false, timeout); + if (ret) + break; + cmd->faults++; + } + + if (ret =3D=3D 0) { + if (copy_to_user(u64_to_user_ptr(cmd->ptr), bounce.ptr, + bounce.size)) + ret =3D -EFAULT; + } + cmd->cpages =3D bounce.cpages; + dmirror_bounce_fini(&bounce); + return ret; +} + static int dmirror_do_write(struct dmirror *dmirror, unsigned long start, unsigned long end, struct dmirror_bounce *bounce) { @@ -1572,7 +1675,9 @@ static long dmirror_fops_unlocked_ioctl(struct file *= filp, dmirror->flags =3D cmd.npages; ret =3D 0; break; - + case HMM_DMIRROR_READ_UNLOCKED: + ret =3D dmirror_read_unlocked(dmirror, &cmd, 0); + break; default: return -EINVAL; } diff --git a/lib/test_hmm_uapi.h b/lib/test_hmm_uapi.h index f94c6d457338..ea9b0ec404fb 100644 --- a/lib/test_hmm_uapi.h +++ b/lib/test_hmm_uapi.h @@ -38,6 +38,7 @@ struct hmm_dmirror_cmd { #define HMM_DMIRROR_CHECK_EXCLUSIVE _IOWR('H', 0x06, struct hmm_dmirror_cm= d) #define HMM_DMIRROR_RELEASE _IOWR('H', 0x07, struct hmm_dmirror_cmd) #define HMM_DMIRROR_FLAGS _IOWR('H', 0x08, struct hmm_dmirror_cmd) +#define HMM_DMIRROR_READ_UNLOCKED _IOWR('H', 0x09, struct hmm_dmirror_cmd) =20 #define HMM_DMIRROR_FLAG_FAIL_ALLOC (1ULL << 0) =20 diff --git a/tools/testing/selftests/mm/hmm-tests.c b/tools/testing/selftes= ts/mm/hmm-tests.c index 6fccbdab02ee..5acb728666f8 100644 --- a/tools/testing/selftests/mm/hmm-tests.c +++ b/tools/testing/selftests/mm/hmm-tests.c @@ -29,6 +29,10 @@ #include #include #include +#include +#include +#include +#include =20 /* * This is a private UAPI to the kernel test module so it isn't exported @@ -2952,4 +2956,150 @@ TEST_F_TIMEOUT(hmm, benchmark_thp_migration, 120) &thp_results, ®ular_results); } } +/* + * Test that HMM can fault in pages backed by userfaultfd using the + * hmm_range_fault_unlocked_timeout() path with no timeout. This exercises + * the lock-drop retry logic in the HMM framework. + */ +struct uffd_thread_args { + int uffd; + int stop_fd; + void *page_buffer; + unsigned long page_size; +}; + +static void *uffd_handler_thread(void *arg) +{ + struct uffd_thread_args *args =3D arg; + struct uffd_msg msg; + struct uffdio_copy copy; + struct pollfd pollfd[2]; + int ret; + + pollfd[0].fd =3D args->uffd; + pollfd[0].events =3D POLLIN; + pollfd[1].fd =3D args->stop_fd; + pollfd[1].events =3D POLLIN; + + while (1) { + ret =3D poll(pollfd, 2, -1); + if (ret <=3D 0) + break; + if (pollfd[1].revents) + break; + if (!(pollfd[0].revents & POLLIN)) + break; + + ret =3D read(args->uffd, &msg, sizeof(msg)); + if (ret !=3D sizeof(msg)) + break; + + if (msg.event !=3D UFFD_EVENT_PAGEFAULT) + break; + + /* Fill the page with a known pattern */ + memset(args->page_buffer, 0xAB, args->page_size); + + copy.dst =3D msg.arg.pagefault.address & ~(args->page_size - 1); + copy.src =3D (unsigned long)args->page_buffer; + copy.len =3D args->page_size; + copy.mode =3D 0; + copy.copy =3D 0; + + ret =3D ioctl(args->uffd, UFFDIO_COPY, ©); + if (ret < 0) + break; + } + + return NULL; +} + +TEST_F(hmm, userfaultfd_read) +{ + struct hmm_buffer *buffer; + struct uffd_thread_args uffd_args; + unsigned long npages; + unsigned long size; + unsigned long i; + unsigned char *ptr; + pthread_t thread; + int uffd; + int stop_fd; + int ret; + struct uffdio_api api; + struct uffdio_register reg; + uint64_t stop =3D 1; + ssize_t nwrite; + + npages =3D 4; + size =3D npages << self->page_shift; + + /* Create userfaultfd */ + uffd =3D syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); + if (uffd < 0) + SKIP(return, "userfaultfd not available"); + + api.api =3D UFFD_API; + api.features =3D 0; + ret =3D ioctl(uffd, UFFDIO_API, &api); + ASSERT_EQ(ret, 0); + + buffer =3D malloc(sizeof(*buffer)); + ASSERT_NE(buffer, NULL); + + buffer->fd =3D -1; + buffer->size =3D size; + buffer->mirror =3D malloc(size); + ASSERT_NE(buffer->mirror, NULL); + + /* Create anonymous mapping */ + buffer->ptr =3D mmap(NULL, size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + ASSERT_NE(buffer->ptr, MAP_FAILED); + + /* Register the region with userfaultfd */ + reg.range.start =3D (unsigned long)buffer->ptr; + reg.range.len =3D size; + reg.mode =3D UFFDIO_REGISTER_MODE_MISSING; + ret =3D ioctl(uffd, UFFDIO_REGISTER, ®); + ASSERT_EQ(ret, 0); + + /* Set up the handler thread */ + uffd_args.uffd =3D uffd; + stop_fd =3D eventfd(0, EFD_CLOEXEC); + ASSERT_GE(stop_fd, 0); + uffd_args.stop_fd =3D stop_fd; + uffd_args.page_buffer =3D malloc(self->page_size); + ASSERT_NE(uffd_args.page_buffer, NULL); + uffd_args.page_size =3D self->page_size; + + ret =3D pthread_create(&thread, NULL, uffd_handler_thread, &uffd_args); + ASSERT_EQ(ret, 0); + + /* + * Use the unlocked read path which allows the mmap lock to be + * dropped during the fault, enabling userfaultfd resolution. + */ + ret =3D hmm_dmirror_cmd(self->fd, HMM_DMIRROR_READ_UNLOCKED, + buffer, npages); + ASSERT_EQ(ret, 0); + ASSERT_EQ(buffer->cpages, npages); + + /* Verify the device read the data filled by the uffd handler */ + ptr =3D buffer->mirror; + for (i =3D 0; i < size; ++i) + ASSERT_EQ(ptr[i], (unsigned char)0xAB); + + nwrite =3D write(stop_fd, &stop, sizeof(stop)); + ASSERT_EQ(nwrite, sizeof(stop)); + pthread_join(thread, NULL); + close(stop_fd); + free(uffd_args.page_buffer); + close(uffd); + hmm_buffer_free(buffer); +} + + TEST_HARNESS_MAIN From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4E5143BADA9 for ; Fri, 10 Jul 2026 21:26:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718817; cv=none; b=dYDaGqy4KkCY/o7Zb1J/q1JTGw5yK5pqXZFFaWY1RXxkeLD3ikjb2Bk/WKaCOrpP09ZnrTb8F1PApVdlY0kiIAfmx3W3QdXSPKpqfYrihKkokcFx5/bMpp3SsYI8DWd+6wjzUacl5/9vcMKsIevwN3JYeKrfvs34ymffqPvGvCI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718817; c=relaxed/simple; bh=UH8EdkvxcBQr7tFP4cWIxItcXG4Yona++Xa1OoLjzWw=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Jh/jlKzo7GkWuZDOs/CtprDIYHEazmCpvRTDQ+LKkEriqw3xPsJZiv0wtXK3MJXpgDUzlRt4xfHUofz8zVuw0txMmpvOXyNJl0aMvbQ3BeCbSdtDpxDwFY7ZPKxKB0xWoPlP3Vpm2RihJUkResp2b5wYWO4/2Ww24NnW5YNniB8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PS+elB01; arc=none smtp.client-ip=209.85.214.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PS+elB01" Received: by mail-pl1-f182.google.com with SMTP id d9443c01a7336-2cae1a3a744so9483235ad.3 for ; Fri, 10 Jul 2026 14:26:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718814; x=1784323614; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=3sr6piRbjR+cpoS2FsjQdy3tGYWA8BG46QjFZOECUzI=; b=PS+elB011jwqaknWI3rbhruNlyMs7K66rAnCdNtjmlTTNBp+Av55fUFSi/OFOLpXuu 4hOprDlzJe+ADXayf9himYn0L49KlhKVLfvhOkKJjVFZghqGHPslBBwomaSYndjkm+33 IZjNe1ISOAOD4VuAwc5okbzUzGhQWKXNlJgTLhX8/FNoeu7VqHe18PpJrj0EIoNrWglo YhunuWdBiBzC0JrXTcou9vz6fyY36vbBDkjmHNJM8jju2inJbO6EBiofJdXJjfg+q6Sb rQPXjPGYCl5rJlsuwc2Lq4ilyNnC4vrCBaCU24kX1gWZdvjopWq5iIeXnC4zxGVPTYHO vSgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718814; x=1784323614; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=3sr6piRbjR+cpoS2FsjQdy3tGYWA8BG46QjFZOECUzI=; b=OzH0+yi9c5ebq/kGOMpavbo3o5wT0qdG8Pp4KjY0rz8mT7khEI5GQOUPCPRtr2P+bP qikHDbuQg7fG8jT0xoRbiC1SVE5N4fHh838fUrAteGl6zswDlYzcMMVXuJd+hMY5O5mQ lKwFuML72yWggODA6ZzwHJaof3yUUMlC7/duFs6udY6wOo2fF8QrSUIMLDzHQ41dZlpI cicXx94wbkwULX5xtyxdJDbB/xb/0nH2jzhlAaUZCz/HIKlYD9k74z/Z8Y9BJwINECZ0 jbdYajWntaUFfxQ7owBOqa7PTlHLuenQDIHGf8bkl0wtyrmx7inbnft+qwnmmZd/W2tY AgQA== X-Forwarded-Encrypted: i=1; AHgh+RqCnd/a1Ba3dDvv/d+XQkjzPu6CuX8dVWYo4RBmdj8Z8cxMMDPTAe4vsQbCjE3pEn0H59TGwbqdx/GMnzY=@vger.kernel.org X-Gm-Message-State: AOJu0YyiSjB824U6Pg5WJ/IEDnFvXrDkW/GN+Bk5lCBhKW6N3EvXx3YV qTymzsomI9UJ8oQMRn/o67NZz9GAG9kvGAOtQr4kMTPfn+6APAz//QN9 X-Gm-Gg: AfdE7cnpvrivCnABFdkpZmTzyrCSF5cVfO/I5qgu5gfXh1kz0S5UMxwSHvN9Efvxmcc bvMbDNhaqDHdzrvRUn0Q+ZGJ0UdyV3/cuiSTQM8JxBLqEjLrkhuOfT8ngMakOcT+RfepjdUCUM2 HdE7iAHfCdKRZvfHL/kC6tKpf+TpBibwZ2h/SOFScNv9jkLlmATa6/rhdwGTPViTw9um7p+gZQu ntKkNUIbNKNGqKj9bRd5cjFjYNotN/CupsQhTeqUP98cZER50yLAm7DIrmp5wKSI1NEsmoNhO/7 tBnlqHLeT8UY4+BPzbhY7fkhDUuhJX9lNo8gFsR3gdueUStLrn74FjVewVSylxsv/qN0iGaND2m qo9Gji0Xy4ndvHHdQkbiQBwXFBqQ7izAaAciGAFkGgxl12usUI7KlITQUj4dmxT9wQ8GI5bcatj 1emBtTMiOvdqj30N/WCeAP4ijdnU6R7BHJgd6RnNSJGwvNuwpyy2obvm9M9Cg= X-Received: by 2002:a17:902:dacf:b0:2c2:7baf:139f with SMTP id d9443c01a7336-2ce9ef1bd15mr7721375ad.30.1783718813633; Fri, 10 Jul 2026 14:26:53 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ccc9d1e0c4sm66015545ad.49.2026.07.10.14.26.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:26:53 -0700 (PDT) Subject: [PATCH v8 4/8] mshv: Use hmm_range_fault_unlocked_timeout() for region faults From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:26:50 -0700 Message-ID: <178371881034.900500.5214601525971121683.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MSHV currently faults movable memory regions by taking mmap_read_lock() around hmm_range_fault(). That prevents the fault path from handling VMAs whose fault handlers need to drop mmap_lock, such as userfaultfd-backed mappings. Use hmm_range_fault_unlocked_timeout() instead. Passing a timeout of 0 preserves MSHV's existing unbounded retry behavior while letting the HMM helper own mmap_lock acquisition and refresh range->notifier_seq internally before walking the range. After the fault succeeds, MSHV still takes mreg_mutex and checks mmu_interval_read_retry() before installing the pages into the region, so the existing invalidation synchronization is preserved. Fold the small fault-and-lock helper into mshv_region_range_fault(), since the remaining retry path is just the standard "fault, take the driver lock, check the interval notifier sequence" pattern. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Jason Gunthorpe --- drivers/hv/mshv_regions.c | 54 ++++++++---------------------------------= ---- 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c index 6d65e5b42152..dddaade31b5d 100644 --- a/drivers/hv/mshv_regions.c +++ b/drivers/hv/mshv_regions.c @@ -381,46 +381,6 @@ int mshv_region_get(struct mshv_mem_region *region) return kref_get_unless_zero(®ion->mreg_refcount); } =20 -/** - * mshv_region_hmm_fault_and_lock - Handle HMM faults and lock the memory = region - * @region: Pointer to the memory region structure - * @range: Pointer to the HMM range structure - * - * This function performs the following steps: - * 1. Reads the notifier sequence for the HMM range. - * 2. Acquires a read lock on the memory map. - * 3. Handles HMM faults for the specified range. - * 4. Releases the read lock on the memory map. - * 5. If successful, locks the memory region mutex. - * 6. Verifies if the notifier sequence has changed during the operation. - * If it has, releases the mutex and returns -EBUSY to match with - * hmm_range_fault() return code for repeating. - * - * Return: 0 on success, a negative error code otherwise. - */ -static int mshv_region_hmm_fault_and_lock(struct mshv_mem_region *region, - struct hmm_range *range) -{ - int ret; - - range->notifier_seq =3D mmu_interval_read_begin(range->notifier); - mmap_read_lock(region->mreg_mni.mm); - ret =3D hmm_range_fault(range); - mmap_read_unlock(region->mreg_mni.mm); - if (ret) - return ret; - - mutex_lock(®ion->mreg_mutex); - - if (mmu_interval_read_retry(range->notifier, range->notifier_seq)) { - mutex_unlock(®ion->mreg_mutex); - cond_resched(); - return -EBUSY; - } - - return 0; -} - /** * mshv_region_range_fault - Handle memory range faults for a given region. * @region: Pointer to the memory region structure. @@ -452,13 +412,19 @@ static int mshv_region_range_fault(struct mshv_mem_re= gion *region, range.start =3D region->start_uaddr + page_offset * HV_HYP_PAGE_SIZE; range.end =3D range.start + page_count * HV_HYP_PAGE_SIZE; =20 - do { - ret =3D mshv_region_hmm_fault_and_lock(region, &range); - } while (ret =3D=3D -EBUSY); - +again: + ret =3D hmm_range_fault_unlocked_timeout(&range, 0); if (ret) goto out; =20 + mutex_lock(®ion->mreg_mutex); + + if (mmu_interval_read_retry(range.notifier, range.notifier_seq)) { + mutex_unlock(®ion->mreg_mutex); + cond_resched(); + goto again; + } + for (i =3D 0; i < page_count; i++) region->mreg_pages[page_offset + i] =3D hmm_pfn_to_page(pfns[i]); From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pf1-f180.google.com (mail-pf1-f180.google.com [209.85.210.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83F823BFE25 for ; Fri, 10 Jul 2026 21:27:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718823; cv=none; b=C9N95TXVn1IBXoV1gfWh8lpklgLnWrjLn5K6fWC/dVTONSjqrCq+wNWyv43z7ZTMaNIyDAv3c1nyw/D17huKYYZ4L1tLVU1t8Mt9fbw7AC3EK1qPRNlViDooSBsQcZndqrZbvpSaa5oI/Pxa8kDM6HrXWj3BSzpudoV1s03gnAo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718823; c=relaxed/simple; bh=oLJSKeCx7nGCL58ICDoU/1+ilBudUYNfbCfVls0zVKM=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dDJiDGpmWVInA6dF9SSRW2T2J/kELW18HIWkyuhpFJUAdYOIVTu/z51ML4lGHibbNcbZ8MOhj3f4zxJk+ldGHVkGBPIjV04GtiPPnxYyHPFoSQejDvHZrugFQxzJQiBUL8v2W/dTVcheDN9TXUuLTrQVVRZU4PimBPOv1xpFF1E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ba7UuVa+; arc=none smtp.client-ip=209.85.210.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ba7UuVa+" Received: by mail-pf1-f180.google.com with SMTP id d2e1a72fcca58-84874b52eabso1601888b3a.0 for ; Fri, 10 Jul 2026 14:27:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718821; x=1784323621; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=i81Mvoxwiz31acM23+HpM6LiopJwdOVnXlQ0p0m7OMc=; b=ba7UuVa+shzeXiuPbfIfB9GNaimyLY+aaJQs1V/AfART1SAYnwC05hG3fJSB4zEAY5 Mp6DpLSz6dcfovvJCW02nGUWjWMqMfKR8WZCdLGpdVCZmrFzDtxEEV/IrLQubfWCHXLM GbWkTPuSqIcNXWWcUCP35u9sUBZD+BfSEBpx84eUuJS0txs3mw+Yar4YvIQOf0I+8D68 GVkWroYoz7DqW7ETsBUHS6PEtmLBHHhp2o4YujhYBDKDV+PCp9hVutWg9A6alTITfMcX jhM28s7vJCz4Ll1UUG/0IHb/iVNyczMejjsKintfCJXKf4CCt71Ba1i+Vlxkr/nAxLRl CEbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718821; x=1784323621; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=i81Mvoxwiz31acM23+HpM6LiopJwdOVnXlQ0p0m7OMc=; b=AzIkx9HQKCDrJIzeKULO2lXr8/AXSKERYdyxsVL+bZJFrL2DisIWKf0zStmupdXIEP wMWC7jy2PmbLDHxYsF5evJD8WlEU48j5GIHKrLTR8k4kcoqxnsydnDguoyQ3dQ1+FA8B yxShDtoe8GD79ItfnWTPTIP5y2SXi2epMgstJ0nwagqY7CMokO0Dxxr7OyMEsTVqGwJ8 y6a4pdg1GwRRUOyTzokalABPuvOvsYlnblRB9zDGlMAovhPqbWo3oGIDNUKb2bu/1510 ZmXk5Ikc3gjZ6nNkA8P65CslBbIhnsmlvqSQmOxB4dOSLbojqy/BPSjg/ll029IX9O5P ceWg== X-Forwarded-Encrypted: i=1; AHgh+RrXFKJt7QgyJGfnLhykY8OM55DdLB7MeGXnmmjfUepo6SoxiuSJKJpN8eODpUVBfgoU5SUj9EsQWKrehqA=@vger.kernel.org X-Gm-Message-State: AOJu0YzFDB8w9fTX+p92XHOMXu3mjSwO1tPV9yEvJ3wLyc47T58w1TuJ UAWe7mEl36T6y5xa37Rm2QylMq3+5SboOtp8QRoREoua1dm2k0u//uie X-Gm-Gg: AfdE7cn2+Xu5AAEMDpOAo/9RMi3BrHcj+1nM1aS15AtKYNwTen0k45c0DBzpWMR7Mi1 5zGuku8nZm7pFru/5bFWJykr5eF4M0Vjo0u8DQ/gVKyUyiYz5mUlIlXFYDOnWurTrQsM+ISffzK hEKTUhDJ3xnODTonOrq5W2Ej1b1BwgEUNzNpYGZvhJJZY+28v0Bttb0y/OfrfJoCGT6yBkS5Yfw SyVeChAasbsNkmmxeh+Fe2nehUSTKQvIqYBavMHQI8UVSEDeKkebWwwLptb/0wws1u5k3UFobuy sKFFs4soH7rLWf2IZA1y56YuPhSDPV+iV4cD8tyJMV8xmeO+jAxhhP4JpzsXEsByVE6YwCbXJl7 w6COe97PyNa3wmvN/ABWRuUQ1udXkzLKmrHGIYTfL7UTfbhthbCBpUH6nFmHxbdvqGZg+r9InQ5 HiUQn3tCKVzGIapzbrlbXrarOMpioRQvzY+X7umYHqn3WzjThrgNmltiGiuQlIXlo8Gh33RA== X-Received: by 2002:a05:6a00:a0e:b0:847:7f38:27ad with SMTP id d2e1a72fcca58-8488975299emr661948b3a.53.1783718820769; Fri, 10 Jul 2026 14:27:00 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8482b333d4fsm6649821b3a.54.2026.07.10.14.26.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:27:00 -0700 (PDT) Subject: [PATCH v8 5/8] drm/nouveau: Use hmm_range_fault_unlocked_timeout() for SVM faults From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:26:58 -0700 Message-ID: <178371881847.900500.8789369230260725500.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable nouveau_range_fault() takes mmap_read_lock() only to call hmm_range_fault(). It also keeps a single HMM_RANGE_DEFAULT_TIMEOUT deadline across both HMM -EBUSY retries and post-fault mmu_interval_read_retry() retries. Use hmm_range_fault_unlocked_timeout() instead. The HMM helper now owns the mmap lock and refreshes range->notifier_seq for its internal retries. Nouveau keeps its existing absolute deadline in the outer loop and passes the remaining jiffies to the helper for each fault attempt, so retries caused by mmu_interval_read_retry() do not reset the overall retry budget. Nouveau still validates the interval notifier sequence while holding svmm->mutex before programming the GPU mapping. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Jason Gunthorpe --- drivers/gpu/drm/nouveau/nouveau_svm.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouvea= u/nouveau_svm.c index dcc92131488e..4cfb6eb7c771 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -683,15 +683,11 @@ static int nouveau_range_fault(struct nouveau_svmm *s= vmm, goto out; } =20 - range.notifier_seq =3D mmu_interval_read_begin(range.notifier); - mmap_read_lock(mm); - ret =3D hmm_range_fault(&range); - mmap_read_unlock(mm); - if (ret) { - if (ret =3D=3D -EBUSY) - continue; + ret =3D hmm_range_fault_unlocked_timeout(&range, + max(timeout - jiffies, + 1L)); + if (ret) goto out; - } =20 mutex_lock(&svmm->mutex); if (mmu_interval_read_retry(range.notifier, From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D43983C10B7 for ; Fri, 10 Jul 2026 21:27:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718831; cv=none; b=forFzSxg8orlDYA/utNmRV227s9yVoxdS6te3AAgX9O6H5KrS4GYJzyvLEyCXNBs2hECNHXbYE94jLOCu+1diPYKXqDEKdaPZM1sBgARvh+y3YTmtbApznnIzTnUf7eqZ20YgmTNH53S8Nbi4wCg7YHnt/mnutnE4qJRgbWbH6o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718831; c=relaxed/simple; bh=yo2fuaOVnmkl0q7h8FrQEKV1A9VgItwbSFDMrCikuws=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MCCFPcIp1FulDCkVHOdQNgH2GacFeTKHF047PraMqEISFSmjAQ0KTp5ORNblgktjA6HE/Hblosio1xorxUcNKLL91jzJCWDm85Xw8cEt63yBNJFrUCSUssdFmPkF1Z7KXjQwWNJBGfmERoS5RGE87XhDoK0+8kYth64GlLwPAYU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=jV9auuzD; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jV9auuzD" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2cc6dd436c6so15163515ad.2 for ; Fri, 10 Jul 2026 14:27:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718828; x=1784323628; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=rz6324+iAv2KNy97kcq58R5fN0X8s7ommcJ7e4qhr4M=; b=jV9auuzDZvDj6VMojq7BIoqTG51cW0CjJxBYhNbsuPpcz2Ct8Eu8lMGcH6kfxw144V yITXCfFyOtrQMkmFOG06jUY4YyptbhnwHE813n2NLHHkiTxUIvTsDk4JgPcWRlCwqnOG UEnSMycGR+PrpW+DtQG7/RAuLyDUbhD0JNV/oE3ujkfjTKYz3lobUU1NHDI5qf6/tsgk UCEJljPHpCE6wO2Tbcg7QlZFYjgeiSAVjRXsj1Xn8RVniVaP1unc7qp5WJ0Khys/jTjl +6x+uXb9E/v6g8vcbPpsV9BhFKGoCCP1bz2XMCxWBzfOws0sCCDMQgMkc81wMf7q5+JJ 91EA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718828; x=1784323628; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=rz6324+iAv2KNy97kcq58R5fN0X8s7ommcJ7e4qhr4M=; b=JGL7LWnRK+sO3AeZa3EBr8uxJ4QijXCS6ghA69bp4Ci9j8mBMpI2z6DOeW7WAvTHzb EPcXQ7lm12ieHzh07rCjei7GCC+gSdJGUw1rp/gWf0B+K9JhXZABAFfsAIkxssurcYDj 4VMOHDOFos/Og04vDyiD9sCr5RxdkLYDY6uK8BuaUpNdkFyVSv5AI+Kmj+l4UX28od/1 CMzaT5KG/2Tbilgkw2mupFDTcstDYB2amTCZvAVdE79tbQwNAg+F/jXu8qcOg87ldfxg gJFMmLtE8IDHra78wiyhewjg5RnHm8217HRSAb8fxHJlqN5a7I3ng4FkQMjcACx/ifWd B7dA== X-Forwarded-Encrypted: i=1; AHgh+RpmjYtIgmdgCD+XKPMESHvs2pBNPYKG1aV1GPNev60vvYHQamnDoWqtWlH6xWUJ4+diiXcpU6/OT24DtpA=@vger.kernel.org X-Gm-Message-State: AOJu0Yw8zXH4IuCCwRdo9CSx6RWfCpWwU47cVXY0NfM/ULAdz0ofUOw+ Y1qOO4mXWEBirLAY0SITElueKJfOZ2GdL8TGLZpF4sx21zWbZ8p4XiVG X-Gm-Gg: AfdE7cmrxGSbmoXFHBfX2SeRL4sEokP3rC6JKwVdBZSsa9ygdUlGfkYRkG8ktkg7mi+ n3zKBfoKtUYeplsxMelQkdJsJm2U5HEU1/BSKEPQVkEAbe+zmRy6PAP2TTZlw3DOc2CLFDwqXdH UHKthdRbQEBNmG8jr3AdWCx+TG3PrUPLQxNIlFAtTO5YW8NwbwWu4a9zO8z02/km/0U9IXyq3tO EHz2EoRd2bQZaYk5qBiv0k8u0qSxtyaum6A9B9F7+i1pHo6PMsCbOsWmFAmj3FmW3ksMAo52/eA hQeFSO6K4fqz+NZ0RdyD1WkFOmItnBthvA1D723vuWtVSBKAggQ6p48PX1wFnbKgXG9toUK7Wxg sTFFGQsgauC6I1EICY8OGr3EdVek41Tjp8pStbIwPWNzPYAgjQO4wPQN/owc1ZPWTmkO6b3vuZ1 kmLoOKXMdTjh7xVahItJ2Zegz1I+dkwXrNddAQf2SVIlngtdd/wVdNtPTlclSlfesN5DEBRw== X-Received: by 2002:a17:902:d98b:b0:2ca:1bbe:c3d0 with SMTP id d9443c01a7336-2ce9f3d5e4amr6769265ad.43.1783718827906; Fri, 10 Jul 2026 14:27:07 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ccc9d3bd33sm65951165ad.58.2026.07.10.14.27.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:27:07 -0700 (PDT) Subject: [PATCH v8 6/8] RDMA/umem: Use hmm_range_fault_unlocked_timeout() for ODP faults From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:27:05 -0700 Message-ID: <178371882559.900500.4008217424194230517.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable ib_umem_odp_map_dma_and_lock() takes mmap_read_lock() only around hmm_range_fault(), then retries -EBUSY until HMM_RANGE_DEFAULT_TIMEOUT expires. Use hmm_range_fault_unlocked_timeout() instead. The HMM helper now owns the mmap lock and refreshes range->notifier_seq for its internal retries. ODP keeps using HMM_RANGE_DEFAULT_TIMEOUT for each HMM fault attempt, while interval invalidation retries continue to be handled by the existing outer loop. ODP still validates the interval notifier sequence while holding umem_mutex before DMA mapping pages. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Jason Gunthorpe --- drivers/infiniband/core/umem_odp.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/u= mem_odp.c index 404fa1cc3254..9cc21cd762d9 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -329,7 +329,7 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *um= em_odp, u64 user_virt, struct mm_struct *owning_mm =3D umem_odp->umem.owning_mm; int pfn_index, dma_index, ret =3D 0, start_idx; unsigned int page_shift, hmm_order, pfn_start_idx; - unsigned long num_pfns, current_seq; + unsigned long num_pfns; struct hmm_range range =3D {}; unsigned long timeout; =20 @@ -363,26 +363,18 @@ int ib_umem_odp_map_dma_and_lock(struct ib_umem_odp *= umem_odp, u64 user_virt, } =20 range.hmm_pfns =3D &(umem_odp->map.pfn_list[pfn_start_idx]); - timeout =3D jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + timeout =3D msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); =20 retry: - current_seq =3D range.notifier_seq =3D - mmu_interval_read_begin(&umem_odp->notifier); - - mmap_read_lock(owning_mm); - ret =3D hmm_range_fault(&range); - mmap_read_unlock(owning_mm); - if (unlikely(ret)) { - if (ret =3D=3D -EBUSY && !time_after(jiffies, timeout)) - goto retry; + ret =3D hmm_range_fault_unlocked_timeout(&range, timeout); + if (unlikely(ret)) goto out_put_mm; - } =20 start_idx =3D (range.start - ib_umem_start(umem_odp)) >> page_shift; dma_index =3D start_idx; =20 mutex_lock(&umem_odp->umem_mutex); - if (mmu_interval_read_retry(&umem_odp->notifier, current_seq)) { + if (mmu_interval_read_retry(&umem_odp->notifier, range.notifier_seq)) { mutex_unlock(&umem_odp->umem_mutex); goto retry; } From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pf1-f179.google.com (mail-pf1-f179.google.com [209.85.210.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C915C3C4551 for ; Fri, 10 Jul 2026 21:27:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718837; cv=none; b=BO55XwBNeq+hOcJgmZaQwZNJgGe8FYgmlvVyA3BCVTsSfX0xtaicvFO1QZ7Kzh9bBmX/tq41TWU69tuJ0v914e42imdV+nyv44oM13+htClTy6phDsukrlHrDqHDzS8Mr6DOZZYT0WDITTxqSrU4rzaalbp8Y6ais6U/Mxp85xw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718837; c=relaxed/simple; bh=frLTEoZS2wGW/Ath+1xF9AQS7YavZ223qWxxIXaQCHM=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JIADfcik6PJGtdbntyQK5NmTmGndtzP9xSGNmnW3r5pqY4vVSN4CTbB4oURVDn8c8NzbnRhIb8BQZA3dmx59nF9qRQ7eyrfVanSR6+jIXDsJzrWlGsFsda801fd7L1q6HuGn2Ez3v5jsXbzEcG1hP2/i1EoU4kt4INEz9OG+xU0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=W/VZYUF/; arc=none smtp.client-ip=209.85.210.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="W/VZYUF/" Received: by mail-pf1-f179.google.com with SMTP id d2e1a72fcca58-84864086bfeso1383450b3a.1 for ; Fri, 10 Jul 2026 14:27:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718835; x=1784323635; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=SsZ1Rl/n/xZapvBLsULQnfYoRJnC5F850v9mJm5328I=; b=W/VZYUF/7h9WMWshohRHlXGNZolufAM16SPlqA7yzSN+qryXDBTHduVRfgW7xo8e11 c0zi3VKDuH6vf9y7+YqUszJKLOvq4DTa5wJ4LNAxi0J+yqEb3MFK0I10Fwk3BTEYvSoW Iyzj7eAXEP4xHbjWawOTmXFDDDyYkF98W+d0h66+QLYr1f0j5wfc8es1nHxGa8nXIMlC k1YlXzuDHFYKhOwN9KUyCiulItSLbyErCNcYUn81aWbFsDaoXmZHVrWnDfx5adiZujQH 2f7EZzIofWVLNS5rzmbWSMVGelsd4WYhX8BKw3vhS1UPMiQewcOuSgDO8M9a0hWuM9I7 B+IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718835; x=1784323635; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=SsZ1Rl/n/xZapvBLsULQnfYoRJnC5F850v9mJm5328I=; b=eZAL7DtbGds3V3xZ3ZY2SmAx2C9Ku907GDnpK2RIb8a99J/i3IyTqZFO2Zi/enOZtI 9thlEgpNrtI+rAp+j1Bj0WCeG9LSfHH7AQlX171/xTTR7/VcI1kvPUnc/+iVzZSxe80m iL4h0CAc739m6/YOyoql33oTSxIZbjZrP7FXb5FAJ3uz0Exc+1nbUsUQp/74g2gtnjus HGLKeUkVxZa070n9XegLdU7maMbk0PCjBQcQlpScLZe2O3RxjsflEpwNRR6yL8oRJQ+B jIH3iIBDJ3gcpirn6nGGPzxRMu7DnyTv8nTKllCMZTPtfpU4LpO7pAWiqHkPC1AXOVRN DoGQ== X-Forwarded-Encrypted: i=1; AHgh+Rr143ViXbnHaFneQTuYdVn/Pcscb+6++1cWBXByqB+DK6yTdWID6HdhpsxOkbZKjYiqvUXbIYrKJ/dZlHk=@vger.kernel.org X-Gm-Message-State: AOJu0YzQX7+d35RxZTjMV8W7xesBrg3AgvunP4lpYWYL+rUQvkgpRQyH JKPmKdLZ12PJ2uc69PEGbTjodaOpQtwaboXTk03WJv+92+H9epCIlLBF X-Gm-Gg: AfdE7cm2iBc4petrfmpJzaGaKw+bVGeaCFbPAQ+cgDPuwYReZRJfZ6sM1NlTjKllP0k TUL8MlhKwMy/7pgDPq3DhA66dX0T3DauWA3v8r3Evab4xRuZ0qGkEA4g6wYE7wCmUPEVYBkqnAN viGCJoD0xBxttCMk3qzoQ8qIwj4oldbtig52DNlTkFFjVKuJLSh3ZQx034Hd2JPRmcIXzFT8wBS wj/bR9DJ/2ZmXcel07A9VhbloYbmaiHf9Iozz2lX1U2j6nla2YdD0r9pqTtnpZOIh9Tt3RXOzSn jh0cABlCV3qyf9wS1xE4cn5e3wCaEsV8rTZI9ZaXh/KgM5KfT+KhGO/RR/eCn64E04C5rkZ4blf 76uuz3XA9bDDouvtgQ+VwVqlWn3Z8kbMYYRaQnQsUm0GqCP2BWhYaTAAZS7IsVpoNSenkyF9c+b jh7Ey7HEqcSjajxcCGn/UsR+5iT74al/2RSGE8BECmllfuzBHirfqhvQ1ZchGleS9+SzQpXg== X-Received: by 2002:a05:6a00:3397:b0:848:2f84:737 with SMTP id d2e1a72fcca58-8488990b261mr583131b3a.74.1783718835015; Fri, 10 Jul 2026 14:27:15 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84870d76ce7sm1801076b3a.55.2026.07.10.14.27.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:27:14 -0700 (PDT) Subject: [PATCH v8 7/8] accel/amdxdna: Use hmm_range_fault_unlocked_timeout() for range population From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:27:12 -0700 Message-ID: <178371883276.900500.12789147320642521200.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable aie2_populate_range() takes mmap_read_lock() only around hmm_range_fault(). It keeps a single HMM_RANGE_DEFAULT_TIMEOUT deadline for the populate pass and retries -EBUSY until that deadline expires. Use hmm_range_fault_unlocked_timeout() instead. The HMM helper now owns the mmap lock and refreshes mapp->range.notifier_seq for its internal retries. Pass the remaining jiffies from the existing deadline to HMM, while preserving the driver's existing outer loop for interval invalidation retries and for selecting the next invalid mapping. Keep returning -ETIME when the retry budget expires, matching the driver's existing timeout error convention. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Jason Gunthorpe --- drivers/accel/amdxdna/aie2_ctx.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_= ctx.c index 54486960cbf5..a16b8d7deaea 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -1061,22 +1061,11 @@ static int aie2_populate_range(struct amdxdna_gem_o= bj *abo) return -EFAULT; } =20 - mapp->range.notifier_seq =3D mmu_interval_read_begin(&mapp->notifier); - mmap_read_lock(mm); - ret =3D hmm_range_fault(&mapp->range); - mmap_read_unlock(mm); + ret =3D hmm_range_fault_unlocked_timeout(&mapp->range, + max_t(long, timeout - jiffies, 1)); if (ret) { - if (time_after(jiffies, timeout)) { + if (ret =3D=3D -EBUSY) ret =3D -ETIME; - goto put_mm; - } - - if (ret =3D=3D -EBUSY) { - amdxdna_umap_put(mapp); - mmput(mm); - goto again; - } - goto put_mm; } From nobody Sun Jul 26 00:20:45 2026 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DDD2B3C8C7F for ; Fri, 10 Jul 2026 21:27:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718845; cv=none; b=a9HrIX142B5J82WX5BWo/X2ckdDA27C1toIy4AFB2tkmD8RZ5hLh0EiGdVnFsumu6/t6Ee/EzZLcjI+Nrz45oUdiZWH52bR5DA0Y9UHFzCuUCoY911IaeOxUJSoCIGnzGiLolN4OwDwqqCsm8AnwmZPvC5EsfvuKuTWqTh7+i4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783718845; c=relaxed/simple; bh=pYhysMeIzYMEv8sb/P2wTG7Vkw/cqtE9UPpQ0ZrJ3m0=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HVjhb+OJDvLzpnHLJPJ5V+RKS6Tw9I11bznRwo1sTQrkKB61QgJr5EhEsjoOVDAsDKQ5FjvHtD/y5bsM6mmr+xQ8uimGdUOPG2ciIpSLYUmcKHe7TCTq7XRdaio+zkQklySwnLsw99xQuNvl4XXTSey0U1aa05Jeozsl0sj/9l4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WpD8hxSt; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WpD8hxSt" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2c7c61b5292so23797295ad.0 for ; Fri, 10 Jul 2026 14:27:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783718843; x=1784323643; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:from:to :cc:subject:date:message-id:reply-to:content-type; bh=9/L8xh2nQ4nR7e9MheG1BnxPJ3sCm51YBcPVud12DY4=; b=WpD8hxStX/pXg0XO4lzmZrLqJGkR2hDSTtTjUomEveeRWZ3613rmaB+mI7Q46hQfc0 9V0tKRSgPubGvz94bZDl3sFc44HJXusdlgQ5786YS6x9FMHXhkPjXigyXGcfvZ4viink +dTxbfqKytycr68xHcVeEyY6quXq2djHpv0C3JKlyCp0enzB3m2RIiNmrrohw3pzJSMe UUZMkE6ZAPQj/vXeKGtD/zEVoS1m1Qh9D2Z9h88lXyJSrXvxNVZb3gpX3n1eilRPZYPH Na7LnwMqDT+o+ehXkIoRSp264EseD9ke2+v78wfFRc6UQmFvTrRRksaw3r1Hz7/DMFrG oX0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783718843; x=1784323643; h=content-transfer-encoding:content-type:mime-version:user-agent :references:in-reply-to:message-id:date:cc:to:from:subject:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=9/L8xh2nQ4nR7e9MheG1BnxPJ3sCm51YBcPVud12DY4=; b=fO9/2g1YzgtNaVT3eIhq553vWoNw6M0RusVlxMEW1Y4f/BmncTI7L2aPFxT64DWGRc eIlNdAeD5PQZu/ZjFR3y+xnavbiTw5KXVElZxoPITVUKRtD3Ci/KfJy7If89Aq7rlk8T FCUSIVHImt7ZSeyRzrluoN8tjPgfkw6UnnX723uTpR/Avap5taGydScOTYFe7P9DnmbI t/NhhNWVoYGE2c8e7IstcZ0CzOOvP6iIjdUE7RQeUWyPd9zaZza8sbBj+XE1vcFeBsdf QRNuOBVnJs9iMiteWAXucWCPqFrmV4JVnFYrYUAnmyDtBSyVYMKclAnEHg3NOOuDDrsd Q/jA== X-Forwarded-Encrypted: i=1; AHgh+RoHg5PXnB2zg/BAOAz7HOBMKtyf1T8+fgVZULieyIQ/VpLYuAClMB9rb18CoecrgBFtQcQjo/o/ZvwBQOA=@vger.kernel.org X-Gm-Message-State: AOJu0YzZqMDyYG8rx8yBAHqare1roP5rUKi+Lm8jRE1QxytLkXT0Z8sm 109PlVCIbNG0cLyM0Ab5M0emIK0ZgNwNZSGjtlyCixxfZxCRBLHMahIo X-Gm-Gg: AfdE7clukFwFb/07L9d0JmvJljIy3/sDKydm1Hu2DL3610LswkMfg9UWY82vus4U77s JBOSItIYaOuhzt66SgUiY55ungLv25nPrPhJEPFu1n1AuUisk9PwLDI1NHSd+RrsX9q9ypJ1AbT sgGXiOizSmNmCOAO958RfbLoCMDuRPZTzLTLE6yhulqeGQ/WA1WgzNVP2/7bHjbehw7Gry8tm/E DscaZxx5iAYVAgkuPuA0wV/KtS7/sikxHcu9LGWl9Tng7P7atlpjTlvNfKn7///Yf3LGd/IOBu5 5yef2wAszILBXPJA/705ge/SRbLpIlHX7saFGo2MreMf/0XpWKR42dbvQEzrPmut9PZpyHU5z5Y mUnlJYsRE5TbRXrg9dR3tqrXAiJe0eSPzGhYFNmCBFpRL5exMevHc4T0nxGQGdW9ZYK99PByCTQ cV1LDlfoftc90CqWXjaS/5ZwyTnhKZdW/0zOT1noSgnOQyEI6qYo2KkKTb5j8= X-Received: by 2002:a17:903:2b0d:b0:2ca:11af:5ee9 with SMTP id d9443c01a7336-2ce9ec0f0b4mr7098515ad.25.1783718843116; Fri, 10 Jul 2026 14:27:23 -0700 (PDT) Received: from [192.168.0.160] (c-98-225-44-182.hsd1.wa.comcast.net. [98.225.44.182]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ccc9bf77e4sm65443035ad.22.2026.07.10.14.27.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2026 14:27:22 -0700 (PDT) Subject: [PATCH v8 8/8] drm/gpusvm: Use hmm_range_fault_unlocked_timeout() for range faults From: Stanislav Kinsburskii To: airlied@gmail.com, akhilesh@ee.iitb.ac.in, akpm@linux-foundation.org, corbet@lwn.net, dakr@kernel.org, david@kernel.org, decui@microsoft.com, haiyangz@microsoft.com, jgg@ziepe.ca, kees@kernel.org, kys@microsoft.com, leon@kernel.org, liam@infradead.org, lizhi.hou@amd.com, ljs@kernel.org, longli@microsoft.com, lyude@redhat.com, maarten.lankhorst@linux.intel.com, mamin506@gmail.com, mhocko@suse.com, mripard@kernel.org, nouveau@lists.freedesktop.org, ogabbay@kernel.org, oleg@redhat.com, rppt@kernel.org, shuah@kernel.org, simona@ffwll.ch, skhan@linuxfoundation.org, skinsburskii@gmail.com, surenb@google.com, tzimmermann@suse.de, vbabka@kernel.org, wei.liu@kernel.org, skinsburskii@gmail.com Cc: dri-devel@lists.freedesktop.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Date: Fri, 10 Jul 2026 14:27:19 -0700 Message-ID: <178371883977.900500.2198446134676328631.stgit@skinsburskii> In-Reply-To: <178371866223.900500.12312667138651735591.stgit@skinsburskii> References: <178371866223.900500.12312667138651735591.stgit@skinsburskii> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Several GPU SVM paths take mmap_read_lock() only to call hmm_range_fault(), then retry -EBUSY until HMM_RANGE_DEFAULT_TIMEOUT expires. Those paths use MMU interval notifiers whose mm matches the mm that was locked for the HMM fault. Use hmm_range_fault_unlocked_timeout() for those faults and pass the remaining retry budget to HMM. The helper owns mmap_lock acquisition and refreshes range->notifier_seq internally for each retry, while GPU SVM keeps its existing driver-lock validation with mmu_interval_read_retry() after a successful fault. Leave drm_gpusvm_check_pages() on hmm_range_fault() because that path is called with the mmap lock already held by its caller. Signed-off-by: Stanislav Kinsburskii Reviewed-by: Jason Gunthorpe --- drivers/gpu/drm/drm_gpusvm.c | 52 ++++++--------------------------------= ---- 1 file changed, 7 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 958cb605aedd..6b7a6eaebcd9 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -788,22 +788,8 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct = drm_gpusvm_range *range, hmm_range.hmm_pfns =3D pfns; =20 retry: - hmm_range.notifier_seq =3D mmu_interval_read_begin(notifier); - mmap_read_lock(range->gpusvm->mm); - - while (true) { - err =3D hmm_range_fault(&hmm_range); - if (err =3D=3D -EBUSY) { - if (time_after(jiffies, timeout)) - break; - - hmm_range.notifier_seq =3D - mmu_interval_read_begin(notifier); - continue; - } - break; - } - mmap_read_unlock(range->gpusvm->mm); + err =3D hmm_range_fault_unlocked_timeout(&hmm_range, + max(timeout - jiffies, 1L)); if (err) goto err_free; =20 @@ -1439,21 +1425,8 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, } =20 hmm_range.hmm_pfns =3D pfns; - while (true) { - mmap_read_lock(mm); - err =3D hmm_range_fault(&hmm_range); - mmap_read_unlock(mm); - - if (err =3D=3D -EBUSY) { - if (time_after(jiffies, timeout)) - break; - - hmm_range.notifier_seq =3D - mmu_interval_read_begin(notifier); - continue; - } - break; - } + err =3D hmm_range_fault_unlocked_timeout(&hmm_range, + max_t(long, timeout - jiffies, 1)); mmput(mm); if (err) goto err_free; @@ -1736,24 +1709,13 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusv= m, return -ENOMEM; =20 hmm_range.hmm_pfns =3D pfns; - while (!time_after(jiffies, timeout)) { - hmm_range.notifier_seq =3D mmu_interval_read_begin(notifier); - if (time_after(jiffies, timeout)) { - err =3D -ETIME; - break; - } - - mmap_read_lock(mm); - err =3D hmm_range_fault(&hmm_range); - mmap_read_unlock(mm); - if (err !=3D -EBUSY) - break; - } + err =3D hmm_range_fault_unlocked_timeout(&hmm_range, + max_t(long, timeout - jiffies, 1)); =20 kvfree(pfns); mmput(mm); =20 - return err; + return err =3D=3D -EBUSY ? -ETIME : err; } EXPORT_SYMBOL_GPL(drm_gpusvm_range_evict);