summaryrefslogtreecommitdiff
path: root/drivers/misc/tegra-profiler/backtrace.c
diff options
context:
space:
mode:
authorIgor Nabirushkin <inabirushkin@nvidia.com>2014-08-22 19:46:15 +0400
committerWinnie Hsu <whsu@nvidia.com>2015-01-29 22:01:31 -0800
commit6fb43a5f1c04e04b83cef5c1fa22d9f460596efa (patch)
tree82c062e0634441390365cb15458be21ef9de5207 /drivers/misc/tegra-profiler/backtrace.c
parent35bf638737a5f9d09ea420c4fee690a76f6f2b2a (diff)
misc: tegra-profiler: support dwarf unwinding
Add implementation of a dwarf unwinding for AArch64. Bug 1465331 Bug 1598009 Change-Id: I1ff0c5411fe63ea5b7291c53c1d5a1d1cde59c25 Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com> Reviewed-on: http://git-master/r/486989 (cherry picked from commit f00783180ee09c5698463a39bed62c08ef17802a) Reviewed-on: http://git-master/r/672019 GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers/misc/tegra-profiler/backtrace.c')
-rw-r--r--drivers/misc/tegra-profiler/backtrace.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/drivers/misc/tegra-profiler/backtrace.c b/drivers/misc/tegra-profiler/backtrace.c
index f16cdabc8f77..e9f01471a594 100644
--- a/drivers/misc/tegra-profiler/backtrace.c
+++ b/drivers/misc/tegra-profiler/backtrace.c
@@ -1,7 +1,7 @@
/*
* drivers/misc/tegra-profiler/backtrace.c
*
- * Copyright (c) 2014, 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,
@@ -25,6 +25,7 @@
#include "quadd.h"
#include "backtrace.h"
#include "eh_unwind.h"
+#include "dwarf_unwind.h"
static inline int
is_thumb_mode(struct pt_regs *regs)
@@ -47,8 +48,8 @@ quadd_user_stack_pointer(struct pt_regs *regs)
return user_stack_pointer(regs);
}
-static inline unsigned long
-get_user_frame_pointer(struct pt_regs *regs)
+unsigned long
+quadd_get_user_frame_pointer(struct pt_regs *regs)
{
unsigned long fp;
@@ -111,6 +112,19 @@ quadd_callchain_store(struct quadd_callchain *cc,
return 1;
}
+static int
+is_ex_entry_exist(struct pt_regs *regs,
+ unsigned long addr,
+ struct task_struct *task)
+{
+#ifdef CONFIG_ARM64
+ if (!compat_user_mode(regs))
+ return quadd_aarch64_is_ex_entry_exist(regs, addr, task);
+#endif
+
+ return quadd_aarch32_is_ex_entry_exist(regs, addr, task);
+}
+
static unsigned long __user *
user_backtrace(struct pt_regs *regs,
unsigned long __user *tail,
@@ -170,7 +184,7 @@ user_backtrace(struct pt_regs *regs,
return NULL;
if (cc->unw_method == QUADD_UNW_METHOD_MIXED &&
- quadd_is_ex_entry_exist(regs, value_lr, task))
+ is_ex_entry_exist(regs, value_lr, task))
return NULL;
if (fp_prev <= tail)
@@ -199,7 +213,7 @@ get_user_callchain_fp(struct pt_regs *regs,
sp = quadd_user_stack_pointer(regs);
pc = instruction_pointer(regs);
- fp = get_user_frame_pointer(regs);
+ fp = quadd_get_user_frame_pointer(regs);
if (fp == 0 || fp < sp || fp & 0x3)
return 0;
@@ -357,7 +371,7 @@ user_backtrace_compat(struct pt_regs *regs,
return NULL;
if (cc->unw_method == QUADD_UNW_METHOD_MIXED &&
- quadd_is_ex_entry_exist(regs, value_lr, task))
+ is_ex_entry_exist(regs, value_lr, task))
return NULL;
if (fp_prev <= tail)
@@ -386,7 +400,7 @@ get_user_callchain_fp_compat(struct pt_regs *regs,
sp = quadd_user_stack_pointer(regs);
pc = instruction_pointer(regs);
- fp = get_user_frame_pointer(regs);
+ fp = quadd_get_user_frame_pointer(regs);
if (fp == 0 || fp < sp || fp & 0x3)
return 0;
@@ -516,6 +530,18 @@ __get_user_callchain_fp(struct pt_regs *regs,
}
static unsigned int
+get_user_callchain_ut(struct pt_regs *regs,
+ struct quadd_callchain *cc,
+ struct task_struct *task)
+{
+#ifdef CONFIG_ARM64
+ if (!compat_user_mode(regs))
+ return quadd_aarch64_get_user_callchain_ut(regs, cc, task);
+#endif
+ return quadd_aarch32_get_user_callchain_ut(regs, cc, task);
+}
+
+static unsigned int
get_user_callchain_mixed(struct pt_regs *regs,
struct quadd_callchain *cc,
struct task_struct *task)
@@ -525,7 +551,7 @@ get_user_callchain_mixed(struct pt_regs *regs,
do {
nr_prev = cc->nr;
- quadd_get_user_callchain_ut(regs, cc, task);
+ get_user_callchain_ut(regs, cc, task);
if (nr_prev > 0 && cc->nr == nr_prev)
break;
@@ -570,7 +596,7 @@ quadd_get_user_callchain(struct pt_regs *regs,
break;
case QUADD_UNW_METHOD_EHT:
- quadd_get_user_callchain_ut(regs, cc, task);
+ get_user_callchain_ut(regs, cc, task);
break;
case QUADD_UNW_METHOD_MIXED: