diff options
author | Igor Nabirushkin <inabirushkin@nvidia.com> | 2013-10-24 17:23:11 +0400 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2013-11-07 12:12:12 -0800 |
commit | 22b4513dd20785fa718250f8bd0e84711acf2cd5 (patch) | |
tree | 1d26d10fde5c84ca75da45bdbc63669b936ce7f3 /drivers | |
parent | 14239d7105ab0d71cf307d3ef7a88a195f63408d (diff) |
misc: tegra-profiler: send mapped memory regions
Tegra Profiler: send information about mapped
memory regions (on demand).
Bug 1394970
Change-Id: Idf9a3c5d2d9fac0fd622f99bd226632c810a8ab6
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/309778
(cherry picked from commit 1a4a86d3faf8cd9a38cf80ed06f6a760264638be)
Reviewed-on: http://git-master/r/326028
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Tested-by: Maxim Morin <mmorin@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/tegra-profiler/hrt.c | 40 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/main.c | 5 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/mmap.c | 144 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/mmap.h | 6 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/version.h | 2 |
5 files changed, 139 insertions, 58 deletions
diff --git a/drivers/misc/tegra-profiler/hrt.c b/drivers/misc/tegra-profiler/hrt.c index 8bc30727d9bb..fef37de8c288 100644 --- a/drivers/misc/tegra-profiler/hrt.c +++ b/drivers/misc/tegra-profiler/hrt.c @@ -222,14 +222,6 @@ static int get_sample_data(struct event_data *event, return 0; } -static char *get_mmap_data(struct pt_regs *regs, - struct quadd_mmap_data *sample, - unsigned int *extra_length) -{ - struct quadd_cpu_context *cpu_ctx = this_cpu_ptr(hrt.cpu_ctx); - return quadd_get_mmap(cpu_ctx, regs, sample, extra_length); -} - static void read_source(struct quadd_event_source_interface *source, struct pt_regs *regs, pid_t pid) { @@ -306,27 +298,13 @@ static void read_source(struct quadd_event_source_interface *source, static void read_all_sources(struct pt_regs *regs, pid_t pid) { - struct quadd_record_data record_data; struct quadd_ctx *ctx = hrt.quadd_ctx; - unsigned int extra_length; - char *extra_data; + struct quadd_cpu_context *cpu_ctx = this_cpu_ptr(hrt.cpu_ctx); if (!regs) return; - extra_data = get_mmap_data(regs, &record_data.mmap, &extra_length); - if (extra_data && extra_length > 0) { - record_data.magic = QUADD_RECORD_MAGIC; - record_data.record_type = QUADD_RECORD_TYPE_MMAP; - record_data.cpu_mode = QUADD_CPU_MODE_USER; - - record_data.mmap.filename_length = extra_length; - record_data.mmap.pid = pid > 0 ? pid : ctx->param.pids[0]; - - quadd_put_sample(&record_data, extra_data, extra_length); - } else { - record_data.mmap.filename_length = 0; - } + quadd_get_mmap_object(cpu_ctx, regs, pid); if (ctx->pmu && ctx->pmu_info.active) read_source(ctx->pmu, regs, pid); @@ -473,9 +451,13 @@ static void reset_cpu_ctx(void) int quadd_hrt_start(void) { + int err; u64 period; long freq; + unsigned int extra; struct quadd_ctx *ctx = hrt.quadd_ctx; + struct quadd_cpu_context *cpu_ctx = this_cpu_ptr(hrt.cpu_ctx); + struct quadd_parameters *param = &ctx->param; freq = ctx->param.freq; freq = max_t(long, QUADD_HRT_MIN_FREQ, freq); @@ -493,6 +475,16 @@ int quadd_hrt_start(void) put_header(); + extra = param->reserved[QUADD_PARAM_IDX_EXTRA]; + + if (extra & QUADD_PARAM_IDX_EXTRA_GET_MMAP) { + err = quadd_get_current_mmap(cpu_ctx, param->pids[0]); + if (err) { + pr_err("error: quadd_get_current_mmap\n"); + return err; + } + } + if (ctx->pl310) ctx->pl310->start(); diff --git a/drivers/misc/tegra-profiler/main.c b/drivers/misc/tegra-profiler/main.c index f1ed75cf5833..2b9b8ad1b59b 100644 --- a/drivers/misc/tegra-profiler/main.c +++ b/drivers/misc/tegra-profiler/main.c @@ -146,6 +146,9 @@ static int set_parameters(struct quadd_parameters *param, uid_t *debug_app_uid) ctx.param.power_rate_freq = param->power_rate_freq; ctx.param.debug_samples = param->debug_samples; + for (i = 0; i < QM_ARRAY_SIZE(param->reserved); i++) + ctx.param.reserved[i] = param->reserved[i]; + /* Currently only one process */ if (param->nr_pids != 1) return -EINVAL; @@ -360,6 +363,8 @@ static void get_capabilities(struct quadd_comm_cap *cap) cap->blocked_read = 1; extra |= QUADD_COMM_CAP_EXTRA_BT_KERNEL_CTX; + extra |= QUADD_COMM_CAP_EXTRA_GET_MMAP; + cap->reserved[QUADD_COMM_CAP_IDX_EXTRA] = extra; } diff --git a/drivers/misc/tegra-profiler/mmap.c b/drivers/misc/tegra-profiler/mmap.c index 2b73e5cd9c0a..cf6f408a0d80 100644 --- a/drivers/misc/tegra-profiler/mmap.c +++ b/drivers/misc/tegra-profiler/mmap.c @@ -101,25 +101,61 @@ static int check_hash(u32 key) return 1; } -char *quadd_get_mmap(struct quadd_cpu_context *cpu_ctx, - struct pt_regs *regs, struct quadd_mmap_data *sample, - unsigned int *extra_length) +static int find_file(const char *file_name, unsigned long addr, + unsigned long len) { u32 crc; + size_t length; + + if (!file_name) + return 0; + + length = strlen(file_name); + + crc = crc32_le(~0, file_name, length); + crc = crc32_le(crc, (unsigned char *)&addr, + sizeof(addr)); + crc = crc32_le(crc, (unsigned char *)&len, + sizeof(len)); + + return check_hash(crc); +} + +static void +put_mmap_sample(struct quadd_mmap_data *s, char *extra_data, + size_t extra_length) +{ + struct quadd_record_data r; + + r.magic = QUADD_RECORD_MAGIC; + r.record_type = QUADD_RECORD_TYPE_MMAP; + r.cpu_mode = QUADD_CPU_MODE_USER; + + memcpy(&r.mmap, s, sizeof(*s)); + r.mmap.filename_length = extra_length; + + pr_debug("MMAP: pid: %d, file_name: '%s', addr: %#x, length: %u", + s->pid, extra_data, s->addr, extra_length); + + quadd_put_sample(&r, extra_data, extra_length); +} + +void quadd_get_mmap_object(struct quadd_cpu_context *cpu_ctx, + struct pt_regs *regs, pid_t pid) +{ unsigned long ip; - int length, length_aligned; + size_t length, length_aligned; struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct file *vm_file; struct path *path; char *file_name = NULL; + struct quadd_mmap_data sample; struct quadd_mmap_cpu_ctx *mm_cpu_ctx = this_cpu_ptr(mmap_ctx.cpu_ctx); char *tmp_buf = mm_cpu_ctx->tmp_buf; - if (!mm) { - *extra_length = 0; - return NULL; - } + if (!mm) + return; ip = instruction_pointer(regs); @@ -138,9 +174,9 @@ char *quadd_get_mmap(struct quadd_cpu_context *cpu_ctx, if (IS_ERR(file_name)) { file_name = NULL; } else { - sample->addr = vma->vm_start; - sample->len = vma->vm_end - vma->vm_start; - sample->pgoff = + sample.addr = vma->vm_start; + sample.len = vma->vm_end - vma->vm_start; + sample.pgoff = (u64)vma->vm_pgoff << PAGE_SHIFT; } break; @@ -156,38 +192,86 @@ char *quadd_get_mmap(struct quadd_cpu_context *cpu_ctx, if (mod) { file_name = mod->name; if (file_name) { - sample->addr = (u32) mod->module_core; - sample->len = mod->core_size; - sample->pgoff = 0; + sample.addr = (u32) mod->module_core; + sample.len = mod->core_size; + sample.pgoff = 0; } } #endif } if (file_name) { - length = strlen(file_name); - if (length >= PATH_MAX) { - *extra_length = 0; - return NULL; - } + if (!find_file(file_name, sample.addr, sample.len)) { + length = strlen(file_name) + 1; + if (length > PATH_MAX) + return; - crc = crc32_le(~0, file_name, length); - crc = crc32_le(crc, (unsigned char *)&sample->addr, - sizeof(sample->addr)); - crc = crc32_le(crc, (unsigned char *)&sample->len, - sizeof(sample->len)); + sample.pid = pid; - if (!check_hash(crc)) { strcpy(cpu_ctx->mmap_filename, file_name); - length_aligned = (length + 1 + 7) & (~7); - *extra_length = length_aligned; + length_aligned = ALIGN(length, 8); - return cpu_ctx->mmap_filename; + put_mmap_sample(&sample, cpu_ctx->mmap_filename, + length_aligned); } } +} + +int quadd_get_current_mmap(struct quadd_cpu_context *cpu_ctx, pid_t pid) +{ + struct vm_area_struct *vma; + struct file *vm_file; + struct path *path; + char *file_name; + struct task_struct *task; + struct mm_struct *mm; + struct quadd_mmap_data sample; + size_t length, length_aligned; + struct quadd_mmap_cpu_ctx *mm_cpu_ctx = this_cpu_ptr(mmap_ctx.cpu_ctx); + char *tmp_buf = mm_cpu_ctx->tmp_buf; + + rcu_read_lock(); + task = pid_task(find_vpid(pid), PIDTYPE_PID); + rcu_read_unlock(); + if (!task) { + pr_err("Process not found: %u\n", pid); + return -ESRCH; + } + mm = task->mm; + + pr_info("Get mapped memory objects\n"); + + for (vma = mm->mmap; vma; vma = vma->vm_next) { + vm_file = vma->vm_file; + if (!vm_file) + continue; - *extra_length = 0; - return NULL; + path = &vm_file->f_path; + + file_name = d_path(path, tmp_buf, PATH_MAX); + if (IS_ERR(file_name)) + continue; + + if (!(vma->vm_flags & VM_EXEC)) + continue; + + length = strlen(file_name) + 1; + if (length > PATH_MAX) + continue; + + sample.pid = pid; + sample.addr = vma->vm_start; + sample.len = vma->vm_end - vma->vm_start; + sample.pgoff = (u64)vma->vm_pgoff << PAGE_SHIFT; + + if (!find_file(file_name, sample.addr, sample.len)) { + strcpy(cpu_ctx->mmap_filename, file_name); + length_aligned = ALIGN(length, 8); + + put_mmap_sample(&sample, file_name, length_aligned); + } + } + return 0; } struct quadd_mmap_ctx *quadd_mmap_init(struct quadd_ctx *quadd_ctx) diff --git a/drivers/misc/tegra-profiler/mmap.h b/drivers/misc/tegra-profiler/mmap.h index dd750f956df9..4030ed216c43 100644 --- a/drivers/misc/tegra-profiler/mmap.h +++ b/drivers/misc/tegra-profiler/mmap.h @@ -39,10 +39,10 @@ struct quadd_mmap_ctx { struct quadd_ctx *quadd_ctx; }; -char *quadd_get_mmap(struct quadd_cpu_context *cpu_ctx, - struct pt_regs *regs, struct quadd_mmap_data *sample, - unsigned int *extra_length); +void quadd_get_mmap_object(struct quadd_cpu_context *cpu_ctx, + struct pt_regs *regs, pid_t pid); +int quadd_get_current_mmap(struct quadd_cpu_context *cpu_ctx, pid_t pid); struct quadd_mmap_ctx *quadd_mmap_init(struct quadd_ctx *quadd_ctx); void quadd_mmap_deinit(void); diff --git a/drivers/misc/tegra-profiler/version.h b/drivers/misc/tegra-profiler/version.h index 32b074609292..3dddadb66156 100644 --- a/drivers/misc/tegra-profiler/version.h +++ b/drivers/misc/tegra-profiler/version.h @@ -18,7 +18,7 @@ #ifndef __QUADD_VERSION_H #define __QUADD_VERSION_H -#define QUADD_MODULE_VERSION "1.37" +#define QUADD_MODULE_VERSION "1.40" #define QUADD_MODULE_BRANCH "Dev" #endif /* __QUADD_VERSION_H */ |