<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 2024-01-26 09:59, Christian König
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:9c59557b-f6e3-45a9-bd4d-bddea9339e92@amd.com">Am
      26.01.24 um 15:38 schrieb Philip Yang:
      <br>
      <blockquote type="cite">svm range support partial migration and
        mapping update, for size 4MB
        <br>
        virtual address 4MB alignment and physical address continuous
        range, if
        <br>
        mapping to GPU with fs=10, after updating mapping of the first
        2MB,
        <br>
        if the second 2MB mapping fs=10 in cache TLB, this causes the
        first 2MB
        <br>
        access to the stale mapping.
        <br>
      </blockquote>
      <br>
      Well that sounds fishy. When that happens with (for example) 4MiB
      and 2MiB, why doesn't it happen with 8KiB and 4KiB as well?
      <br>
    </blockquote>
    <p>unmap svm range is aligned to granularity size, if the range size
      is 8KB (all within one 2MB granularity range), it will be
      mapped/unmapped as 8KB, even if only 4KB is migrated. This is
      handled in another patch series "amd/amdkfd: Unmap range from GPU
      based on granularity".</p>
    <p>Regards,</p>
    <p>Philip<br>
    </p>
    <blockquote type="cite" cite="mid:9c59557b-f6e3-45a9-bd4d-bddea9339e92@amd.com">
      <br>
      Christian.
      <br>
      <br>
      <blockquote type="cite">
        <br>
        Limit the maximum fragment size to granularity size, 2MB by
        default,
        <br>
        with the mapping and unmapping based on gramularity size, to
        solve this
        <br>
        issue.
        <br>
        <br>
        The change is only for SVM map/unmap range, no change for gfx
        and legacy
        <br>
        API path.
        <br>
        <br>
        Signed-off-by: Philip Yang <a class="moz-txt-link-rfc2396E" href="mailto:Philip.Yang@amd.com"><Philip.Yang@amd.com></a>
        <br>
        ---
        <br>
          drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c    | 12 +++++++-----
        <br>
          drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h    |  4 ++--
        <br>
          drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 22
        ++++++++++++----------
        <br>
          drivers/gpu/drm/amd/amdkfd/kfd_svm.c      |  9 +++++----
        <br>
          4 files changed, 26 insertions(+), 21 deletions(-)
        <br>
        <br>
        diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
        b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
        <br>
        index ed4a8c5d26d7..a2bef94cb959 100644
        <br>
        --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
        <br>
        +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
        <br>
        @@ -897,6 +897,7 @@ static void amdgpu_vm_tlb_seq_cb(struct
        dma_fence *fence,
        <br>
           * @res: ttm_resource to map
        <br>
           * @pages_addr: DMA addresses to use for mapping
        <br>
           * @fence: optional resulting fence
        <br>
        + * @frag_size: max map fragment size
        <br>
           *
        <br>
           * Fill in the page table entries between @start and @last.
        <br>
           *
        <br>
        @@ -908,7 +909,7 @@ int amdgpu_vm_update_range(struct
        amdgpu_device *adev, struct amdgpu_vm *vm,
        <br>
                         struct dma_resv *resv, uint64_t start, uint64_t
        last,
        <br>
                         uint64_t flags, uint64_t offset, uint64_t
        vram_base,
        <br>
                         struct ttm_resource *res, dma_addr_t
        *pages_addr,
        <br>
        -               struct dma_fence **fence)
        <br>
        +               struct dma_fence **fence, unsigned int
        frag_size)
        <br>
          {
        <br>
              struct amdgpu_vm_update_params params;
        <br>
              struct amdgpu_vm_tlb_seq_struct *tlb_cb;
        <br>
        @@ -1016,7 +1017,7 @@ int amdgpu_vm_update_range(struct
        amdgpu_device *adev, struct amdgpu_vm *vm,
        <br>
                  }
        <br>
                    tmp = start + num_entries;
        <br>
        -        r = amdgpu_vm_ptes_update(&params, start, tmp,
        addr, flags);
        <br>
        +        r = amdgpu_vm_ptes_update(&params, start, tmp,
        addr, flags, frag_size);
        <br>
                  if (r)
        <br>
                      goto error_free;
        <br>
          @@ -1197,7 +1198,7 @@ int amdgpu_vm_bo_update(struct
        amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
        <br>
                                 !uncached, resv, mapping->start,
        mapping->last,
        <br>
                                 update_flags, mapping->offset,
        <br>
                                 vram_base, mem, pages_addr,
        <br>
        -                       last_update);
        <br>
        +                       last_update, 0);
        <br>
                  if (r)
        <br>
                      return r;
        <br>
              }
        <br>
        @@ -1392,7 +1393,7 @@ int amdgpu_vm_clear_freed(struct
        amdgpu_device *adev,
        <br>
                  r = amdgpu_vm_update_range(adev, vm, false, false,
        true, false,
        <br>
                                 resv, mapping->start,
        mapping->last,
        <br>
                                 init_pte_value, 0, 0, NULL, NULL,
        <br>
        -                       &f);
        <br>
        +                       &f, 0);
        <br>
                  amdgpu_vm_free_mapping(adev, vm, mapping, f);
        <br>
                  if (r) {
        <br>
                      dma_fence_put(f);
        <br>
        @@ -2733,7 +2734,8 @@ bool amdgpu_vm_handle_fault(struct
        amdgpu_device *adev, u32 pasid,
        <br>
              }
        <br>
                r = amdgpu_vm_update_range(adev, vm, true, false, false,
        false,
        <br>
        -                   NULL, addr, addr, flags, value, 0, NULL,
        NULL, NULL);
        <br>
        +                   NULL, addr, addr, flags, value, 0, NULL,
        NULL,
        <br>
        +                   NULL, 0);
        <br>
              if (r)
        <br>
                  goto error_unlock;
        <br>
          diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
        b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
        <br>
        index 666698a57192..b34466b5086f 100644
        <br>
        --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
        <br>
        +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
        <br>
        @@ -465,7 +465,7 @@ int amdgpu_vm_update_range(struct
        amdgpu_device *adev, struct amdgpu_vm *vm,
        <br>
                         struct dma_resv *resv, uint64_t start, uint64_t
        last,
        <br>
                         uint64_t flags, uint64_t offset, uint64_t
        vram_base,
        <br>
                         struct ttm_resource *res, dma_addr_t
        *pages_addr,
        <br>
        -               struct dma_fence **fence);
        <br>
        +               struct dma_fence **fence, unsigned int
        frag_size);
        <br>
          int amdgpu_vm_bo_update(struct amdgpu_device *adev,
        <br>
                      struct amdgpu_bo_va *bo_va,
        <br>
                      bool clear);
        <br>
        @@ -531,7 +531,7 @@ int amdgpu_vm_pde_update(struct
        amdgpu_vm_update_params *params,
        <br>
                       struct amdgpu_vm_bo_base *entry);
        <br>
          int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params
        *params,
        <br>
                        uint64_t start, uint64_t end,
        <br>
        -              uint64_t dst, uint64_t flags);
        <br>
        +              uint64_t dst, uint64_t flags, unsigned int
        frag_size);
        <br>
          void amdgpu_vm_pt_free_work(struct work_struct *work);
        <br>
            #if defined(CONFIG_DEBUG_FS)
        <br>
        diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
        b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
        <br>
        index a160265ddc07..4647f700f1c6 100644
        <br>
        --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
        <br>
        +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
        <br>
        @@ -860,12 +860,14 @@ static void
        amdgpu_vm_pte_update_flags(struct amdgpu_vm_update_params
        *params,
        <br>
           * @flags: hw mapping flags
        <br>
           * @frag: resulting fragment size
        <br>
           * @frag_end: end of this fragment
        <br>
        + * @frag_size: max map fragment size
        <br>
           *
        <br>
           * Returns the first possible fragment for the start and end
        address.
        <br>
           */
        <br>
          static void amdgpu_vm_pte_fragment(struct
        amdgpu_vm_update_params *params,
        <br>
                             uint64_t start, uint64_t end, uint64_t
        flags,
        <br>
        -                   unsigned int *frag, uint64_t *frag_end)
        <br>
        +                   unsigned int *frag, uint64_t *frag_end,
        <br>
        +                   unsigned int frag_size)
        <br>
          {
        <br>
              /**
        <br>
               * The MC L1 TLB supports variable sized pages, based on a
        fragment
        <br>
        @@ -893,7 +895,7 @@ static void amdgpu_vm_pte_fragment(struct
        amdgpu_vm_update_params *params,
        <br>
              if (params->adev->asic_type < CHIP_VEGA10)
        <br>
                  max_frag =
        params->adev->vm_manager.fragment_size;
        <br>
              else
        <br>
        -        max_frag = 31;
        <br>
        +        max_frag = frag_size ? frag_size : 31;
        <br>
                /* system pages are non continuously */
        <br>
              if (params->pages_addr) {
        <br>
        @@ -904,12 +906,10 @@ static void amdgpu_vm_pte_fragment(struct
        amdgpu_vm_update_params *params,
        <br>
                /* This intentionally wraps around if no bit is set */
        <br>
              *frag = min_t(unsigned int, ffs(start) - 1, fls64(end -
        start) - 1);
        <br>
        -    if (*frag >= max_frag) {
        <br>
        +    if (*frag >= max_frag)
        <br>
                  *frag = max_frag;
        <br>
        -        *frag_end = end & ~((1ULL << max_frag) - 1);
        <br>
        -    } else {
        <br>
        -        *frag_end = start + (1 << *frag);
        <br>
        -    }
        <br>
        +
        <br>
        +    *frag_end = start + (1 << *frag);
        <br>
          }
        <br>
            /**
        <br>
        @@ -920,6 +920,7 @@ static void amdgpu_vm_pte_fragment(struct
        amdgpu_vm_update_params *params,
        <br>
           * @end: end of GPU address range
        <br>
           * @dst: destination address to map to, the next dst inside
        the function
        <br>
           * @flags: mapping flags
        <br>
        + * @frag_size: max map fragment size
        <br>
           *
        <br>
           * Update the page tables in the range @start - @end.
        <br>
           *
        <br>
        @@ -928,7 +929,7 @@ static void amdgpu_vm_pte_fragment(struct
        amdgpu_vm_update_params *params,
        <br>
           */
        <br>
          int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params
        *params,
        <br>
                        uint64_t start, uint64_t end,
        <br>
        -              uint64_t dst, uint64_t flags)
        <br>
        +              uint64_t dst, uint64_t flags, unsigned int
        frag_size)
        <br>
          {
        <br>
              struct amdgpu_device *adev = params->adev;
        <br>
              struct amdgpu_vm_pt_cursor cursor;
        <br>
        @@ -938,7 +939,7 @@ int amdgpu_vm_ptes_update(struct
        amdgpu_vm_update_params *params,
        <br>
                /* figure out the initial fragment */
        <br>
              amdgpu_vm_pte_fragment(params, frag_start, end, flags,
        &frag,
        <br>
        -                   &frag_end);
        <br>
        +                   &frag_end, frag_size);
        <br>
                /* walk over the address space and update the PTs */
        <br>
              amdgpu_vm_pt_start(adev, params->vm, start,
        &cursor);
        <br>
        @@ -1040,7 +1041,8 @@ int amdgpu_vm_ptes_update(struct
        amdgpu_vm_update_params *params,
        <br>
                      if (frag_start >= frag_end) {
        <br>
                          /* figure out the next fragment */
        <br>
                          amdgpu_vm_pte_fragment(params, frag_start,
        end,
        <br>
        -                               flags, &frag,
        &frag_end);
        <br>
        +                               flags, &frag, &frag_end,
        <br>
        +                               frag_size);
        <br>
                          if (frag < shift)
        <br>
                              break;
        <br>
                      }
        <br>
        diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
        b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
        <br>
        index ed35a490fd9e..d71b2c8bf51a 100644
        <br>
        --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
        <br>
        +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
        <br>
        @@ -1488,7 +1488,7 @@ svm_range_get_pte_flags(struct kfd_node
        *node,
        <br>
          static int
        <br>
          svm_range_unmap_from_gpu(struct amdgpu_device *adev, struct
        amdgpu_vm *vm,
        <br>
                       uint64_t start, uint64_t last,
        <br>
        -             struct dma_fence **fence)
        <br>
        +             struct dma_fence **fence, unsigned int frag_size)
        <br>
          {
        <br>
              uint64_t init_pte_value = 0;
        <br>
          @@ -1496,7 +1496,7 @@ svm_range_unmap_from_gpu(struct
        amdgpu_device *adev, struct amdgpu_vm *vm,
        <br>
                return amdgpu_vm_update_range(adev, vm, false, true,
        true, false, NULL, start,
        <br>
                                last, init_pte_value, 0, 0, NULL, NULL,
        <br>
        -                      fence);
        <br>
        +                      fence, frag_size);
        <br>
          }
        <br>
            /**
        <br>
        @@ -1579,7 +1579,7 @@ svm_range_unmap_from_gpus(struct svm_range
        *prange, unsigned long start,
        <br>
                    r = svm_range_unmap_from_gpu(pdd->dev->adev,
        <br>
                                   drm_priv_to_vm(pdd->drm_priv),
        <br>
        -                         start, last, &fence);
        <br>
        +                         start, last, &fence,
        prange->granularity);
        <br>
                  if (r)
        <br>
                      break;
        <br>
          @@ -1647,7 +1647,8 @@ svm_range_map_to_gpu(struct
        kfd_process_device *pdd, struct svm_range *prange,
        <br>
                                 pte_flags,
        <br>
                                 (last_start - prange->start)
        << PAGE_SHIFT,
        <br>
                                 bo_adev ?
        bo_adev->vm_manager.vram_base_offset : 0,
        <br>
        -                       NULL, dma_addr,
        &vm->last_update);
        <br>
        +                       NULL, dma_addr, &vm->last_update,
        <br>
        +                       prange->granularity);
        <br>
                    for (j = last_start - prange->start; j <= i;
        j++)
        <br>
                      dma_addr[j] |= last_domain;
        <br>
      </blockquote>
      <br>
    </blockquote>
  </body>
</html>