From nobody Sat Jul 25 16:51:29 2026 Received: from mail-pj1-f45.google.com (mail-pj1-f45.google.com [209.85.216.45]) (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 0434D3B8921 for ; Wed, 15 Jul 2026 18:16:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139365; cv=none; b=UR3+98kwBy3zF+FM3cmpVfQf095gwBts8P+dADLpzZlQy3HE2QNoQa13n8B36KkPZWcsKHLr8QEyZfY6SIBKRcCb9XOmm66Kb6iqM/rB20jtAi9pxl8YKHY4DwBdLD5OZT/nek3ouV1Ji3SotKAFCRr5Stq1bIs7MESC1vGmcxM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139365; c=relaxed/simple; bh=csnB1QKwJjGzPlvn3izvxV3TwVDwmp1zkOvD5m4n8qU=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eXWn//Yt/Nj7HXLE8ncwfN1IUPef+ZhlrpY1vpl0t/150wFC69fLEQ6Rf6Fgm/aWI0Pfy7Iwmfg1/VMvcEVvQqBVsGo7Zb4jw+7qs7eckP/BqTka/bzl5j8YvFWyzzvgVgYhdsFwTsc7NvcEkiK/wynAwDKlbDxe303l/iuGobQ= 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=gBfM7pKb; arc=none smtp.client-ip=209.85.216.45 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="gBfM7pKb" Received: by mail-pj1-f45.google.com with SMTP id 98e67ed59e1d1-38dc69c74b8so3992682a91.0 for ; Wed, 15 Jul 2026 11:16:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139360; x=1784744160; 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=PtG97ghw8TeTsbq/X2mfNjjQ8OBxNKf1PEUnxppKus0=; b=gBfM7pKbKlnEULf2heCR4xnnyLiZRqCB39cZrfBZ/J+X+OX6osBDBRj9cZUNonymyY NAVNBUXiIlsqeEPcPIRTT9EHuUXf6EdFgAS6Nj+O4tRZZEE7DiH6SvzimsJ4y8xLX2Gn FchPkgG3kede3c+1/cWwQZtoOYZ5vEh6lBYBQE+HR08XJyfAf549nX6ohuautxIom2Wb JtN6NDRWNLi+jbQFg/1OxcqN5lbGe1rxovUjKlicgdkI9XaUiDXlttc+yHnjD33EoLXK z1O5V7z+KBRFXB3ESNDBjOFss7D0eUVpFX7AtTdaWyzkrFIjY/LN7DGdURPNiY8ffvTO gWgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139360; x=1784744160; 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=PtG97ghw8TeTsbq/X2mfNjjQ8OBxNKf1PEUnxppKus0=; b=NaoVVXUdcFyc4Q5F9ar41UEGfT+CzRVPLzp/u9Xqu0jPP0JskGX+bB2go2/BtJVXoR Zf482sR1d/dAui3UKmBp5J7QPSh1jl1sJxScvGXeF3XvLaxXKBFXkpuaigdbpsB9Dsco rB8PdJpissPkGzGs4dw1nxfGfyOM+pHKoPQYmnphSiUlaJhR2Jo9vfY4Q1XQShn0O3G3 MB/0WwtD4ijffiDhL+GPtS5oa6BP9MsIN6yVJgK7Fa+IgHg+7Oas9NXVwjfZYkdX+lVO WBEGw8nEmmjUwXlZUphCi9EsYytcIOctBXCkuz4SAftnbY95af0J6jOQp/UbZF4krOZC Mshw== X-Forwarded-Encrypted: i=1; AHgh+RoFYJu2gubu8c/sZv71ZzLxGn6wWYmBixVkSHPi6zQ3zq56zq6dK0gnJCO/rVzUYZ9HHEOzjpJCjoD8hd0=@vger.kernel.org X-Gm-Message-State: AOJu0YyEZFFP3qOPN7ZUuuOHjOv8uianHg2nGTiVsaZ1WwXX+oIbda2u G+fA2kIL1oQy0luhqv7Ryi46zaLVaWWqICy2z1NWnaoxDogfMkvfI7pG X-Gm-Gg: AfdE7clSDbiSmXo95HAqQjIDR/mbTBApoHtzJGbd2MZQlcfaVrm6zox8D/Gcz3XUjBC Qb+SoU6sWlVLttVkiwpQNqHWLm8bLV4O80dd+Ob4h/uVOSRk4ofovhNgL3bU4egglvI0xPIw44J lvgun/gGm7hYps5VwURCaiNu3Hghu6Ah622WGDh5ZFK0ovHiT1GEAMGZHMNsv2XSNmgCc/vVgft xL5W+lKxOa5TVb+hx7snYjXnPh85iCeStgUtPW/Ol1OTTLXQqxThyhK6UuOe+fvnJ2lVGiCg1W6 WpYJu6d58/j7FrFswFzopyqjgNVbZo23/N0XM/sP+5vWBsGQIVYpxpZIq58PJBunULyVNxbGOeO fuw7h0/+6EMDD3JRHt8NRW96+J0Ynd5FtVu9wCFjz2QiZr9TDLn9selHFDE01MOIqzeOtJMX7Ua YFu63FgGkohaAmkxk0GJ7WHGslWeexn3d+jxSsZ9mpbdyo+RBERWqt9V4oxtw= X-Received: by 2002:a17:90b:2645:b0:37e:1430:769b with SMTP id 98e67ed59e1d1-38e2a0c3c4amr3028190a91.24.1784139360154; Wed, 15 Jul 2026 11:16: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 98e67ed59e1d1-38e39e5e176sm7928a91.13.2026.07.15.11.15.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:15:59 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:15:58 -0700 Message-ID: <178413935809.1155966.6398279131483632373.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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. Reviewed-by: Jason Gunthorpe Signed-off-by: Stanislav Kinsburskii Reviewed-by: David Hildenbrand (Arm) --- 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 Sat Jul 25 16:51:29 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 ECD7A42FCD0 for ; Wed, 15 Jul 2026 18:16:10 +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=1784139375; cv=none; b=gOIumbPzDbcZvmlJQzM7jQNtkCv8w/Sf1v59fkW+peiIZLhZPxLw5iNcVQ5/KwPIMKKR3/dLI+4qWfnPA7HOFMshPxI4T3zaB+KWv8LI4eQ06oMVUn2Qtx2Bh/MAijoUURxGouXV75Dn/CSY0Y1VE7//XbBzY78Z/FJeRzLpDD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139375; c=relaxed/simple; bh=R7Se7EKg54RPJoNjEKXaxglPstd5d3w0Qqc2J1Qwk00=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Joh/MzeBg5n/s/mgmu6Pn3rVLlOSBIiUpkAr3zy+8knFgd2RrUvWTkDlUlaiSIFsSvua7oLovxtSKOfOfhdWBGRGLuBDCOF+HIhiH9c3aLY++ircWlg2arDpOW51xlHxNuaex+pD3+X3bmf0wrJWIc6IIbCXbY0hgnl3QXMl8z4= 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=XJ0Pjtci; 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="XJ0Pjtci" Received: by mail-pf1-f179.google.com with SMTP id d2e1a72fcca58-848593533cbso3160447b3a.3 for ; Wed, 15 Jul 2026 11:16:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139368; x=1784744168; 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=X1eUoVHSnHskW+MbFeQBIOVKlHe2gqu47BByG1/mCCQ=; b=XJ0Pjtcip4b46aIltxcxbWi+sBXlrgeXpyGIJiN8JJOz6cmke9/VXxZ2M9zbyr1rK1 4+A1IsC2o8pnne+AdmbVmVX3xqw/elxiDZ5BUwHnxuwI1hoc6z0AUV1h2VHgpoCKVNV9 ygwuxaZfC9sKRglJZchd/D28glDF/+boUWbX9BniLGe2JZPHtDB5rYYAoJbgY+cipeOA seeic05KoR2KO/oyXO6CwL31h1JlApS26FYzt9bGdEskqy1bKwRDsWAdhMqoJMmHOPKt U8/RON1xFS0DW9XmdEGcVSJ57hP4xD6bHq8JYhPPf+BX70lSDRBiLcz1Tj18c/HXf/Em kYIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139368; x=1784744168; 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=X1eUoVHSnHskW+MbFeQBIOVKlHe2gqu47BByG1/mCCQ=; b=qVK2M7gxp0z6z2AQrbrUD4HAEB4TUZ3khzEhntsOD64kqNV+NmMmp4bIYzGXwt66C0 o09IfSMw7wcuxRh0+enOl4zBOYhNR4gxxQ2WZbadtcND0Vy1msAx//DkWgrAgEyGEC/J uUyNv69xbUncrwDzmjbQetXNwfCCyU2SELa3byBoBZ/JUbL9WqCE0KRwlHSkorl0XzCp yjCGDHSA5S5eDgJIR7kC2NLvzFP6XsFfY0W+7D94p8NiDgjVUqb+X55CrZH+zobhDW51 3Mtxo5BwykqNnOKwVDOubiGV0ENg+Tthwsd6Fj2R7Whahd1qMNLtFgI5cRi7hhh1MO1H BGuQ== X-Forwarded-Encrypted: i=1; AHgh+Rr5p7Uays8DFs4ZurWvZi2XkK2q09zLc5fv7JY5ew9lq5gf1J/0U1bifxdMmOTRCK5NhBCvm88ziMZ8fEE=@vger.kernel.org X-Gm-Message-State: AOJu0YxaOjpb7yug3fTlIDfpDIOzh2XPThPcStnPd9UYSF1jBMvn9RZf Xg/cSg+WijIMDBAQd5oqhv0bUERf0Xd5EEd5PUGxLzVrah6DxlDPAOvi X-Gm-Gg: AfdE7ckXHemUd5qFWeSivGuiykhaU3QQgdy0tD8RNdl/SzYOOkPOrlScEvRCJUKJzWT AW4bSp9fUb45kaPl/ksqh4u64vyIErkpjDEAe1MVxBRn78pQ0H6nVY0ycgdR4cikAkijz+djjSb QM57Ghc0rASl/GicrhkMvGYGIQs0DS3OqQJt1sfsrILQmslkZkKwctDX9DkrEb6JvisMZ8WJqBg cRkVMk5jLZ6KCmPnITasEmm35PavRGL+kKhd4wm+ZimoGaMIWiaCgGnkecK8EgN0MHY/RrWRXtU fdSQELkiiYrDlh4JYzp4YqGjgLiQKn8gEzU5vxHSTOY+ksdt6QWNmm3sRxRfevvAfgOktNgWvaJ POxcZCT5K5R/ahw27l12CBiyYnQRn3ILjtLXdLHg/AhRegP6n02G+jbV6kcJnZARp/LeQjyUSWT 9zU7CiF1SiOzZtmcUVJH1kuL55Ie69jRfIzGb8jYgFMFB+lVDep2zIdDeZDMk= X-Received: by 2002:a05:6a00:2e1e:b0:847:95a6:eb7b with SMTP id d2e1a72fcca58-84a67299584mr3403646b3a.33.1784139368236; Wed, 15 Jul 2026 11:16:08 -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-cb25902b597sm620787a12.32.2026.07.15.11.16.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:16:07 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:16:05 -0700 Message-ID: <178413936536.1155966.8918127042760531802.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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 | 79 ++++++++++++++++------ include/linux/hmm.h | 2 + mm/hmm.c | 165 ++++++++++++++++++++++++++++++++++++++----= ---- 3 files changed, 194 insertions(+), 52 deletions(-) diff --git a/Documentation/mm/hmm.rst b/Documentation/mm/hmm.rst index 7d61b7a8b65b..e021218ada58 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(range.notifier, range.notifier_seq)) { release_lock(driver->update); goto again; } @@ -200,13 +215,31 @@ 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 invalidate() callback. That lock must be held before calling mmu_interval_read_retry() to avoid any race with a concurrent CPU page tab= le -update. +update. The retry check must use the same notifier and sequence number sto= red +in ``range`` by ``hmm_range_fault_unlocked_timeout()``. + +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. =20 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 @@ -221,8 +254,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 +269,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 Sat Jul 25 16:51:29 2026 Received: from mail-pg1-f172.google.com (mail-pg1-f172.google.com [209.85.215.172]) (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 DD7EA41BA84 for ; Wed, 15 Jul 2026 18:16:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139383; cv=none; b=stRW7NleBGYIMOoaS3Jwkn2kO1MDilOUqv7a05yWpGpjl7wNs9AgwgrBGZ/PcrA7UxuxWiuqgLPzVyRaJQfrc+iHAoU7x1GFOBvG1HhfEvCwtZEzRvWMO/scmRREHeRsGacwwK0KeLwvSMoLdqkRYorr82lqz+j1btDigLdwk7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139383; c=relaxed/simple; bh=a5vRcLyCKSKmKjk3x4G/kwnSbNGO0aDPFY7NNkdnxw0=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rB9lyTdWKZaOkhBI20kUglAzuB0w74nMbYl6Q6NVNYQZaLgHhf48qWksDL8OdHB3azbatu1sJAoD+xSZlB52aVji5Z8daSfaDKROUESI6OE6/M4Ic6vpfoIE5nixu0Tj9VH2cZ45l4wjxm14dsCf23LXOuemPShgLklwcD5BE5Q= 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=MlNV15AE; arc=none smtp.client-ip=209.85.215.172 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="MlNV15AE" Received: by mail-pg1-f172.google.com with SMTP id 41be03b00d2f7-ca97d139d8dso1625895a12.2 for ; Wed, 15 Jul 2026 11:16:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139377; x=1784744177; 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=MlNV15AE7OSkIN+ehT/gwa8ddCzDAbn3gJ2z9/0JB3i9Wdk/TcrsahVFrdfhOPufqU YHFr8g+3zmRrIi+uBKxsxUT4zUFsg8hPFxnbZfcZ0U5cf7kdMxvGt5YX3KfLIo5O7tt3 xh/X60jgu7hdXRyeNx9LikXBjAzEkzaSKmz8ekGSTohqsgMHMSalhZ4PmlHkCeBgaSxR P6P7iD11/MOic7qNP8uQOnJ+vW15Pxw8sx0cLZpXcyEL+28nAw7BNvozHoYYCWrrZHIZ AfhpnPBVrUUapdIEOo0PRyYrAmFZucYZ81ktdqeFFEolnxT+PPWXKQ5MnV8Y43z3kkoc QMMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139377; x=1784744177; 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=E6FZmplTTtWNfLJhZTJHuU9nuetLBXPM752iQsiOZER5yMgfSdWq6fxgekH9s60uxW ciU/Dadbr1RIU4e0w/d3rsZlP8hBJ7YZkED9kCChcp2r9CCd+O0r7GCl5vY2nwQ8wZP6 LUQlC6bY9vdCxCOkJxd0kkInmfyCICtqk3d0vahFzh+49EP0onkIHLNyxE7yVmdf8QlR etmMEcLryoVxpF5WVWcsgXCOmBiyofTVhXrqgGzA1OrDNaQtWV15GELV/wMsuEiDLNrQ 9AUITqQRgeG0XQqgnaTBCMK9StFQ6RT0SZGiuLtBLSnO0+f8ibj7bfb05b7IJZIgVFoq gdfw== X-Forwarded-Encrypted: i=1; AHgh+Rq523KTjpuHE1xb6uCCRSiSw0Nbt6AYzXpMc3UCES1Q0uoakZAu3bek/zNfYgNxAO/KEi8+VEaNl/T67RQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yz2Z+D/QSMH3OdX7gXlE/EtllRUnJ8ACb6ls5ip5yDea2tsSogv 8MgJlkBMvFYHxbJJUK9p37PQOaDv3VReBEncK65SQG9Is8VsTtRUd7Ml X-Gm-Gg: AfdE7cnVclleW7jDcEEA5rR+iW/SQoa1GThQVNinCfo/qHlQf121eVc+ZDmb5UBirlw 6KI7TfLWx1xas2cC4FvZjYo+ukHSZKYP0FEbqTCbDPKEUIC1Tqb9it2WWnG1uHOKBQTf2OIbi8O vCG/RbxRPlwVVgEb55rVHuFe/fZ8qAIcLGNAchjgGdE20Tiq+zeuucALmI5Epg5jVMW06ocQVHc 951rY7HECIcghhUoURdd9rzBxcnAH5txYUaxsglyb93lcLb+8HQJqImB3F6vIlOWpBHLIjor7RJ hB+8c9stlso9gFbun9Fq78QWO7jjlZrlzT2H5gC2C5mgpV2/+WgfLK+J1TnHHQb3M9qYEiXfWWe 8vxrevtzou8cYLmtSuLANSoDd67tJJW2ut6zzb9cqWhafHfvTwuNAyMacED1lmhfdQ4nCQgCMKK h+wLnP5MT0UlLWjO6rt/auxzb5o4DiHB1y8Il59x6uhk+dC2GWPmeCNBzCBe8= X-Received: by 2002:a05:6a20:9149:b0:3bf:aa1f:4881 with SMTP id adf61e73a8af0-3c110ad509cmr19061608637.56.1784139377267; Wed, 15 Jul 2026 11:16:17 -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-cb25902b597sm620902a12.32.2026.07.15.11.16.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:16:16 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:16:13 -0700 Message-ID: <178413937354.1155966.16649896548407894107.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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 Sat Jul 25 16:51:29 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 C22634248D1 for ; Wed, 15 Jul 2026 18:16:28 +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=1784139392; cv=none; b=mkv1uiEUyMbG6YuSsfYFOpWAWDrVFxLDLwGkpfnACuQ5UDXROP/xStjp557RBjP0otVaVHPROEYfiON3yc6S9lIYb+RadkqaaiKWh3Bk1di5p/cugOGqaHL8v8jzLU/QU2kqTXz4iKe5tWi0AqhIV53AUKQRw53AuX88YNX0CRY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139392; c=relaxed/simple; bh=EOg2ZjoPxr72IvBeSadtcakyUfjjFdqXJkBKoJGcRuc=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Yj2gMPT2BoBGVkRJPbVUjybf9QNrwgZakc7auTO//GfT1KnJ7lqdslCYAwssK27EVwcdoiDYRu2Qs19I5EAelLs6/dcKDNwyCHh5tIEai3J8OT8MrjZe4o2dS6Z8qWj8o1hNimcpnz021g6+rJT86baZ58/r+UPvFWINDU220+E= 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=P6gkHHSo; 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="P6gkHHSo" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2c7c61b5292so34907005ad.0 for ; Wed, 15 Jul 2026 11:16:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139385; x=1784744185; 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=hJyDStROVAjhZv77Mf9h0pLyMcLfVsgmfa9JsYP9Vb0=; b=P6gkHHSoPcOHTtXVT5ndm82zHgiCao4WSKbPZQZqMrFzfi9b91NHW6W6bDf76GFKc+ V2//TfZzlXpKALwHQhMPY8Zl3D4XV8JjwdGBV1pH0U6phUjFagHjCGfRtk8IXLV2Imum CfKvSoZlVDw3iOkQclgUWd+JAVizHPpai9ki4fyAz9uVerKub4iY6BPqKndnhSHBAGoo gyreqXpRoG/SFVbEopCCzpdRGB0QKHCgl4GVIa3zBRXGaZtSz/1jqB9W4YTSvDJJabNE INBxbwdX/APtpw8aQ5JpmPySK4qLr3M9klrZ7csLhkKTpHYxDBEh3Ouy4UBzptYziWP7 pbXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139385; x=1784744185; 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=hJyDStROVAjhZv77Mf9h0pLyMcLfVsgmfa9JsYP9Vb0=; b=YpPoadNHzj6tbw1byC2zSWBOKjuXQvHyONuo0wHP/oaR7HZ06fUEAVpnou7tuxzJ9n 0aPTznpq8bKa6VtWqBZeSuilSOgIS6+nK4i7ZZFQZbJu0p5UmX8H/riTuSGurNhOURc7 3GuRrrvqVC9vLFkNu54IBnt26ddwdo07WIBNCZ9O7tl9QBfQQaS+2WCZz5fCgWoPOc56 lS5x+YoEcxpDFzxY8EOwy0Vu/IH0PkKE2qhGKhD45/jio2YSabSXeglD41Ys1Cx50TBG rK84/kLmy5GyVpf+k9Nor4sloXUN8xs5bcYO20fYU/FtClE2qyYV15WqcIohoyUGbI59 lF9w== X-Forwarded-Encrypted: i=1; AHgh+Roar4nX2SjseIyWwcFgDx9Da7A7T8Eyb/4LTZneGHAenbCLjtKy+zpLjrZkdmY9n0Q16ZDrEHLTrDbkPr4=@vger.kernel.org X-Gm-Message-State: AOJu0YzST1aNPOrCwE7Ont31ZYw6+KiztQaJZzZw2RVU1OKwHE7cwpA1 VeNXDo3tYSLq3RJSLQQAIH1EVPF6CooQQn6hYhKguu09ptNI9P/SApY6 X-Gm-Gg: AfdE7ck7f/c+t5kOK2DrX/KYiH4ditcJD1WJC41qgjIiL9Dct60ARXOGRnjB0hUxchj blMJAGYDupfLvwCMoHKQArKfl+/AEfnSktsn/KJGCrSFd9e2NKKqlOVKD5FeM1yZb/SE08z7Vuf pZWHALve4DmEJYX80MNvdcsmEEhY/coRe+mRZNibZzLs3AbIcIbYVhCfYT+8jIhFAEwk7kb7a+Z 8jCmPlTzAB9mr+fC9E46N1tQvyNuXfMYBSlWPqHbWkxX5d8t3AXYhneBZuWg3u4uBN1mkO+iHr0 1nvS1q541KWvJStYpYlV1QQxgvRn9WeSh+GAJ6obZM4Hn2BRs9k/ogZHEX8LvAIA41a83Mep8IX xL9VMSzeFrr/rwhsIg9R3dSv42a5soam6IcOs7Fm4e9emfjNI7C9HvSANYx6ERtR32jpBkKy1ue by9XflJarm/uNyhXgxHilex0ohNvYJZv5MlMUOTEJlfRs1g9cQaL5LjF4wnsM= X-Received: by 2002:a17:903:19c5:b0:2ca:bb6:e7c6 with SMTP id d9443c01a7336-2ce9ef22bc9mr189071215ad.37.1784139385005; Wed, 15 Jul 2026 11:16:25 -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-2cf0fdb3a0asm7052845ad.0.2026.07.15.11.16.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:16:24 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:16:22 -0700 Message-ID: <178413938249.1155966.292562154596800687.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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. Reviewed-by: Jason Gunthorpe Signed-off-by: Stanislav Kinsburskii --- 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 Sat Jul 25 16:51:29 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 C9D1842FCC6 for ; Wed, 15 Jul 2026 18:16:34 +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=1784139398; cv=none; b=N4w//E1gah2Q+bkfdTx1FTS/lzCw12B763kAis4O8/IkatiDC+uI4DZnutd3ZrYBMEwHsbL9+wIy/KoHNALRapLyotuZIpnnl25P7CQbhnDI6bAw62j7P4B+17raSJzAPGtruQLsE5HebkxNn6kcjVCuzdKQ8gfMxysRy6dr8Go= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139398; c=relaxed/simple; bh=WjbR1yYJvUnP6Ki/Ch1cSCwnR1/UzkvRzcRqts53AcQ=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u2CaKJ2zhQLSbiHxSfCcRSgN9gjvHQPYac+HefcwW5GlTgzSU1LvSkkkpDtLrFkSmlWahIw9jodPc7wl5A0EKae31HhHShhfsymC/aUd13g3wJo9hf0dUW6RoQ9D97Bi8UnA8EckVSE5VEvwjAu+YkzTT7IVpLFd2Tr5M3JHWoA= 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=m6TbMt8n; 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="m6TbMt8n" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2ce7d2adef4so34915185ad.3 for ; Wed, 15 Jul 2026 11:16:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139392; x=1784744192; 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=4IcjMhwypTXX14WXh1GVYxiUX1ayGU/csb6g5Y2UiV8=; b=m6TbMt8nz8qqpVH9SrEubmKEspUu6JhWcAApw1JPE61+7AWvolXapr4mB2nrMlYsni 2tig5XKQc7+3FW/8Su2jrLSVrhUMM2bjhdAEHABjuHd6/+5iR0lzw7jqGpuyGbtCmP0j fbKiAYXs74bIoxYYeheAjWKRcjWNMcY0nxrr+6663ZWL4XSpB6s1VMvgYCPEUK0UwGyn ELvQyTwhhmHJrY7hBt9tPnbf426fiDdmz+7nKgOjjt/DRaH9Q1hBXmrq9Y8NkOGQ5/Lj HN4YpvvjcMqUQa8pwhNusanW0pp/pKhGNGSNHpZqpL4rHVklUxLNFQ0qbh7nU1jVQHkQ weIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139392; x=1784744192; 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=4IcjMhwypTXX14WXh1GVYxiUX1ayGU/csb6g5Y2UiV8=; b=TFtMg7gKQFA0jJRtJ2r9MpAD/pvcAOR2pSGFqwQhqKjfuPpHw3r0FCXBPRELgSnT6L I8axp4P5HABMSVPFfw2ylRieF2IoFck52d28MSqSPE8AX7ZH+cVo6GktPdXjnIhoDHwX H3rvK7TyXj1okmGxlhc+pMicVSKYkq/kYOJ9Q3BKuJThO8T7DcKfe7GoXU2KiFIAqmZ1 C0+wTQWlGj0gKjz1noAHeVWAhcfep2MF411Fk96DyubCUj1WUAM1HpsGSsQmVv1fzWaQ MlG5g7fNh3MMf1hxeQbDqI45ymdmu59yyLe0U3Qa+LKrMXXIZgCtgAOpkczxYBq/O8rK x6xA== X-Forwarded-Encrypted: i=1; AHgh+RpQecPSOxmTG5i1L6f4QYftZX+yv0DVbwxH1LqSncbjlc+V5b4SBdpC1QUNJOrS09uCeUR5LsGdByWdit0=@vger.kernel.org X-Gm-Message-State: AOJu0Yw7LQsbG+1dCbw53LBR1lBLrL0YC9o+sDdn7ZONXoEOr58nYPI9 JM7H/PZt7SjbK43hSCQJELzDjkuQYnK53kGxE+9AI2CeGUXnjrjdG9hK X-Gm-Gg: AfdE7cmujNx1tOm/FTQvxBtcPYQKsMbQebUE+NayD6dMHHfk57WYMTjR8w/RZ3teMoo bLxUdjiTgGQUZjS2615+XiakCBA51O0cPJOtNd+gnOE4+Gks4TOKqtgz/LCewSdi5ByWpdCsdlA uxMFIV2i3Rp1qzqBlbcEPx74mreEr3H8VIcE25u0kRMpAugvaGtEp+XimWo0DDuy9EAThd9xDfO CPtO5D2UFvxN/eiKcrEwugRVvRijF1KzgxSwe4mWplsdkFF9I4mHICU5+RRasI3CDA72q6xASvA o8rskFS65Xnyx0qw/tCpzDmT8Gm5sxnsgi8crWLUF2QlipH4b01f32hPITFCLkudCoXsihFrZf+ xytOx1h10l+6WgmELN/wfxe5Bb7dXXz+1te03UP5eHrh5ahesBWOhy/bx80Y6el7IZOh365u7+G cTMellp1z8YfNCunKMEF8ZZaRAKT+zCr10rpqcigjy9dAjwzZVqtFfaWxVAns= X-Received: by 2002:a17:902:f645:b0:2c9:fc14:588f with SMTP id d9443c01a7336-2ce9ec0f95fmr181359435ad.29.1784139392357; Wed, 15 Jul 2026 11:16:32 -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-2cf100e3946sm6817295ad.4.2026.07.15.11.16.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:16:31 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:16:30 -0700 Message-ID: <178413939024.1155966.6246787744253724390.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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. Reviewed-by: Jason Gunthorpe Signed-off-by: Stanislav Kinsburskii --- drivers/gpu/drm/nouveau/nouveau_svm.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouvea= u/nouveau_svm.c index dcc92131488e..58735446d783 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -678,20 +678,22 @@ static int nouveau_range_fault(struct nouveau_svmm *s= vmm, range.end =3D notifier->notifier.interval_tree.last + 1; =20 while (true) { - if (time_after(jiffies, timeout)) { + long remaining =3D timeout - jiffies; + + /* + * The HMM timeout only bounds retries while HMM is walking and + * faulting the range. This fault is handled by a kernel worker, + * so fatal signals from the faulting process cannot stop an + * endless stream of invalidations here. + */ + if (time_after_eq(jiffies, timeout)) { ret =3D -EBUSY; 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, remaining); + if (ret) goto out; - } =20 mutex_lock(&svmm->mutex); if (mmu_interval_read_retry(range.notifier, From nobody Sat Jul 25 16:51:29 2026 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (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 3291F41BA9F for ; Wed, 15 Jul 2026 18:16:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139404; cv=none; b=W36RvcpDbvGIQ7cRtSch6x7Ktd9hyvGQK6fk3BtJXsjerI/wVoPaoNXXPBuA4uMhu/jy+nys2eaZjJ08adpuQ4JgfTUeBJNA+nY0IXLFTFxNhxczF+00Di529raWC/bXYCxOLPIi0YkB/19xEXUn3mFAd8Q+1AKydTOcoBWarAw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139404; c=relaxed/simple; bh=QDkn/RQPvTt4rCrtIK7bOiEWlSwSa2c8a6ijlJ6xk/E=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rZv8BgKmwuSmqh+RAmbj1QC6E4VD1jXwQM1nefoJKWvAMLpltAsmbdAw16PRerjd/oyVuHp69xNYyR7ytWdggU573EHjOSANoPz/vfq81BbhZHjJxrLwTjRbb7TyggkujlYujBQAwUn2KtLEjp9wc6RmATQNYY8EHQ/t2AJQBeQ= 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=HWXDJQHB; arc=none smtp.client-ip=209.85.214.178 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="HWXDJQHB" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-2ce87c7e3bbso63990425ad.1 for ; Wed, 15 Jul 2026 11:16:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139400; x=1784744200; 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=xews/oLHPsdqsmPpn1oXU4/lUwRmc6mOTrGvCA27l7U=; b=HWXDJQHBm4rFxdLm2+gv56gw+psJw2vVt5OZf1Y01gGSkeE4EW9Iw1ITC8mJfcU9Mc nFmYSlzE7OrNHy8QGK/stl3aQHjzk3uld6y7z/UymSuWaCx41XhpjaWVuqqQ9SghtLWI n+UzeG8MpoFpas+nJieykgj/qH1+p6tZfI7GAgeF78ymdjVvyiilieEiTbAOvbZQpeQV LFFoN4VDcskkFCsL6Eqpo2bQ1uRHo0Yrt6n0J0nSx72d39oyNsDMFjXeiV/4YtjN7YFi xCLO3M30GnghdfKEHgrM5/7c5EZPFD85fZuNth2j3B1hwals7RQhwaUFXVc0cTTXsxdr I2Ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139400; x=1784744200; 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=xews/oLHPsdqsmPpn1oXU4/lUwRmc6mOTrGvCA27l7U=; b=l4rhEq6rWE11VE7z9UgPaGagMCjwbvsoCcEGXY/j2MYsFJVchPHjl5BZm+QxYns+Dl +24acnbsdAsI5iNOo9tkVkkjz4Oy+5MXA6+7yMyfktmOYG5cB0ou98/bV7F+IX/5Gzk0 uVkfB5UfwsQREbvMa88DVeVdOHl7dcT3k1hzXLTgkBEVa1aY0IfLqwMjjVkqHZKQ7U49 +zz7e8o39ry74IaB253aKhoVjMKWKadlMYQd2TL4IxoFY/GVS95AtjMWlk/J9PHmXcOS zlE2DqR7AGC4MO17X0dcqwucsiPW8RulxJNp4R+J9ZbkdkayDMyvT9W5NI8gu5WJsBPb zRjw== X-Forwarded-Encrypted: i=1; AHgh+Rr7UN97IpgwqflPVVeXaObYNeffnYyMz0F6gr+KM8ar50hrXvfC0pkTce8IZ8GLEbhb7Y99ZtMGVfuZaug=@vger.kernel.org X-Gm-Message-State: AOJu0YxSY8fppJ/Sl7Ukkh4FP0UTZKdhP6xz9XCjjaXr9Q21o2qM7tn1 XwsVuBt+KHl3ZI23EfGA1+4VAsD0uWRL2dEgG3YGHMQzRFV2b1CeAXxW X-Gm-Gg: AfdE7ckVwzDRpJj6F8piwjCRQhkyFL5pF+h/tx7eOfBCzL1zqQDf+7jLQIIFtRVZFs6 YNqKxoxrT5Yjf/oyBSpKXNlBvogARzN3k8GIGG7xCEmIJIxcTC7+5o8VlacflzsJO/98FwJIa86 CkZET2w9Mn8E8iYqbwxlUV3zGg2XjhOcseg43czlhUJr8Ama4BcE2q9zSo3WtVmN/SWpjLTctvq CseLnbfuFmo8LeQ0HYNGMF8DG9hmz9R0y6cpZ/zcPuDZxCW9AoFfycYH0iyg1y/dOZh5EtxH/D1 QCf71bneuh5UYFdNg7hTTa7z9GhujD9xiMg2Ru5d+lFOUM5lUdZUh+Gie8CZU1Kxlc86KC0Lhf2 +7YLF+Q2lwOETxxLZRRDwnfOHR0atV4GqK9xtsejsXm7pHc00gMwemw6fp3yuy1bhwjoPa7j+uj qlAYMidV+AK5fXx+dDwAV/xBXEjJy+sMM5DzLTc0D2Jk8H36Q/+RI//bSCSa8= X-Received: by 2002:a17:902:ccd2:b0:2c8:4c29:afeb with SMTP id d9443c01a7336-2cee9a64cf7mr89372715ad.8.1784139399557; Wed, 15 Jul 2026 11:16:39 -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-2cf10592040sm6621985ad.55.2026.07.15.11.16.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:16:38 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:16:37 -0700 Message-ID: <178413939750.1155966.3639451690646685854.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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. Reviewed-by: Jason Gunthorpe Signed-off-by: Stanislav Kinsburskii --- 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 Sat Jul 25 16:51:29 2026 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (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 539F24DB541 for ; Wed, 15 Jul 2026 18:16:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139412; cv=none; b=OWSHanKsw4V4lEvCHDnM6q1vGhcDiDPxup8PuOI7cFrVyAxGD/uacQkTqqgFB8RPyD1Uuf9h2GwahSW0i7CFzPjKMO6DMa2ZiZp13qzSWW6jEtaR2t15rq9sFTD/WeadE6wZ28+P5HeoTItYkBEbg9pObkx5C4KmfPomO3qFs7M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139412; c=relaxed/simple; bh=xAOaqD9o05fm96vslZiqqo0PDijNJtR0XV7t4d/e/as=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oE0f1gAjA+7N042gm1KHZyh8XDI5RuBX6/simBuKi9jA14Q4td4ngwlR6260D2zaoXW3muYw5mIebDi+6FuILDWqUEvyhjBaD0vvisXatfeA8eE3sHI/wYvBNwhjEt2LogRmRk12lhfsSYhCcgVsEnni/sZD4IYaLk8Hn+p7x8A= 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=SE47BdFA; arc=none smtp.client-ip=209.85.214.172 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="SE47BdFA" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2ceed7018c8so16433865ad.1 for ; Wed, 15 Jul 2026 11:16:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139407; x=1784744207; 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=+q3csfDWWlHf03esSbv28913HL95J8hCqGqZ6tTf+OA=; b=SE47BdFAKydCpd3F0xQvH+uV4OK+/DfA0ukeyxnJhoOMwEyaZ6uynE9gF/5aMEwqBe CHYJ3cIQlGddeFo3GB2+re2p6ohhBBFoJ9a2OggO34cy4v7+T5H9LhdXqYqnqvYh27jj epveLpJerNf7bSeBcBAB1Spr79INN3BGE4tAsLSq1Y8SEhyyqnOTumk+xKgnXgwJC8dw 4o1RZfrRhGjpApZsl3rYdxRXOnKMwcjIkxaxtHdF8Lm0K2gB67MlbIRkd1XAADgNQRgs coFN3L+hylwUI0Jnf6zel8dPMH1mJjjc1mxkcCm1Fdo/hYj2r7m4v65I8gubN2e0Meln BwDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139407; x=1784744207; 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=+q3csfDWWlHf03esSbv28913HL95J8hCqGqZ6tTf+OA=; b=Hq59rjInKREG3XR6M5Gq0zJlid3QqPx7a7NPlajMfdFf8BbQcMh+WqyfAa0+HTSMMS lIIVAmUiLKE9yRZz0jE0heV40PmtF+CJ6PlWpgZrd6i7RASFsYPnGbXetSFTsSQ3c8hj iBa/q1cFr0rkr49Vs48eAWz44pIgRS4xfBSCowHhEuR/GZJZaqxE2BlCbTKkG3ErCtZv bGzIRCjT+FlyCxvYj2e8Y7Wj5W1yr42Hwnv4+Ntxn1OhKIbNHeeuE9djAx0giC9a3yHX y9sDOssUvDeoSiN183slbHW81hdXTaetGg15sdc/sxZBFfd1JT3JWWHj/bR4iEXhyYOV HRsg== X-Forwarded-Encrypted: i=1; AHgh+RoXZZipXlKRqNWepmrlF31pAfUOAv+IomN6wkhA9ksJGmhBRyBqVF93+343YTpDHdeGoDB+9Zje0mU+w/k=@vger.kernel.org X-Gm-Message-State: AOJu0Ywjj+ItscH9o3nmv3uYm3tDdodercWRgwtegDNiX+1+J1b0lAUa a9bvYCHsO+Q5OlGgxNnMjt3KbCCGcur4ztwVVLtO5I8XV2YvxnRgzciu X-Gm-Gg: AfdE7cmHGW8rQN6A0yDEv7koe5sW7yB8Ri/j0Sk04m5NYRjzLBfMlFOvV4LpH1kC4YO pwPpWHuohHD5l3lZ+Z6+jn/FrR4v9PF5qQjAAcRrbdUOXdIi1ZZohzK99xqBtCmKckHX+5kdYlT NDdjWI8FfrydKvskvOW5vLu3jf/fyEcVBpl2GwhdRKwya0a/cFjXa8CxLhemN/23eLAFYcVzDKy DwSAiZrPO5GzD0wk8Pd+Ps2V09JsLGjJwsUgs1bjXgz5wFPYQdxWgUbqNqIPP9jdHfhXAc/iYUv 7W0vCJRy0Po0y19AlYarwp2eOEfZDefrK1pGayDohXeltdrSUeoSrvrX0vCS1DUlCT6DEFTIhPq +WmrJSUy3ZseupatgSAQ5c7CJZZjiOllJDhDaPp4oCIamfO1PU8N/KrHtork8BdVZyNdzm8UNow jeCR+raLT8P8w761dh5tIB5w4QeRnc0VfzAwFe/YdXhNMtpSdCt7l2RzH/Rgg= X-Received: by 2002:a17:902:c94a:b0:2ca:b8fd:f31 with SMTP id d9443c01a7336-2ce9e9a175bmr176469515ad.15.1784139406969; Wed, 15 Jul 2026 11:16:46 -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-2cf1055d661sm6778695ad.42.2026.07.15.11.16.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:16:46 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:16:44 -0700 Message-ID: <178413940486.1155966.10368807598827608499.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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 also open-codes the mmu interval sequence setup before each HMM walk and 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 mapp->range.notifier_seq for its internal retries, so the driver only needs to call the helper and then validate the sequence before marking the mapping populated. Pass HMM_RANGE_DEFAULT_TIMEOUT as the helper retry budget for each HMM population attempt. This scopes the timeout to repeated HMM notifier retries while preserving the existing outer loop that moves between invalid mappings and restarts when the interval is invalidated before the driver updates its mapping state. Keep returning -ETIME when the HMM retry budget expires, matching the driver's existing timeout error convention. Reviewed-by: Jason Gunthorpe Signed-off-by: Stanislav Kinsburskii --- drivers/accel/amdxdna/aie2_ctx.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_= ctx.c index 54486960cbf5..b5b4ca263002 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -1034,7 +1034,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj= *abo) bool found; int ret; =20 - timeout =3D jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + timeout =3D msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); again: found =3D false; down_write(&xdna->notifier_lock); @@ -1061,24 +1061,9 @@ static int aie2_populate_range(struct amdxdna_gem_ob= j *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); - if (ret) { - if (time_after(jiffies, timeout)) { - ret =3D -ETIME; - goto put_mm; - } - - if (ret =3D=3D -EBUSY) { - amdxdna_umap_put(mapp); - mmput(mm); - goto again; - } - + ret =3D hmm_range_fault_unlocked_timeout(&mapp->range, timeout); + if (ret) goto put_mm; - } =20 down_write(&xdna->notifier_lock); if (mmu_interval_read_retry(&mapp->notifier, mapp->range.notifier_seq)) { @@ -1096,7 +1081,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj= *abo) put_mm: amdxdna_umap_put(mapp); mmput(mm); - return ret; + return ret =3D=3D -EBUSY ? -ETIME : ret; } =20 int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job = *job, u64 *seq) From nobody Sat Jul 25 16:51:29 2026 Received: from mail-pf1-f182.google.com (mail-pf1-f182.google.com [209.85.210.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 D09A541A573 for ; Wed, 15 Jul 2026 18:16:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139420; cv=none; b=gjT65u+OFbCm37/TMn051JW4JpKLuxRGjU9mKcB/Ih1gUtGMQ0lcV2wiWoka6odfjBFvZekrx6py66vHr176YnFxHs8ufaFegUhy6FcbQ2Y1w2/OTRh22LmBmT1vmdxJQDHL7r+BtL5XTn28D34UUSecaYp7+o1vuoalsFwmFX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784139420; c=relaxed/simple; bh=6NKYp0288qzLifvPuOSD1Je8XdLGvJewQimz4GqkDvY=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=V4F88LGarSbI7uTenJxd1nMbpsC1e1zeDFOspX/HYqzQT6MUDO2ATSwI1sa14WPJfJ/wpqug/Y2yMdDyFs80k0tnoZfHhY9LV9cAS0KLcDAs3+Ph+Z/460CDn+7Wsodlj29lomfShNT+kiM0bA3UaC1V9KTpWcmBu1Nspfnh/28= 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=XrjHT2VK; arc=none smtp.client-ip=209.85.210.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="XrjHT2VK" Received: by mail-pf1-f182.google.com with SMTP id d2e1a72fcca58-845b6d9bf39so2580887b3a.1 for ; Wed, 15 Jul 2026 11:16:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784139414; x=1784744214; 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=kQ5Orso9YJMZEBfqLHTmR8qEZ0VQA0+aPO2YU4j8nyU=; b=XrjHT2VKQ8wiUtUJfEJLZtQG0DFxIdba+PxVYeqNbrUigLMA7tel0Na/hJm21QIteP AcYFy8Xhvdv8JAAQfwdPAU2cPGb5bFuqZhlzo55sE9RTzF0+qus+jXbytsXHsqD6v60y +XCq0Jh3DLMXDQfJp+3HK01Bkw83DgcHVPqHJGqjnBpyr8C1B54JzBYMkTCbqkj3/PUZ hOC/zNGGsmp6wQ/HX6Qqal+NEsalXIgLtEUv53vztsvMuc4M/ayCSBMY1W4PjMfdWhfT TA3toRSVz5VF04oh1QMKoq4CWgT3bS0KDtFZ86QMlu0eaD8K7UyddIhEtU3c2XwprgZB G+XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784139414; x=1784744214; 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=kQ5Orso9YJMZEBfqLHTmR8qEZ0VQA0+aPO2YU4j8nyU=; b=YyxWt9gh11RDgcMqVfiQljjtBQ0upg7S240gpVSbjrxx9Tytglm4GHqFpuD7hc+uVS fQdp0gSDP83CfhlzfRVzDINNp2Vuou7IhGUyxRe9b1lPKJqVe9NY+ZYyWCMQn5IUuyht NCRy9qNwzRrlyNp0l29sNJpkNNV5F4r4f2mcBizNgH1/+hfb+0sD415RDKEqTXbFdWas MSXy/Zaz0ARB2XAD64qAWEW5KfQOVm2MVzVqETn+sFrXIL/fj/ZoLg14QaQ/K6lYY2/A BY4HR/AfK87zNy7jXZsjKYqIPoTkbubeirSm85C7dZo1e5NMd5p0lp33llprK32eaMSI /0FA== X-Forwarded-Encrypted: i=1; AHgh+RoesdCX1TgSAUQIoOLwgs+IlzP4yy6LObQ9/zKYFQIHrATKz92NLrVsZk18rbQzO6i6v2FilnotJaINKTk=@vger.kernel.org X-Gm-Message-State: AOJu0Yw0wjtp98psGkxwU6GSpgVNYKDFA/pqlpU64aJ34I7eFPd5M/ie kcd0p2Ikuyre+Ha1bcBMnGZnoo+JDKd7VxB+Ba75irFpMkqgvum7eOfd X-Gm-Gg: AfdE7cnKCRY0PSl8GTd9un1gYeFooOGMW2tTlEWOkceuDJInFwHZhfUffU4WFpMMAtx +fNlY/mnM3R+iklp4vs7wgZwiTNYFbGxiocATczFYvfY+BJRgllwYjSwDqHBXzPGMXRqG8j/JFr +X0TFJ/j85DK6D3uwTEP+M1x50tvSkOIr30ubJWDNVRh9Mz38MhvjcIZ8HM6rnjmEXzHu6TokMS Hg3RTDY7ggiIcRfBUezq//K0djJpHOt0tCHWUuHqXcOtjilWko9lyi5bmPE3g6Kh9fD/H05cJd5 I9+w+FUqQwX4eVCjUFmklQqE0r3qsyy/hC0vea/5645d+zas+PfL0zJ9h56eVwy7Y5o+HNhXhqF 8Xi2pkakqv141qcyv6RYrq0NdNphsHQzN42aruG6T8TV+AzClH51EiQUc0yfPPynT9dTJRQ7XD2 GvG5uYmdau302VePnTOG1esuuHLyYIYnqx09q1sN3cSNAFLExnBFI8yTNHr6c= X-Received: by 2002:a05:6a00:10d1:b0:836:6f2e:bb6d with SMTP id d2e1a72fcca58-84a9d0e5e99mr412854b3a.14.1784139414332; Wed, 15 Jul 2026 11:16:54 -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-cb258ede81asm621883a12.11.2026.07.15.11.16.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jul 2026 11:16:53 -0700 (PDT) Subject: [PATCH v9 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, intel-xe@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: Wed, 15 Jul 2026 11:16:52 -0700 Message-ID: <178413941236.1155966.14485211391150425997.stgit@skinsburskii> In-Reply-To: <178413903133.1155966.3904063656020521607.stgit@skinsburskii> References: <178413903133.1155966.3904063656020521607.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() and open-code mmu interval sequence setup before each HMM walk. They also retry -EBUSY until HMM_RANGE_DEFAULT_TIMEOUT expires. Use hmm_range_fault_unlocked_timeout() for those faults. The HMM helper now owns mmap_lock acquisition and refreshes range->notifier_seq for its internal retries, while GPU SVM keeps its existing driver-lock validation with mmu_interval_read_retry() after a successful fault. Pass HMM_RANGE_DEFAULT_TIMEOUT as the helper retry budget for each HMM fault attempt. This scopes the timeout to repeated HMM notifier retries while preserving the outer retry loops that restart when the interval is invalidated before GPU SVM updates or consumes the mapping state. Leave drm_gpusvm_check_pages() on hmm_range_fault() because that path is called with the mmap lock already held by its caller. Reviewed-by: Jason Gunthorpe Signed-off-by: Stanislav Kinsburskii --- drivers/gpu/drm/drm_gpusvm.c | 61 +++++---------------------------------= ---- 1 file changed, 7 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 958cb605aedd..de5bbfe58ee9 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -773,8 +773,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct d= rm_gpusvm_range *range, .end =3D end, .dev_private_owner =3D dev_private_owner, }; - unsigned long timeout =3D - jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + unsigned long timeout =3D msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); enum drm_gpusvm_scan_result state =3D DRM_GPUSVM_SCAN_UNPOPULATED, new_st= ate; unsigned long *pfns; unsigned long npages =3D npages_in_range(start, end); @@ -788,22 +787,7 @@ 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, timeout); if (err) goto err_free; =20 @@ -1406,8 +1390,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, .dev_private_owner =3D ctx->device_private_page_owner, }; void *zdd; - unsigned long timeout =3D - jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + unsigned long timeout =3D msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); unsigned long i, j; unsigned long npages =3D npages_in_range(pages_start, pages_end); unsigned long num_dma_mapped; @@ -1422,9 +1405,6 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, struct dma_iova_state *state =3D &svm_pages->state; =20 retry: - if (time_after(jiffies, timeout)) - return -EBUSY; - hmm_range.notifier_seq =3D mmu_interval_read_begin(notifier); if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages)) goto set_seqno; @@ -1439,21 +1419,7 @@ 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, timeout); mmput(mm); if (err) goto err_free; @@ -1720,8 +1686,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm, .end =3D drm_gpusvm_range_end(range), .dev_private_owner =3D NULL, }; - unsigned long timeout =3D - jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + unsigned long timeout =3D msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); unsigned long *pfns; unsigned long npages =3D npages_in_range(drm_gpusvm_range_start(range), drm_gpusvm_range_end(range)); @@ -1736,24 +1701,12 @@ 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, timeout); =20 kvfree(pfns); mmput(mm); =20 - return err; + return err =3D=3D -EBUSY ? -ETIME : err; } EXPORT_SYMBOL_GPL(drm_gpusvm_range_evict);