From cc6ccd2e3fc1b097465e093a6294748113ab2cc7 Mon Sep 17 00:00:00 2001 From: Sami Kiminki Date: Tue, 28 Oct 2014 16:55:12 +0200 Subject: gpu: nvgpu: Implement NVGPU_AS_IOCTL_GET_VA_REGIONS Implement NVGPU_AS_IOCTL_GET_VA_REGIONS which returns a list of GPU VA regions for different page sizes. This is required for the userspace for safe fixed-address address space allocation. Bug 1551752 Change-Id: I63ddde30935db2471bec498dae0caa870e89c1a5 Signed-off-by: Sami Kiminki Reviewed-on: http://git-master/r/590814 Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/as_gk20a.c | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/gk20a/as_gk20a.c b/drivers/gpu/nvgpu/gk20a/as_gk20a.c index 0f587a30..34423d21 100644 --- a/drivers/gpu/nvgpu/gk20a/as_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/as_gk20a.c @@ -175,6 +175,52 @@ static int gk20a_as_ioctl_unmap_buffer( return gk20a_vm_unmap_buffer(as_share, args->offset); } +static int gk20a_as_ioctl_get_va_regions( + struct gk20a_as_share *as_share, + struct nvgpu_as_get_va_regions_args *args) +{ + unsigned int i; + unsigned int write_entries; + struct nvgpu_as_va_region __user *user_region_ptr; + struct vm_gk20a *vm = as_share->vm; + + gk20a_dbg_fn(""); + + write_entries = args->buf_size / sizeof(struct nvgpu_as_va_region); + if (write_entries > gmmu_nr_page_sizes) + write_entries = gmmu_nr_page_sizes; + + user_region_ptr = + (struct nvgpu_as_va_region __user *)(uintptr_t)args->buf_addr; + + for (i = 0; i < write_entries; ++i) { + struct nvgpu_as_va_region region; + u32 base, limit; + + memset(®ion, 0, sizeof(struct nvgpu_as_va_region)); + + if (!vm->vma[i].constraint.enable) { + base = vm->vma[i].base; + limit = vm->vma[i].limit; + } else { + base = vm->vma[i].constraint.base; + limit = vm->vma[i].constraint.limit; + } + + region.page_size = vm->gmmu_page_sizes[i]; + region.offset = (u64)base * region.page_size; + region.pages = limit - base; /* NOTE: limit is exclusive */ + + if (copy_to_user(user_region_ptr + i, ®ion, sizeof(region))) + return -EFAULT; + } + + args->buf_size = + gmmu_nr_page_sizes * sizeof(struct nvgpu_as_va_region); + + return 0; +} + int gk20a_as_dev_open(struct inode *inode, struct file *filp) { struct gk20a_as_share *as_share; @@ -275,6 +321,11 @@ long gk20a_as_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = gk20a_as_ioctl_unmap_buffer(as_share, (struct nvgpu_as_unmap_buffer_args *)buf); break; + case NVGPU_AS_IOCTL_GET_VA_REGIONS: + trace_gk20a_as_ioctl_get_va_regions(dev_name(dev_from_gk20a(g))); + err = gk20a_as_ioctl_get_va_regions(as_share, + (struct nvgpu_as_get_va_regions_args *)buf); + break; default: dev_dbg(dev_from_gk20a(g), "unrecognized as ioctl: 0x%x", cmd); err = -ENOTTY; -- cgit v1.2.2