* [PATCH 0/4] mm/hmm: Clarify notifier retry state and scope HMM timeouts
@ 2026-07-14 20:13 Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 1/4] fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support Stanislav Kinsburskii
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Stanislav Kinsburskii @ 2026-07-14 20:13 UTC (permalink / raw)
To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
skinsburskii, surenb, tzimmermann, vbabka
Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
linux-rdma
This small fixup series applies on top of:
[PATCH v8 0/8] mm/hmm: Add mmap lock-drop support for userfaultfd-backed mappings
The first patch updates the HMM documentation example to make the
mmu_interval_read_retry() state explicit: callers should use the notifier and
notifier_seq stored in the same hmm_range that was passed to
hmm_range_fault_unlocked_timeout().
The remaining patches adjust nouveau, amdxdna, and drm_gpusvm users so the
timeout passed to hmm_range_fault_unlocked_timeout() is treated as a relative
HMM retry budget. These callers no longer keep an absolute deadline around
their outer driver retry loops or pass a computed remaining time into HMM.
This keeps the timeout scoped to HMM's internal mmu-notifier retry handling. If
HMM succeeds and the driver later observes an invalidation through
mmu_interval_read_retry(), the driver retries the operation with a fresh HMM
retry budget.
---
Stanislav Kinsburskii (4):
fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support
fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population
fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults
Documentation/mm/hmm.rst | 5 +++--
drivers/accel/amdxdna/aie2_ctx.c | 12 ++++--------
drivers/gpu/drm/drm_gpusvm.c | 21 ++++++---------------
drivers/gpu/drm/nouveau/nouveau_svm.c | 30 ++++++++++--------------------
4 files changed, 23 insertions(+), 45 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support
2026-07-14 20:13 [PATCH 0/4] mm/hmm: Clarify notifier retry state and scope HMM timeouts Stanislav Kinsburskii
@ 2026-07-14 20:13 ` Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults Stanislav Kinsburskii
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Stanislav Kinsburskii @ 2026-07-14 20:13 UTC (permalink / raw)
To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
skinsburskii, surenb, tzimmermann, vbabka
Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
linux-rdma
The hmm_range_fault_unlocked_timeout() example checks for a concurrent
mmu_interval_notifier invalidation after the HMM fault has succeeded.
The sequence number used for that check is stored in range->notifier_seq
by hmm_range_fault_unlocked_timeout(), so the retry check should use the
same notifier stored in range as well.
Update the example to pass range.notifier to mmu_interval_read_retry(),
and spell out that the retry check uses the notifier and sequence number
stored in range by the HMM fault helper. This makes the relationship
between the HMM walk and the later invalidation check explicit.
Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
Documentation/mm/hmm.rst | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/mm/hmm.rst b/Documentation/mm/hmm.rst
index 5c88d2cf0818..fc1b8dc19825 100644
--- a/Documentation/mm/hmm.rst
+++ b/Documentation/mm/hmm.rst
@@ -206,7 +206,7 @@ The usage pattern is::
goto out_put;
take_lock(driver->update);
- if (mmu_interval_read_retry(&interval_sub, range.notifier_seq)) {
+ if (mmu_interval_read_retry(range.notifier, range.notifier_seq)) {
release_lock(driver->update);
goto again;
}
@@ -225,7 +225,8 @@ The usage pattern is::
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 table
-update.
+update. The retry check must use the same notifier and sequence number stored
+in ``range`` by ``hmm_range_fault_unlocked_timeout()``.
Holding the mmap lock across HMM faults
=======================================
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
2026-07-14 20:13 [PATCH 0/4] mm/hmm: Clarify notifier retry state and scope HMM timeouts Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 1/4] fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support Stanislav Kinsburskii
@ 2026-07-14 20:13 ` Stanislav Kinsburskii
2026-07-14 20:30 ` sashiko-bot
2026-07-14 21:33 ` Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults Stanislav Kinsburskii
3 siblings, 2 replies; 9+ messages in thread
From: Stanislav Kinsburskii @ 2026-07-14 20:13 UTC (permalink / raw)
To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
skinsburskii, surenb, tzimmermann, vbabka
Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
linux-rdma
nouveau_range_fault() now uses hmm_range_fault_unlocked_timeout() for
the HMM fault path. The timeout passed to that helper is meant to bound
HMM's internal mmu-notifier retry loop, not the whole nouveau retry loop
around mmu_interval_read_retry().
Pass the full relative HMM_RANGE_DEFAULT_TIMEOUT value to
hmm_range_fault_unlocked_timeout() on each attempt, and retry from the
nouveau-side mmu_interval_read_retry() check with a fresh HMM retry
budget. This lets HMM continue when it has made progress, while still
preserving a timeout for repeated notifier invalidation retries inside
one HMM fault attempt.
This also removes the open-coded absolute deadline and remaining-time
calculation from nouveau_range_fault().
Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
drivers/gpu/drm/nouveau/nouveau_svm.c | 30 ++++++++++--------------------
1 file changed, 10 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
index 4cfb6eb7c771..b1415c2e49fc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -655,8 +655,7 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
unsigned long hmm_flags,
struct svm_notifier *notifier)
{
- unsigned long timeout =
- jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
/* Have HMM fault pages within the fault window to the GPU. */
unsigned long hmm_pfns[1];
struct hmm_range range = {
@@ -677,25 +676,16 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
range.start = notifier->notifier.interval_tree.start;
range.end = notifier->notifier.interval_tree.last + 1;
- while (true) {
- if (time_after(jiffies, timeout)) {
- ret = -EBUSY;
- goto out;
- }
-
- ret = hmm_range_fault_unlocked_timeout(&range,
- max(timeout - jiffies,
- 1L));
- if (ret)
- goto out;
+again:
+ ret = hmm_range_fault_unlocked_timeout(&range, timeout);
+ if (ret)
+ goto out;
- mutex_lock(&svmm->mutex);
- if (mmu_interval_read_retry(range.notifier,
- range.notifier_seq)) {
- mutex_unlock(&svmm->mutex);
- continue;
- }
- break;
+ mutex_lock(&svmm->mutex);
+ if (mmu_interval_read_retry(range.notifier,
+ range.notifier_seq)) {
+ mutex_unlock(&svmm->mutex);
+ goto again;
}
nouveau_hmm_convert_pfn(drm, &range, args);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population
2026-07-14 20:13 [PATCH 0/4] mm/hmm: Clarify notifier retry state and scope HMM timeouts Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 1/4] fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults Stanislav Kinsburskii
@ 2026-07-14 20:13 ` Stanislav Kinsburskii
2026-07-14 20:27 ` sashiko-bot
2026-07-14 20:13 ` [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults Stanislav Kinsburskii
3 siblings, 1 reply; 9+ messages in thread
From: Stanislav Kinsburskii @ 2026-07-14 20:13 UTC (permalink / raw)
To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
skinsburskii, surenb, tzimmermann, vbabka
Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
linux-rdma
nouveau_range_fault() now uses hmm_range_fault_unlocked_timeout() for
the HMM fault path. The timeout passed to that helper is meant to bound
HMM's internal mmu-notifier retry loop, not the whole nouveau retry loop
around mmu_interval_read_retry().
Pass the full relative HMM_RANGE_DEFAULT_TIMEOUT value to
hmm_range_fault_unlocked_timeout() on each attempt, and retry from the
nouveau-side mmu_interval_read_retry() check with a fresh HMM retry
budget. This lets HMM continue when it has made progress, while still
preserving a timeout for repeated notifier invalidation retries inside
one HMM fault attempt.
This also removes the open-coded absolute deadline and remaining-time
calculation from nouveau_range_fault().
Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
drivers/accel/amdxdna/aie2_ctx.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index 548ba4315554..21f2817751f9 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -1037,7 +1037,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
bool found;
int ret;
- timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
again:
found = false;
down_write(&xdna->notifier_lock);
@@ -1062,13 +1062,9 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
return -EFAULT;
}
- ret = hmm_range_fault_unlocked_timeout(&mapp->range,
- max_t(long, timeout - jiffies, 1));
- if (ret) {
- if (ret == -EBUSY)
- ret = -ETIME;
+ ret = hmm_range_fault_unlocked_timeout(&mapp->range, timeout);
+ if (ret)
goto put_mm;
- }
down_write(&xdna->notifier_lock);
if (mmu_interval_read_retry(&mapp->notifier, mapp->range.notifier_seq)) {
@@ -1086,7 +1082,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
put_mm:
amdxdna_umap_put(mapp);
mmput(mm);
- return ret;
+ return ret == -EBUSY ? -ETIME : ret;
}
int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq)
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults
2026-07-14 20:13 [PATCH 0/4] mm/hmm: Clarify notifier retry state and scope HMM timeouts Stanislav Kinsburskii
` (2 preceding siblings ...)
2026-07-14 20:13 ` [PATCH 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population Stanislav Kinsburskii
@ 2026-07-14 20:13 ` Stanislav Kinsburskii
2026-07-14 20:24 ` sashiko-bot
3 siblings, 1 reply; 9+ messages in thread
From: Stanislav Kinsburskii @ 2026-07-14 20:13 UTC (permalink / raw)
To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
skinsburskii, surenb, tzimmermann, vbabka
Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
linux-rdma
The timeout passed to hmm_range_fault_unlocked_timeout() is a relative
retry budget for HMM's internal mmu-notifier retry loop. drm_gpusvm was
still keeping an absolute deadline around the outer driver retry logic
and passing the remaining time into HMM.
Pass HMM_RANGE_DEFAULT_TIMEOUT directly to
hmm_range_fault_unlocked_timeout() on each HMM fault attempt instead.
If HMM succeeds but the later drm_gpusvm-side mmu_interval_read_retry()
check observes an invalidation, retry with a fresh HMM retry budget.
This keeps the timeout focused on repeated notifier retries inside HMM,
while avoiding an outer deadline that also accounts unrelated driver-side
work after HMM has made progress.
Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
drivers/gpu/drm/drm_gpusvm.c | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index b8f2dd9982f5..76e8a0028c7f 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -852,8 +852,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
.end = end,
.dev_private_owner = dev_private_owner,
};
- unsigned long timeout =
- jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
enum drm_gpusvm_scan_result state = DRM_GPUSVM_SCAN_UNPOPULATED, new_state;
unsigned long *pfns;
unsigned long npages = npages_in_range(start, end);
@@ -867,8 +866,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
hmm_range.hmm_pfns = pfns;
retry:
- err = hmm_range_fault_unlocked_timeout(&hmm_range,
- max(timeout - jiffies, 1L));
+ err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
if (err)
goto err_free;
@@ -1459,8 +1457,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
.dev_private_owner = ctx->device_private_page_owner,
};
void *zdd;
- unsigned long timeout =
- jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
unsigned long i, j;
unsigned long npages = npages_in_range(pages_start, pages_end);
unsigned long num_dma_mapped;
@@ -1478,9 +1475,6 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
return -EINVAL;
retry:
- if (time_after(jiffies, timeout))
- return -EBUSY;
-
hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
goto set_seqno;
@@ -1495,8 +1489,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
}
hmm_range.hmm_pfns = pfns;
- err = hmm_range_fault_unlocked_timeout(&hmm_range,
- max_t(long, timeout - jiffies, 1));
+ err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
mmput(mm);
if (err)
goto err_free;
@@ -1718,8 +1711,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
.end = drm_gpusvm_range_end(range),
.dev_private_owner = NULL,
};
- unsigned long timeout =
- jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
unsigned long *pfns;
unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
drm_gpusvm_range_end(range));
@@ -1734,8 +1726,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
return -ENOMEM;
hmm_range.hmm_pfns = pfns;
- err = hmm_range_fault_unlocked_timeout(&hmm_range,
- max_t(long, timeout - jiffies, 1));
+ err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
kvfree(pfns);
mmput(mm);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults
2026-07-14 20:13 ` [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults Stanislav Kinsburskii
@ 2026-07-14 20:24 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-07-14 20:24 UTC (permalink / raw)
To: Stanislav Kinsburskii; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] drm_gpusvm passes uninitialized pfns arrays to hmm_range_fault, causing unintended page faults and write requests.
- [High] Memory leak of `mm_struct` in `drm_gpusvm_range_evict` on allocation failure.
--
--- Patch [4]: [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults ---
commit afecb2c70fcbb0789fe0b4b948e05bb9f8070c63
Author: Stanislav Kinsburskii <skinsburskii@gmail.com>
fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults
The patch removes the outer deadline tracking from hmm_range_fault loops
and passes msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT) directly to each
hmm_range_fault_unlocked_timeout() call. This avoids accounting for outer
driver retry logic inside the HMM retry budget.
> diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
> index b8f2dd9982f53..76e8a0028c7fc 100644
> --- a/drivers/gpu/drm/drm_gpusvm.c
> +++ b/drivers/gpu/drm/drm_gpusvm.c
> @@ -867,8 +866,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
> hmm_range.hmm_pfns = pfns;
>
> retry:
> - err = hmm_range_fault_unlocked_timeout(&hmm_range,
> - max(timeout - jiffies, 1L));
> + err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
[Severity: High]
This is a pre-existing issue, but does using kvmalloc_array() without
zeroing memory cause unintended page faults?
HMM reads hmm_pfns as input to determine per-page fault requests. The
uninitialized memory can contain random bits like HMM_PFN_REQ_FAULT or
HMM_PFN_REQ_WRITE, potentially triggering unintended faults or violating
read-only mapping constraints.
Additionally, the retry loop reuses output flags (HMM_PFN_VALID), which
aliases with HMM_PFN_REQ_FAULT (both are the MSB), unintentionally forcing
faults on previously valid pages during a scan.
Should this allocate with kvcalloc() instead?
[ ... ]
> @@ -1495,8 +1489,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
> }
>
> hmm_range.hmm_pfns = pfns;
> - err = hmm_range_fault_unlocked_timeout(&hmm_range,
> - max_t(long, timeout - jiffies, 1));
> + err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
[Severity: High]
This is also a pre-existing issue, but similar to drm_gpusvm_scan_mm(),
pfns is allocated with kvmalloc_array() earlier in drm_gpusvm_get_pages()
and passed to hmm_range_fault_unlocked_timeout() here.
Could this uninitialized memory cause unintended write requests or page
faults?
[ ... ]
> @@ -1734,8 +1726,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
> return -ENOMEM;
[Severity: High]
This isn't a bug introduced by this patch, but does returning -ENOMEM here
leak the mm_struct?
Earlier in drm_gpusvm_range_evict(), mmget_not_zero(mm) increments the
reference count:
if (!mmget_not_zero(mm))
return -EFAULT;
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
if (!pfns)
return -ENOMEM;
If the kvmalloc_array() allocation for pfns fails, it returns directly
without calling mmput(mm).
>
> hmm_range.hmm_pfns = pfns;
> - err = hmm_range_fault_unlocked_timeout(&hmm_range,
> - max_t(long, timeout - jiffies, 1));
> + err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
[Severity: High]
This is a pre-existing issue, but again, pfns is allocated with
kvmalloc_array() and passed here. Does this need to be kvcalloc() to
prevent uninitialized memory from causing unintended page faults?
>
> kvfree(pfns);
> mmput(mm);
--
Sashiko AI review · https://sashiko.dev/#/patchset/178405975214.1082778.5193079941156341151.stgit@skinsburskii?part=4
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population
2026-07-14 20:13 ` [PATCH 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population Stanislav Kinsburskii
@ 2026-07-14 20:27 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-07-14 20:27 UTC (permalink / raw)
To: Stanislav Kinsburskii; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The commit message describes changes to the nouveau driver, but the patch modifies the amdxdna driver.
--
--- Patch [3]: [PATCH 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population ---
commit b015bb79070e6f1c36006ca6ff7e7e113d7ecbd7
Author: Stanislav Kinsburskii <skinsburskii@gmail.com>
fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population
This commit updates the hmm_range_fault_unlocked_timeout() usage to pass
the full timeout value on each retry attempt. It also removes the open-coded
absolute deadline and remaining-time calculation from the range population path.
> nouveau_range_fault() now uses hmm_range_fault_unlocked_timeout() for
> the HMM fault path. The timeout passed to that helper is meant to bound
> HMM's internal mmu-notifier retry loop, not the whole nouveau retry loop
> around mmu_interval_read_retry().
>
> Pass the full relative HMM_RANGE_DEFAULT_TIMEOUT value to
> hmm_range_fault_unlocked_timeout() on each attempt, and retry from the
> nouveau-side mmu_interval_read_retry() check with a fresh HMM retry
> budget. This lets HMM continue when it has made progress, while still
> preserving a timeout for repeated notifier invalidation retries inside
> one HMM fault attempt.
>
> This also removes the open-coded absolute deadline and remaining-time
> calculation from nouveau_range_fault().
[Severity: Medium]
Is this description meant for a different patch? The commit message describes
changes to nouveau_range_fault() and the nouveau driver, but the actual patch
modifies aie2_populate_range() in the amdxdna driver.
--
Sashiko AI review · https://sashiko.dev/#/patchset/178405975214.1082778.5193079941156341151.stgit@skinsburskii?part=3
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
2026-07-14 20:13 ` [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults Stanislav Kinsburskii
@ 2026-07-14 20:30 ` sashiko-bot
2026-07-14 21:33 ` Stanislav Kinsburskii
1 sibling, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-07-14 20:30 UTC (permalink / raw)
To: Stanislav Kinsburskii; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Removal of the absolute timeout in nouveau_range_fault() allows an attacker to cause an infinite loop in the global GPU page fault worker thread, stalling all SVM faults.
--
--- Patch [2]: [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults ---
commit acde5c43961cd86d28658d26f11cdfcde5a9ad23
Author: Stanislav Kinsburskii <skinsburskii@gmail.com>
fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
This commit updates nouveau_range_fault() to pass the full relative timeout
to hmm_range_fault_unlocked_timeout() on each attempt. It also removes the
open-coded absolute deadline and remaining-time calculation, replacing the
bounded while loop with a goto-based retry loop.
> diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
> index 4cfb6eb7c7715..b1415c2e49fcc 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_svm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
[ ... ]
> @@ -677,25 +676,16 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
> range.start = notifier->notifier.interval_tree.start;
> range.end = notifier->notifier.interval_tree.last + 1;
>
> - while (true) {
> - if (time_after(jiffies, timeout)) {
> - ret = -EBUSY;
> - goto out;
> - }
> -
> - ret = hmm_range_fault_unlocked_timeout(&range,
> - max(timeout - jiffies,
> - 1L));
> - if (ret)
> - goto out;
> +again:
> + ret = hmm_range_fault_unlocked_timeout(&range, timeout);
> + if (ret)
> + goto out;
>
> - mutex_lock(&svmm->mutex);
> - if (mmu_interval_read_retry(range.notifier,
> - range.notifier_seq)) {
> - mutex_unlock(&svmm->mutex);
> - continue;
> - }
> - break;
> + mutex_lock(&svmm->mutex);
> + if (mmu_interval_read_retry(range.notifier,
> + range.notifier_seq)) {
> + mutex_unlock(&svmm->mutex);
> + goto again;
[Severity: High]
Can this sequence lead to an infinite loop and stall the global GPU page fault
worker thread?
If a user-space program triggers an SVM page fault and simultaneously runs
memory invalidations like madvise(MADV_DONTNEED) in a loop on the same
memory range, mmu_interval_read_retry() will continuously return true.
Since this runs in a kernel worker thread, fatal_signal_pending(current)
inside hmm_range_fault_unlocked_timeout() will check the worker thread rather
than the user process. With the absolute timeout removed from
nouveau_range_fault(), does this allow an attacker to loop here indefinitely
and block all other SVM faults?
> }
>
> nouveau_hmm_convert_pfn(drm, &range, args);
--
Sashiko AI review · https://sashiko.dev/#/patchset/178405975214.1082778.5193079941156341151.stgit@skinsburskii?part=2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
2026-07-14 20:13 ` [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults Stanislav Kinsburskii
2026-07-14 20:30 ` sashiko-bot
@ 2026-07-14 21:33 ` Stanislav Kinsburskii
1 sibling, 0 replies; 9+ messages in thread
From: Stanislav Kinsburskii @ 2026-07-14 21:33 UTC (permalink / raw)
To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
surenb, tzimmermann, vbabka
Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
linux-rdma
On Tue, Jul 14, 2026 at 01:13:38PM -0700, Stanislav Kinsburskii wrote:
> nouveau_range_fault() now uses hmm_range_fault_unlocked_timeout() for
> the HMM fault path. The timeout passed to that helper is meant to bound
> HMM's internal mmu-notifier retry loop, not the whole nouveau retry loop
> around mmu_interval_read_retry().
>
> Pass the full relative HMM_RANGE_DEFAULT_TIMEOUT value to
> hmm_range_fault_unlocked_timeout() on each attempt, and retry from the
> nouveau-side mmu_interval_read_retry() check with a fresh HMM retry
> budget. This lets HMM continue when it has made progress, while still
> preserving a timeout for repeated notifier invalidation retries inside
> one HMM fault attempt.
>
> This also removes the open-coded absolute deadline and remaining-time
> calculation from nouveau_range_fault().
>
Sashiko is right. I'll need to do it differently.
There will be a v2 of this series.
Thanks,
Stanislav
> Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
> ---
> drivers/gpu/drm/nouveau/nouveau_svm.c | 30 ++++++++++--------------------
> 1 file changed, 10 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
> index 4cfb6eb7c771..b1415c2e49fc 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_svm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
> @@ -655,8 +655,7 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
> unsigned long hmm_flags,
> struct svm_notifier *notifier)
> {
> - unsigned long timeout =
> - jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
> + unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
> /* Have HMM fault pages within the fault window to the GPU. */
> unsigned long hmm_pfns[1];
> struct hmm_range range = {
> @@ -677,25 +676,16 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
> range.start = notifier->notifier.interval_tree.start;
> range.end = notifier->notifier.interval_tree.last + 1;
>
> - while (true) {
> - if (time_after(jiffies, timeout)) {
> - ret = -EBUSY;
> - goto out;
> - }
> -
> - ret = hmm_range_fault_unlocked_timeout(&range,
> - max(timeout - jiffies,
> - 1L));
> - if (ret)
> - goto out;
> +again:
> + ret = hmm_range_fault_unlocked_timeout(&range, timeout);
> + if (ret)
> + goto out;
>
> - mutex_lock(&svmm->mutex);
> - if (mmu_interval_read_retry(range.notifier,
> - range.notifier_seq)) {
> - mutex_unlock(&svmm->mutex);
> - continue;
> - }
> - break;
> + mutex_lock(&svmm->mutex);
> + if (mmu_interval_read_retry(range.notifier,
> + range.notifier_seq)) {
> + mutex_unlock(&svmm->mutex);
> + goto again;
> }
>
> nouveau_hmm_convert_pfn(drm, &range, args);
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-07-16 8:21 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 20:13 [PATCH 0/4] mm/hmm: Clarify notifier retry state and scope HMM timeouts Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 1/4] fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults Stanislav Kinsburskii
2026-07-14 20:30 ` sashiko-bot
2026-07-14 21:33 ` Stanislav Kinsburskii
2026-07-14 20:13 ` [PATCH 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population Stanislav Kinsburskii
2026-07-14 20:27 ` sashiko-bot
2026-07-14 20:13 ` [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults Stanislav Kinsburskii
2026-07-14 20:24 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox