All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits
@ 2026-10-20 13:28 Daniel Huang
  2026-10-20 13:29 ` [PATCH v3 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses Daniel Huang
  2026-10-20 13:29 ` [PATCH v3 2/2] drm/amdkfd: bound SVM ranges by the smallest GPU address limit Daniel Huang
  0 siblings, 2 replies; 4+ messages in thread
From: Daniel Huang @ 2026-10-20 13:28 UTC (permalink / raw)
  To: amd-gfx; +Cc: Felix Kuehling, Christian König, Alex Deucher, Daniel Huang

KFD SVM maps memory in GPUVM at the same virtual address used by the
CPU, but no code bounds that address against what the GPU can actually
represent. kfd_ioctl_svm() validates only page alignment and a non-zero
size, and svm_range_map_to_gpu() passes the PFNs straight to
amdgpu_vm_update_range(). The BO mapping path, by contrast, validates
through amdgpu_vm_verify_parameters().

Patch 1 is the crash reported in [1]: with an explicit amdgpu.vm_size
override the GPUVM can be smaller than the CPU address range, and the
page-table walker indexes past the root page-table entries. It disables
SVM when the GPUVM cannot cover AMDGPU_GMC_HOLE_START.

Patch 2 addresses a gap in that check, found by the Sashiko AI review
bot [3]. The comparison is against the GPU's own address hole, so on a
system whose CPU address space is larger than the GPU's it succeeds and
SVM stays enabled, while individual addresses can still fall outside the
GPUVM. Every current GMC generation uses a 4-level, 48-bit GPUVM except
one gfx12 variant, so a 5-level paging CPU reaches this whenever
userspace passes an mmap hint above DEFAULT_MAP_WINDOW.

Changes since v2 [2]:
- Dropped the Fixes: tag and the stable Cc from both patches, and
  dropped stable@vger.kernel.org from the Cc list of this posting. The
  crash requires an explicit amdgpu.vm_size override, which exists for
  driver testing rather than normal end-user configuration, so this is
  not a conventional bug fix (Christian).
- Patch 1 now states in its changelog why GMC v6/v7/v8 cannot be
  affected: kgd2kfd_init_zone_device() returns early for GC IP versions
  below 9.0.1, leaving kfd.pgmap.type at zero, so those parts never
  advertised HSA_CAP_SVMAPI_SUPPORTED to begin with and the new
  condition cannot change their behaviour. Thanks to Felix for
  confirming that KFD SVM has never been supported before GFXv9.
- Patch 2 rewritten following Felix's review. v2 checked every range
  against every GPU at map time, and svm_range_map_to_gpus() skipped a
  GPU that could not represent the range without reporting anything to
  userspace. v3 instead determines the smallest GPUVM among the SVM
  capable GPUs of the process in svm_range_list_init(), stores it in
  svm_range_list, and validates where ranges are created.
- Canonicalised the Closes: URL in patch 1; the previous repository
  redirects to [1].

Three points in patch 2 where I did not follow the suggestion exactly,
flagged here so they are easy to object to:

- The set-attribute check went into svm_range_is_valid() rather than
  svm_range_add(). svm_range_set_attr() calls it immediately before
  svm_range_add(), it already takes (p, start, size) in pages and
  already computes the inclusive last page, it runs before anything is
  allocated, and it additionally covers svm_range_get_attr(). Happy to
  move it into svm_range_add() if you prefer the literal placement.

- svm_range_create_unregistered_range() clamps rather than rejects. Its
  range boundaries widen the fault address to the granularity, so a
  fault that is itself in range can produce a last page that is not.
  Rejecting the widened range would fail a legitimate fault, so only
  the fault address itself is rejected and the widened range is clamped.

- One late check is kept, the hard -EINVAL in svm_range_map_to_gpu(),
  immediately before amdgpu_vm_update_range() walks the page tables.
  With the creation-time validation in place it should be unreachable;
  it is there as a backstop on the exact path that produced the GPF in
  [1]. Say the word and I will drop it.

Note that a process wide minimum makes a GPU with a larger GPUVM
unusable above the smallest limit in the process, even for ranges that
only that GPU would map. Given the 4-level, 48-bit uniformity noted
above this should not be observable on real systems, but it is a
behaviour change and I would rather state it than have it found later.

[1] https://github.com/ROCm/TheRock/issues/9302
[2] https://lore.kernel.org/amd-gfx/20261016170546.88570-1-danielhu@amd.com/
[3] https://sashiko.dev/#/patchset/20261016145129.69645-1-danielhu%40amd.com

