summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Nabirushkin <inabirushkin@nvidia.com>2013-10-24 17:23:11 +0400
committerHarry Hong <hhong@nvidia.com>2013-12-10 16:23:17 -0800
commit0b550db040aab353f7c8c998e042f797e81179d9 (patch)
tree12199f59a61a40181510ae90700550b4c7c4dee8
parentb8d7347b29a301713bac8f044bfbfa30ae1c6d31 (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/324093 (cherry picked from commit 9b684c4808301c89c8d479d562afc5830ff3835a) Reviewed-on: http://git-master/r/340018 Reviewed-by: Harry Hong <hhong@nvidia.com> Tested-by: Harry Hong <hhong@nvidia.com>
-rw-r--r--drivers/misc/tegra-profiler/hrt.c40
-rw-r--r--drivers/misc/tegra-profiler/main.c5
-rw-r--r--drivers/misc/tegra-profiler/mmap.c144
-rw-r--r--drivers/misc/tegra-profiler/mmap.h6
-rw-r--r--drivers/misc/tegra-profiler/version.h2
-rw-r--r--include/linux/tegra_profiler.h9
6 files changed, 146 insertions, 60 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 */
diff --git a/include/linux/tegra_profiler.h b/include/linux/tegra_profiler.h
index ed21f75e9556..b122b97dd521 100644
--- a/include/linux/tegra_profiler.h
+++ b/include/linux/tegra_profiler.h
@@ -20,12 +20,13 @@
#include <linux/ioctl.h>
#define QUADD_SAMPLES_VERSION 17
-#define QUADD_IO_VERSION 8
+#define QUADD_IO_VERSION 9
#define QUADD_IO_VERSION_DYNAMIC_RB 5
#define QUADD_IO_VERSION_RB_MAX_FILL_COUNT 6
#define QUADD_IO_VERSION_MOD_STATE_STATUS_FIELD 7
#define QUADD_IO_VERSION_BT_KERNEL_CTX 8
+#define QUADD_IO_VERSION_GET_MMAP 9
#define QUADD_SAMPLE_VERSION_THUMB_MODE_FLAG 17
@@ -236,9 +237,12 @@ struct quadd_record_data {
#define QUADD_MAX_PACKAGE_NAME 320
enum {
- QUADD_PARAM_IDX_SIZE_OF_RB = 0,
+ QUADD_PARAM_IDX_SIZE_OF_RB = 0,
+ QUADD_PARAM_IDX_EXTRA = 1,
};
+#define QUADD_PARAM_IDX_EXTRA_GET_MMAP (1 << 0)
+
struct quadd_parameters {
u32 freq;
u32 ma_freq;
@@ -281,6 +285,7 @@ enum {
};
#define QUADD_COMM_CAP_EXTRA_BT_KERNEL_CTX (1 << 0)
+#define QUADD_COMM_CAP_EXTRA_GET_MMAP (1 << 1)
struct quadd_comm_cap {
u32 pmu:1,