diff options
author | Jack Diver <diverj@google.com> | 2022-09-02 11:38:04 +0000 |
---|---|---|
committer | Jack Diver <diverj@google.com> | 2022-09-02 14:33:02 +0000 |
commit | c30533582604fe0365bc3ce4e9e8e19dec3109da (patch) | |
tree | 2dc4d074c820b535e9f18b8cd81d7e91bff042e5 /mali_kbase/mali_kbase_kinstr_prfcnt.c | |
parent | 88d7d984fed1c2a4358ce2bbc334e82d71e3a391 (diff) | |
download | gpu-c30533582604fe0365bc3ce4e9e8e19dec3109da.tar.gz |
Mali Valhall Android DDK r38p1-01eac0
VX504X08X-BU-00000-r38p1-01eac0 - Valhall Android DDK
VX504X08X-BU-60000-r38p1-01eac0 - Valhall Android Document Bundle
VX504X08X-DC-11001-r38p1-01eac0 - Valhall Android DDK Software Errata
VX504X08X-SW-99006-r38p1-01eac0 - Valhall Android Renderscript AOSP parts
Signed-off-by: Jack Diver <diverj@google.com>
Change-Id: I242060ad8ddc14475bda657cbbbe6b6c26ecfd57
Diffstat (limited to 'mali_kbase/mali_kbase_kinstr_prfcnt.c')
-rw-r--r-- | mali_kbase/mali_kbase_kinstr_prfcnt.c | 113 |
1 files changed, 33 insertions, 80 deletions
diff --git a/mali_kbase/mali_kbase_kinstr_prfcnt.c b/mali_kbase/mali_kbase_kinstr_prfcnt.c index e0c2c2c..26b9220 100644 --- a/mali_kbase/mali_kbase_kinstr_prfcnt.c +++ b/mali_kbase/mali_kbase_kinstr_prfcnt.c @@ -36,6 +36,7 @@ #include <linux/mutex.h> #include <linux/poll.h> #include <linux/slab.h> +#include <linux/version_compat_defs.h> #include <linux/workqueue.h> /* The minimum allowed interval between dumps, in nanoseconds @@ -87,16 +88,13 @@ struct kbase_kinstr_prfcnt_sample { /** * struct kbase_kinstr_prfcnt_sample_array - Array of sample data. - * @page_addr: Address of allocated pages. A single allocation is used + * @user_buf: Address of allocated userspace buffer. A single allocation is used * for all Dump Buffers in the array. - * @page_order: The allocation order of the pages, the order is on a - * logarithmic scale. * @sample_count: Number of allocated samples. * @samples: Non-NULL pointer to the array of Dump Buffers. */ struct kbase_kinstr_prfcnt_sample_array { - u64 page_addr; - unsigned int page_order; + u8 *user_buf; size_t sample_count; struct kbase_kinstr_prfcnt_sample *samples; }; @@ -229,25 +227,19 @@ static struct prfcnt_enum_item kinstr_prfcnt_supported_requests[] = { * Return: POLLIN if data can be read without blocking, 0 if data can not be * read without blocking, else error code. */ -#if KERNEL_VERSION(4, 16, 0) >= LINUX_VERSION_CODE -static unsigned int -kbasep_kinstr_prfcnt_hwcnt_reader_poll(struct file *filp, - struct poll_table_struct *wait) -#else static __poll_t kbasep_kinstr_prfcnt_hwcnt_reader_poll(struct file *filp, struct poll_table_struct *wait) -#endif { struct kbase_kinstr_prfcnt_client *cli; if (!filp || !wait) - return -EINVAL; + return (__poll_t)-EINVAL; cli = filp->private_data; if (!cli) - return -EINVAL; + return (__poll_t)-EINVAL; poll_wait(filp, &cli->waitq, wait); @@ -392,7 +384,10 @@ kbase_hwcnt_metadata_block_type_to_prfcnt_block_type(u64 type) block_type = PRFCNT_BLOCK_TYPE_MEMORY; break; - case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_UNDEFINED: + case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_FE_UNDEFINED: + case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_SC_UNDEFINED: + case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_TILER_UNDEFINED: + case KBASE_HWCNT_GPU_V5_BLOCK_TYPE_PERF_MEMSYS_UNDEFINED: default: block_type = PRFCNT_BLOCK_TYPE_RESERVED; break; @@ -426,7 +421,7 @@ static bool kbase_kinstr_is_block_type_reserved(const struct kbase_hwcnt_metadat int kbasep_kinstr_prfcnt_set_block_meta_items(struct kbase_hwcnt_enable_map *enable_map, struct kbase_hwcnt_dump_buffer *dst, struct prfcnt_metadata **block_meta_base, - u64 base_addr, u8 counter_set) + u8 *base_addr, u8 counter_set) { size_t grp, blk, blk_inst; struct prfcnt_metadata **ptr_md = block_meta_base; @@ -437,7 +432,7 @@ int kbasep_kinstr_prfcnt_set_block_meta_items(struct kbase_hwcnt_enable_map *ena metadata = dst->metadata; kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { - u64 *dst_blk; + u8 *dst_blk; /* Skip unavailable or non-enabled blocks */ if (kbase_kinstr_is_block_type_reserved(metadata, grp, blk) || @@ -445,7 +440,7 @@ int kbasep_kinstr_prfcnt_set_block_meta_items(struct kbase_hwcnt_enable_map *ena !kbase_hwcnt_enable_map_block_enabled(enable_map, grp, blk, blk_inst)) continue; - dst_blk = kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); + dst_blk = (u8 *)kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); (*ptr_md)->hdr.item_type = PRFCNT_SAMPLE_META_TYPE_BLOCK; (*ptr_md)->hdr.item_version = PRFCNT_READER_API_VERSION; (*ptr_md)->u.block_md.block_type = @@ -455,7 +450,7 @@ int kbasep_kinstr_prfcnt_set_block_meta_items(struct kbase_hwcnt_enable_map *ena (*ptr_md)->u.block_md.block_idx = (u8)blk_inst; (*ptr_md)->u.block_md.set = counter_set; (*ptr_md)->u.block_md.block_state = BLOCK_STATE_UNKNOWN; - (*ptr_md)->u.block_md.values_offset = (u32)((u64)(uintptr_t)dst_blk - base_addr); + (*ptr_md)->u.block_md.values_offset = (u32)(dst_blk - base_addr); /* update the buf meta data block pointer to next item */ (*ptr_md)++; @@ -501,7 +496,7 @@ static void kbasep_kinstr_prfcnt_set_sample_metadata( /* Dealing with counter blocks */ ptr_md++; if (WARN_ON(kbasep_kinstr_prfcnt_set_block_meta_items(&cli->enable_map, dump_buf, &ptr_md, - cli->sample_arr.page_addr, + cli->sample_arr.user_buf, cli->config.counter_set))) return; @@ -1011,12 +1006,8 @@ kbasep_kinstr_prfcnt_get_sample(struct kbase_kinstr_prfcnt_client *cli, } read_idx %= cli->sample_arr.sample_count; - sample_offset_bytes = - (u64)(uintptr_t)cli->sample_arr.samples[read_idx].sample_meta - - (u64)(uintptr_t)cli->sample_arr.page_addr; - sample_meta = - (struct prfcnt_metadata *)cli->sample_arr.samples[read_idx] - .sample_meta; + sample_meta = cli->sample_arr.samples[read_idx].sample_meta; + sample_offset_bytes = (u8 *)sample_meta - cli->sample_arr.user_buf; /* Verify that a valid sample has been dumped in the read_idx. * There are situations where this may not be the case, @@ -1061,8 +1052,7 @@ kbasep_kinstr_prfcnt_put_sample(struct kbase_kinstr_prfcnt_client *cli, read_idx %= cli->sample_arr.sample_count; sample_offset_bytes = - (u64)(uintptr_t)cli->sample_arr.samples[read_idx].sample_meta - - (u64)(uintptr_t)cli->sample_arr.page_addr; + (u8 *)cli->sample_arr.samples[read_idx].sample_meta - cli->sample_arr.user_buf; if (sample_access->sample_offset_bytes != sample_offset_bytes) { err = -EINVAL; @@ -1154,40 +1144,15 @@ static int kbasep_kinstr_prfcnt_hwcnt_reader_mmap(struct file *filp, struct vm_area_struct *vma) { struct kbase_kinstr_prfcnt_client *cli; - unsigned long vm_size, size, addr, pfn, offset; if (!filp || !vma) return -EINVAL; - cli = filp->private_data; + cli = filp->private_data; if (!cli) return -EINVAL; - vm_size = vma->vm_end - vma->vm_start; - - /* The mapping is allowed to span the entirety of the page allocation, - * not just the chunk where the dump buffers are allocated. - * This accommodates the corner case where the combined size of the - * dump buffers is smaller than a single page. - * This does not pose a security risk as the pages are zeroed on - * allocation, and anything out of bounds of the dump buffers is never - * written to. - */ - size = (1ull << cli->sample_arr.page_order) * PAGE_SIZE; - - if (vma->vm_pgoff > (size >> PAGE_SHIFT)) - return -EINVAL; - - offset = vma->vm_pgoff << PAGE_SHIFT; - - if (vm_size > size - offset) - return -EINVAL; - - addr = __pa(cli->sample_arr.page_addr + offset); - pfn = addr >> PAGE_SHIFT; - - return remap_pfn_range(vma, vma->vm_start, pfn, vm_size, - vma->vm_page_prot); + return remap_vmalloc_range(vma, cli->sample_arr.user_buf, 0); } static void kbasep_kinstr_prfcnt_sample_array_free( @@ -1196,8 +1161,8 @@ static void kbasep_kinstr_prfcnt_sample_array_free( if (!sample_arr) return; - kfree((void *)sample_arr->samples); - kfree((void *)(size_t)sample_arr->page_addr); + kfree(sample_arr->samples); + vfree(sample_arr->user_buf); memset(sample_arr, 0, sizeof(*sample_arr)); } @@ -1431,8 +1396,6 @@ void kbase_kinstr_prfcnt_term(struct kbase_kinstr_prfcnt_context *kinstr_ctx) if (!kinstr_ctx) return; - cancel_work_sync(&kinstr_ctx->dump_work); - /* Non-zero client count implies client leak */ if (WARN_ON(kinstr_ctx->client_count > 0)) { struct kbase_kinstr_prfcnt_client *pos, *n; @@ -1444,6 +1407,8 @@ void kbase_kinstr_prfcnt_term(struct kbase_kinstr_prfcnt_context *kinstr_ctx) } } + cancel_work_sync(&kinstr_ctx->dump_work); + WARN_ON(kinstr_ctx->client_count > 0); kfree(kinstr_ctx); } @@ -1518,8 +1483,6 @@ static int kbasep_kinstr_prfcnt_sample_array_alloc(struct kbase_kinstr_prfcnt_cl struct kbase_kinstr_prfcnt_sample_array *sample_arr = &cli->sample_arr; struct kbase_kinstr_prfcnt_sample *samples; size_t sample_idx; - u64 addr; - unsigned int order; size_t dump_buf_bytes; size_t clk_cnt_buf_bytes; size_t sample_meta_bytes; @@ -1542,16 +1505,13 @@ static int kbasep_kinstr_prfcnt_sample_array_alloc(struct kbase_kinstr_prfcnt_cl if (!samples) return -ENOMEM; - order = get_order(sample_size * buffer_count); - addr = (u64)(uintptr_t)kzalloc(sample_size * buffer_count, GFP_KERNEL); + sample_arr->user_buf = vmalloc_user(sample_size * buffer_count); - if (!addr) { - kfree((void *)samples); + if (!sample_arr->user_buf) { + kfree(samples); return -ENOMEM; } - sample_arr->page_addr = addr; - sample_arr->page_order = order; sample_arr->sample_count = buffer_count; sample_arr->samples = samples; @@ -1565,12 +1525,11 @@ static int kbasep_kinstr_prfcnt_sample_array_alloc(struct kbase_kinstr_prfcnt_cl /* Internal layout in a sample buffer: [sample metadata, dump_buf, clk_cnt_buf]. */ samples[sample_idx].dump_buf.metadata = metadata; samples[sample_idx].sample_meta = - (struct prfcnt_metadata *)(uintptr_t)( - addr + sample_meta_offset); + (struct prfcnt_metadata *)(sample_arr->user_buf + sample_meta_offset); samples[sample_idx].dump_buf.dump_buf = - (u64 *)(uintptr_t)(addr + dump_buf_offset); + (u64 *)(sample_arr->user_buf + dump_buf_offset); samples[sample_idx].dump_buf.clk_cnt_buf = - (u64 *)(uintptr_t)(addr + clk_cnt_buf_offset); + (u64 *)(sample_arr->user_buf + clk_cnt_buf_offset); } return 0; @@ -2015,7 +1974,6 @@ static int kbasep_kinstr_prfcnt_enum_info_count( struct kbase_kinstr_prfcnt_context *kinstr_ctx, struct kbase_ioctl_kinstr_prfcnt_enum_info *enum_info) { - int err = 0; uint32_t count = 0; size_t block_info_count = 0; const struct kbase_hwcnt_metadata *metadata; @@ -2036,7 +1994,7 @@ static int kbasep_kinstr_prfcnt_enum_info_count( enum_info->info_item_size = sizeof(struct prfcnt_enum_item); kinstr_ctx->info_item_count = count; - return err; + return 0; } static int kbasep_kinstr_prfcnt_enum_info_list( @@ -2149,15 +2107,10 @@ int kbase_kinstr_prfcnt_setup(struct kbase_kinstr_prfcnt_context *kinstr_ctx, } bytes = item_count * sizeof(*req_arr); - req_arr = kmalloc(bytes, GFP_KERNEL); + req_arr = memdup_user(u64_to_user_ptr(setup->in.requests_ptr), bytes); - if (!req_arr) - return -ENOMEM; - - if (copy_from_user(req_arr, u64_to_user_ptr(setup->in.requests_ptr), bytes)) { - err = -EFAULT; - goto free_buf; - } + if (IS_ERR(req_arr)) + return PTR_ERR(req_arr); err = kbasep_kinstr_prfcnt_client_create(kinstr_ctx, setup, &cli, req_arr); |