<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 2023-10-02 15:27, Felix Kuehling
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:3c56e437-b901-4d93-a3bb-1b788d1aba18@amd.com">
      
      <div class="moz-cite-prefix">On 2023-09-29 10:11, Philip Yang
        wrote:<br>
      </div>
      <blockquote type="cite" cite="mid:20230929141115.10016-2-Philip.Yang@amd.com">
        <pre class="moz-quote-pre" wrap="">Align unmap range start and last address to granularity boundary.
Skip unmap if range is already unmapped from GPUs.</pre>
      </blockquote>
      <p>This only handles unmap due to MMU notifiers with XNACK on.
        What about svm_range_unmap_from_cpu?<br>
      </p>
    </blockquote>
    unmap_from_cpu is going to remove the range, we cannot align range
    based on granularity, still split the prange and unmap from GPU the
    exact range .<br>
    <blockquote type="cite" cite="mid:3c56e437-b901-4d93-a3bb-1b788d1aba18@amd.com">
      <p> </p>
      <p>Regards,<br>
          Felix</p>
      <p><br>
      </p>
      <blockquote type="cite" cite="mid:20230929141115.10016-2-Philip.Yang@amd.com">
        <pre class="moz-quote-pre" wrap="">This also solve the rocgdb CWSR migration related issue.

Signed-off-by: Philip Yang <a class="moz-txt-link-rfc2396E" href="mailto:Philip.Yang@amd.com" moz-do-not-send="true"><Philip.Yang@amd.com></a>
---
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 35 ++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 626e0dd4ec79..ac65bf25c685 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2004,6 +2004,26 @@ static void svm_range_restore_work(struct work_struct *work)
        mmput(mm);
 }
 
+static unsigned long
+svm_range_align_start(struct svm_range *prange, unsigned long start)
+{
+       unsigned long start_align;
+
+       start_align = ALIGN_DOWN(start, 1UL << prange->granularity);
+       start_align = max_t(unsigned long, start_align, prange->start);
+       return start_align;
+}
+
+static unsigned long
+svm_range_align_last(struct svm_range *prange, unsigned long last)
+{
+       unsigned long last_align;
+
+       last_align = ALIGN(last, 1UL << prange->granularity) - 1;</pre>
      </blockquote>
      <p>I think this should be</p>
      <pre>       last_align = ALIGN(last + 1, 1UL << prange->granularity) - 1;
</pre>
      <p>Otherwise you're off by one granule when (last & (1UL
        << prange->granularity)) == 0.<br>
      </p>
      <p><br>
      </p>
      <blockquote type="cite" cite="mid:20230929141115.10016-2-Philip.Yang@amd.com">
        <pre class="moz-quote-pre" wrap="">+  last_align = min_t(unsigned long, last_align, prange->last);
+       return last_align;
+}
+
 /**
  * svm_range_evict - evict svm range
  * @prange: svm range structure
@@ -2078,6 +2098,12 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm,
                unsigned long s, l;
                uint32_t trigger;
 
+               if (!svm_range_partial_mapped(prange, start, last)) {
+                       pr_debug("svms 0x%p [0x%lx 0x%lx] unmapped already\n",
+                               prange->svms, start, last);
+                       return 0;
+               }
+
                if (event == MMU_NOTIFY_MIGRATE)
                        trigger = KFD_SVM_UNMAP_TRIGGER_MMU_NOTIFY_MIGRATE;
                else
@@ -2085,16 +2111,17 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm,
 
                pr_debug("invalidate unmap svms 0x%p [0x%lx 0x%lx] from GPUs\n",
                         prange->svms, start, last);
+
                list_for_each_entry(pchild, &prange->child_list, child_list) {
                        mutex_lock_nested(&pchild->lock, 1);
-                       s = max(start, pchild->start);
-                       l = min(last, pchild->last);
+                       s = svm_range_align_start(pchild, start);
+                       l = svm_range_align_last(pchild, last);
                        if (l >= s)
                                svm_range_unmap_from_gpus(pchild, s, l, trigger);
                        mutex_unlock(&pchild->lock);
                }
-               s = max(start, prange->start);
-               l = min(last, prange->last);
+               s = svm_range_align_start(prange, start);
+               l = svm_range_align_last(prange, last);
                if (l >= s)
                        svm_range_unmap_from_gpus(prange, s, l, trigger);
        }
</pre>
      </blockquote>
    </blockquote>
  </body>
</html>