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 ++++++++++++++++++++++++++++++++++++++ include/trace/events/gk20a.h | 12 +++++++++ include/uapi/linux/nvgpu.h | 20 ++++++++++++++- 3 files changed, 82 insertions(+), 1 deletion(-) 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; diff --git a/include/trace/events/gk20a.h b/include/trace/events/gk20a.h index e94c5be6..84a525bd 100644 --- a/include/trace/events/gk20a.h +++ b/include/trace/events/gk20a.h @@ -237,6 +237,18 @@ TRACE_EVENT(gk20a_as_ioctl_unmap_buffer, TP_printk("name=%s ", __entry->name) ); +TRACE_EVENT(gk20a_as_ioctl_get_va_regions, + TP_PROTO(const char *name), + TP_ARGS(name), + TP_STRUCT__entry( + __field(const char *, name) + ), + TP_fast_assign( + __entry->name = name; + ), + TP_printk("name=%s ", __entry->name) +); + TRACE_EVENT(gk20a_mmu_fault, TP_PROTO(u32 fault_hi, u32 fault_lo, u32 fault_info, diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h index 42673820..97e791df 100644 --- a/include/uapi/linux/nvgpu.h +++ b/include/uapi/linux/nvgpu.h @@ -793,6 +793,22 @@ struct nvgpu_as_unmap_buffer_args { __u64 offset; /* in, byte address */ }; + +struct nvgpu_as_va_region { + __u64 offset; + __u32 page_size; + __u32 reserved; + __u64 pages; +}; + +struct nvgpu_as_get_va_regions_args { + __u64 buf_addr; /* Pointer to array of nvgpu_as_va_region:s. + * Ignored if buf_size is 0 */ + __u32 buf_size; /* in: userspace buf size (in bytes) + out: kernel buf size (in bytes) */ + __u32 reserved; +}; + #define NVGPU_AS_IOCTL_BIND_CHANNEL \ _IOWR(NVGPU_AS_IOCTL_MAGIC, 1, struct nvgpu_as_bind_channel_args) #define NVGPU32_AS_IOCTL_ALLOC_SPACE \ @@ -807,9 +823,11 @@ struct nvgpu_as_unmap_buffer_args { _IOWR(NVGPU_AS_IOCTL_MAGIC, 6, struct nvgpu_as_alloc_space_args) #define NVGPU_AS_IOCTL_MAP_BUFFER_EX \ _IOWR(NVGPU_AS_IOCTL_MAGIC, 7, struct nvgpu_as_map_buffer_ex_args) +#define NVGPU_AS_IOCTL_GET_VA_REGIONS \ + _IOWR(NVGPU_AS_IOCTL_MAGIC, 8, struct nvgpu_as_get_va_regions_args) #define NVGPU_AS_IOCTL_LAST \ - _IOC_NR(NVGPU_AS_IOCTL_MAP_BUFFER_EX) + _IOC_NR(NVGPU_AS_IOCTL_GET_VA_REGIONS) #define NVGPU_AS_IOCTL_MAX_ARG_SIZE \ sizeof(struct nvgpu_as_map_buffer_ex_args) -- cgit v1.2.2