AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] drm/amdgpu: svm check hmm range kzalloc return NULL
@ 2025-10-03 18:15 Philip Yang
  2025-10-03 18:15 ` [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address Philip Yang
  2025-10-03 18:15 ` [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker Philip Yang
  0 siblings, 2 replies; 11+ messages in thread
From: Philip Yang @ 2025-10-03 18:15 UTC (permalink / raw)
  To: amd-gfx; +Cc: Felix.Kuehling, harish.kasiviswanathan, Xiaogang.Chen,
	Philip Yang

Add hmm_range kzalloc return NULL error check. In case the get_pages
return failed, free and set hmm_range to NULL, to avoid double free in
get_pages_done.

Fixes: 29e6f5716115 ("drm/amdgpu: use user provided hmm_range buffer in amdgpu_ttm_tt_get_user_pages")
Signed-off-by: Philip Yang <Philip.Yang@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 8c3787b00f36..e8a15751c125 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1736,15 +1736,20 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
 				continue;
 			}
 
-			WRITE_ONCE(p->svms.faulting_task, current);
 			hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
-			r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
-						       readonly, owner,
-						       hmm_range);
-			WRITE_ONCE(p->svms.faulting_task, NULL);
-			if (r) {
-				kfree(hmm_range);
-				pr_debug("failed %d to get svm range pages\n", r);
+			if (unlikely(!hmm_range)) {
+				r = -ENOMEM;
+			} else {
+				WRITE_ONCE(p->svms.faulting_task, current);
+				r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
+							       readonly, owner,
+							       hmm_range);
+				WRITE_ONCE(p->svms.faulting_task, NULL);
+				if (r) {
+					kfree(hmm_range);
+					hmm_range = NULL;
+					pr_debug("failed %d to get svm range pages\n", r);
+				}
 			}
 		} else {
 			r = -EFAULT;
-- 
2.49.0


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

* [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address
  2025-10-03 18:15 [PATCH v2 1/3] drm/amdgpu: svm check hmm range kzalloc return NULL Philip Yang
@ 2025-10-03 18:15 ` Philip Yang
  2025-10-03 19:11   ` Chen, Xiaogang
  2025-10-03 20:27   ` Felix Kuehling
  2025-10-03 18:15 ` [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker Philip Yang
  1 sibling, 2 replies; 11+ messages in thread
From: Philip Yang @ 2025-10-03 18:15 UTC (permalink / raw)
  To: amd-gfx; +Cc: Felix.Kuehling, harish.kasiviswanathan, Xiaogang.Chen,
	Philip Yang

svm_range_unmap_from_gpus uses page aligned start, end address, the end
address is inclusive.

Fixes: 38c55f6719f7 ("drm/amdkfd: Handle lack of READ permissions in SVM mapping")
Signed-off-by: Philip Yang <Philip.Yang@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index e8a15751c125..0aadd20be56a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1723,10 +1723,9 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
 				svm_range_lock(prange);
 				if (vma->vm_flags & VM_WRITE)
 					pr_debug("VM_WRITE without VM_READ is not supported");
-				s = max(start, prange->start);
-				e = min(end, prange->last);
-				if (e >= s)
-					r = svm_range_unmap_from_gpus(prange, s, e,
+				s = max(addr >> PAGE_SHIFT, prange->start);
+				e = s + npages - 1;
+				r = svm_range_unmap_from_gpus(prange, s, e,
 						       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
 				svm_range_unlock(prange);
 				/* If unmap returns non-zero, we'll bail on the next for loop
-- 
2.49.0


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

* [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
  2025-10-03 18:15 [PATCH v2 1/3] drm/amdgpu: svm check hmm range kzalloc return NULL Philip Yang
  2025-10-03 18:15 ` [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address Philip Yang
@ 2025-10-03 18:15 ` Philip Yang
  2025-10-03 18:22   ` Chen, Xiaogang
  2025-10-03 19:10   ` Chen, Xiaogang
  1 sibling, 2 replies; 11+ messages in thread
From: Philip Yang @ 2025-10-03 18:15 UTC (permalink / raw)
  To: amd-gfx; +Cc: Felix.Kuehling, harish.kasiviswanathan, Xiaogang.Chen,
	Philip Yang

If vma is not found, the application has freed the memory using madvise
MADV_FREE, but driver don't receive the unmap from CPU MMU notifier
callback, the memory is still mapped on GPUs. svm restore work will
schedule the work to retry forever. Then user queues not resumed and
cause application hangs to wait for queue finish.

svm restore work should unmap the memory range from GPUs then resume
queues. If GPU page fault happens on the unmapped address, it is
application use-after-free bug.

Signed-off-by: Philip Yang <Philip.Yang@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 75 ++++++++++++++--------------
 1 file changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 0aadd20be56a..e87c9b3533b9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1708,50 +1708,51 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
 		bool readonly;
 
 		vma = vma_lookup(mm, addr);
-		if (vma) {
-			readonly = !(vma->vm_flags & VM_WRITE);
+		next = vma ? min(vma->vm_end, end) : end;
+		npages = (next - addr) >> PAGE_SHIFT;
 
-			next = min(vma->vm_end, end);
-			npages = (next - addr) >> PAGE_SHIFT;
+		if (!vma || !(vma->vm_flags & VM_READ)) {
 			/* HMM requires at least READ permissions. If provided with PROT_NONE,
 			 * unmap the memory. If it's not already mapped, this is a no-op
 			 * If PROT_WRITE is provided without READ, warn first then unmap
+			 * If vma is not found, addr is invalid, unmap from GPUs
 			 */
-			if (!(vma->vm_flags & VM_READ)) {
-				unsigned long e, s;
-
-				svm_range_lock(prange);
-				if (vma->vm_flags & VM_WRITE)
-					pr_debug("VM_WRITE without VM_READ is not supported");
-				s = max(addr >> PAGE_SHIFT, prange->start);
-				e = s + npages - 1;
-				r = svm_range_unmap_from_gpus(prange, s, e,
-						       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
-				svm_range_unlock(prange);
-				/* If unmap returns non-zero, we'll bail on the next for loop
-				 * iteration, so just leave r and continue
-				 */
-				addr = next;
-				continue;
-			}
+			unsigned long e, s;
+
+			svm_range_lock(prange);
+			if (!vma)
+				pr_debug("vma not found\n");
+			else if (vma->vm_flags & VM_WRITE)
+				pr_debug("VM_WRITE without VM_READ is not supported");
+
+			s = max(addr >> PAGE_SHIFT, prange->start);
+			e = s + npages - 1;
+			r = svm_range_unmap_from_gpus(prange, s, e,
+					       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
+			svm_range_unlock(prange);
+			/* If unmap returns non-zero, we'll bail on the next for loop
+			 * iteration, so just leave r and continue
+			 */
+			addr = next;
+			continue;
+		}
 
-			hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
-			if (unlikely(!hmm_range)) {
-				r = -ENOMEM;
-			} else {
-				WRITE_ONCE(p->svms.faulting_task, current);
-				r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
-							       readonly, owner,
-							       hmm_range);
-				WRITE_ONCE(p->svms.faulting_task, NULL);
-				if (r) {
-					kfree(hmm_range);
-					hmm_range = NULL;
-					pr_debug("failed %d to get svm range pages\n", r);
-				}
-			}
+		readonly = !(vma->vm_flags & VM_WRITE);
+
+		hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
+		if (unlikely(!hmm_range)) {
+			r = -ENOMEM;
 		} else {
-			r = -EFAULT;
+			WRITE_ONCE(p->svms.faulting_task, current);
+			r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
+						       readonly, owner,
+						       hmm_range);
+			WRITE_ONCE(p->svms.faulting_task, NULL);
+			if (r) {
+				kfree(hmm_range);
+				hmm_range = NULL;
+				pr_debug("failed %d to get svm range pages\n", r);
+			}
 		}
 
 		if (!r) {
-- 
2.49.0


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

* RE: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
  2025-10-03 18:15 ` [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker Philip Yang
@ 2025-10-03 18:22   ` Chen, Xiaogang
  2025-10-03 18:27     ` Philip Yang
  2025-10-03 19:10   ` Chen, Xiaogang
  1 sibling, 1 reply; 11+ messages in thread
From: Chen, Xiaogang @ 2025-10-03 18:22 UTC (permalink / raw)
  To: Yang, Philip, amd-gfx@lists.freedesktop.org
  Cc: Kuehling, Felix, Kasiviswanathan, Harish

[AMD Official Use Only - AMD Internal Distribution Only]

The MADV_FREE is handled at madvise_free_single_vma(madvise_dontneed_free) from madvise_vma_behavior at mm/madvice.c.

It calls mmu_notifier_invalidate_range_start(&range) with MMU_NOTIFY_CLEAR to notify registered vm intervals. I am not sure how driver don't receive the notification. Is there something else cause the problem?

Regards

Xiaogang

-----Original Message-----
From: Yang, Philip <Philip.Yang@amd.com>
Sent: Friday, October 3, 2025 1:15 PM
To: amd-gfx@lists.freedesktop.org
Cc: Kuehling, Felix <Felix.Kuehling@amd.com>; Kasiviswanathan, Harish <Harish.Kasiviswanathan@amd.com>; Chen, Xiaogang <Xiaogang.Chen@amd.com>; Yang, Philip <Philip.Yang@amd.com>
Subject: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker

If vma is not found, the application has freed the memory using madvise MADV_FREE, but driver don't receive the unmap from CPU MMU notifier callback, the memory is still mapped on GPUs. svm restore work will schedule the work to retry forever. Then user queues not resumed and cause application hangs to wait for queue finish.

svm restore work should unmap the memory range from GPUs then resume queues. If GPU page fault happens on the unmapped address, it is application use-after-free bug.

Signed-off-by: Philip Yang <Philip.Yang@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 75 ++++++++++++++--------------
 1 file changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 0aadd20be56a..e87c9b3533b9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1708,50 +1708,51 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
                bool readonly;

                vma = vma_lookup(mm, addr);
-               if (vma) {
-                       readonly = !(vma->vm_flags & VM_WRITE);
+               next = vma ? min(vma->vm_end, end) : end;
+               npages = (next - addr) >> PAGE_SHIFT;

-                       next = min(vma->vm_end, end);
-                       npages = (next - addr) >> PAGE_SHIFT;
+               if (!vma || !(vma->vm_flags & VM_READ)) {
                        /* HMM requires at least READ permissions. If provided with PROT_NONE,
                         * unmap the memory. If it's not already mapped, this is a no-op
                         * If PROT_WRITE is provided without READ, warn first then unmap
+                        * If vma is not found, addr is invalid, unmap from GPUs
                         */
-                       if (!(vma->vm_flags & VM_READ)) {
-                               unsigned long e, s;
-
-                               svm_range_lock(prange);
-                               if (vma->vm_flags & VM_WRITE)
-                                       pr_debug("VM_WRITE without VM_READ is not supported");
-                               s = max(addr >> PAGE_SHIFT, prange->start);
-                               e = s + npages - 1;
-                               r = svm_range_unmap_from_gpus(prange, s, e,
-                                                      KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
-                               svm_range_unlock(prange);
-                               /* If unmap returns non-zero, we'll bail on the next for loop
-                                * iteration, so just leave r and continue
-                                */
-                               addr = next;
-                               continue;
-                       }
+                       unsigned long e, s;
+
+                       svm_range_lock(prange);
+                       if (!vma)
+                               pr_debug("vma not found\n");
+                       else if (vma->vm_flags & VM_WRITE)
+                               pr_debug("VM_WRITE without VM_READ is not supported");
+
+                       s = max(addr >> PAGE_SHIFT, prange->start);
+                       e = s + npages - 1;
+                       r = svm_range_unmap_from_gpus(prange, s, e,
+                                              KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
+                       svm_range_unlock(prange);
+                       /* If unmap returns non-zero, we'll bail on the next for loop
+                        * iteration, so just leave r and continue
+                        */
+                       addr = next;
+                       continue;
+               }

-                       hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
-                       if (unlikely(!hmm_range)) {
-                               r = -ENOMEM;
-                       } else {
-                               WRITE_ONCE(p->svms.faulting_task, current);
-                               r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
-                                                              readonly, owner,
-                                                              hmm_range);
-                               WRITE_ONCE(p->svms.faulting_task, NULL);
-                               if (r) {
-                                       kfree(hmm_range);
-                                       hmm_range = NULL;
-                                       pr_debug("failed %d to get svm range pages\n", r);
-                               }
-                       }
+               readonly = !(vma->vm_flags & VM_WRITE);
+
+               hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
+               if (unlikely(!hmm_range)) {
+                       r = -ENOMEM;
                } else {
-                       r = -EFAULT;
+                       WRITE_ONCE(p->svms.faulting_task, current);
+                       r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
+                                                      readonly, owner,
+                                                      hmm_range);
+                       WRITE_ONCE(p->svms.faulting_task, NULL);
+                       if (r) {
+                               kfree(hmm_range);
+                               hmm_range = NULL;
+                               pr_debug("failed %d to get svm range pages\n", r);
+                       }
                }

                if (!r) {
--
2.49.0


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

* Re: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
  2025-10-03 18:22   ` Chen, Xiaogang
@ 2025-10-03 18:27     ` Philip Yang
  2025-10-03 18:34       ` Chen, Xiaogang
  0 siblings, 1 reply; 11+ messages in thread
From: Philip Yang @ 2025-10-03 18:27 UTC (permalink / raw)
  To: Chen, Xiaogang, Yang, Philip, amd-gfx@lists.freedesktop.org
  Cc: Kuehling, Felix, Kasiviswanathan, Harish


On 2025-10-03 14:22, Chen, Xiaogang wrote:
> [AMD Official Use Only - AMD Internal Distribution Only]
>
> The MADV_FREE is handled at madvise_free_single_vma(madvise_dontneed_free) from madvise_vma_behavior at mm/madvice.c.
>
> It calls mmu_notifier_invalidate_range_start(&range) with MMU_NOTIFY_CLEAR to notify registered vm intervals. I am not sure how driver don't receive the notification. Is there something else cause the problem?

I cannot repro the vma not found issue with madvise MADV_FREE on Ubunut 
kernel 6.16, this issue reported on a customized older kernel version.

Regards,

Philip

>
> Regards
>
> Xiaogang
>
> -----Original Message-----
> From: Yang, Philip <Philip.Yang@amd.com>
> Sent: Friday, October 3, 2025 1:15 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Kuehling, Felix <Felix.Kuehling@amd.com>; Kasiviswanathan, Harish <Harish.Kasiviswanathan@amd.com>; Chen, Xiaogang <Xiaogang.Chen@amd.com>; Yang, Philip <Philip.Yang@amd.com>
> Subject: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
>
> If vma is not found, the application has freed the memory using madvise MADV_FREE, but driver don't receive the unmap from CPU MMU notifier callback, the memory is still mapped on GPUs. svm restore work will schedule the work to retry forever. Then user queues not resumed and cause application hangs to wait for queue finish.
>
> svm restore work should unmap the memory range from GPUs then resume queues. If GPU page fault happens on the unmapped address, it is application use-after-free bug.
>
> Signed-off-by: Philip Yang <Philip.Yang@amd.com>
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 75 ++++++++++++++--------------
>   1 file changed, 38 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index 0aadd20be56a..e87c9b3533b9 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -1708,50 +1708,51 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
>                  bool readonly;
>
>                  vma = vma_lookup(mm, addr);
> -               if (vma) {
> -                       readonly = !(vma->vm_flags & VM_WRITE);
> +               next = vma ? min(vma->vm_end, end) : end;
> +               npages = (next - addr) >> PAGE_SHIFT;
>
> -                       next = min(vma->vm_end, end);
> -                       npages = (next - addr) >> PAGE_SHIFT;
> +               if (!vma || !(vma->vm_flags & VM_READ)) {
>                          /* HMM requires at least READ permissions. If provided with PROT_NONE,
>                           * unmap the memory. If it's not already mapped, this is a no-op
>                           * If PROT_WRITE is provided without READ, warn first then unmap
> +                        * If vma is not found, addr is invalid, unmap from GPUs
>                           */
> -                       if (!(vma->vm_flags & VM_READ)) {
> -                               unsigned long e, s;
> -
> -                               svm_range_lock(prange);
> -                               if (vma->vm_flags & VM_WRITE)
> -                                       pr_debug("VM_WRITE without VM_READ is not supported");
> -                               s = max(addr >> PAGE_SHIFT, prange->start);
> -                               e = s + npages - 1;
> -                               r = svm_range_unmap_from_gpus(prange, s, e,
> -                                                      KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
> -                               svm_range_unlock(prange);
> -                               /* If unmap returns non-zero, we'll bail on the next for loop
> -                                * iteration, so just leave r and continue
> -                                */
> -                               addr = next;
> -                               continue;
> -                       }
> +                       unsigned long e, s;
> +
> +                       svm_range_lock(prange);
> +                       if (!vma)
> +                               pr_debug("vma not found\n");
> +                       else if (vma->vm_flags & VM_WRITE)
> +                               pr_debug("VM_WRITE without VM_READ is not supported");
> +
> +                       s = max(addr >> PAGE_SHIFT, prange->start);
> +                       e = s + npages - 1;
> +                       r = svm_range_unmap_from_gpus(prange, s, e,
> +                                              KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
> +                       svm_range_unlock(prange);
> +                       /* If unmap returns non-zero, we'll bail on the next for loop
> +                        * iteration, so just leave r and continue
> +                        */
> +                       addr = next;
> +                       continue;
> +               }
>
> -                       hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
> -                       if (unlikely(!hmm_range)) {
> -                               r = -ENOMEM;
> -                       } else {
> -                               WRITE_ONCE(p->svms.faulting_task, current);
> -                               r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
> -                                                              readonly, owner,
> -                                                              hmm_range);
> -                               WRITE_ONCE(p->svms.faulting_task, NULL);
> -                               if (r) {
> -                                       kfree(hmm_range);
> -                                       hmm_range = NULL;
> -                                       pr_debug("failed %d to get svm range pages\n", r);
> -                               }
> -                       }
> +               readonly = !(vma->vm_flags & VM_WRITE);
> +
> +               hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
> +               if (unlikely(!hmm_range)) {
> +                       r = -ENOMEM;
>                  } else {
> -                       r = -EFAULT;
> +                       WRITE_ONCE(p->svms.faulting_task, current);
> +                       r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
> +                                                      readonly, owner,
> +                                                      hmm_range);
> +                       WRITE_ONCE(p->svms.faulting_task, NULL);
> +                       if (r) {
> +                               kfree(hmm_range);
> +                               hmm_range = NULL;
> +                               pr_debug("failed %d to get svm range pages\n", r);
> +                       }
>                  }
>
>                  if (!r) {
> --
> 2.49.0
>

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

* Re: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
  2025-10-03 18:27     ` Philip Yang
@ 2025-10-03 18:34       ` Chen, Xiaogang
  2025-10-03 20:46         ` Felix Kuehling
  0 siblings, 1 reply; 11+ messages in thread
From: Chen, Xiaogang @ 2025-10-03 18:34 UTC (permalink / raw)
  To: Philip Yang, Yang, Philip, amd-gfx@lists.freedesktop.org
  Cc: Kuehling, Felix, Kasiviswanathan, Harish


On 10/3/2025 1:27 PM, Philip Yang wrote:
>
> On 2025-10-03 14:22, Chen, Xiaogang wrote:
>> [AMD Official Use Only - AMD Internal Distribution Only]
>>
>> The MADV_FREE is handled at 
>> madvise_free_single_vma(madvise_dontneed_free) from 
>> madvise_vma_behavior at mm/madvice.c.
>>
>> It calls mmu_notifier_invalidate_range_start(&range) with 
>> MMU_NOTIFY_CLEAR to notify registered vm intervals. I am not sure how 
>> driver don't receive the notification. Is there something else cause 
>> the problem?
>
> I cannot repro the vma not found issue with madvise MADV_FREE on 
> Ubunut kernel 6.16, this issue reported on a customized older kernel 
> version.
>
> Regards,

One principle of hmm is gpu vm is mirror of cpu vm. Whatever happened at 
cpu vm need to reflect to gpu vm. If there is something wrong from hmm 
that driver did not get notification from mmu notifier driver need 
update gpu vm, also the correspondent prange. So, besides unmap from gpu 
vm, I think driver also need split prange to remove correspondent vm 
range from prange.

Regards

Xiaogang

>
> Philip
>
>>
>> Regards
>>
>> Xiaogang
>>
>> -----Original Message-----
>> From: Yang, Philip <Philip.Yang@amd.com>
>> Sent: Friday, October 3, 2025 1:15 PM
>> To: amd-gfx@lists.freedesktop.org
>> Cc: Kuehling, Felix <Felix.Kuehling@amd.com>; Kasiviswanathan, Harish 
>> <Harish.Kasiviswanathan@amd.com>; Chen, Xiaogang 
>> <Xiaogang.Chen@amd.com>; Yang, Philip <Philip.Yang@amd.com>
>> Subject: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
>>
>> If vma is not found, the application has freed the memory using 
>> madvise MADV_FREE, but driver don't receive the unmap from CPU MMU 
>> notifier callback, the memory is still mapped on GPUs. svm restore 
>> work will schedule the work to retry forever. Then user queues not 
>> resumed and cause application hangs to wait for queue finish.
>>
>> svm restore work should unmap the memory range from GPUs then resume 
>> queues. If GPU page fault happens on the unmapped address, it is 
>> application use-after-free bug.
>>
>> Signed-off-by: Philip Yang <Philip.Yang@amd.com>
>> ---
>>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 75 ++++++++++++++--------------
>>   1 file changed, 38 insertions(+), 37 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
>> b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> index 0aadd20be56a..e87c9b3533b9 100644
>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> @@ -1708,50 +1708,51 @@ static int svm_range_validate_and_map(struct 
>> mm_struct *mm,
>>                  bool readonly;
>>
>>                  vma = vma_lookup(mm, addr);
>> -               if (vma) {
>> -                       readonly = !(vma->vm_flags & VM_WRITE);
>> +               next = vma ? min(vma->vm_end, end) : end;
>> +               npages = (next - addr) >> PAGE_SHIFT;
>>
>> -                       next = min(vma->vm_end, end);
>> -                       npages = (next - addr) >> PAGE_SHIFT;
>> +               if (!vma || !(vma->vm_flags & VM_READ)) {
>>                          /* HMM requires at least READ permissions. 
>> If provided with PROT_NONE,
>>                           * unmap the memory. If it's not already 
>> mapped, this is a no-op
>>                           * If PROT_WRITE is provided without READ, 
>> warn first then unmap
>> +                        * If vma is not found, addr is invalid, 
>> unmap from GPUs
>>                           */
>> -                       if (!(vma->vm_flags & VM_READ)) {
>> -                               unsigned long e, s;
>> -
>> -                               svm_range_lock(prange);
>> -                               if (vma->vm_flags & VM_WRITE)
>> -                                       pr_debug("VM_WRITE without 
>> VM_READ is not supported");
>> -                               s = max(addr >> PAGE_SHIFT, 
>> prange->start);
>> -                               e = s + npages - 1;
>> -                               r = svm_range_unmap_from_gpus(prange, 
>> s, e,
>> - KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
>> -                               svm_range_unlock(prange);
>> -                               /* If unmap returns non-zero, we'll 
>> bail on the next for loop
>> -                                * iteration, so just leave r and 
>> continue
>> -                                */
>> -                               addr = next;
>> -                               continue;
>> -                       }
>> +                       unsigned long e, s;
>> +
>> +                       svm_range_lock(prange);
>> +                       if (!vma)
>> +                               pr_debug("vma not found\n");
>> +                       else if (vma->vm_flags & VM_WRITE)
>> +                               pr_debug("VM_WRITE without VM_READ is 
>> not supported");
>> +
>> +                       s = max(addr >> PAGE_SHIFT, prange->start);
>> +                       e = s + npages - 1;
>> +                       r = svm_range_unmap_from_gpus(prange, s, e,
>> + KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
>> +                       svm_range_unlock(prange);
>> +                       /* If unmap returns non-zero, we'll bail on 
>> the next for loop
>> +                        * iteration, so just leave r and continue
>> +                        */
>> +                       addr = next;
>> +                       continue;
>> +               }
>>
>> -                       hmm_range = kzalloc(sizeof(*hmm_range), 
>> GFP_KERNEL);
>> -                       if (unlikely(!hmm_range)) {
>> -                               r = -ENOMEM;
>> -                       } else {
>> - WRITE_ONCE(p->svms.faulting_task, current);
>> -                               r = 
>> amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
>> - readonly, owner,
>> - hmm_range);
>> - WRITE_ONCE(p->svms.faulting_task, NULL);
>> -                               if (r) {
>> -                                       kfree(hmm_range);
>> -                                       hmm_range = NULL;
>> -                                       pr_debug("failed %d to get 
>> svm range pages\n", r);
>> -                               }
>> -                       }
>> +               readonly = !(vma->vm_flags & VM_WRITE);
>> +
>> +               hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
>> +               if (unlikely(!hmm_range)) {
>> +                       r = -ENOMEM;
>>                  } else {
>> -                       r = -EFAULT;
>> +                       WRITE_ONCE(p->svms.faulting_task, current);
>> +                       r = 
>> amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
>> +                                                      readonly, owner,
>> + hmm_range);
>> +                       WRITE_ONCE(p->svms.faulting_task, NULL);
>> +                       if (r) {
>> +                               kfree(hmm_range);
>> +                               hmm_range = NULL;
>> +                               pr_debug("failed %d to get svm range 
>> pages\n", r);
>> +                       }
>>                  }
>>
>>                  if (!r) {
>> -- 
>> 2.49.0
>>

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

* Re: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
  2025-10-03 18:15 ` [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker Philip Yang
  2025-10-03 18:22   ` Chen, Xiaogang
@ 2025-10-03 19:10   ` Chen, Xiaogang
  1 sibling, 0 replies; 11+ messages in thread
From: Chen, Xiaogang @ 2025-10-03 19:10 UTC (permalink / raw)
  To: Philip Yang, amd-gfx; +Cc: Felix.Kuehling, harish.kasiviswanathan


Reviewed-by: Xiaogang Chen <Xiaogang.Chen@amd.com>

On 10/3/2025 1:15 PM, Philip Yang wrote:
> If vma is not found, the application has freed the memory using madvise
> MADV_FREE, but driver don't receive the unmap from CPU MMU notifier
> callback, the memory is still mapped on GPUs. svm restore work will
> schedule the work to retry forever. Then user queues not resumed and
> cause application hangs to wait for queue finish.
>
> svm restore work should unmap the memory range from GPUs then resume
> queues. If GPU page fault happens on the unmapped address, it is
> application use-after-free bug.
>
> Signed-off-by: Philip Yang <Philip.Yang@amd.com>
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 75 ++++++++++++++--------------
>   1 file changed, 38 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index 0aadd20be56a..e87c9b3533b9 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -1708,50 +1708,51 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
>   		bool readonly;
>   
>   		vma = vma_lookup(mm, addr);
> -		if (vma) {
> -			readonly = !(vma->vm_flags & VM_WRITE);
> +		next = vma ? min(vma->vm_end, end) : end;
> +		npages = (next - addr) >> PAGE_SHIFT;
>   
> -			next = min(vma->vm_end, end);
> -			npages = (next - addr) >> PAGE_SHIFT;
> +		if (!vma || !(vma->vm_flags & VM_READ)) {
>   			/* HMM requires at least READ permissions. If provided with PROT_NONE,
>   			 * unmap the memory. If it's not already mapped, this is a no-op
>   			 * If PROT_WRITE is provided without READ, warn first then unmap
> +			 * If vma is not found, addr is invalid, unmap from GPUs
>   			 */
> -			if (!(vma->vm_flags & VM_READ)) {
> -				unsigned long e, s;
> -
> -				svm_range_lock(prange);
> -				if (vma->vm_flags & VM_WRITE)
> -					pr_debug("VM_WRITE without VM_READ is not supported");
> -				s = max(addr >> PAGE_SHIFT, prange->start);
> -				e = s + npages - 1;
> -				r = svm_range_unmap_from_gpus(prange, s, e,
> -						       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
> -				svm_range_unlock(prange);
> -				/* If unmap returns non-zero, we'll bail on the next for loop
> -				 * iteration, so just leave r and continue
> -				 */
> -				addr = next;
> -				continue;
> -			}
> +			unsigned long e, s;
> +
> +			svm_range_lock(prange);
> +			if (!vma)
> +				pr_debug("vma not found\n");
> +			else if (vma->vm_flags & VM_WRITE)
> +				pr_debug("VM_WRITE without VM_READ is not supported");
> +
> +			s = max(addr >> PAGE_SHIFT, prange->start);
> +			e = s + npages - 1;
> +			r = svm_range_unmap_from_gpus(prange, s, e,
> +					       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
> +			svm_range_unlock(prange);
> +			/* If unmap returns non-zero, we'll bail on the next for loop
> +			 * iteration, so just leave r and continue
> +			 */
> +			addr = next;
> +			continue;
> +		}
>   
> -			hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
> -			if (unlikely(!hmm_range)) {
> -				r = -ENOMEM;
> -			} else {
> -				WRITE_ONCE(p->svms.faulting_task, current);
> -				r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
> -							       readonly, owner,
> -							       hmm_range);
> -				WRITE_ONCE(p->svms.faulting_task, NULL);
> -				if (r) {
> -					kfree(hmm_range);
> -					hmm_range = NULL;
> -					pr_debug("failed %d to get svm range pages\n", r);
> -				}
> -			}
> +		readonly = !(vma->vm_flags & VM_WRITE);
> +
> +		hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
> +		if (unlikely(!hmm_range)) {
> +			r = -ENOMEM;
>   		} else {
> -			r = -EFAULT;
> +			WRITE_ONCE(p->svms.faulting_task, current);
> +			r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
> +						       readonly, owner,
> +						       hmm_range);
> +			WRITE_ONCE(p->svms.faulting_task, NULL);
> +			if (r) {
> +				kfree(hmm_range);
> +				hmm_range = NULL;
> +				pr_debug("failed %d to get svm range pages\n", r);
> +			}
>   		}
>   
>   		if (!r) {

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

* Re: [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address
  2025-10-03 18:15 ` [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address Philip Yang
@ 2025-10-03 19:11   ` Chen, Xiaogang
  2025-10-03 20:27   ` Felix Kuehling
  1 sibling, 0 replies; 11+ messages in thread
From: Chen, Xiaogang @ 2025-10-03 19:11 UTC (permalink / raw)
  To: Philip Yang, amd-gfx; +Cc: Felix.Kuehling, harish.kasiviswanathan

Reviewed-by: Xiaogang Chen <Xiaogang.Chen@amd.com>

On 10/3/2025 1:15 PM, Philip Yang wrote:
> svm_range_unmap_from_gpus uses page aligned start, end address, the end
> address is inclusive.
>
> Fixes: 38c55f6719f7 ("drm/amdkfd: Handle lack of READ permissions in SVM mapping")
> Signed-off-by: Philip Yang <Philip.Yang@amd.com>
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 7 +++----
>   1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index e8a15751c125..0aadd20be56a 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -1723,10 +1723,9 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
>   				svm_range_lock(prange);
>   				if (vma->vm_flags & VM_WRITE)
>   					pr_debug("VM_WRITE without VM_READ is not supported");
> -				s = max(start, prange->start);
> -				e = min(end, prange->last);
> -				if (e >= s)
> -					r = svm_range_unmap_from_gpus(prange, s, e,
> +				s = max(addr >> PAGE_SHIFT, prange->start);
> +				e = s + npages - 1;
> +				r = svm_range_unmap_from_gpus(prange, s, e,
>   						       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
>   				svm_range_unlock(prange);
>   				/* If unmap returns non-zero, we'll bail on the next for loop

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

* Re: [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address
  2025-10-03 18:15 ` [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address Philip Yang
  2025-10-03 19:11   ` Chen, Xiaogang
@ 2025-10-03 20:27   ` Felix Kuehling
  2025-10-03 21:46     ` Philip Yang
  1 sibling, 1 reply; 11+ messages in thread
From: Felix Kuehling @ 2025-10-03 20:27 UTC (permalink / raw)
  To: Philip Yang, amd-gfx; +Cc: harish.kasiviswanathan, Xiaogang.Chen

On 2025-10-03 14:15, Philip Yang wrote:
> svm_range_unmap_from_gpus uses page aligned start, end address, the end
> address is inclusive.
>
> Fixes: 38c55f6719f7 ("drm/amdkfd: Handle lack of READ permissions in SVM mapping")
> Signed-off-by: Philip Yang <Philip.Yang@amd.com>
> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 7 +++----
>   1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> index e8a15751c125..0aadd20be56a 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
> @@ -1723,10 +1723,9 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
>   				svm_range_lock(prange);
>   				if (vma->vm_flags & VM_WRITE)
>   					pr_debug("VM_WRITE without VM_READ is not supported");
> -				s = max(start, prange->start);
> -				e = min(end, prange->last);
> -				if (e >= s)
> -					r = svm_range_unmap_from_gpus(prange, s, e,
> +				s = max(addr >> PAGE_SHIFT, prange->start);
> +				e = s + npages - 1;

This is confusing. The old code was clamping prange->start/last with 
start/end. start/end are based on map_start/map_end. Your updated code 
uses npages, which comes from the VMA, which may not start at the same 
address as the prange or the map_start. So I think just using npages 
here is incorrect.

You also completely removed the condition that s >= e. I think that's 
OK, since all callers make sure that map_start/map_end fall inside 
prange->start/last.

What are you actually trying to unmap here? Do you want to unmap the 
entire prange, the part of prange inside map_start..map_end, or the part 
of prange that overlaps with the VMA, or something else?

Regards,
   Felix


> +				r = svm_range_unmap_from_gpus(prange, s, e,
>   						       KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
>   				svm_range_unlock(prange);
>   				/* If unmap returns non-zero, we'll bail on the next for loop

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

* Re: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
  2025-10-03 18:34       ` Chen, Xiaogang
@ 2025-10-03 20:46         ` Felix Kuehling
  0 siblings, 0 replies; 11+ messages in thread
From: Felix Kuehling @ 2025-10-03 20:46 UTC (permalink / raw)
  To: Chen, Xiaogang, Philip Yang, Yang, Philip,
	amd-gfx@lists.freedesktop.org
  Cc: Kasiviswanathan, Harish

On 2025-10-03 14:34, Chen, Xiaogang wrote:
>
> On 10/3/2025 1:27 PM, Philip Yang wrote:
>>
>> On 2025-10-03 14:22, Chen, Xiaogang wrote:
>>> [AMD Official Use Only - AMD Internal Distribution Only]
>>>
>>> The MADV_FREE is handled at 
>>> madvise_free_single_vma(madvise_dontneed_free) from 
>>> madvise_vma_behavior at mm/madvice.c.
>>>
>>> It calls mmu_notifier_invalidate_range_start(&range) with 
>>> MMU_NOTIFY_CLEAR to notify registered vm intervals. I am not sure 
>>> how driver don't receive the notification. Is there something else 
>>> cause the problem?

I guess we got that notification. That's why we're trying to restore the 
range later in the first place.


>>
>> I cannot repro the vma not found issue with madvise MADV_FREE on 
>> Ubunut kernel 6.16, this issue reported on a customized older kernel 
>> version.
>>
>> Regards,
>
> One principle of hmm is gpu vm is mirror of cpu vm. Whatever happened 
> at cpu vm need to reflect to gpu vm. If there is something wrong from 
> hmm that driver did not get notification from mmu notifier driver need 
> update gpu vm, also the correspondent prange. So, besides unmap from 
> gpu vm, I think driver also need split prange to remove correspondent 
> vm range from prange.

I would agree. It's strange that the vma disappeared without sending us 
a MMU_NOTIFY_UNMAP. If we're adding a workaround here that unmaps things 
for missing VMAs, we're potentially leaking the prange structure and any 
associated svm_bo. Because I don't think we can expect that someone else 
will later send us the MMU_NOTIFY_UNMAP.

If we cannot reproduce this problem in an upstream kernel, we should not 
include a workaround for it. If we can reproduce it in an upstream 
kernel, we should discuss the proper solution with the HMM maintainers. 
It may not be in our driver.

The only place where we can put such a workaround for a bug that may be 
specific to an old or modified customer kernel would be our DKMS branch. 
And even there I would be hesitant with a workaround for a problem 
that's not fully understood. It makes the branch harder to maintain, and 
may be broken at any time if we can't test it.

Regards,
   Felix


>
> Regards
>
> Xiaogang
>
>>
>> Philip
>>
>>>
>>> Regards
>>>
>>> Xiaogang
>>>
>>> -----Original Message-----
>>> From: Yang, Philip <Philip.Yang@amd.com>
>>> Sent: Friday, October 3, 2025 1:15 PM
>>> To: amd-gfx@lists.freedesktop.org
>>> Cc: Kuehling, Felix <Felix.Kuehling@amd.com>; Kasiviswanathan, 
>>> Harish <Harish.Kasiviswanathan@amd.com>; Chen, Xiaogang 
>>> <Xiaogang.Chen@amd.com>; Yang, Philip <Philip.Yang@amd.com>
>>> Subject: [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker
>>>
>>> If vma is not found, the application has freed the memory using 
>>> madvise MADV_FREE, but driver don't receive the unmap from CPU MMU 
>>> notifier callback, the memory is still mapped on GPUs. svm restore 
>>> work will schedule the work to retry forever. Then user queues not 
>>> resumed and cause application hangs to wait for queue finish.
>>>
>>> svm restore work should unmap the memory range from GPUs then resume 
>>> queues. If GPU page fault happens on the unmapped address, it is 
>>> application use-after-free bug.
>>>
>>> Signed-off-by: Philip Yang <Philip.Yang@amd.com>
>>> ---
>>>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 75 
>>> ++++++++++++++--------------
>>>   1 file changed, 38 insertions(+), 37 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
>>> b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>>> index 0aadd20be56a..e87c9b3533b9 100644
>>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>>> @@ -1708,50 +1708,51 @@ static int svm_range_validate_and_map(struct 
>>> mm_struct *mm,
>>>                  bool readonly;
>>>
>>>                  vma = vma_lookup(mm, addr);
>>> -               if (vma) {
>>> -                       readonly = !(vma->vm_flags & VM_WRITE);
>>> +               next = vma ? min(vma->vm_end, end) : end;
>>> +               npages = (next - addr) >> PAGE_SHIFT;
>>>
>>> -                       next = min(vma->vm_end, end);
>>> -                       npages = (next - addr) >> PAGE_SHIFT;
>>> +               if (!vma || !(vma->vm_flags & VM_READ)) {
>>>                          /* HMM requires at least READ permissions. 
>>> If provided with PROT_NONE,
>>>                           * unmap the memory. If it's not already 
>>> mapped, this is a no-op
>>>                           * If PROT_WRITE is provided without READ, 
>>> warn first then unmap
>>> +                        * If vma is not found, addr is invalid, 
>>> unmap from GPUs
>>>                           */
>>> -                       if (!(vma->vm_flags & VM_READ)) {
>>> -                               unsigned long e, s;
>>> -
>>> -                               svm_range_lock(prange);
>>> -                               if (vma->vm_flags & VM_WRITE)
>>> -                                       pr_debug("VM_WRITE without 
>>> VM_READ is not supported");
>>> -                               s = max(addr >> PAGE_SHIFT, 
>>> prange->start);
>>> -                               e = s + npages - 1;
>>> -                               r = 
>>> svm_range_unmap_from_gpus(prange, s, e,
>>> - KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
>>> -                               svm_range_unlock(prange);
>>> -                               /* If unmap returns non-zero, we'll 
>>> bail on the next for loop
>>> -                                * iteration, so just leave r and 
>>> continue
>>> -                                */
>>> -                               addr = next;
>>> -                               continue;
>>> -                       }
>>> +                       unsigned long e, s;
>>> +
>>> +                       svm_range_lock(prange);
>>> +                       if (!vma)
>>> +                               pr_debug("vma not found\n");
>>> +                       else if (vma->vm_flags & VM_WRITE)
>>> +                               pr_debug("VM_WRITE without VM_READ 
>>> is not supported");
>>> +
>>> +                       s = max(addr >> PAGE_SHIFT, prange->start);
>>> +                       e = s + npages - 1;
>>> +                       r = svm_range_unmap_from_gpus(prange, s, e,
>>> + KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
>>> +                       svm_range_unlock(prange);
>>> +                       /* If unmap returns non-zero, we'll bail on 
>>> the next for loop
>>> +                        * iteration, so just leave r and continue
>>> +                        */
>>> +                       addr = next;
>>> +                       continue;
>>> +               }
>>>
>>> -                       hmm_range = kzalloc(sizeof(*hmm_range), 
>>> GFP_KERNEL);
>>> -                       if (unlikely(!hmm_range)) {
>>> -                               r = -ENOMEM;
>>> -                       } else {
>>> - WRITE_ONCE(p->svms.faulting_task, current);
>>> -                               r = 
>>> amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
>>> - readonly, owner,
>>> - hmm_range);
>>> - WRITE_ONCE(p->svms.faulting_task, NULL);
>>> -                               if (r) {
>>> -                                       kfree(hmm_range);
>>> -                                       hmm_range = NULL;
>>> -                                       pr_debug("failed %d to get 
>>> svm range pages\n", r);
>>> -                               }
>>> -                       }
>>> +               readonly = !(vma->vm_flags & VM_WRITE);
>>> +
>>> +               hmm_range = kzalloc(sizeof(*hmm_range), GFP_KERNEL);
>>> +               if (unlikely(!hmm_range)) {
>>> +                       r = -ENOMEM;
>>>                  } else {
>>> -                       r = -EFAULT;
>>> +                       WRITE_ONCE(p->svms.faulting_task, current);
>>> +                       r = 
>>> amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
>>> + readonly, owner,
>>> + hmm_range);
>>> +                       WRITE_ONCE(p->svms.faulting_task, NULL);
>>> +                       if (r) {
>>> +                               kfree(hmm_range);
>>> +                               hmm_range = NULL;
>>> +                               pr_debug("failed %d to get svm range 
>>> pages\n", r);
>>> +                       }
>>>                  }
>>>
>>>                  if (!r) {
>>> -- 
>>> 2.49.0
>>>

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

* Re: [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address
  2025-10-03 20:27   ` Felix Kuehling
@ 2025-10-03 21:46     ` Philip Yang
  0 siblings, 0 replies; 11+ messages in thread
From: Philip Yang @ 2025-10-03 21:46 UTC (permalink / raw)
  To: Felix Kuehling, Philip Yang, amd-gfx
  Cc: harish.kasiviswanathan, Xiaogang.Chen


On 2025-10-03 16:27, Felix Kuehling wrote:
> On 2025-10-03 14:15, Philip Yang wrote:
>> svm_range_unmap_from_gpus uses page aligned start, end address, the end
>> address is inclusive.
>>
>> Fixes: 38c55f6719f7 ("drm/amdkfd: Handle lack of READ permissions in 
>> SVM mapping")
>> Signed-off-by: Philip Yang <Philip.Yang@amd.com>
>> ---
>>   drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 7 +++----
>>   1 file changed, 3 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
>> b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> index e8a15751c125..0aadd20be56a 100644
>> --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
>> @@ -1723,10 +1723,9 @@ static int svm_range_validate_and_map(struct 
>> mm_struct *mm,
>>                   svm_range_lock(prange);
>>                   if (vma->vm_flags & VM_WRITE)
>>                       pr_debug("VM_WRITE without VM_READ is not 
>> supported");
>> -                s = max(start, prange->start);
>> -                e = min(end, prange->last);
>> -                if (e >= s)
>> -                    r = svm_range_unmap_from_gpus(prange, s, e,
>> +                s = max(addr >> PAGE_SHIFT, prange->start);
>> +                e = s + npages - 1;
>
> This is confusing. The old code was clamping prange->start/last with 
> start/end. start/end are based on map_start/map_end. Your updated code 
> uses npages, which comes from the VMA, which may not start at the same 
> address as the prange or the map_start. So I think just using npages 
> here is incorrect.
For restore_pages, the map_start and map_end could be partial range, but 
we should not get here as vm_flags VM_NONE or VM_WRITE. For svm restore 
worker, map_start, map_end is entire prange, start is from loop variable 
addr, npages clamp to VMA end, to go over VMAs of prange.

> You also completely removed the condition that s >= e. I think that's 
> OK, since all callers make sure that map_start/map_end fall inside 
> prange->start/last.
>
> What are you actually trying to unmap here? Do you want to unmap the 
> entire prange, the part of prange inside map_start..map_end, or the 
> part of prange that overlaps with the VMA, or something else?
>
For svm restore work no VMA case in next patch, this will unmap entire 
prange.

Regards,

Philip

> Regards,
>   Felix
>
>
>> +                r = svm_range_unmap_from_gpus(prange, s, e,
>> KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
>>                   svm_range_unlock(prange);
>>                   /* If unmap returns non-zero, we'll bail on the 
>> next for loop

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

end of thread, other threads:[~2025-10-03 21:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-03 18:15 [PATCH v2 1/3] drm/amdgpu: svm check hmm range kzalloc return NULL Philip Yang
2025-10-03 18:15 ` [PATCH v2 2/3] drm/amdkfd: svm unmap use page aligned address Philip Yang
2025-10-03 19:11   ` Chen, Xiaogang
2025-10-03 20:27   ` Felix Kuehling
2025-10-03 21:46     ` Philip Yang
2025-10-03 18:15 ` [PATCH v2 3/3] drm/amdkfd: Don't stuck in svm restore worker Philip Yang
2025-10-03 18:22   ` Chen, Xiaogang
2025-10-03 18:27     ` Philip Yang
2025-10-03 18:34       ` Chen, Xiaogang
2025-10-03 20:46         ` Felix Kuehling
2025-10-03 19:10   ` Chen, Xiaogang

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