1 /**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
10 /*
11 * EABI backtrace stores {fp,lr} on the stack.
12 */
13 struct frame_tail_eabi {
14 unsigned long fp; // points to prev_lr
15 unsigned long lr;
16 };
18 static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int depth)
19 {
20 #if defined(__arm__) || defined(__aarch64__)
21 struct frame_tail_eabi *tail;
22 struct frame_tail_eabi *next;
23 struct frame_tail_eabi *ptrtail;
24 struct frame_tail_eabi buftail;
25 #if defined(__arm__)
26 unsigned long fp = regs->ARM_fp;
27 unsigned long sp = regs->ARM_sp;
28 unsigned long lr = regs->ARM_lr;
29 const int frame_offset = 4;
30 #else
31 unsigned long fp = regs->regs[29];
32 unsigned long sp = regs->sp;
33 unsigned long lr = regs->regs[30];
34 const int frame_offset = 0;
35 #endif
36 int is_user_mode = user_mode(regs);
38 if (!is_user_mode) {
39 return;
40 }
42 /* entry preamble may not have executed */
43 gator_add_trace(cpu, lr);
45 /* check tail is valid */
46 if (fp == 0 || fp < sp) {
47 return;
48 }
50 tail = (struct frame_tail_eabi *)(fp - frame_offset);
52 while (depth-- && tail && !((unsigned long)tail & 3)) {
53 /* Also check accessibility of one struct frame_tail beyond */
54 if (!access_ok(VERIFY_READ, tail, sizeof(struct frame_tail_eabi)))
55 return;
56 if (__copy_from_user_inatomic(&buftail, tail, sizeof(struct frame_tail_eabi)))
57 return;
58 ptrtail = &buftail;
60 lr = ptrtail[0].lr;
61 gator_add_trace(cpu, lr);
63 /* frame pointers should progress back up the stack, towards higher addresses */
64 next = (struct frame_tail_eabi *)(lr - frame_offset);
65 if (tail >= next || lr == 0) {
66 fp = ptrtail[0].fp;
67 next = (struct frame_tail_eabi *)(fp - frame_offset);
68 /* check tail is valid */
69 if (tail >= next || fp == 0) {
70 return;
71 }
72 }
74 tail = next;
75 }
76 #endif
77 }
79 #if defined(__arm__) || defined(__aarch64__)
80 static int report_trace(struct stackframe *frame, void *d)
81 {
82 struct module *mod;
83 unsigned int *depth = d, cookie = NO_COOKIE, cpu = smp_processor_id();
84 unsigned long addr = frame->pc;
86 if (*depth) {
87 mod = __module_address(addr);
88 if (mod) {
89 cookie = get_cookie(cpu, current, mod->name, false);
90 addr = addr - (unsigned long)mod->module_core;
91 }
92 marshal_backtrace(addr & ~1, cookie);
93 (*depth)--;
94 }
96 return *depth == 0;
97 }
98 #endif
100 // Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
101 // #define GATOR_KERNEL_STACK_UNWINDING
102 static void kernel_backtrace(int cpu, struct pt_regs *const regs)
103 {
104 #if defined(__arm__) || defined(__aarch64__)
105 #ifdef GATOR_KERNEL_STACK_UNWINDING
106 int depth = gator_backtrace_depth;
107 #else
108 int depth = 1;
109 #endif
110 struct stackframe frame;
111 if (depth == 0)
112 depth = 1;
113 #if defined(__arm__)
114 frame.fp = regs->ARM_fp;
115 frame.sp = regs->ARM_sp;
116 frame.lr = regs->ARM_lr;
117 frame.pc = regs->ARM_pc;
118 #else
119 frame.fp = regs->regs[29];
120 frame.sp = regs->sp;
121 frame.pc = regs->pc;
122 #endif
123 walk_stackframe(&frame, report_trace, &depth);
124 #else
125 marshal_backtrace(PC_REG & ~1, NO_COOKIE);
126 #endif
127 }