diff options
| author | Jesse Zhang <Jesse.Zhang@amd.com> | 2026-10-13 13:17:53 +0800 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-10-27 17:03:36 -0400 |
| commit | 52957e813f2f025c86e4aa6e86cb4963ef94fd00 (patch) | |
| tree | 2db8ef5041b11fbbd1015142fc76d28eef892ea2 /drivers/gpu | |
| parent | ba4c3c202919405f461a393e823e4b72c8518494 (diff) | |
drm/amdkfd: split vram_pages of SVM ranges prefetched without a GPU mapping
When an SVM range is split, svm_range_split_pages() gives the new range
the number of VRAM pages counted in its part of the dma_addr arrays and
subtracts it from the old range. Pages migrated to VRAM by a prefetch
have no dma_addr entries until the range is mapped on a GPU, e.g. with
no ACCESS attribute, or with XNACK off before the delayed restore worker
mapped it, so the new range gets 0 and the old one keeps the count for
both.
Migrating the parts back to system memory then gets the accounting
wrong: the old part keeps a VRAM page count after all its pages are
gone, so its svm_bo is never freed, and the new part underflows. On
navi31, as an unprivileged process: prefetch 4 MiB to the GPU, prefetch
the upper 2 MiB and then the lower 2 MiB back to system memory:
Recorded vram pages(0x0) should not be less than migration pages(0x200).
WARNING: ../amdkfd/kfd_migrate.c:922 at svm_migrate_vram_to_ram+0xbdc/0xcd0 [amdgpu]
and /sys/class/kfd/kfd/proc/<pid>/vram_<gpu_id> stays at 4194304 until
the process exits.
Without dma_addr arrays, the split is still exact when the old range is
completely in VRAM, which is what a prefetch of the whole range leaves.
Give the new range all its pages in that case. The warning is gone and
the VRAM usage drops back to 0.
This doesn't cover a range that is only partly in VRAM without dma_addr
arrays, e.g. after a partial migration, since svm_migrate_ram_to_vram()
only counts the pages it actually migrated. That would need VRAM
residency to be tracked per page independently of dma_addr.
v2:
- Rename counted to has_dma_addr and compare against old->npages (Philip)
- Mention the XNACK off case and the partial migration limitation (Philip)
Fixes: 006ad514a50c ("drm/amdkfd: Use partial hmm page walk during buffer validation in SVM")
Reviewed-by: Philip Yang <philip.yang@amd.com>
Signed-off-by: Jesse Zhang <Jesse.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 7ca6f3359b557a267c7b07a2fd748b1473395e10)
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index a4ce54b06975..ed5e3318877b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1020,9 +1020,12 @@ svm_range_split_pages(struct svm_range *new, struct svm_range *old, uint64_t start, uint64_t last) { uint64_t npages = last - start + 1; + bool has_dma_addr = false; int i, r; for (i = 0; i < MAX_GPU_INSTANCE; i++) { + if (old->dma_addr[i]) + has_dma_addr = true; r = svm_range_split_array(&new->dma_addr[i], &old->dma_addr[i], sizeof(*old->dma_addr[i]), old->start, npages, new->start, new->npages, @@ -1030,8 +1033,16 @@ svm_range_split_pages(struct svm_range *new, struct svm_range *old, if (r) return r; } - if (old->actual_loc) + if (old->actual_loc) { + /* + * Pages migrated by prefetch have no dma_addr until they are + * mapped on a GPU. A fully resident range still splits exactly, + * old->npages isn't adjusted yet here. + */ + if (!has_dma_addr && old->vram_pages == old->npages) + new->vram_pages = new->npages; old->vram_pages -= new->vram_pages; + } return 0; } |
