misc: tegra-profiler: kprobes is no longer used
Igor Nabirushkin [Fri, 4 Oct 2013 21:35:23 +0000 (01:35 +0400)]
Tegra Profiler: kprobes is no longer used
Use callbacks from the scheduler instead of kprobes

Bug 1343930

Change-Id: I67589dbe972cc5c853addfb6ed82c488529eed55
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/324049
(cherry picked from commit b61817c8d9ad5e45ca17dfd47cb3f9ee864b744e)
Reviewed-on: http://git-master/r/340004
Reviewed-by: Harry Hong <hhong@nvidia.com>
Tested-by: Harry Hong <hhong@nvidia.com>

drivers/misc/tegra-profiler/Kconfig
drivers/misc/tegra-profiler/hrt.c
drivers/misc/tegra-profiler/hrt.h
drivers/misc/tegra-profiler/ma.c
drivers/misc/tegra-profiler/main.c
drivers/misc/tegra-profiler/mmap.c
drivers/misc/tegra-profiler/version.h
include/linux/tegra_profiler.h
kernel/sched/core.c

index 312b75e..d07cb3c 100644 (file)
@@ -1,6 +1,5 @@
 config TEGRA_PROFILER
        bool "Enable Tegra profiler"
        depends on ARCH_TEGRA
-       select KPROBES
        help
          This option enables Tegra profiler
index fdfbb96..f0a8b27 100644 (file)
@@ -374,121 +374,75 @@ static int remove_active_thread(struct quadd_cpu_context *cpu_ctx, pid_t pid)
        return 0;
 }
 
