summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérôme Glisse <jglisse@redhat.com>2017-08-02 00:22:27 -0400
committerJérôme Glisse <jglisse@redhat.com>2017-08-02 00:22:27 -0400
commitfe684469bb2e5c7834f94e4683da6f48e23c6dc7 (patch)
tree62bc89a8ec3884305556ce3cff3dfb21a84812e9
parent9181b002500eb07575a2d782e0f6fd5878d6e1bd (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.c52
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,