]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blobdiff - drivers/misc/tegra-profiler/mmap.c
misc: tegra-profiler: fix debug preempt warnings
[sojka/nv-tegra/linux-3.10.git] / drivers / misc / tegra-profiler / mmap.c
index cf6f408a0d80a7c0087018da9bc494d3003afeeb..2347047d98736fc84e3fda87e0a29a907d3beff3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/misc/tegra-profiler/mmap.c
  *
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -16,9 +16,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/crc32.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/tegra_profiler.h>
 
 #include "mmap.h"
+#include "comm.h"
 #include "hrt.h"
-#include "debug.h"
-
-static struct quadd_mmap_ctx mmap_ctx;
-
-static int binary_search_and_add(unsigned int *array,
-                       unsigned int length, unsigned int key)
-{
-       unsigned int i_min, i_max, mid;
-
-       if (length == 0) {
-               array[0] = key;
-               return 1;
-       } else if (length == 1 && array[0] == key) {
-               return 0;
-       }
-
-       i_min = 0;
-       i_max = length;
-
-       if (array[0] > key) {
-               memmove((char *)((unsigned int *)array + 1), array,
-                       length * sizeof(unsigned int));
-               array[0] = key;
-               return 1;
-       } else if (array[length - 1] < key) {
-               array[length] = key;
-               return 1;
-       }
-
-       while (i_min < i_max) {
-               mid = i_min + (i_max - i_min) / 2;
-
-               if (key <= array[mid])
-                       i_max = mid;
-               else
-                       i_min = mid + 1;
-       }
-
-       if (array[i_max] == key) {
-               return 0;
-       } else {
-               memmove((char *)((unsigned int *)array + i_max + 1),
-                       (char *)((unsigned int *)array + i_max),
-                       (length - i_max) * sizeof(unsigned int));
-               array[i_max] = key;
-               return 1;
-       }
-}
-
-static int check_hash(u32 key)
-{
-       int res;
-       unsigned long flags;
-
-       spin_lock_irqsave(&mmap_ctx.lock, flags);
-
-       if (mmap_ctx.nr_hashes >= QUADD_MMAP_SIZE_ARRAY) {
-               spin_unlock_irqrestore(&mmap_ctx.lock, flags);
-               return 1;
-       }
-
-       res = binary_search_and_add(mmap_ctx.hash_array,
-                                   mmap_ctx.nr_hashes, key);
-       if (res > 0) {
-               mmap_ctx.nr_hashes++;
-               spin_unlock_irqrestore(&mmap_ctx.lock, flags);
-               return 0;
-       }
-
-       spin_unlock_irqrestore(&mmap_ctx.lock, flags);
-       return 1;
-}
-
-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)
+put_mmap_sample(struct quadd_mmap_data *s, char *filename,
+               size_t length, unsigned long pgoff, int is_file_exists)
 {
+       u64 mmap_ed = 0;
        struct quadd_record_data r;
+       struct quadd_iovec vec[3];
+       u64 pgoff_val = (u64)pgoff << PAGE_SHIFT;
 
-       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;
+       r.mmap.filename_length = length;
+
+       if (is_file_exists)
+               mmap_ed |= QUADD_MMAP_ED_IS_FILE_EXISTS;
+
+       vec[0].base = &pgoff_val;
+       vec[0].len = sizeof(pgoff_val);
+
+       vec[1].base = &mmap_ed;
+       vec[1].len = sizeof(mmap_ed);
 
-       pr_debug("MMAP: pid: %d, file_name: '%s', addr: %#x, length: %u",
-                s->pid, extra_data, s->addr, extra_length);
+       vec[2].base = filename;
+       vec[2].len = length;
 
-       quadd_put_sample(&r, extra_data, extra_length);
+       pr_debug("MMAP: pid: %u, file_name: '%s', addr: %#llx - %#llx, len: %llx, pgoff: %#llx\n",
+                s->pid, filename,
+                s->addr, s->addr + s->len, s->len, pgoff_val);
+
+       quadd_put_sample(&r, vec, ARRAY_SIZE(vec));
 }
 
