* [PATCH 0/2] drm/amdkfd: fix SVM error handling
@ 2026-11-08 5:13 Aveline Noir
2026-11-08 5:13 ` [PATCH 1/2] drm/amdkfd: handle SVM interval notifier registration failures Aveline Noir
2026-11-08 5:13 ` [PATCH 2/2] drm/amdkfd: check HMM errors before testing range validity Aveline Noir
0 siblings, 2 replies; 5+ messages in thread
From: Aveline Noir @ 2026-11-08 5:13 UTC (permalink / raw)
To: Felix Kuehling, Alex Deucher, Christian König
Cc: David Airlie, Simona Vetter, Philip Yang, Sunil Khatri, honghuan,
honglei1.huang, psirt, amd-gfx, dri-devel, linux-kernel
These patches fix two error paths found while reviewing KFD SVM range
handling. A failed interval notifier registration can leave a published
range without a notifier, and an HMM allocation failure can lead to a
NULL notifier dereference during validation.
The fixes were tested with targeted KUnit tests under KVM with KASAN and
lockdep. The error paths use injected failures or equivalent failure
states; no AMD GPU was tested.
---
Aveline Noir (2):
drm/amdkfd: handle SVM interval notifier registration failures
drm/amdkfd: check HMM errors before testing range validity
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 58 +++++++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 14 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261108-kfd-svm-baseline-errors-20261107-355a3d0c4792
Best regards,
--
Aveline Noir <jm5905938@gmail.com>
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 1/2] drm/amdkfd: handle SVM interval notifier registration failures 2026-11-08 5:13 [PATCH 0/2] drm/amdkfd: fix SVM error handling Aveline Noir @ 2026-11-08 5:13 ` Aveline Noir 2026-11-08 5:35 ` sashiko-bot 2026-11-08 5:13 ` [PATCH 2/2] drm/amdkfd: check HMM errors before testing range validity Aveline Noir 1 sibling, 1 reply; 5+ messages in thread From: Aveline Noir @ 2026-11-08 5:13 UTC (permalink / raw) To: Felix Kuehling, Alex Deucher, Christian König Cc: David Airlie, Simona Vetter, Philip Yang, Sunil Khatri, honghuan, honglei1.huang, psirt, amd-gfx, dri-devel, linux-kernel The first interval notifier registration for an mm can fail while initializing the interval tree. svm_range_add_notifier_locked() ignores that error, so SET_ATTR and retry-fault handling can publish an SVM range without a registered notifier. Subsequent HMM access can then dereference an uninitialized notifier. Propagate the registration error and register staged ranges before publishing the SET_ATTR transaction. Remove successful registrations on failure before freeing the staged ranges, preserving the original ranges and the existing memory-accounting rollback. Also free an unpublished retry-fault range and return its registration error. Fixes: b1c46c7d622b ("drm/amdkfd: validate svm range system memory") Signed-off-by: Aveline Noir <jm5905938@gmail.com> --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 56 +++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index ed5e3318877b..8184cbbb829e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -106,16 +106,21 @@ static void svm_range_unlink(struct svm_range *prange) interval_tree_remove(&prange->it_node, &prange->svms->objects); } -static void +static int svm_range_add_notifier_locked(struct mm_struct *mm, struct svm_range *prange) { + int r; + pr_debug("svms 0x%p prange 0x%p [0x%lx 0x%lx]\n", prange->svms, prange, prange->start, prange->last); - mmu_interval_notifier_insert_locked(&prange->notifier, mm, + r = mmu_interval_notifier_insert_locked(&prange->notifier, mm, prange->start << PAGE_SHIFT, prange->npages << PAGE_SHIFT, &svm_range_mn_ops); + if (r) + prange->notifier.mm = NULL; + return r; } /** @@ -2257,6 +2262,7 @@ svm_range_split_new(struct svm_range_list *svms, uint64_t start, uint64_t last, /** * svm_range_add - add svm range and handle overlap * @p: the range add to this process svms + * @mm: the process address space, write locked by the caller * @start: page size aligned * @size: page size aligned * @nattr: number of attributes @@ -2285,7 +2291,8 @@ svm_range_split_new(struct svm_range_list *svms, uint64_t start, uint64_t last, * 0 - OK, otherwise error code */ static int -svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size, +svm_range_add(struct kfd_process *p, struct mm_struct *mm, + uint64_t start, uint64_t size, uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs, struct list_head *update_list, struct list_head *insert_list, struct list_head *remove_list, struct list_head *remap_list) @@ -2373,17 +2380,38 @@ svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size, } /* add a final range at the end if needed */ - if (start <= last) + if (start <= last) { r = svm_range_split_new(svms, start, last, READ_ONCE(max_svm_range_pages), &new_list, update_list); + if (r) + goto out; + } + + /* Register all notifiers before publishing any of the new ranges. */ + list_for_each_entry(prange, &new_list, list) { + r = svm_range_add_notifier_locked(mm, prange); + if (r) + goto out; + } + list_for_each_entry(prange, insert_list, list) { + r = svm_range_add_notifier_locked(mm, prange); + if (r) + goto out; + } out: if (r) { - list_for_each_entry_safe(prange, tmp, insert_list, list) + list_for_each_entry_safe(prange, tmp, insert_list, list) { + if (prange->notifier.mm) + mmu_interval_notifier_remove(&prange->notifier); svm_range_free(prange, false); - list_for_each_entry_safe(prange, tmp, &new_list, list) + } + list_for_each_entry_safe(prange, tmp, &new_list, list) { + if (prange->notifier.mm) + mmu_interval_notifier_remove(&prange->notifier); svm_range_free(prange, true); + } } else { list_splice(&new_list, insert_list); } @@ -3011,8 +3039,12 @@ svm_range *svm_range_create_unregistered_range(struct kfd_node *node, if (is_heap_stack) prange->preferred_loc = KFD_IOCTL_SVM_LOCATION_SYSMEM; + r = svm_range_add_notifier_locked(mm, prange); + if (r) { + svm_range_free(prange, true); + return ERR_PTR(r); + } svm_range_add_to_svms(prange); - svm_range_add_notifier_locked(mm, prange); return prange; } @@ -3203,11 +3235,11 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, goto retry_write_locked; } prange = svm_range_create_unregistered_range(node, p, mm, addr); - if (!prange) { + if (IS_ERR_OR_NULL(prange)) { pr_debug("failed to create unregistered range svms 0x%p address [0x%llx]\n", svms, addr); mmap_write_downgrade(mm); - r = -EFAULT; + r = prange ? PTR_ERR(prange) : -EFAULT; goto out_unlock_svms; } } @@ -3839,7 +3871,7 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm, mutex_lock(&svms->lock); /* Add new range and split existing ranges as needed */ - r = svm_range_add(p, start, size, nattr, attrs, &update_list, + r = svm_range_add(p, mm, start, size, nattr, attrs, &update_list, &insert_list, &remove_list, &remap_list); if (r) { mutex_unlock(&svms->lock); @@ -3847,10 +3879,8 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm, goto out; } /* Apply changes as a transaction */ - list_for_each_entry_safe(prange, next, &insert_list, list) { + list_for_each_entry_safe(prange, next, &insert_list, list) svm_range_add_to_svms(prange); - svm_range_add_notifier_locked(mm, prange); - } list_for_each_entry(prange, &update_list, update_list) svm_range_apply_attrs(p, prange, nattr, attrs, &update_mapping); -- 2.56.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] drm/amdkfd: handle SVM interval notifier registration failures 2026-11-08 5:13 ` [PATCH 1/2] drm/amdkfd: handle SVM interval notifier registration failures Aveline Noir @ 2026-11-08 5:35 ` sashiko-bot 2026-11-08 9:25 ` Aveline Noir 0 siblings, 1 reply; 5+ messages in thread From: sashiko-bot @ 2026-11-08 5:35 UTC (permalink / raw) To: Aveline Noir; +Cc: dri-devel Thank you for your contribution! Sashiko AI review found no new issues in this patch, but noticed 1 related pre-existing issue it does not introduce: - [High] drm/amdkfd: incorrect address unit in svm_range_restore_pages() [1] -- commit 1895ed01e5a9a263f9ad3ebb51b71149e38c2024 Author: Aveline Noir <jm5905938@gmail.com> drm/amdkfd: handle SVM interval notifier registration failures This commit propagates MMU interval notifier registration errors and registers staged SVM ranges before publishing them to the process SVMS or handling retry faults. > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c > index ed5e3318877be..8184cbbb829ef 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c [ ... ] > @@ -3203,11 +3235,11 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, > goto retry_write_locked; > } > prange = svm_range_create_unregistered_range(node, p, mm, addr); > - if (!prange) { > + if (IS_ERR_OR_NULL(prange)) { > pr_debug("failed to create unregistered range svms 0x%p address [0x%llx]\n", > svms, addr); > mmap_write_downgrade(mm); > - r = -EFAULT; > + r = prange ? PTR_ERR(prange) : -EFAULT; > goto out_unlock_svms; > } > } [Severity: High] This problem wasn't introduced by this patch, but does svm_range_restore_pages() pass a page number instead of a byte address to amdgpu_gmc_filter_faults_remove() [1]? amdgpu_vm_handle_fault() passes addr >> PAGE_SHIFT into svm_range_restore_pages(), which then passes addr unchanged to amdgpu_gmc_filter_faults_remove() on the -EAGAIN exit path (and when svm_range_skip_recover() returns true): drivers/gpu/drm/amd/amdkfd/kfd_svm.c:svm_range_restore_pages() { ... if (r == -EAGAIN) { pr_debug("recover vm fault later\n"); amdgpu_gmc_filter_faults_remove(node->adev, addr, pasid); r = 0; } } amdgpu_gmc_filter_faults_remove() hashes its address argument via amdgpu_gmc_fault_key(addr, pasid), which expects the page-aligned byte address that amdgpu_gmc_filter_faults() originally inserted. Passing the shifted page number produces a mismatched key, so the fault entry is never removed from the hardware fault filter and subsequent retries of the fault are suppressed, leading to unrecoverable page faults and GPU hangs. [1] https://sashiko.dev/#/bug/linux-c3a1de9c-2a28-405f-a897-3418639e7854 -- Sashiko AI review · https://sashiko.dev/#/patchset/20261108-kfd-svm-baseline-errors-20261107-v1-0-9ef4008019ab@gmail.com?part=1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] drm/amdkfd: handle SVM interval notifier registration failures 2026-11-08 5:35 ` sashiko-bot @ 2026-11-08 9:25 ` Aveline Noir 0 siblings, 0 replies; 5+ messages in thread From: Aveline Noir @ 2026-11-08 9:25 UTC (permalink / raw) To: sashiko-reviews Cc: David Airlie, Alex Deucher, amd-gfx, Christian König, dri-devel, Felix Kuehling, honghuan, honglei1.huang, linux-kernel, Philip Yang, psirt, sashiko-bot, Simona Vetter, Sunil Khatri Hi Sashiko, On Sun, 08 Nov 2026 05:35:46 +0000 sashiko-bot@kernel.org wrote: > This problem wasn't introduced by this patch, but does > svm_range_restore_pages() pass a page number instead of a byte address to > amdgpu_gmc_filter_faults_remove() [1]? Yes, I'll fix this in a separate patch. Thanks, Aveline Noir ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] drm/amdkfd: check HMM errors before testing range validity 2026-11-08 5:13 [PATCH 0/2] drm/amdkfd: fix SVM error handling Aveline Noir 2026-11-08 5:13 ` [PATCH 1/2] drm/amdkfd: handle SVM interval notifier registration failures Aveline Noir @ 2026-11-08 5:13 ` Aveline Noir 1 sibling, 0 replies; 5+ messages in thread From: Aveline Noir @ 2026-11-08 5:13 UTC (permalink / raw) To: Felix Kuehling, Alex Deucher, Christian König Cc: David Airlie, Simona Vetter, Philip Yang, Sunil Khatri, honghuan, honglei1.huang, psirt, amd-gfx, dri-devel, linux-kernel If the first PFN-array allocation in amdgpu_hmm_range_get_pages() fails, the allocated HMM range still has a NULL notifier. The validity condition in svm_range_validate_and_map() calls amdgpu_hmm_range_valid() before checking the error, dereferencing that NULL notifier. Check the error first so failed requests retain their original error and reach the existing cleanup without testing an uninitialized HMM range. Fixes: c0de552910bb ("drm/amdkfd: clean up the code to free hmm_range") Signed-off-by: Aveline Noir <jm5905938@gmail.com> --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 8184cbbb829e..79455e23a030 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1901,7 +1901,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm, * Override return value to TRY AGAIN only if prior returns * were successful */ - if (range && !amdgpu_hmm_range_valid(range) && !r) { + if (!r && range && !amdgpu_hmm_range_valid(range)) { pr_debug("hmm update the range, need validate again\n"); r = -EAGAIN; } -- 2.56.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-08 9:29 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-08 5:13 [PATCH 0/2] drm/amdkfd: fix SVM error handling Aveline Noir 2026-11-08 5:13 ` [PATCH 1/2] drm/amdkfd: handle SVM interval notifier registration failures Aveline Noir 2026-11-08 5:35 ` sashiko-bot 2026-11-08 9:25 ` Aveline Noir 2026-11-08 5:13 ` [PATCH 2/2] drm/amdkfd: check HMM errors before testing range validity Aveline Noir
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.