mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits
@ 2026-10-16 17:05 Daniel Huang
  2026-10-16 17:05 ` [PATCH v2 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses Daniel Huang
  2026-10-16 17:05 ` [PATCH v2 2/2] drm/amdkfd: validate SVM ranges against the target GPU address limits Daniel Huang
  0 siblings, 2 replies; 4+ messages in thread
From: Daniel Huang @ 2026-10-16 17:05 UTC (permalink / raw)
  To: Felix.Kuehling, alexander.deucher
  Cc: christian.koenig, alex.sierra, Philip.Yang, amd-gfx, dri-devel,
	linux-kernel, stable, 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.

Patch 2 validates each range against the limits of the GPU it is mapped
on instead, covering the mapping, unmapping and fault recovery paths.
Using TASK_SIZE_MAX for the patch 1 check was considered and rejected:
it would disable SVM on every 5-level paging host for every 4-level
GPU, including the gfx9 datacenter parts.

Patch 2 alone would also prevent the crash in [1], by rejecting the
mapping rather than by refusing to advertise SVM. Both are included
because without patch 1 the topology still reports
HSA_CAP_SVMAPI_SUPPORTED, so userspace sees runtime failures instead of
a clear signal that the device cannot do SVM. If only one is wanted,
dropping either is straightforward.

Changes since v1 [2]:
- Moved the warning from amdgpu_amdkfd_device_init() to
  kfd_update_svm_support_properties(). pgmap.type is only assigned in
  kgd2kfd_init_zone_device(), which runs in late init, after
  amdgpu_amdkfd_device_init(). Testing the capability at the old site
  therefore never fired for dGPUs, and amdgpu_reset.c calls the two in
  the opposite order, making the behaviour path dependent.
- Scoped the warning to devices that would otherwise have advertised
  SVM, so GMC v6/v7/v8 no longer warn, and made it dev_warn_once() since
  the surrounding loop can match several topology nodes per adev.
- Guarded the new code with CONFIG_HSA_AMD_SVM. kfd_topology.o builds
  unconditionally while kfd_svm.o does not, so the reference to the new
  helper breaks a CONFIG_HSA_AMD_SVM=n build without it.
- Fixed the [1] reference, which was a placeholder in v1.
- Added patch 2.

[1] https://lore.kernel.org/amd-gfx/da43b0e3-5bd9-4aa1-86d3-b733f3bad108@amd.com/
[2] https://lore.kernel.org/amd-gfx/20261016145129.69645-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 kfd_svm_range_fits_gpu() 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
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 in kfd_svm_range_fits_gpu() would be welcome.

Daniel Huang (2):
  drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses
  drm/amdkfd: validate SVM ranges against the target GPU address limits

 drivers/gpu/drm/amd/amdkfd/kfd_svm.c      | 42 +++++++++++++++++++++
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h      | 45 ++++++++++++++++++++++-
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 14 ++++++-
 3 files changed, 98 insertions(+), 3 deletions(-)


base-commit: fe9f3ed36c83dcc24b4ca3e8913edd6e33a89150
-- 
2.53.0


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