-void quadd_get_mmap_object(struct quadd_cpu_context *cpu_ctx,
-                          struct pt_regs *regs, pid_t pid)
+void quadd_process_mmap(struct vm_area_struct *vma, pid_t pid)
 {
-       unsigned long ip;
-       size_t length, length_aligned;
-       struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
+       int is_file_exists;
        struct file *vm_file;
        struct path *path;
-       char *file_name = NULL;
+       char *file_name, *tmp_buf = 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;
+       size_t length, length_aligned;
 
-       if (!mm)
+       if (!vma)
                return;
 
-       ip = instruction_pointer(regs);
+       if (!(vma->vm_flags & VM_EXEC))
+               return;
 
-       if (user_mode(regs)) {
-               for (vma = find_vma(mm, ip); vma; vma = vma->vm_next) {
-                       if (ip < vma->vm_start || ip >= vma->vm_end)
-                               continue;
+       tmp_buf = kzalloc(PATH_MAX + sizeof(u64), GFP_ATOMIC);
+       if (!tmp_buf)
+               return;
 
-                       vm_file = vma->vm_file;
-                       if (!vm_file)
-                               break;
+       vm_file = vma->vm_file;
+       if (vm_file) {
+               path = &vm_file->f_path;
 
-                       path = &vm_file->f_path;
+               file_name = d_path(path, tmp_buf, PATH_MAX);
+               if (IS_ERR(file_name))
+                       goto out;
 
-                       file_name = d_path(path, tmp_buf, PATH_MAX);
-                       if (IS_ERR(file_name)) {
-                               file_name = NULL;
-                       } else {
-                               sample.addr = vma->vm_start;
-                               sample.len = vma->vm_end - vma->vm_start;
-                               sample.pgoff =
-                                       (u64)vma->vm_pgoff << PAGE_SHIFT;
-                       }
-                       break;
-               }
+               length = strlen(file_name) + 1;
+               is_file_exists = 1;
        } else {
-#ifdef CONFIG_MODULES
-               struct module *mod;
-
-               preempt_disable();
-               mod = __module_address(ip);
-               preempt_enable();
-
-               if (mod) {
-                       file_name = mod->name;
-                       if (file_name) {
-                               sample.addr = (u32) mod->module_core;
-                               sample.len = mod->core_size;
-                               sample.pgoff = 0;
+               const char *name = NULL;
+
+               name = arch_vma_name(vma);
+               if (!name) {
+                       struct mm_struct *mm = vma->vm_mm;
+
+                       if (!mm) {
+                               name = "[vdso]";
+                       } else if (vma->vm_start <= mm->start_brk &&
+                                  vma->vm_end >= mm->brk) {
+                               name = "[heap]";
+                       } else if (vma->vm_start <= mm->start_stack &&
+                                  vma->vm_end >= mm->start_stack) {
+                               name = "[stack]";
                        }
                }
-#endif
+
+               if (name)
+                       strcpy(tmp_buf, name);
+               else
+                       sprintf(tmp_buf, "[vma:%08lx-%08lx]",
+                               vma->vm_start, vma->vm_end);
+
+               file_name = tmp_buf;
+               length = strlen(file_name) + 1;
+
+               is_file_exists = 0;
        }
 
-       if (file_name) {
-               if (!find_file(file_name, sample.addr, sample.len)) {
-                       length = strlen(file_name) + 1;
-                       if (length > PATH_MAX)
-                               return;
+       length_aligned = ALIGN(length, sizeof(u64));
 
-                       sample.pid = pid;
+       sample.pid = pid;
+       sample.user_mode = 1;
 
-                       strcpy(cpu_ctx->mmap_filename, file_name);
-                       length_aligned = ALIGN(length, 8);
+       sample.addr = vma->vm_start;
+       sample.len = vma->vm_end - vma->vm_start;
 
-                       put_mmap_sample(&sample, cpu_ctx->mmap_filename,
-                                       length_aligned);
-               }
-       }
+       put_mmap_sample(&sample, file_name, length_aligned,
+                       vma->vm_pgoff, is_file_exists);
+
+out:
+       kfree(tmp_buf);
 }
 
-int quadd_get_current_mmap(struct quadd_cpu_context *cpu_ctx, pid_t pid)
+int quadd_get_current_mmap(pid_t pid)
 {
+       int is_file_exists;
        struct vm_area_struct *vma;
        struct file *vm_file;
        struct path *path;
@@ -227,116 +146,85 @@ int quadd_get_current_mmap(struct quadd_cpu_context *cpu_ctx, pid_t pid)
        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;
+       char *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);
+               pr_err("Process not found: %d\n", pid);
                return -ESRCH;
        }
+
        mm = task->mm;
+       if (!mm) {
+               pr_warn("mm is not existed for task: %d\n", pid);
+               return 0;
+       }
 
        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;
-
-               path = &vm_file->f_path;
-
-               file_name = d_path(path, tmp_buf, PATH_MAX);
-               if (IS_ERR(file_name))
-                       continue;
+       tmp_buf = kzalloc(PATH_MAX + sizeof(u64), GFP_ATOMIC);
+       if (!tmp_buf)
+               return -ENOMEM;
 
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
                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;
-}
+               vm_file = vma->vm_file;
+               if (vm_file) {
+                       path = &vm_file->f_path;
 
-struct quadd_mmap_ctx *quadd_mmap_init(struct quadd_ctx *quadd_ctx)
-{
-       int cpu_id;
-       u32 *hash;
-       char *tmp;
-       struct quadd_mmap_cpu_ctx *cpu_ctx;
-
-       mmap_ctx.quadd_ctx = quadd_ctx;
-
-       hash = kzalloc(QUADD_MMAP_SIZE_ARRAY * sizeof(unsigned int),
-                      GFP_KERNEL);
-       if (!hash) {
-               pr_err("Failed to allocate mmap buffer\n");
-               return ERR_PTR(-ENOMEM);
-       }
-       mmap_ctx.hash_array = hash;
+                       file_name = d_path(path, tmp_buf, PATH_MAX);
+                       if (IS_ERR(file_name))
+                               continue;
 
-       mmap_ctx.nr_hashes = 0;
-       spin_lock_init(&mmap_ctx.lock);
+                       length = strlen(file_name) + 1;
+                       is_file_exists = 1;
+               } else {
+                       const char *name = NULL;
+
+                       name = arch_vma_name(vma);
+                       if (!name) {
+                               mm = vma->vm_mm;
+
+                               if (!mm) {
+                                       name = "[vdso]";
+                               } else if (vma->vm_start <= mm->start_brk &&
+                                          vma->vm_end >= mm->brk) {
+                                       name = "[heap]";
+                               } else if (vma->vm_start <= mm->start_stack &&
+                                          vma->vm_end >= mm->start_stack) {
+                                       name = "[stack]";
+                               }
+                       }
 
-       mmap_ctx.cpu_ctx = alloc_percpu(struct quadd_mmap_cpu_ctx);
-       if (!mmap_ctx.cpu_ctx)
-               return ERR_PTR(-ENOMEM);
+                       if (name)
+                               strcpy(tmp_buf, name);
+                       else
+                               sprintf(tmp_buf, "[vma:%08lx-%08lx]",
+                                       vma->vm_start, vma->vm_end);
 
-       for (cpu_id = 0; cpu_id < nr_cpu_ids; cpu_id++) {
-               cpu_ctx = per_cpu_ptr(mmap_ctx.cpu_ctx, cpu_id);
+                       file_name = tmp_buf;
+                       length = strlen(file_name) + 1;
 
-               tmp = kzalloc(PATH_MAX + sizeof(unsigned long long),
-                             GFP_KERNEL);
-               if (!tmp) {
-                       pr_err("Failed to allocate mmap buffer\n");
-                       return ERR_PTR(-ENOMEM);
+                       is_file_exists = 0;
                }
-               cpu_ctx->tmp_buf = tmp;
-       }
-
-       return &mmap_ctx;
-}
 
-void quadd_mmap_reset(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&mmap_ctx.lock, flags);
-       mmap_ctx.nr_hashes = 0;
-       spin_unlock_irqrestore(&mmap_ctx.lock, flags);
-}
+               length_aligned = ALIGN(length, sizeof(u64));
 
-void quadd_mmap_deinit(void)
-{
-       int cpu_id;
-       unsigned long flags;
-       struct quadd_mmap_cpu_ctx *cpu_ctx;
+               sample.pid = pid;
+               sample.user_mode = 1;
 
-       spin_lock_irqsave(&mmap_ctx.lock, flags);
-       kfree(mmap_ctx.hash_array);
-       mmap_ctx.hash_array = NULL;
+               sample.addr = vma->vm_start;
+               sample.len = vma->vm_end - vma->vm_start;
 
-       for (cpu_id = 0; cpu_id < nr_cpu_ids; cpu_id++) {
-               cpu_ctx = per_cpu_ptr(mmap_ctx.cpu_ctx, cpu_id);
-               kfree(cpu_ctx->tmp_buf);
+               put_mmap_sample(&sample, file_name, length_aligned,
+                               vma->vm_pgoff, is_file_exists);
        }
-       free_percpu(mmap_ctx.cpu_ctx);
 
-       spin_unlock_irqrestore(&mmap_ctx.lock, flags);
+       kfree(tmp_buf);
+
+       return 0;
 }