Per Documentation/process/generated-content.rst: an AI coding assistant
was used throughout this series, as recorded by the Assisted-by tags. It
diagnosed the fault path ordering that determines where patch 1 emits
its warning, designed the creation-time validation and its call sites in
patch 2, and drafted both changelogs and this cover letter. I reviewed
and tested the result and take responsibility for it.

Patch 1 is tested on a Radeon 780M as described in its notes. Patch 2 is
built for CONFIG_HSA_AMD_SVM=y and =n and otherwise compile-tested only;
I do not have a 5-level paging host with a 4-level GPU to exercise the
out-of-range path directly, so review of the bounds arithmetic would be
welcome.

Daniel Huang (2):
  drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses
  drm/amdkfd: bound SVM ranges by the smallest GPU address limit

 drivers/gpu/drm/amd/amdkfd/kfd_priv.h     |  4 +++
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c      | 44 +++++++++++++++++++++--
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h      | 23 ++++++++++--
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 11 +++++-
 4 files changed, 76 insertions(+), 6 deletions(-)


base-commit: fe9f3ed36c83dcc24b4ca3e8913edd6e33a89150
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v3 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses
  2026-10-20 13:28 [PATCH v3 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits Daniel Huang
@ 2026-10-20 13:29 ` Daniel Huang
  2026-10-20 18:30   ` Felix Kuehling
  2026-10-20 13:29 ` [PATCH v3 2/2] drm/amdkfd: bound SVM ranges by the smallest GPU address limit Daniel Huang
  1 sibling, 1 reply; 4+ messages in thread
From: Daniel Huang @ 2026-10-20 13:29 UTC (permalink / raw)
  To: amd-gfx; +Cc: Felix Kuehling, Christian König, Alex Deucher, Daniel Huang

KFD SVM maps memory in GPUVM at the same virtual address used by
the CPU. However, svm_range_map_to_gpu() passes the corresponding
PFNs to amdgpu_vm_update_range() without checking them against
vm_manager.max_pfn.

If the GPUVM address range is smaller than the CPU address range,
the page-table walker can index beyond the allocated root page-table
entries. Unlike the SVM path, the BO mapping path validates the
address range through amdgpu_vm_verify_parameters().

Only an explicit amdgpu.vm_size override configures a GPUVM smaller
than the driver would select on its own, and that parameter is meant
for driver testing rather than normal end-user configuration.

Reproduced on a Radeon 780M (gfx1103) with amdgpu.vm_size=64.
Repeated hipMallocManaged() allocations attempted to map CPU
address 0x74bd48000000, well beyond the 64 GiB GPUVM limit.
The out-of-bounds root entry contained SLUB poison with
slub_debug=FZPU and recycled heap data without it, resulting in
a general protection fault:

  RIP: 0010:amdgpu_vm_cpu_update+0x2f/0x140 [amdgpu]
   amdgpu_vm_pte_update_flags+0xfa/0x1e0 [amdgpu]
   amdgpu_vm_ptes_update+0x38b/0xa00 [amdgpu]
   amdgpu_vm_update_range+0x279/0x930 [amdgpu]
   svm_range_map_to_gpu+0x13d/0x400 [amdgpu]
   svm_range_validate_and_map+0x8d3/0xaa0 [amdgpu]
   svm_ioctl+0x66/0x80 [amdgpu]
   kfd_ioctl+0x40a/0x650 [amdgpu]

As discussed in [1], rejecting out-of-range PFNs in
amdgpu_vm_update_range() is too late. SVM must not be initialized
when the GPUVM cannot represent the required CPU addresses.

Prevent this by disabling KFD SVM support when the GPUVM address
range is smaller than AMDGPU_GMC_HOLE_START. This prevents
affected devices from advertising SVM support and excludes them
from SVM mappings. Warn from kfd_update_svm_support_properties(),
which runs after the device memory pgmap is registered, so that
only devices that would otherwise have advertised SVM report the
loss of the capability.

KFD SVM has never been supported before GFXv9: kgd2kfd_init_zone_device()
returns early for GC IP versions below 9.0.1, leaving kfd.pgmap.type at
zero, so KFD_IS_SVM_API_SUPPORTED() is already false and
HSA_CAP_SVMAPI_SUPPORTED is never advertised on GMC v6/v7/v8. The new
condition therefore cannot change behaviour on those generations.

The BO and userptr paths are unaffected. Their GPU virtual address is
chosen by user space independently of the CPU address and validated by
amdgpu_vm_verify_parameters() in amdgpu_vm_bo_map(), so an out of range
address is rejected at map time instead of reaching the page tables.
SVM is the only path whose address is dictated by the CPU mapping.

[1] https://lore.kernel.org/amd-gfx/da43b0e3-5bd9-4aa1-86d3-b733f3bad108@amd.com/

Closes: https://github.com/ROCm/TheRock/issues/9302
Assisted-by: Claude:claude-opus-5
Signed-off-by: Daniel Huang <danielhu@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h      | 15 +++++++++++++--
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 11 ++++++++++-
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index c7d7adae4476..f61030408f45 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -203,11 +203,22 @@ struct kfd_process_device *
 svm_range_get_pdd_by_node(struct svm_range *prange, struct kfd_node *node);
 void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm);
 
+/* SVM uses CPU virtual addresses for GPU mappings. Disable SVM if the GPUVM
+ * address range cannot cover the required CPU address range. The parameter
+ * must be named adev, AMDGPU_GMC_HOLE_START dereferences it.
+ */
+static inline bool kfd_svm_vm_covers_user_va(struct amdgpu_device *adev)
+{
+	return (adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT) >=
+		AMDGPU_GMC_HOLE_START;
+}
+
 /* SVM API and HMM page migration work together, device memory type
  * is initialized to not 0 when page migration register device memory.
  */
-#define KFD_IS_SVM_API_SUPPORTED(adev) ((adev)->kfd.pgmap.type != 0 ||\
-					((adev)->apu_prefer_gtt))
+#define KFD_IS_SVM_API_SUPPORTED(adev)					\
+	(((adev)->kfd.pgmap.type != 0 || (adev)->apu_prefer_gtt) &&	\
+	 kfd_svm_vm_covers_user_va(adev))
 
 void svm_range_bo_unref_async(struct svm_range_bo *svm_bo);
 
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 35b3abe57b80..5d12446b8ea8 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -2471,8 +2471,17 @@ void kfd_update_svm_support_properties(struct amdgpu_device *adev)
 				sys_props.generation_count++;
 			else
 				dev_err(adev->dev, "Failed to update SVM support properties. ret=%d\n", ret);
-		} else
+		} else {
+#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
+			if ((adev->kfd.pgmap.type || adev->apu_prefer_gtt) &&
+			    !kfd_svm_vm_covers_user_va(adev))
+				dev_warn_once(adev->dev,
+					      "GPUVM size 0x%llx is too small for KFD SVM; SVM disabled (amdgpu.vm_size=%d)\n",
+					      adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT,
+					      amdgpu_vm_size);
+#endif
 			dev->node_props.capability &= ~HSA_CAP_SVMAPI_SUPPORTED;
+		}
 	}
 	up_write(&topology_lock);
 }
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v3 2/2] drm/amdkfd: bound SVM ranges by the smallest GPU address limit
  2026-10-20 13:28 [PATCH v3 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits Daniel Huang
  2026-10-20 13:29 ` [PATCH v3 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses Daniel Huang
@ 2026-10-20 13:29 ` Daniel Huang
  1 sibling, 0 replies; 4+ messages in thread
From: Daniel Huang @ 2026-10-20 13:29 UTC (permalink / raw)
  To: amd-gfx; +Cc: Felix Kuehling, Christian König, Alex Deucher, Daniel Huang

KFD SVM maps memory in GPUVM at the same virtual address used by the
CPU, but nothing bounds that address against what the GPU can
represent. kfd_ioctl_svm() checks only page alignment and a non-zero
size, so the PFNs reach amdgpu_vm_update_range() unvalidated. Unlike
the SVM path, the BO mapping path validates the address range through
amdgpu_vm_verify_parameters().

Disabling SVM when the GPUVM cannot cover AMDGPU_GMC_HOLE_START closes
the case where the GPUVM is globally too small, but it compares the
GPUVM against the GPU's own address hole. When the CPU address space is
larger than the GPU's, the comparison succeeds and SVM stays enabled
while individual addresses can still fall outside the GPUVM.

On a 5-level paging CPU with a 4-level GPU, mmap() returns addresses
above the GPU limit when user space passes a hint above
DEFAULT_MAP_WINDOW. Passing such an address to KFD SVM indexes beyond
the allocated root page-table entries in amdgpu_vm_pt_descendant().

This gap was found by the Sashiko AI review bot, during review of the
first patch in this series.

Determine the smallest GPUVM among the SVM capable GPUs of the process
in svm_range_list_init(), where the pdds are already final, and store
it in svm_range_list as the first CPU page index that cannot be mapped.
Reuse shared_resources.gpuvm_size, which the KFD already derives from
vm_manager.max_pfn and the GPUVM address hole, and reports to user
space as pdd->gpuvm_limit.

Validate against that limit where ranges are created, so that an
address the GPUs cannot map is rejected as early as possible and never
results in a range that is silently left unmapped:

 - svm_range_is_valid() rejects out of range set_attr and get_attr
   ioctls with -EINVAL, before any range is allocated.
 - svm_range_create_unregistered_range() rejects an out of range fault
   address, which svm_range_restore_pages() reports as -EFAULT. The
   range boundaries widen the fault address to the granularity, so the
   widened range is clamped rather than the fault refused.

svm_range_map_to_gpu() keeps a hard check so that no out of range PFN
can reach amdgpu_vm_update_range() through any caller.

A process wide minimum makes a GPU with a larger GPUVM unusable above
the smallest limit in the process, even for ranges only that GPU would
map. Every SVM capable GMC generation uses a 4-level, 48-bit GPUVM
except one gfx12 variant, so the minimum is uniform in practice.

Link: https://sashiko.dev/#/patchset/20261016145129.69645-1-danielhu%40amd.com
Assisted-by: Claude:claude-opus-5
Signed-off-by: Daniel Huang <danielhu@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_priv.h |  4 +++
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c  | 44 +++++++++++++++++++++++++--
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h  |  8 +++++
 3 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index b9a31489b1c8..a800515baf4a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -907,6 +907,10 @@ struct svm_range_list {
 	atomic_t			drain_pagefaults;
 	struct delayed_work		restore_work;
 	DECLARE_BITMAP(bitmap_supported, MAX_GPU_INSTANCE);
+	/* First CPU page index beyond the smallest GPUVM supported by the
+	 * SVM capable GPUs of this process. Zero if none support SVM.
+	 */
+	uint64_t			max_va_pfn;
 	struct task_struct		*faulting_task;
 	/* check point ts decides if page fault recovery need be dropped */
 	atomic64_t			checkpoint_ts[MAX_GPU_INSTANCE];
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index cfb428c72686..3fa0d6ff7236 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1504,6 +1504,15 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange,
 		return -EINVAL;
 	}
 
+	/* Backstop before amdgpu_vm_update_range() walks the page tables.
+	 * Ranges are bounded when created, so this is not expected to trigger.
+	 */
+	if (npages && last_start + npages - 1 >= kfd_svm_gpu_va_limit_pfn(pdd)) {
+		pr_debug("CPU[0x%lx 0x%lx] exceeds GPUVM, canceling map\n",
+			 last_start, last_start + npages - 1);
+		return -EINVAL;
+	}
+
 	for (i = offset; i < offset + npages; i++) {
 		uint64_t gpu_start;
 		uint64_t gpu_end;
@@ -2960,6 +2969,15 @@ svm_range *svm_range_create_unregistered_range(struct kfd_node *node,
 					   &is_heap_stack))
 		return NULL;
 
+	if (p->svms.max_va_pfn) {
+		if (addr >= p->svms.max_va_pfn) {
+			pr_debug("fault address 0x%llx exceeds GPUVM limit 0x%llx\n",
+				 addr, p->svms.max_va_pfn);
+			return NULL;
+		}
+		last = min_t(unsigned long, last, p->svms.max_va_pfn - 1);
+	}
+
 	r = svm_range_check_vm(p, start, last, &bo_s, &bo_l);
 	if (r != -EADDRINUSE)
 		r = svm_range_check_vm_userptr(p, start, last, &bo_s, &bo_l);
@@ -3410,9 +3428,18 @@ int svm_range_list_init(struct kfd_process *p)
 	INIT_LIST_HEAD(&svms->criu_svm_metadata_list);
 	spin_lock_init(&svms->deferred_list_lock);
 
-	for (i = 0; i < p->n_pdds; i++)
-		if (KFD_IS_SVM_API_SUPPORTED(p->pdds[i]->dev->adev))
-			bitmap_set(svms->bitmap_supported, i, 1);
+	/* The ranges of this process must fit in every GPU that can map them,
+	 * so bound them by the smallest GPUVM among the SVM capable GPUs.
+	 */
+	for (i = 0; i < p->n_pdds; i++) {
+		struct kfd_process_device *pdd = p->pdds[i];
+
+		if (!KFD_IS_SVM_API_SUPPORTED(pdd->dev->adev))
+			continue;
+		bitmap_set(svms->bitmap_supported, i, 1);
+		svms->max_va_pfn = min_not_zero(svms->max_va_pfn,
+						kfd_svm_gpu_va_limit_pfn(pdd));
+	}
 
 	 /* Value of default granularity cannot exceed 0x1B, the
 	  * number of pages supported by a 4-level paging table
@@ -3511,6 +3538,17 @@ svm_range_is_valid(struct kfd_process *p, uint64_t start, uint64_t size)
 	if (check_add_overflow(start, size << PAGE_SHIFT, &end))
 		return -EOVERFLOW;
 
+	/* Reject up front what the GPUs of this process cannot map, rather
+	 * than letting the mapping fail later on.
+	 */
+	if (p->svms.max_va_pfn &&
+	    (end - 1) >> PAGE_SHIFT >= p->svms.max_va_pfn) {
+		pr_debug("CPU[0x%lx 0x%lx] exceeds GPUVM limit 0x%llx\n",
+			 start_unchg, (end - 1) >> PAGE_SHIFT,
+			 p->svms.max_va_pfn);
+		return -EINVAL;
+	}
+
 	do {
 		vma = vma_lookup(p->mm, start);
 		if (!vma || (vma->vm_flags & device_vma))
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index f61030408f45..268a545302bd 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -213,6 +213,14 @@ static inline bool kfd_svm_vm_covers_user_va(struct amdgpu_device *adev)
 		AMDGPU_GMC_HOLE_START;
 }
 
+/* First CPU page index that this GPU's GPUVM cannot represent. An SVM range
+ * is mappable on pdd only if its last page lies below this.
+ */
+static inline uint64_t kfd_svm_gpu_va_limit_pfn(struct kfd_process_device *pdd)
+{
+	return pdd->dev->kfd->shared_resources.gpuvm_size >> PAGE_SHIFT;
+}
+
 /* SVM API and HMM page migration work together, device memory type
  * is initialized to not 0 when page migration register device memory.
  */
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses
  2026-10-20 13:29 ` [PATCH v3 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses Daniel Huang
@ 2026-10-20 18:30   ` Felix Kuehling
  0 siblings, 0 replies; 4+ messages in thread
From: Felix Kuehling @ 2026-10-20 18:30 UTC (permalink / raw)
  To: Daniel Huang, amd-gfx; +Cc: Christian König, Alex Deucher

On 2026-10-20 09:29, Daniel Huang wrote:
> KFD SVM maps memory in GPUVM at the same virtual address used by
> the CPU. However, svm_range_map_to_gpu() passes the corresponding
> PFNs to amdgpu_vm_update_range() without checking them against
> vm_manager.max_pfn.
>
> If the GPUVM address range is smaller than the CPU address range,
> the page-table walker can index beyond the allocated root page-table
> entries. Unlike the SVM path, the BO mapping path validates the
> address range through amdgpu_vm_verify_parameters().
>
> Only an explicit amdgpu.vm_size override configures a GPUVM smaller
> than the driver would select on its own, and that parameter is meant
> for driver testing rather than normal end-user configuration.
>
> Reproduced on a Radeon 780M (gfx1103) with amdgpu.vm_size=64.
> Repeated hipMallocManaged() allocations attempted to map CPU
> address 0x74bd48000000, well beyond the 64 GiB GPUVM limit.
> The out-of-bounds root entry contained SLUB poison with
> slub_debug=FZPU and recycled heap data without it, resulting in
> a general protection fault:
>
>    RIP: 0010:amdgpu_vm_cpu_update+0x2f/0x140 [amdgpu]
>     amdgpu_vm_pte_update_flags+0xfa/0x1e0 [amdgpu]
>     amdgpu_vm_ptes_update+0x38b/0xa00 [amdgpu]
>     amdgpu_vm_update_range+0x279/0x930 [amdgpu]
>     svm_range_map_to_gpu+0x13d/0x400 [amdgpu]
>     svm_range_validate_and_map+0x8d3/0xaa0 [amdgpu]
>     svm_ioctl+0x66/0x80 [amdgpu]
>     kfd_ioctl+0x40a/0x650 [amdgpu]
>
> As discussed in [1], rejecting out-of-range PFNs in
> amdgpu_vm_update_range() is too late. SVM must not be initialized
> when the GPUVM cannot represent the required CPU addresses.
>
> Prevent this by disabling KFD SVM support when the GPUVM address
> range is smaller than AMDGPU_GMC_HOLE_START. This prevents
> affected devices from advertising SVM support and excludes them
> from SVM mappings. Warn from kfd_update_svm_support_properties(),
> which runs after the device memory pgmap is registered, so that
> only devices that would otherwise have advertised SVM report the
> loss of the capability.
>
> KFD SVM has never been supported before GFXv9: kgd2kfd_init_zone_device()
> returns early for GC IP versions below 9.0.1, leaving kfd.pgmap.type at
> zero, so KFD_IS_SVM_API_SUPPORTED() is already false and
> HSA_CAP_SVMAPI_SUPPORTED is never advertised on GMC v6/v7/v8. The new
> condition therefore cannot change behaviour on those generations.
>
> The BO and userptr paths are unaffected. Their GPU virtual address is
> chosen by user space independently of the CPU address and validated by
> amdgpu_vm_verify_parameters() in amdgpu_vm_bo_map(), so an out of range
> address is rejected at map time instead of reaching the page tables.
> SVM is the only path whose address is dictated by the CPU mapping.
>
> [1] https://lore.kernel.org/amd-gfx/da43b0e3-5bd9-4aa1-86d3-b733f3bad108@amd.com/
>
> Closes: https://github.com/ROCm/TheRock/issues/9302
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Daniel Huang <danielhu@amd.com>

Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>


> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_svm.h      | 15 +++++++++++++--
>   drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 11 ++++++++++-
>   2 files changed, 23 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> index c7d7adae4476..f61030408f45 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> @@ -203,11 +203,22 @@ struct kfd_process_device *
>   svm_range_get_pdd_by_node(struct svm_range *prange, struct kfd_node *node);
>   void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm);
>   
> +/* SVM uses CPU virtual addresses for GPU mappings. Disable SVM if the GPUVM
> + * address range cannot cover the required CPU address range. The parameter
> + * must be named adev, AMDGPU_GMC_HOLE_START dereferences it.
> + */
> +static inline bool kfd_svm_vm_covers_user_va(struct amdgpu_device *adev)
> +{
> +	return (adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT) >=
> +		AMDGPU_GMC_HOLE_START;
> +}
> +
>   /* SVM API and HMM page migration work together, device memory type
>    * is initialized to not 0 when page migration register device memory.
>    */
> -#define KFD_IS_SVM_API_SUPPORTED(adev) ((adev)->kfd.pgmap.type != 0 ||\
> -					((adev)->apu_prefer_gtt))
> +#define KFD_IS_SVM_API_SUPPORTED(adev)					\
> +	(((adev)->kfd.pgmap.type != 0 || (adev)->apu_prefer_gtt) &&	\
> +	 kfd_svm_vm_covers_user_va(adev))
>   
>   void svm_range_bo_unref_async(struct svm_range_bo *svm_bo);
>   
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> index 35b3abe57b80..5d12446b8ea8 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
> @@ -2471,8 +2471,17 @@ void kfd_update_svm_support_properties(struct amdgpu_device *adev)
>   				sys_props.generation_count++;
>   			else
>   				dev_err(adev->dev, "Failed to update SVM support properties. ret=%d\n", ret);
> -		} else
> +		} else {
> +#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
> +			if ((adev->kfd.pgmap.type || adev->apu_prefer_gtt) &&
> +			    !kfd_svm_vm_covers_user_va(adev))
> +				dev_warn_once(adev->dev,
> +					      "GPUVM size 0x%llx is too small for KFD SVM; SVM disabled (amdgpu.vm_size=%d)\n",
> +					      adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT,
> +					      amdgpu_vm_size);
> +#endif
>   			dev->node_props.capability &= ~HSA_CAP_SVMAPI_SUPPORTED;
> +		}
>   	}
>   	up_write(&topology_lock);
>   }

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-20 18:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-20 13:28 [PATCH v3 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits Daniel Huang
2026-10-20 13:29 ` [PATCH v3 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses Daniel Huang
2026-10-20 18:30   ` Felix Kuehling
2026-10-20 13:29 ` [PATCH v3 2/2] drm/amdkfd: bound SVM ranges by the smallest GPU address limit Daniel Huang

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.