aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/mediatek/systracker/backtrace_64bit.c
blob: 6e29f19ad4453a99d3cd4d0226b159003deaaa22 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <asm/traps.h>
#include <asm/stacktrace.h>
#include <asm/system_misc.h>
#include <linux/mtk_ram_console.h>

static inline void aee_print_ip_sym(unsigned long ip)
{
	char buf[256];

	snprintf(buf, sizeof(buf), "[<%p>] %pS\n", (void *) ip, (void *) ip);
	aee_sram_fiq_log(buf);
}

static void dump_backtrace_entry(unsigned long where, unsigned long stack)
{
        aee_print_ip_sym(where);
}

void aee_dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
{
        struct stackframe frame;
        const register unsigned long current_sp asm ("sp");

        pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);

        if (!tsk)
                tsk = current;

        if (regs) {
                frame.fp = regs->regs[29];
                frame.sp = regs->sp;
                frame.pc = regs->pc;
        } else if (tsk == current) {
                frame.fp = (unsigned long)__builtin_frame_address(0);
                frame.sp = current_sp;
                frame.pc = (unsigned long)aee_dump_backtrace;
        } else {
                /*
                 * task blocked in __switch_to
                 */
                frame.fp = thread_saved_fp(tsk);
                frame.sp = thread_saved_sp(tsk);
                frame.pc = thread_saved_pc(tsk);
        }

        aee_sram_fiq_log("Call trace:\n");
        while (1) {
                unsigned long where = frame.pc;
                int ret;

                ret = unwind_frame(&frame);
                if (ret < 0)
                        break;
                dump_backtrace_entry(where, frame.sp);
        }
}