misc: tegra-profiler: send mapped memory regions
Igor Nabirushkin [Thu, 24 Oct 2013 13:23:11 +0000 (17:23 +0400)]
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>

drivers/misc/tegra-profiler/hrt.c
drivers/misc/tegra-profiler/main.c
drivers/misc/tegra-profiler/mmap.c
drivers/misc/tegra-profiler/mmap.h
drivers/misc/tegra-profiler/version.h
include/linux/tegra_profiler.h

index 8bc3072..fef37de 100644 (file)
@@ -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();
 
index f1ed75c..2b9b8ad 100644 (file)
@@ -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;
 }
 
index 2b73e5c..cf6f408 100644 (file)
@@ -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)
index dd750f9..4030ed2 100644 (file)
@@ -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);
index 32b0746..3dddadb 100644 (file)
@@ -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 */
index ed21f75..b122b97 100644 (file)
 #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,