-static int task_sched_in(struct kprobe *kp, struct pt_regs *regs)
+void __quadd_task_sched_in(struct task_struct *prev,
+                          struct task_struct *task)
 {
-       int n, prev_flag, current_flag;
-       struct task_struct *prev, *task;
-       int prev_nr_active, new_nr_active;
+       int current_flag;
        struct quadd_cpu_context *cpu_ctx = this_cpu_ptr(hrt.cpu_ctx);
        struct quadd_ctx *ctx = hrt.quadd_ctx;
        struct event_data events[QUADD_MAX_COUNTERS];
        /* static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 2); */
 
-       if (hrt.active == 0)
-               return 0;
-
-       prev = (struct task_struct *)regs->ARM_r1;
-       task = current;
+       if (likely(hrt.active == 0))
+               return;
 /*
        if (__ratelimit(&ratelimit_state))
-               pr_info("cpu: %d, prev: %u (%u) \t--> curr: %u (%u)\n",
+               pr_info("sch_in, cpu: %d, prev: %u (%u) \t--> curr: %u (%u)\n",
                        quadd_get_processor_id(), (unsigned int)prev->pid,
                        (unsigned int)prev->tgid, (unsigned int)task->pid,
                        (unsigned int)task->tgid);
 */
-       if (!prev || !prev->real_parent || !prev->group_leader ||
-               prev->group_leader->tgid != prev->tgid) {
-               pr_err_once("Warning\n");
-               return 0;
-       }
-
-       prev_flag = is_profile_process(prev->tgid);
        current_flag = is_profile_process(task->tgid);
 
-       if (prev_flag || current_flag) {
-               prev_nr_active = atomic_read(&cpu_ctx->nr_active);
-               qm_debug_task_sched_in(prev->pid, task->pid, prev_nr_active);
-
-               if (prev_flag) {
-                       n = remove_active_thread(cpu_ctx, prev->pid);
-                       atomic_sub(n, &cpu_ctx->nr_active);
-               }
-               if (current_flag) {
-                       add_active_thread(cpu_ctx, task->pid, task->tgid);
-                       atomic_inc(&cpu_ctx->nr_active);
-               }
-
-               new_nr_active = atomic_read(&cpu_ctx->nr_active);
-               if (prev_nr_active != new_nr_active) {
-                       if (prev_nr_active == 0) {
-                               if (ctx->pmu)
-                                       ctx->pmu->start();
+       if (current_flag) {
+               add_active_thread(cpu_ctx, task->pid, task->tgid);
+               atomic_inc(&cpu_ctx->nr_active);
 
-                               if (ctx->pl310)
-                                       ctx->pl310->read(events);
+               if (atomic_read(&cpu_ctx->nr_active) == 1) {
+                       if (ctx->pmu)
+                               ctx->pmu->start();
 
-                               start_hrtimer(cpu_ctx);
-                               atomic_inc(&hrt.nr_active_all_core);
-                       } else if (new_nr_active == 0) {
-                               cancel_hrtimer(cpu_ctx);
-                               atomic_dec(&hrt.nr_active_all_core);
+                       if (ctx->pl310)
+                               ctx->pl310->read(events);
 
-                               if (ctx->pmu)
-                                       ctx->pmu->stop();
-                       }
+                       start_hrtimer(cpu_ctx);
+                       atomic_inc(&hrt.nr_active_all_core);
                }
        }
-
-       return 0;
 }
 
-static int handler_fault(struct kprobe *kp, struct pt_regs *regs, int trapnr)
+void __quadd_task_sched_out(struct task_struct *prev,
+                           struct task_struct *next)
 {
-       pr_err_once("addr: %p, symbol: %s\n", kp->addr, kp->symbol_name);
-       return 0;
-}
-
-static int start_instr(void)
-{
-       int err;
-
-       memset(&hrt.kp_in, 0, sizeof(struct kprobe));
+       int n, prev_flag;
+       struct quadd_cpu_context *cpu_ctx = this_cpu_ptr(hrt.cpu_ctx);
+       struct quadd_ctx *ctx = hrt.quadd_ctx;
+       /* static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 2); */
 
-       hrt.kp_in.pre_handler = task_sched_in;
-       hrt.kp_in.fault_handler = handler_fault;
-       hrt.kp_in.addr = 0;
-       hrt.kp_in.symbol_name = QUADD_HRT_SCHED_IN_FUNC;
+       if (likely(hrt.active == 0))
+               return;
+/*
+       if (__ratelimit(&ratelimit_state))
+               pr_info("sch_out: cpu: %d, prev: %u (%u) \t--> next: %u (%u)\n",
+                       quadd_get_processor_id(), (unsigned int)prev->pid,
+                       (unsigned int)prev->tgid, (unsigned int)next->pid,
+                       (unsigned int)next->tgid);
+*/
 
-       err = register_kprobe(&hrt.kp_in);
-       if (err) {
-               pr_err("register_kprobe error, symbol_name: %s\n",
-                       hrt.kp_in.symbol_name);
-               return err;
-       }
-       return 0;
-}
+       prev_flag = is_profile_process(prev->tgid);
 
-static void stop_instr(void)
-{
-       unregister_kprobe(&hrt.kp_in);
-}
+       if (prev_flag) {
+               n = remove_active_thread(cpu_ctx, prev->pid);
+               atomic_sub(n, &cpu_ctx->nr_active);
 
-static int init_instr(void)
-{
-       int err;
+               if (atomic_read(&cpu_ctx->nr_active) == 0) {
+                       cancel_hrtimer(cpu_ctx);
+                       atomic_dec(&hrt.nr_active_all_core);
 
-       err = start_instr();
-       if (err) {
-               pr_err("Init instr failed\n");
-               return err;
+                       if (ctx->pmu)
+                               ctx->pmu->stop();
+               }
        }
-       stop_instr();
-       return 0;
-}
-
-static int deinit_instr(void)
-{
-       return 0;
 }
 
 static void reset_cpu_ctx(void)
@@ -512,7 +466,6 @@ static void reset_cpu_ctx(void)
 
 int quadd_hrt_start(void)
 {
-       int err;
        u64 period;
        long freq;
        struct quadd_ctx *ctx = hrt.quadd_ctx;
@@ -531,12 +484,6 @@ int quadd_hrt_start(void)
 
        reset_cpu_ctx();
 
-       err = start_instr();
-       if (err) {
-               pr_err("error: start_instr is failed\n");
-               return err;
-       }
-
        put_header();
 
        if (ctx->pl310)
@@ -563,7 +510,6 @@ void quadd_hrt_stop(void)
        quadd_ma_stop(&hrt);
 
        hrt.active = 0;
-       stop_instr();
 
        atomic64_set(&hrt.counter_samples, 0);
 
@@ -575,7 +521,6 @@ void quadd_hrt_deinit(void)
        if (hrt.active)
                quadd_hrt_stop();
 
-       deinit_instr();
        free_percpu(hrt.cpu_ctx);
 }
 
@@ -622,8 +567,5 @@ struct quadd_hrt_ctx *quadd_hrt_init(struct quadd_ctx *ctx)
                init_hrtimer(cpu_ctx);
        }
 
-       if (init_instr())
-               return NULL;
-
        return &hrt;
 }
index f113b88..7eff30a 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/hrtimer.h>
 #include <linux/limits.h>
-#include <linux/kprobes.h>
 
 #include "backtrace.h"
 
@@ -53,9 +52,6 @@ struct quadd_hrt_ctx {
        struct quadd_cpu_context * __percpu cpu_ctx;
        u64 sample_period;
 
-       struct kprobe kp_in;
-       /* struct kinstr ki_out; */
-
        struct quadd_ctx *quadd_ctx;
 
        int active;
index 2021954..d561a24 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
+#include <linux/sched.h>
 
 #include <linux/tegra_profiler.h>
 
index 823fa4d..2b84dd0 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/sched.h>
 
 #include <linux/tegra_profiler.h>
 
index 370508b..2b73e5c 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/sched.h>
 
 #include <linux/tegra_profiler.h>
 
@@ -145,6 +146,7 @@ char *quadd_get_mmap(struct quadd_cpu_context *cpu_ctx,
                        break;
                }
        } else {
+#ifdef CONFIG_MODULES
                struct module *mod;
 
                preempt_disable();
@@ -159,6 +161,7 @@ char *quadd_get_mmap(struct quadd_cpu_context *cpu_ctx,
                                sample->pgoff = 0;
                        }
                }
+#endif
        }
 
        if (file_name) {
index 3c03b29..8d2eec0 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __QUADD_VERSION_H
 #define __QUADD_VERSION_H
 
-#define QUADD_MODULE_VERSION           "1.30"
+#define QUADD_MODULE_VERSION           "1.31"
 #define QUADD_MODULE_BRANCH            "Dev"
 
 #endif /* __QUADD_VERSION_H */
index e8f17ad..5840ba3 100644 (file)
@@ -305,4 +305,33 @@ struct quadd_module_version {
 
 #pragma pack(pop)
 
+#ifdef CONFIG_TEGRA_PROFILER
+extern void __quadd_task_sched_in(struct task_struct *prev,
+                                 struct task_struct *task);
+extern void __quadd_task_sched_out(struct task_struct *prev,
+                                  struct task_struct *next);
+
+static inline void quadd_task_sched_in(struct task_struct *prev,
+                                      struct task_struct *task)
+{
+       __quadd_task_sched_in(prev, task);
+}
+
+static inline void quadd_task_sched_out(struct task_struct *prev,
+                                       struct task_struct *next)
+{
+       __quadd_task_sched_out(prev, next);
+}
+#else
+static inline void quadd_task_sched_in(struct task_struct *prev,
+                                      struct task_struct *task)
+{
+}
+
+static inline void quadd_task_sched_out(struct task_struct *prev,
+                                       struct task_struct *next)
+{
+}
+#endif
+
 #endif  /* __TEGRA_PROFILER_H */
index 99d701e..5226fcd 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/slab.h>
 #include <linux/init_task.h>
 #include <linux/binfmts.h>
+#include <linux/tegra_profiler.h>
 
 #include <asm/switch_to.h>
 #include <asm/tlb.h>
@@ -1917,6 +1918,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
 {
        sched_info_switch(prev, next);
        perf_event_task_sched_out(prev, next);
+       quadd_task_sched_out(prev, next);
        fire_sched_out_preempt_notifiers(prev, next);
        prepare_lock_switch(rq, next);
        prepare_arch_switch(next);
@@ -1963,6 +1965,7 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
        local_irq_disable();
 #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
        perf_event_task_sched_in(prev, current);
+       quadd_task_sched_in(prev, current);
 #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
        local_irq_enable();
 #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */