Any comments on this one?

This was requested by the HSA runtime team a long time ago as a
debugging feature. It allows gdb to access the content of CPU-mapped
BOs. I imagine this may be useful for user mode driver developers.

Does anyone dare to give me a Reviewed-by?

Regards,
  Felix


On 17-07-03 05:11 PM, Felix Kuehling wrote:
> Allows gdb to access contents of user mode mapped BOs.
>
> Signed-off-by: Felix Kuehling <felix.kuehl...@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 130 
> +++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h |   2 +
>  2 files changed, 131 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> index 15148f1..3f927c2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> @@ -1237,6 +1237,134 @@ void amdgpu_ttm_set_active_vram_size(struct 
> amdgpu_device *adev, u64 size)
>       man->size = size >> PAGE_SHIFT;
>  }
>  
> +static struct vm_operations_struct amdgpu_ttm_vm_ops;
> +static const struct vm_operations_struct *ttm_vm_ops /* = NULL;
> +                                                   * (appease checkpatch) */;
> +static int amdgpu_ttm_bo_access_vram(struct amdgpu_bo *abo,
> +                                  unsigned long offset,
> +                                  void *buf, int len, int write)
> +{
> +     struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
> +     struct drm_mm_node *nodes = abo->tbo.mem.mm_node;
> +     uint32_t value = 0;
> +     int result = 0;
> +     uint64_t pos;
> +     unsigned long flags;
> +
> +     while (offset >= (nodes->size << PAGE_SHIFT)) {
> +             offset -= nodes->size << PAGE_SHIFT;
> +             ++nodes;
> +     }
> +     pos = (nodes->start << PAGE_SHIFT) + offset;
> +
> +     while (len && pos < adev->mc.mc_vram_size) {
> +             uint64_t aligned_pos = pos & ~(uint64_t)3;
> +             uint32_t bytes = 4 - (pos & 3);
> +             uint32_t shift = (pos & 3) * 8;
> +             uint32_t mask = 0xffffffff << shift;
> +
> +             if (len < bytes) {
> +                     mask &= 0xffffffff >> (bytes - len) * 8;
> +                     bytes = len;
> +             }
> +
> +             spin_lock_irqsave(&adev->mmio_idx_lock, flags);
> +             WREG32(mmMM_INDEX, ((uint32_t)aligned_pos) | 0x80000000);
> +             WREG32(mmMM_INDEX_HI, aligned_pos >> 31);
> +             if (!write || mask != 0xffffffff)
> +                     value = RREG32(mmMM_DATA);
> +             if (write) {
> +                     value &= ~mask;
> +                     value |= (*(uint32_t *)buf << shift) & mask;
> +                     WREG32(mmMM_DATA, value);
> +             }
> +             spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
> +             if (!write) {
> +                     value = (value & mask) >> shift;
> +                     memcpy(buf, &value, bytes);
> +             }
> +
> +             result += bytes;
> +             buf = (uint8_t *)buf + bytes;
> +             pos += bytes;
> +             len -= bytes;
> +             if (pos >= (nodes->start + nodes->size) << PAGE_SHIFT) {
> +                     ++nodes;
> +                     pos = (nodes->start << PAGE_SHIFT);
> +             }
> +     }
> +
> +     return result;
> +}
> +
> +static int amdgpu_ttm_bo_access_kmap(struct amdgpu_bo *abo,
> +                                  unsigned long offset,
> +                                  void *buf, int len, int write)
> +{
> +     struct ttm_buffer_object *bo = &abo->tbo;
> +     struct ttm_bo_kmap_obj map;
> +     void *ptr;
> +     bool is_iomem;
> +     int r;
> +
> +     r = ttm_bo_kmap(bo, 0, bo->num_pages, &map);
> +     if (r)
> +             return r;
> +     ptr = (uint8_t *)ttm_kmap_obj_virtual(&map, &is_iomem) + offset;
> +     WARN_ON(is_iomem);
> +     if (write)
> +             memcpy(ptr, buf, len);
> +     else
> +             memcpy(buf, ptr, len);
> +     ttm_bo_kunmap(&map);
> +
> +     return len;
> +}
> +
> +static int amdgpu_ttm_vm_access(struct vm_area_struct *vma, unsigned long 
> addr,
> +                             void *buf, int len, int write)
> +{
> +     unsigned long offset = (addr) - vma->vm_start;
> +     struct ttm_buffer_object *bo = vma->vm_private_data;
> +     struct amdgpu_bo *abo = container_of(bo, struct amdgpu_bo, tbo);
> +     unsigned domain;
> +     int result;
> +
> +     result = amdgpu_bo_reserve(abo, false);
> +     if (result != 0)
> +             return result;
> +
> +     domain = amdgpu_mem_type_to_domain(bo->mem.mem_type);
> +     if (domain == AMDGPU_GEM_DOMAIN_VRAM)
> +             result = amdgpu_ttm_bo_access_vram(abo, offset,
> +                                                buf, len, write);
> +     else
> +             result = amdgpu_ttm_bo_access_kmap(abo, offset,
> +                                                buf, len, write);
> +     amdgpu_bo_unreserve(abo);
> +
> +     return len;
> +}
> +
> +int amdgpu_bo_mmap(struct file *filp, struct vm_area_struct *vma,
> +                struct ttm_bo_device *bdev)
> +{
> +     int r;
> +
> +     r = ttm_bo_mmap(filp, vma, bdev);
> +     if (unlikely(r != 0))
> +             return r;
> +
> +     if (unlikely(ttm_vm_ops == NULL)) {
> +             ttm_vm_ops = vma->vm_ops;
> +             amdgpu_ttm_vm_ops = *ttm_vm_ops;
> +             amdgpu_ttm_vm_ops.access = &amdgpu_ttm_vm_access;
> +     }
> +     vma->vm_ops = &amdgpu_ttm_vm_ops;
> +
> +     return 0;
> +}
> +
>  int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma)
>  {
>       struct drm_file *file_priv;
> @@ -1250,7 +1378,7 @@ int amdgpu_mmap(struct file *filp, struct 
> vm_area_struct *vma)
>       if (adev == NULL)
>               return -EINVAL;
>  
> -     return ttm_bo_mmap(filp, vma, &adev->mman.bdev);
> +     return amdgpu_bo_mmap(filp, vma, &adev->mman.bdev);
>  }
>  
>  int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> index 776a20a..1eb605c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> @@ -73,6 +73,8 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
>                       struct dma_fence **fence);
>  
>  int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
> +int amdgpu_bo_mmap(struct file *filp, struct vm_area_struct *vma,
> +                struct ttm_bo_device *bdev);
>  bool amdgpu_ttm_is_bound(struct ttm_tt *ttm);
>  int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg 
> *bo_mem);
>  

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to