summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorIgor Nabirushkin <inabirushkin@nvidia.com>2015-02-26 15:16:21 +0400
committerWinnie Hsu <whsu@nvidia.com>2015-05-29 14:25:28 -0700
commitaf01aa37409408815278e81aacd9346beb0be1c0 (patch)
tree0d258bd6ead7ed78508e92d35e30fe8fe965e856 /drivers/misc
parentd18306d725e35e6431e04745d97c3a61c0d1280d (diff)
misc: tegra-profiler: fix broken call chains
Fix broken call chains for thumb code with dwarf and arm ehabi information simultaneously. Bug 1615165 Change-Id: If34ecfac26657546170121c363cf89b8b7256dbb Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com> Reviewed-on: http://git-master/r/711611 (cherry picked from commit 7d98345d6f2f1ba476161d91853dd82b23a92d1d) Reviewed-on: http://git-master/r/747749 GVS: Gerrit_Virtual_Submit Reviewed-by: Andrey Trachenko <atrachenko@nvidia.com> Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/tegra-profiler/backtrace.c17
-rw-r--r--drivers/misc/tegra-profiler/backtrace.h1
-rw-r--r--drivers/misc/tegra-profiler/dwarf_unwind.c10
-rw-r--r--drivers/misc/tegra-profiler/eh_unwind.c7
-rw-r--r--drivers/misc/tegra-profiler/version.h2
5 files changed, 26 insertions, 11 deletions
diff --git a/drivers/misc/tegra-profiler/backtrace.c b/drivers/misc/tegra-profiler/backtrace.c
index 352095b1cfac..a249bfd30f92 100644
--- a/drivers/misc/tegra-profiler/backtrace.c
+++ b/drivers/misc/tegra-profiler/backtrace.c
@@ -168,12 +168,12 @@ user_backtrace(struct pt_regs *regs,
return NULL;
}
+ if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp)))
+ return NULL;
+
cc->curr_fp = value_fp;
cc->curr_sp = (unsigned long)tail + sizeof(value_fp);
cc->curr_pc = value_lr = value;
-
- if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp)))
- return NULL;
}
fp_prev = (unsigned long __user *)value_fp;
@@ -355,12 +355,12 @@ user_backtrace_compat(struct pt_regs *regs,
return NULL;
}
+ if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp)))
+ return NULL;
+
cc->curr_fp = value_fp;
cc->curr_sp = (unsigned long)tail + sizeof(value_fp);
cc->curr_pc = value_lr = value;
-
- if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp)))
- return NULL;
}
fp_prev = (u32 __user *)(unsigned long)value_fp;
@@ -561,9 +561,11 @@ get_user_callchain_mixed(struct pt_regs *regs,
nr_prev = cc->nr;
quadd_get_user_cc_dwarf(regs, cc, task);
-
quadd_get_user_cc_arm32_ehabi(regs, cc, task);
+ if (nr_prev != cc->nr)
+ continue;
+
__get_user_callchain_fp(regs, cc, task);
} while (nr_prev != cc->nr);
@@ -587,6 +589,7 @@ quadd_get_user_callchain(struct pt_regs *regs,
cc->curr_sp = 0;
cc->curr_fp = 0;
+ cc->curr_fp_thumb = 0;
cc->curr_pc = 0;
#ifdef CONFIG_ARM64
diff --git a/drivers/misc/tegra-profiler/backtrace.h b/drivers/misc/tegra-profiler/backtrace.h
index 3046ac60fdb5..5ee544cdd496 100644
--- a/drivers/misc/tegra-profiler/backtrace.h
+++ b/drivers/misc/tegra-profiler/backtrace.h
@@ -44,6 +44,7 @@ struct quadd_callchain {
unsigned long curr_sp;
unsigned long curr_fp;
+ unsigned long curr_fp_thumb;
unsigned long curr_pc;
struct quadd_hrt_ctx *hrt;
diff --git a/drivers/misc/tegra-profiler/dwarf_unwind.c b/drivers/misc/tegra-profiler/dwarf_unwind.c
index b5582a7c55e2..72062e66a4ab 100644
--- a/drivers/misc/tegra-profiler/dwarf_unwind.c
+++ b/drivers/misc/tegra-profiler/dwarf_unwind.c
@@ -1983,8 +1983,13 @@ unwind_backtrace(struct quadd_callchain *cc,
pr_debug("[%s]: function at [<%08lx>] from [<%08lx>]\n",
is_eh ? "eh" : "debug", where, sf->pc);
+
cc->curr_sp = sf->vregs[regnum_sp(mode)];
+
cc->curr_fp = sf->vregs[regnum_fp(mode)];
+ if (mode == DW_MODE_ARM32)
+ cc->curr_fp_thumb = sf->vregs[ARM32_FP_THUMB];
+
cc->curr_pc = sf->pc;
nr_added = quadd_callchain_store(cc, sf->pc, unw_type);
@@ -2044,7 +2049,7 @@ quadd_get_user_cc_dwarf(struct pt_regs *regs,
ip = cc->curr_pc;
sp = cc->curr_sp;
fp = cc->curr_fp;
- fp_thumb = 0;
+ fp_thumb = cc->curr_fp_thumb;
lr = 0;
} else {
ip = instruction_pointer(regs);
@@ -2084,7 +2089,8 @@ quadd_get_user_cc_dwarf(struct pt_regs *regs,
sf.vregs[regnum_sp(mode)] = sp;
sf.vregs[regnum_fp(mode)] = fp;
- sf.vregs[ARM32_FP_THUMB] = fp_thumb;
+ if (mode == DW_MODE_ARM32)
+ sf.vregs[ARM32_FP_THUMB] = fp_thumb;
cpu_ctx->dw_ptr_size = (mode == DW_MODE_ARM32) ?
sizeof(u32) : sizeof(u64);
diff --git a/drivers/misc/tegra-profiler/eh_unwind.c b/drivers/misc/tegra-profiler/eh_unwind.c
index 888c2d49b037..e97ed5a3e062 100644
--- a/drivers/misc/tegra-profiler/eh_unwind.c
+++ b/drivers/misc/tegra-profiler/eh_unwind.c
@@ -1120,6 +1120,7 @@ unwind_backtrace(struct quadd_callchain *cc,
cc->curr_sp = frame->sp;
cc->curr_fp = frame->fp_arm;
+ cc->curr_fp_thumb = frame->fp_thumb;
cc->curr_pc = frame->pc;
nr_added = quadd_callchain_store(cc, frame->pc, unw_type);
@@ -1159,7 +1160,7 @@ quadd_get_user_cc_arm32_ehabi(struct pt_regs *regs,
sp = cc->curr_sp;
lr = 0;
- frame.fp_thumb = 0;
+ frame.fp_thumb = cc->curr_fp_thumb;
frame.fp_arm = cc->curr_fp;
} else {
ip = instruction_pointer(regs);
@@ -1179,6 +1180,10 @@ quadd_get_user_cc_arm32_ehabi(struct pt_regs *regs,
frame.sp = sp;
frame.lr = lr;
+ pr_debug("pc: %#lx, lr: %#lx\n", ip, lr);
+ pr_debug("sp: %#lx, fp_arm: %#lx, fp_thumb: %#lx\n",
+ sp, frame.fp_arm, frame.fp_thumb);
+
vma = find_vma(mm, ip);
if (!vma)
return 0;
diff --git a/drivers/misc/tegra-profiler/version.h b/drivers/misc/tegra-profiler/version.h
index 2281ec87dbbb..279861411474 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.91"
+#define QUADD_MODULE_VERSION "1.92"
#define QUADD_MODULE_BRANCH "Dev"
#endif /* __QUADD_VERSION_H */