Re: [PATCH] drm/amdkfd: don't repeat a SVM migration that collected no pages
"Chen, Xiaogang" <[email protected]> Thu, 6 Aug 2026 11:19:43 -0500
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
On 8/6/2026 9:31 AM, William Palacek wrote:
> svm_range_restore_pages() migrates the faulting granule to best_loc
> whenever prange->actual_loc or best_loc is set, without checking whether
> that window already lives there.
>
> When it does, MIGRATE_VMA_SELECT_SYSTEM has nothing to collect and
> migrate_vma_setup() returns cpages == 0. By then it has already issued
Can you explain how cpage == 0 after migrate_vma_setup? if
migrate_vma_setup cannot collect src pages correspondent to vm range,
have previous code like svm_range_create_unregistered_range or
vma_lookup already failed?
> MMU_NOTIFY_MIGRATE, which svm_range_cpu_invalidate_pagetables() turns
> into svm_range_unmap_from_gpus() for that window, so the mapping the
Is there gpu mapping at that range if at cpu side there is no page can
be collected for same range? One case I can think is src pages got
pinned at cpu side, then cannot be collected, then app should not
register the range to svm since the page cannot be migrated to gpu, then
has no gpu mapping.
> fault needed is torn down to service a migration that moves nothing and
> the fault is re-armed rather than resolved. Under XNACK on an
> oversubscribed range this becomes a loop: svm_range_restore_pages() and
> svm_migrate_to_vram() are entered thousands of times per second,
> svm_migrate_copy_to_vram() is never reached, and the per process
> migration counters stop advancing while the GPU stays busy.
I am not sure if it can cause infinite loop. If there is no page got
migrated to vram the following amdgpu_hmm_range_get_pages will get sys
ram for that range, then driver maps the range to sys ram pages unless
there even no sys ram pages for the range that can be faulted in, then
amdgpu_hmm_range_get_pages will fail, then this page fault cannot be
restored.
The main concern is under what situation there is gpu page fault and hmm
cannot collect sys ram pages at cpu side? If it happens, is it app issue
or has been detected/handled?
>
> The notification cannot be filtered by pgmap owner, as it is what
> invalidates the PTEs for pages that really do move. Avoid starting a
> migration that cannot move anything instead. Per window residency is not
> cheaply available beforehand, so record the window of a migration that
> collected nothing and do not repeat it there until a short backoff
> expires.
>
> Fixes: a546a2768440 ("drm/amdkfd: Use partial migrations/mapping for GPU/CPU page faults in SVM")
Why it is related to partial migration for page restore? If there is no
page can be collected at cpu side this issue is more general, not
related to migration amount.
Regards
Xiaogang
> Signed-off-by: William Palacek<[email protected]>
> ---
> drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 23 +++++++++++++++++++++++
> drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 4 ++++
> 2 files changed, 27 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index fa4054d51f60..b946ae95ff12 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -50,6 +50,11 @@
> * page table is updated.
> */
> #define AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING (2UL * NSEC_PER_MSEC)
> +
> +/* Long enough that a retry fault storm cannot re-arm a migration which
> + * has already been found to have nothing to collect.
> + */
> +#define AMDGPU_SVM_RANGE_NOOP_MIGRATE_BACKOFF (100UL * NSEC_PER_MSEC)
> #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG)
> #define dynamic_svm_range_dump(svms) \
> _dynamic_func_call_no_desc("svm_range_dump", svm_range_debug_dump, svms)
> @@ -3221,8 +3226,25 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
> last = min_t(unsigned long, ALIGN(addr + 1, size) - 1, prange->last);
> if (prange->actual_loc != 0 || best_loc != 0) {
> if (best_loc) {
> + uint64_t vram_pages = prange->vram_pages;
> +
> + /* migrate_vma_setup() unmaps the window before it knows
> + * whether it can collect anything, so a migration that
> + * collects nothing re-arms this fault instead of
> + * resolving it.
> + */
> + if (start == prange->noop_migrate_start &&
> + ktime_before(timestamp,
> + ktime_add_ns(prange->noop_migrate_timestamp,
> + AMDGPU_SVM_RANGE_NOOP_MIGRATE_BACKOFF)))
> + goto skip_migrate;
> +
> r = svm_migrate_to_vram(prange, best_loc, start, last,
> mm, KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU);
> + if (!r && prange->vram_pages == vram_pages) {
> + prange->noop_migrate_start = start;
> + prange->noop_migrate_timestamp = ktime_get_boottime();
> + }
> if (r) {
> pr_debug("svm_migrate_to_vram failed (%d) at %llx, falling back to system memory\n",
> r, addr);
> @@ -3248,6 +3270,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
> }
> }
>
> +skip_migrate:
> r = svm_range_validate_and_map(mm, start, last, prange, gpuidx, false,
> false, false);
> if (r)
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> index c7d7adae4476..508a086195ac 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> @@ -93,6 +93,8 @@ struct svm_work_list_item {
> * @granularity:migration granularity, log2 num pages
> * @invalid: not 0 means cpu page table is invalidated
> * @validate_timestamp: system timestamp when range is validated
> + * @noop_migrate_start: start of the last migration that collected no pages
> + * @noop_migrate_timestamp: system timestamp of that migration
> * @notifier: register mmu interval notifier
> * @work_item: deferred work item information
> * @deferred_list: list header used to add range to deferred list
> @@ -131,6 +133,8 @@ struct svm_range {
> uint8_t granularity;
> atomic_t invalid;
> ktime_t validate_timestamp;
> + unsigned long noop_migrate_start;
> + ktime_t noop_migrate_timestamp;
> struct mmu_interval_notifier notifier;
> struct svm_work_list_item work_item;
> struct list_head deferred_list;