diff options
author | Jérôme Glisse <jglisse@redhat.com> | 2017-08-02 00:22:27 -0400 |
---|---|---|
committer | Jérôme Glisse <jglisse@redhat.com> | 2017-08-02 00:22:27 -0400 |
commit | fe684469bb2e5c7834f94e4683da6f48e23c6dc7 (patch) | |
tree | 62bc89a8ec3884305556ce3cff3dfb21a84812e9 | |
parent | 9181b002500eb07575a2d782e0f6fd5878d6e1bd (diff) |
drm/amdgpu: add support to read virtual address rangeamdgpu-debug
File offset is interpreted as a gpu virtual address inside the currently
bound vm to the debug device file. So read on the debug device file allows
to read buffer behind a virtual address.
WIP there seems to be no protection to concurrent insert/remove inside the
gpu virtual address space which is kind of worrisome. I am probably missing
something that is very obvious otherwise. Bottom line is that we would need
to block remove from happening while reading mapping so that nothing end up
dereferencing something that is no longer there.
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_debug.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debug.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debug.c index bc233e8082fc..56b2c1d90682 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debug.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debug.c @@ -21,13 +21,63 @@ static dev_t _amdgpu_debug_devt; +static int amdgpu_debug_read_mapping(struct amdgpu_debug_file *file, + struct amdgpu_bo_va_mapping *mapping, + uint64_t start, uint64_t end, + char __user *buf) +{ + return -EINVAL; +} + +static struct amdgpu_bo_va_mapping *amdgpu_debug_find_mapping(struct amdgpu_debug_file *file, + uint64_t addr) +{ + struct amdgpu_device *adev = file->dev->adev; + struct amdgpu_vm *vm; + + vm = adev->vm_manager.id_mgr[file->hub_id].ids[file->vm_id]; + return amdgpu_vm_find_mapping(vm, addr); +} static ssize_t amdgpu_debug_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - return -EINVAL; + uint64_t start, addr, end, next, offset; + struct amdgpu_debug_file *file; + int ret = 0; + + if ((*ppos) < 0) + return -EINVAL; + if (!count) + return 0; + start = *ppos; + end = start + count; + + if (!filp->private_data) + return -EINVAL; + file = filp->private_data; + + down_read(&file->rwsem); + for (addr = start; addr < end;) { + struct amdgpu_bo_va_mapping *mapping; + + mapping = amdgpu_debug_find_mapping(file, addr); + if (!mapping) + break; + + next = min(mapping->last, end); + ret = amdgpu_debug_read_mapping(file, mapping, addr, next, buf); + if (ret) + break; + buf += (next - addr); + addr = next; + } + up_read(&file->rwsem); + + offset = addr - start; + return offset ? offset : ret; } static ssize_t amdgpu_debug_write(struct file *filp, |