misc: tegra-profiler: prevent infinite loop
Igor Nabirushkin [Mon, 9 Mar 2015 16:16:55 +0000 (20:16 +0400)]
* Prevent false recursion in mixed mode.
* Unwinding based on frame pointers: do not save lr address
  if previous frame is incorrect.

Bug 1619030

Change-Id: Iadeb8ca87ead576b18821964878cddf7aa94cf27
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/715291
(cherry picked from commit d8e79953332c96786da5f57475013b045d7ef817)
Reviewed-on: http://git-master/r/747752
GVS: Gerrit_Virtual_Submit
Reviewed-by: Andrey Trachenko <atrachenko@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>

drivers/misc/tegra-profiler/backtrace.c
drivers/misc/tegra-profiler/power_clk.c
drivers/misc/tegra-profiler/version.h

index 675ce85..2dc39b1 100644 (file)
 #include "eh_unwind.h"
 #include "dwarf_unwind.h"
 #include "hrt.h"
-
-static inline int
-is_thumb_mode(struct pt_regs *regs)
-{
-#ifdef CONFIG_ARM64
-       return compat_thumb_mode(regs);
-#else
-       return thumb_mode(regs);
-#endif
-}
+#include "tegra.h"
 
 unsigned long
 quadd_user_stack_pointer(struct pt_regs *regs)
@@ -177,6 +168,8 @@ user_backtrace(struct pt_regs *regs,
        }
 
        fp_prev = (unsigned long __user *)value_fp;
+       if (fp_prev <= tail)
+               return NULL;
 
        nr_added = quadd_callchain_store(cc, value_lr, QUADD_UNW_TYPE_FP);
        if (nr_added == 0)
@@ -186,9 +179,6 @@ user_backtrace(struct pt_regs *regs,
            is_ex_entry_exist(regs, value_lr, task))
                return NULL;
 
-       if (fp_prev <= tail)
-               return NULL;
-
        return fp_prev;
 }
 
@@ -364,6 +354,8 @@ user_backtrace_compat(struct pt_regs *regs,
        }
 
        fp_prev = (u32 __user *)(unsigned long)value_fp;
+       if (fp_prev <= tail)
+               return NULL;
 
        nr_added = quadd_callchain_store(cc, value_lr, QUADD_UNW_TYPE_FP);
        if (nr_added == 0)
@@ -373,9 +365,6 @@ user_backtrace_compat(struct pt_regs *regs,
            is_ex_entry_exist(regs, value_lr, task))
                return NULL;
 
-       if (fp_prev <= tail)
-               return NULL;
-
        return fp_prev;
 }
 
@@ -534,9 +523,11 @@ get_user_callchain_ut(struct pt_regs *regs,
                      struct task_struct *task)
 {
        int nr_prev;
+       unsigned long prev_sp;
 
        do {
                nr_prev = cc->nr;
+               prev_sp = cc->curr_sp;
 
                quadd_get_user_cc_dwarf(regs, cc, task);
                if (nr_prev > 0 && cc->nr == nr_prev)
@@ -545,7 +536,8 @@ get_user_callchain_ut(struct pt_regs *regs,
                nr_prev = cc->nr;
 
                quadd_get_user_cc_arm32_ehabi(regs, cc, task);
-       } while (nr_prev != cc->nr);
+       } while (nr_prev != cc->nr &&
+                (cc->nr <= 1 || cc->curr_sp > prev_sp));
 
        return cc->nr;
 }
@@ -556,18 +548,26 @@ get_user_callchain_mixed(struct pt_regs *regs,
                      struct task_struct *task)
 {
        int nr_prev;
+       unsigned long prev_sp;
 
        do {
                nr_prev = cc->nr;
+               prev_sp = cc->curr_sp;
 
                quadd_get_user_cc_dwarf(regs, cc, task);
                quadd_get_user_cc_arm32_ehabi(regs, cc, task);
 
-               if (nr_prev != cc->nr)
+               if (nr_prev != cc->nr) {
+                       if (cc->nr > 1 &&
+                           cc->curr_sp <= prev_sp)
+                               break;
+
                        continue;
+               }
 
                __get_user_callchain_fp(regs, cc, task);
-       } while (nr_prev != cc->nr);
+       } while (nr_prev != cc->nr &&
+                (cc->nr <= 1 || cc->curr_sp > prev_sp));
 
        return cc->nr;
 }
index b29c24d..fc31ecc 100644 (file)
@@ -118,11 +118,11 @@ static void make_sample(void)
                power_rate->emc = 0;
 
        mutex_unlock(&s->lock);
-
+/*
        pr_debug("make_sample: cpu: %u/%u/%u/%u, gpu: %u, emc: %u\n",
                 extra_cpus[0], extra_cpus[1], extra_cpus[2], extra_cpus[3],
                 power_rate->gpu, power_rate->emc);
-
+*/
        vec.base = extra_cpus;
        vec.len = power_rate->nr_cpus * sizeof(extra_cpus[0]);
 
index e92e395..bf4c275 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __QUADD_VERSION_H
 #define __QUADD_VERSION_H
 
-#define QUADD_MODULE_VERSION           "1.94"
+#define QUADD_MODULE_VERSION           "1.95"
 #define QUADD_MODULE_BRANCH            "Dev"
 
 #endif /* __QUADD_VERSION_H */