* [PATCH v2 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses
  2026-10-16 17:05 [PATCH v2 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits Daniel Huang
@ 2026-10-16 17:05 ` Daniel Huang
  2026-10-16 17:05 ` [PATCH v2 2/2] drm/amdkfd: validate SVM ranges against the target GPU address limits Daniel Huang
  1 sibling, 0 replies; 4+ messages in thread
From: Daniel Huang @ 2026-10-16 17:05 UTC (permalink / raw)
  To: Felix.Kuehling, alexander.deucher
  Cc: christian.koenig, alex.sierra, Philip.Yang, amd-gfx, dri-devel,
	linux-kernel, stable, 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().

An explicit amdgpu.vm_size override can trigger this condition by
configuring a smaller GPUVM than the driver would normally select.

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.

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

Fixes: f80fe9d3c114 ("drm/amdkfd: map svm range to GPUs")
Closes: https://github.com/ROCm/legacy-rocm-build/issues/6691
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5
Signed-off-by: Daniel Huang <danielhu@amd.com>
---

Tested on a Radeon 780M (gfx1103, PCI 1002:15bf), kernel
7.0.0-38-generic, and ROCm 7.13.0-2.

The reproducer performs 24 iterations of hipMallocManaged(1 GiB),
hipMemset(), and hipFree() per run, with 40 runs per attempt.

With amdgpu.vm_size=64:
- Stock module: kernel Oops within approximately 2 seconds on
  every attempt.
- Patched module: completed 40/40 runs in two attempts, with
  stock and patched modules tested alternately on the same kernel.

With the default GPUVM size, the patched module preserved SVM
support, emitted no warning, and completed the same test.

Two questions for maintainers:

1. I interpreted "SVM must fail to initialize" as disabling
   the SVM capability for affected devices rather than failing
   KFD initialization or rejecting the vm_size override.
   Would a different approach be preferable?

2. This check also affects GMC v6/v7/v8, whose GPUVM address
   ranges cannot reach AMDGPU_GMC_HOLE_START. Although these
   devices do not register device-private memory, an APU with
   apu_prefer_gtt can currently advertise SVM support.

   Should the check apply to these devices as well, or should
   it be limited to explicitly configured amdgpu.vm_size
   overrides?
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h      | 18 ++++++++++++++++--
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 14 +++++++++++++-
 2 files changed, 29 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..6235ce0f988e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -203,11 +203,25 @@ 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 since AMDGPU_GMC_HOLE_START references
+ * adev->vm_manager.max_level.
+ */
+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..5de19fa27d12 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -2471,8 +2471,20 @@ 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)
+			/* Report it rather than letting the capability
+			 * silently vanish from the KFD topology.
+			 */
+			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	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] drm/amdkfd: validate SVM ranges against the target GPU address limits
  2026-10-16 17:05 [PATCH v2 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits Daniel Huang
  2026-10-16 17:05 ` [PATCH v2 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses Daniel Huang
@ 2026-10-16 17:05 ` Daniel Huang
  2026-10-16 19:54   ` Felix Kuehling
  1 sibling, 1 reply; 4+ messages in thread
From: Daniel Huang @ 2026-10-16 17:05 UTC (permalink / raw)
  To: Felix.Kuehling, alexander.deucher
  Cc: christian.koenig, alex.sierra, Philip.Yang, amd-gfx, dri-devel,
	linux-kernel, stable, 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 target 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 userspace 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.

Validate every range against the limits of the GPU it is being mapped
on, using both vm_manager.max_pfn and the GPUVM address hole, and
check the end of the range rather than only its start.

GPUs in one process can have different address limits, so the range is
checked per GPU. svm_range_validate_and_map() skips the GPUs that
cannot represent the range instead of failing the whole mapping,
matching how it already skips GPUs outside the XGMI hive.
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.

Page fault recovery is rejected early in svm_range_restore_pages(), and
svm_range_unmap_from_gpu() skips ranges that were never mappable rather
than returning an error, since unmap also runs on the eviction and
process teardown paths.

Link: https://sashiko.dev/#/patchset/20261016145129.69645-1-danielhu%40amd.com
Fixes: f80fe9d3c114 ("drm/amdkfd: map svm range to GPUs")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5
Signed-off-by: Daniel Huang <danielhu@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 42 ++++++++++++++++++++++++++++
 drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 27 ++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index cfb428c72686..c3e4f0367522 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1427,6 +1427,16 @@ svm_range_unmap_from_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
 		return -EINVAL;
 	}
 
+	/* Such a range was rejected by svm_range_map_to_gpu() and so was
+	 * never mapped. Skip it rather than failing, since unmap is also
+	 * used on the eviction and process teardown paths.
+	 */
+	if (!kfd_svm_range_fits_gpu(adev, start, last)) {
+		pr_debug("CPU[0x%llx 0x%llx] exceeds GPUVM, skipping unmap\n",
+			 start, last);
+		return 0;
+	}
+
 	return amdgpu_vm_update_range(adev, vm, false, true, true, false, NULL, gpu_start,
 				      gpu_end, init_pte_value, 0, 0, NULL, NULL,
 				      fence);
@@ -1504,6 +1514,16 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange,
 		return -EINVAL;
 	}
 
+	/* Last line of defence before amdgpu_vm_update_range() walks the
+	 * page tables with these PFNs.
+	 */
+	if (npages && !kfd_svm_range_fits_gpu(adev, last_start,
+					      last_start + npages - 1)) {
+		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;
@@ -1604,6 +1624,20 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
 			continue;
 		}
 
+		/* GPUs in the same process can have different address limits.
+		 * Skip the ones that cannot represent this range instead of
+		 * failing the whole mapping.
+		 */
+		if (npages && !kfd_svm_range_fits_gpu(pdd->dev->adev,
+						      prange->start + offset,
+						      prange->start + offset +
+						      npages - 1)) {
+			pr_debug("device idx %d cannot map CPU[0x%lx 0x%lx]\n",
+				 gpuidx, prange->start + offset,
+				 prange->start + offset + npages - 1);
+			continue;
+		}
+
 		set_bit(gpuidx, prange->bitmap_mapped);
 
 		r = svm_range_map_to_gpu(pdd, prange, offset, npages, readonly,
@@ -3096,6 +3130,14 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
 		return -EFAULT;
 	}
 
+	/* addr is a CPU page index here. Reject faults the GPUVM cannot
+	 * represent before any range is looked up or migrated.
+	 */
+	if (!kfd_svm_range_fits_gpu(adev, addr, addr)) {
+		pr_debug("fault address 0x%llx exceeds GPUVM\n", addr);
+		return -EFAULT;
+	}
+
 	p = kfd_lookup_process_by_pasid(pasid, NULL);
 	if (!p) {
 		pr_debug("kfd process not founded pasid 0x%x\n", pasid);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
index 6235ce0f988e..57d4d79a6266 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
@@ -216,6 +216,33 @@ static inline bool kfd_svm_vm_covers_user_va(struct amdgpu_device *adev)
 		AMDGPU_GMC_HOLE_START;
 }
 
+/*
+ * A range is mappable on adev only if it lies below both the page table
+ * limit and the GPUVM address hole. start and last are CPU page indices
+ * and are inclusive, matching svm_range.start and svm_range.last.
+ *
+ * Each GPU is checked against its own limits, so a range that only some
+ * GPUs can represent is rejected for those GPUs alone.
+ *
+ * The parameter must be named adev since AMDGPU_GMC_HOLE_START references
+ * adev->vm_manager.max_level.
+ */
+static inline bool kfd_svm_range_fits_gpu(struct amdgpu_device *adev,
+					  uint64_t start, uint64_t last)
+{
+	uint64_t limit;
+
+	/* Rejects empty and wrapped ranges, so last bounds start as well. */
+	if (start > last)
+		return false;
+
+	/* First CPU page the GPUVM cannot represent. */
+	limit = min(adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT,
+		    AMDGPU_GMC_HOLE_START) >> PAGE_SHIFT;
+
+	return last < limit;
+}
+
 /* 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	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/2] drm/amdkfd: validate SVM ranges against the target GPU address limits
  2026-10-16 17:05 ` [PATCH v2 2/2] drm/amdkfd: validate SVM ranges against the target GPU address limits Daniel Huang
@ 2026-10-16 19:54   ` Felix Kuehling
  0 siblings, 0 replies; 4+ messages in thread
From: Felix Kuehling @ 2026-10-16 19:54 UTC (permalink / raw)
  To: Daniel Huang, alexander.deucher
  Cc: christian.koenig, alex.sierra, Philip.Yang, amd-gfx, dri-devel,
	linux-kernel, stable

On 2026-10-16 13:05, Daniel Huang wrote:
> KFD SVM maps memory in GPUVM at the same virtual address used by the
> CPU, but nothing bounds that address against what the target 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 userspace 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.
>
> Validate every range against the limits of the GPU it is being mapped
> on, using both vm_manager.max_pfn and the GPUVM address hole, and
> check the end of the range rather than only its start.
>
> GPUs in one process can have different address limits, so the range is
> checked per GPU. svm_range_validate_and_map() skips the GPUs that
> cannot represent the range instead of failing the whole mapping,
> matching how it already skips GPUs outside the XGMI hive.
> 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.
>
> Page fault recovery is rejected early in svm_range_restore_pages(), and
> svm_range_unmap_from_gpu() skips ranges that were never mappable rather
> than returning an error, since unmap also runs on the eviction and
> process teardown paths.

AFAICT, this breaks mapping of memory to GPUs without any feedback to 
user mode (until a VM fault kills the application). It also duplicates 
the check many times (every time a range is mapped or unmapped for any 
reason). I'd rather reject address ranges that aren't GPU-addressable as 
early as possible in the set-attribute calls that create SVM ranges. 
That way user mode can observe the failure when it happens, which makes 
the problem easier to debug or recover from.

In other words, save the minimum virtual address limit of all supported 
GPUs used in a process in process->svms during 
svm_range_list_init. Check virtual addresses against that limit in 
svm_range_add (for ranges created by set_attribute ioctls) and 
svm_range_create_unregistered_range (for ranges created by page fault 
interrupts).

Regards,
   Felix


>
> Link: https://sashiko.dev/#/patchset/20261016145129.69645-1-danielhu%40amd.com
> Fixes: f80fe9d3c114 ("drm/amdkfd: map svm range to GPUs")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Daniel Huang <danielhu@amd.com>
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 42 ++++++++++++++++++++++++++++
>   drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 27 ++++++++++++++++++
>   2 files changed, 69 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index cfb428c72686..c3e4f0367522 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -1427,6 +1427,16 @@ svm_range_unmap_from_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
>   		return -EINVAL;
>   	}
>   
> +	/* Such a range was rejected by svm_range_map_to_gpu() and so was
> +	 * never mapped. Skip it rather than failing, since unmap is also
> +	 * used on the eviction and process teardown paths.
> +	 */
> +	if (!kfd_svm_range_fits_gpu(adev, start, last)) {
> +		pr_debug("CPU[0x%llx 0x%llx] exceeds GPUVM, skipping unmap\n",
> +			 start, last);
> +		return 0;
> +	}
> +
>   	return amdgpu_vm_update_range(adev, vm, false, true, true, false, NULL, gpu_start,
>   				      gpu_end, init_pte_value, 0, 0, NULL, NULL,
>   				      fence);
> @@ -1504,6 +1514,16 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange,
>   		return -EINVAL;
>   	}
>   
> +	/* Last line of defence before amdgpu_vm_update_range() walks the
> +	 * page tables with these PFNs.
> +	 */
> +	if (npages && !kfd_svm_range_fits_gpu(adev, last_start,
> +					      last_start + npages - 1)) {
> +		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;
> @@ -1604,6 +1624,20 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
>   			continue;
>   		}
>   
> +		/* GPUs in the same process can have different address limits.
> +		 * Skip the ones that cannot represent this range instead of
> +		 * failing the whole mapping.
> +		 */
> +		if (npages && !kfd_svm_range_fits_gpu(pdd->dev->adev,
> +						      prange->start + offset,
> +						      prange->start + offset +
> +						      npages - 1)) {
> +			pr_debug("device idx %d cannot map CPU[0x%lx 0x%lx]\n",
> +				 gpuidx, prange->start + offset,
> +				 prange->start + offset + npages - 1);
> +			continue;
> +		}
> +
>   		set_bit(gpuidx, prange->bitmap_mapped);
>   
>   		r = svm_range_map_to_gpu(pdd, prange, offset, npages, readonly,
> @@ -3096,6 +3130,14 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
>   		return -EFAULT;
>   	}
>   
> +	/* addr is a CPU page index here. Reject faults the GPUVM cannot
> +	 * represent before any range is looked up or migrated.
> +	 */
> +	if (!kfd_svm_range_fits_gpu(adev, addr, addr)) {
> +		pr_debug("fault address 0x%llx exceeds GPUVM\n", addr);
> +		return -EFAULT;
> +	}
> +
>   	p = kfd_lookup_process_by_pasid(pasid, NULL);
>   	if (!p) {
>   		pr_debug("kfd process not founded pasid 0x%x\n", pasid);
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> index 6235ce0f988e..57d4d79a6266 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h
> @@ -216,6 +216,33 @@ static inline bool kfd_svm_vm_covers_user_va(struct amdgpu_device *adev)
>   		AMDGPU_GMC_HOLE_START;
>   }
>   
> +/*
> + * A range is mappable on adev only if it lies below both the page table
> + * limit and the GPUVM address hole. start and last are CPU page indices
> + * and are inclusive, matching svm_range.start and svm_range.last.
> + *
> + * Each GPU is checked against its own limits, so a range that only some
> + * GPUs can represent is rejected for those GPUs alone.
> + *
> + * The parameter must be named adev since AMDGPU_GMC_HOLE_START references
> + * adev->vm_manager.max_level.
> + */
> +static inline bool kfd_svm_range_fits_gpu(struct amdgpu_device *adev,
> +					  uint64_t start, uint64_t last)
> +{
> +	uint64_t limit;
> +
> +	/* Rejects empty and wrapped ranges, so last bounds start as well. */
> +	if (start > last)
> +		return false;
> +
> +	/* First CPU page the GPUVM cannot represent. */
> +	limit = min(adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT,
> +		    AMDGPU_GMC_HOLE_START) >> PAGE_SHIFT;
> +
> +	return last < limit;
> +}
> +
>   /* SVM API and HMM page migration work together, device memory type
>    * is initialized to not 0 when page migration register device memory.
>    */

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

end of thread, other threads:[~2026-10-16 19:55 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-16 17:05 [PATCH v2 0/2] drm/amdkfd: bound SVM mappings by the GPU address limits Daniel Huang
2026-10-16 17:05 ` [PATCH v2 1/2] drm/amdkfd: disable SVM when the GPUVM cannot cover CPU addresses Daniel Huang
2026-10-16 17:05 ` [PATCH v2 2/2] drm/amdkfd: validate SVM ranges against the target GPU address limits Daniel Huang
2026-10-16 19:54   ` Felix Kuehling

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®