From 19186c8a02a158095e56f23a781bb46d70cf57b7 Mon Sep 17 00:00:00 2001 From: Lakshmanan M Date: Mon, 29 Mar 2021 15:02:08 +0530 Subject: [PATCH] gpu: nvgpu: select map access type from dmabuf permission and user request Add api to translate dmabuf's fmode_t to gk20a_mem_rw_flag for read only/read write mapping selection. By default dmabuf fd mapping permission should be a maximum access permission associated to a particual dmabuf fd. Remove bit flag MAP_ACCESS_NO_WRITE and add 2 bit values for user access requests NVGPU_VM_MAP_ACCESS_DEFAULT|READ_ONLY| READ_WRITE. To unify map access type handling in Linux and QNX move the parameter NVGPU_VM_MAP_ACCESS_* check to common function nvgpu_vm_map. Set MAP_ACCESS_TYPE enabled flag in common characteristics init function as it is supported for Linux and QNX. Bug 200717195 Bug 3250920 Change-Id: I1a249f7c52bda099390dd4f371b005e1a7cef62f Signed-off-by: Lakshmanan M Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2507150 Reviewed-by: svc_kernel_abi Reviewed-by: Vijayakumar Subbu Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-misra Reviewed-by: svc-mobile-cert Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/init/nvgpu_init.c | 1 + drivers/gpu/nvgpu/common/mm/vm.c | 14 +++- drivers/gpu/nvgpu/include/nvgpu/linux/vm.h | 1 + drivers/gpu/nvgpu/include/nvgpu/vm.h | 6 +- drivers/gpu/nvgpu/os/linux/cde.c | 1 + drivers/gpu/nvgpu/os/linux/module.c | 1 - drivers/gpu/nvgpu/os/linux/vm.c | 82 ++++++++++++++++++---- include/uapi/linux/nvgpu-as.h | 8 ++- userspace/units/mm/vm/vm.c | 8 +++ 9 files changed, 105 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/nvgpu/common/init/nvgpu_init.c b/drivers/gpu/nvgpu/common/init/nvgpu_init.c index a46cf5979..38c400ae1 100644 --- a/drivers/gpu/nvgpu/common/init/nvgpu_init.c +++ b/drivers/gpu/nvgpu/common/init/nvgpu_init.c @@ -912,6 +912,7 @@ int nvgpu_init_gpu_characteristics(struct gk20a *g) nvgpu_set_enabled(g, NVGPU_SUPPORT_MAP_DIRECT_KIND_CTRL, true); nvgpu_set_enabled(g, NVGPU_SUPPORT_MAP_BUFFER_BATCH, true); nvgpu_set_enabled(g, NVGPU_SUPPORT_SPARSE_ALLOCS, true); + nvgpu_set_enabled(g, NVGPU_SUPPORT_MAP_ACCESS_TYPE, true); /* * Fast submits are supported as long as the user doesn't request diff --git a/drivers/gpu/nvgpu/common/mm/vm.c b/drivers/gpu/nvgpu/common/mm/vm.c index b62574eea..aac948b85 100644 --- a/drivers/gpu/nvgpu/common/mm/vm.c +++ b/drivers/gpu/nvgpu/common/mm/vm.c @@ -1462,7 +1462,8 @@ int nvgpu_vm_map(struct vm_gk20a *vm, u64 map_addr, u64 map_size, u64 phys_offset, - enum gk20a_mem_rw_flag rw, + enum gk20a_mem_rw_flag buffer_rw_mode, + u32 map_access_requested, u32 flags, s16 compr_kind, s16 incompr_kind, @@ -1473,6 +1474,7 @@ int nvgpu_vm_map(struct vm_gk20a *vm, struct gk20a *g = gk20a_from_vm(vm); struct nvgpu_mapped_buf *mapped_buffer = NULL; struct nvgpu_ctag_buffer_info binfo = { 0 }; + enum gk20a_mem_rw_flag rw = buffer_rw_mode; struct nvgpu_vm_area *vm_area = NULL; int err = 0; bool va_allocated = true; @@ -1484,6 +1486,16 @@ int nvgpu_vm_map(struct vm_gk20a *vm, */ s16 map_key_kind; + if ((map_access_requested == NVGPU_VM_MAP_ACCESS_READ_WRITE) && + (buffer_rw_mode == gk20a_mem_flag_read_only)) { + nvgpu_err(g, "RW mapping requested for RO buffer"); + return -EINVAL; + } + + if (map_access_requested == NVGPU_VM_MAP_ACCESS_READ_ONLY) { + rw = gk20a_mem_flag_read_only; + } + *mapped_buffer_arg = NULL; err = nvgpu_vm_map_check_attributes(vm, os_buf, &binfo, flags, diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h b/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h index 53bbfeda6..c2aa7d55e 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h +++ b/drivers/gpu/nvgpu/include/nvgpu/linux/vm.h @@ -56,6 +56,7 @@ struct nvgpu_mapped_buf_priv { int nvgpu_vm_map_linux(struct vm_gk20a *vm, struct dma_buf *dmabuf, u64 map_addr, + u32 map_access_requested, u32 flags, u32 page_size, s16 compr_kind, diff --git a/drivers/gpu/nvgpu/include/nvgpu/vm.h b/drivers/gpu/nvgpu/include/nvgpu/vm.h index e93ab47b9..5db38bde3 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/vm.h +++ b/drivers/gpu/nvgpu/include/nvgpu/vm.h @@ -352,7 +352,10 @@ struct vm_gk20a { #define NVGPU_VM_MAP_DIRECT_KIND_CTRL BIT32(4) #define NVGPU_VM_MAP_L3_ALLOC BIT32(5) #define NVGPU_VM_MAP_PLATFORM_ATOMIC BIT32(6) -#define NVGPU_VM_MAP_ACCESS_NO_WRITE BIT32(7) + +#define NVGPU_VM_MAP_ACCESS_DEFAULT 0U +#define NVGPU_VM_MAP_ACCESS_READ_ONLY 1U +#define NVGPU_VM_MAP_ACCESS_READ_WRITE 2U #define NVGPU_KIND_INVALID S16(-1) @@ -604,6 +607,7 @@ int nvgpu_vm_map(struct vm_gk20a *vm, u64 map_size, u64 phys_offset, enum gk20a_mem_rw_flag rw, + u32 map_access_requested, u32 flags, s16 compr_kind, s16 incompr_kind, diff --git a/drivers/gpu/nvgpu/os/linux/cde.c b/drivers/gpu/nvgpu/os/linux/cde.c index a98c5cb07..3865857c7 100644 --- a/drivers/gpu/nvgpu/os/linux/cde.c +++ b/drivers/gpu/nvgpu/os/linux/cde.c @@ -1107,6 +1107,7 @@ __releases(&l->cde_app->mutex) /* map the destination buffer */ get_dma_buf(compbits_scatter_buf); /* a ref for nvgpu_vm_map_linux */ err = nvgpu_vm_map_linux(cde_ctx->vm, compbits_scatter_buf, 0, + NVGPU_VM_MAP_ACCESS_DEFAULT, NVGPU_VM_MAP_CACHEABLE | NVGPU_VM_MAP_DIRECT_KIND_CTRL, gk20a_cde_mapping_page_size(cde_ctx->vm, diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 333a33a2a..2cfbca8dd 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -316,7 +316,6 @@ void gk20a_init_linux_characteristics(struct gk20a *g) nvgpu_set_enabled(g, NVGPU_SUPPORT_PARTIAL_MAPPINGS, true); nvgpu_set_enabled(g, NVGPU_SUPPORT_DETERMINISTIC_OPTS, true); nvgpu_set_enabled(g, NVGPU_SUPPORT_USERSPACE_MANAGED_AS, true); - nvgpu_set_enabled(g, NVGPU_SUPPORT_MAP_ACCESS_TYPE, true); if (!IS_ENABLED(CONFIG_NVGPU_SYNCFD_NONE)) { nvgpu_set_enabled(g, NVGPU_SUPPORT_SYNC_FENCE_FDS, true); diff --git a/drivers/gpu/nvgpu/os/linux/vm.c b/drivers/gpu/nvgpu/os/linux/vm.c index c533def8b..49dc5433e 100644 --- a/drivers/gpu/nvgpu/os/linux/vm.c +++ b/drivers/gpu/nvgpu/os/linux/vm.c @@ -43,6 +43,9 @@ static u32 nvgpu_vm_translate_linux_flags(struct gk20a *g, u32 flags) { u32 core_flags = 0; + u32 map_access_bitmask = + (BIT32(NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_BITMASK_SIZE) - 1U) << + NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_BITMASK_OFFSET; if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_FIXED_OFFSET) core_flags |= NVGPU_VM_MAP_FIXED_OFFSET; @@ -58,8 +61,9 @@ static u32 nvgpu_vm_translate_linux_flags(struct gk20a *g, u32 flags) core_flags |= NVGPU_VM_MAP_DIRECT_KIND_CTRL; if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_PLATFORM_ATOMIC) core_flags |= NVGPU_VM_MAP_PLATFORM_ATOMIC; - if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_NO_WRITE) - core_flags |= NVGPU_VM_MAP_ACCESS_NO_WRITE; + + /* copy the map access bitfield from flags */ + core_flags |= (flags & map_access_bitmask); if (flags & NVGPU_AS_MAP_BUFFER_FLAGS_MAPPABLE_COMPBITS) nvgpu_warn(g, "Ignoring deprecated flag: " @@ -68,6 +72,20 @@ static u32 nvgpu_vm_translate_linux_flags(struct gk20a *g, u32 flags) return core_flags; } +static int nvgpu_vm_translate_map_access(struct gk20a *g, u32 flags, + u32 *map_access) +{ + *map_access = (flags >> NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_BITMASK_OFFSET) & + (BIT32(NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_BITMASK_SIZE) - 1U); + + if (*map_access > NVGPU_AS_MAP_BUFFER_ACCESS_READ_WRITE) { + nvgpu_err(g, "Invalid map access specified %u", *map_access); + return -EINVAL; + } + + return 0; +} + static struct nvgpu_mapped_buf *nvgpu_vm_find_mapped_buf_reverse( struct vm_gk20a *vm, struct dma_buf *dmabuf, s16 kind) { @@ -183,9 +201,40 @@ struct nvgpu_mapped_buf *nvgpu_vm_find_mapping(struct vm_gk20a *vm, return mapped_buffer; } +static int nvgpu_convert_fmode_to_gmmu_rw_attr(struct gk20a *g, fmode_t mode, + enum gk20a_mem_rw_flag *rw_attr) +{ + fmode_t fmode_rw_flag = mode & (FMODE_READ | FMODE_PREAD | + FMODE_WRITE | FMODE_PWRITE); + int ret = 0; + + if (!fmode_rw_flag) { + return -EINVAL; + } + + switch (fmode_rw_flag) { + case FMODE_READ: + case FMODE_PREAD: + case (FMODE_READ | FMODE_PREAD): + *rw_attr = gk20a_mem_flag_read_only; + break; + case FMODE_WRITE: + case FMODE_PWRITE: + case (FMODE_WRITE | FMODE_PWRITE): + ret = -EINVAL; + break; + default: + *rw_attr = gk20a_mem_flag_none; + break; + } + + return ret; +} + int nvgpu_vm_map_linux(struct vm_gk20a *vm, struct dma_buf *dmabuf, u64 map_addr, + u32 map_access_requested, u32 flags, u32 page_size, s16 compr_kind, @@ -195,7 +244,7 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, struct vm_gk20a_mapping_batch *batch, u64 *gpu_va) { - enum gk20a_mem_rw_flag rw_flag = gk20a_mem_flag_none; + enum gk20a_mem_rw_flag buffer_rw_mode = gk20a_mem_flag_none; struct gk20a *g = gk20a_from_vm(vm); struct device *dev = dev_from_gk20a(g); struct nvgpu_os_buffer os_buf; @@ -208,10 +257,12 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, nvgpu_log(g, gpu_dbg_map, "dmabuf file mode: 0x%x mapping flags: 0x%x", dmabuf->file->f_mode, flags); - if (!(dmabuf->file->f_mode & (FMODE_WRITE | FMODE_PWRITE)) && - !(flags & NVGPU_VM_MAP_ACCESS_NO_WRITE)) { - nvgpu_err(g, "RW access requested for RO mapped buffer"); - return -EINVAL; + err = nvgpu_convert_fmode_to_gmmu_rw_attr(g, dmabuf->file->f_mode, + &buffer_rw_mode); + if (err != 0) { + nvgpu_err(g, "dmabuf file mode 0x%x not supported for GMMU map", + dmabuf->file->f_mode); + return err; } sgt = nvgpu_mm_pin(dev, dmabuf, &attachment); @@ -234,17 +285,14 @@ int nvgpu_vm_map_linux(struct vm_gk20a *vm, goto clean_up; } - if (flags & NVGPU_VM_MAP_ACCESS_NO_WRITE) { - rw_flag = gk20a_mem_flag_read_only; - } - err = nvgpu_vm_map(vm, &os_buf, nvgpu_sgt, map_addr, mapping_size, buffer_offset, - rw_flag, + buffer_rw_mode, + map_access_requested, flags, compr_kind, incompr_kind, @@ -284,6 +332,7 @@ int nvgpu_vm_map_buffer(struct vm_gk20a *vm, { struct gk20a *g = gk20a_from_vm(vm); struct dma_buf *dmabuf; + u32 map_access; u64 ret_va; int err = 0; @@ -333,7 +382,14 @@ int nvgpu_vm_map_buffer(struct vm_gk20a *vm, return -EINVAL; } - err = nvgpu_vm_map_linux(vm, dmabuf, *map_addr, + err = nvgpu_vm_translate_map_access(g, flags, &map_access); + if (err != 0) { + nvgpu_err(g, "map access translation failed"); + dma_buf_put(dmabuf); + return -EINVAL; + } + + err = nvgpu_vm_map_linux(vm, dmabuf, *map_addr, map_access, nvgpu_vm_translate_linux_flags(g, flags), page_size, compr_kind, incompr_kind, diff --git a/include/uapi/linux/nvgpu-as.h b/include/uapi/linux/nvgpu-as.h index 675f3c316..b349ece92 100644 --- a/include/uapi/linux/nvgpu-as.h +++ b/include/uapi/linux/nvgpu-as.h @@ -110,7 +110,13 @@ struct nvgpu_as_bind_channel_args { #define NVGPU_AS_MAP_BUFFER_FLAGS_L3_ALLOC (1 << 7) #define NVGPU_AS_MAP_BUFFER_FLAGS_DIRECT_KIND_CTRL (1 << 8) #define NVGPU_AS_MAP_BUFFER_FLAGS_PLATFORM_ATOMIC (1 << 9) -#define NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_NO_WRITE (1 << 10) + +#define NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_BITMASK_OFFSET 10U +#define NVGPU_AS_MAP_BUFFER_FLAGS_ACCESS_BITMASK_SIZE 2U + +#define NVGPU_AS_MAP_BUFFER_ACCESS_DEFAULT 0U +#define NVGPU_AS_MAP_BUFFER_ACCESS_READ_ONLY 1U +#define NVGPU_AS_MAP_BUFFER_ACCESS_READ_WRITE 2U /* * VM map buffer IOCTL diff --git a/userspace/units/mm/vm/vm.c b/userspace/units/mm/vm/vm.c index 161b8f639..b1a89b46b 100644 --- a/userspace/units/mm/vm/vm.c +++ b/userspace/units/mm/vm/vm.c @@ -355,6 +355,7 @@ int test_map_buffer_error_cases(struct unit_module *m, struct gk20a *g, buf_size, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, NVGPU_VM_MAP_CACHEABLE, NV_KIND_INVALID, 0, @@ -377,6 +378,7 @@ int test_map_buffer_error_cases(struct unit_module *m, struct gk20a *g, buf_size, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, NVGPU_VM_MAP_CACHEABLE, NV_KIND_INVALID, 0, @@ -399,6 +401,7 @@ int test_map_buffer_error_cases(struct unit_module *m, struct gk20a *g, buf_size, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, NVGPU_VM_MAP_CACHEABLE, NV_KIND_INVALID, 0, @@ -420,6 +423,7 @@ int test_map_buffer_error_cases(struct unit_module *m, struct gk20a *g, SZ_1G, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, NVGPU_VM_MAP_CACHEABLE, NV_KIND_INVALID, 0, @@ -441,6 +445,7 @@ int test_map_buffer_error_cases(struct unit_module *m, struct gk20a *g, buf_size, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, NVGPU_VM_MAP_CACHEABLE, NVGPU_KIND_INVALID, NVGPU_KIND_INVALID, @@ -463,6 +468,7 @@ int test_map_buffer_error_cases(struct unit_module *m, struct gk20a *g, buf_size, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, NVGPU_VM_MAP_CACHEABLE, NV_KIND_INVALID, 0, @@ -616,6 +622,7 @@ static int map_buffer(struct unit_module *m, buf_size, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, flags, compr_kind, 0, @@ -641,6 +648,7 @@ static int map_buffer(struct unit_module *m, buf_size, 0, gk20a_mem_flag_none, + NVGPU_VM_MAP_ACCESS_READ_WRITE, flags, compr_kind, 0,