2173d8a6ea5ab7823ca3134723995aa78067d22b
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__)
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 unsigned long fp = regs->ARM_fp;
26 unsigned long sp = regs->ARM_sp;
27 unsigned long lr = regs->ARM_lr;
28 int is_user_mode = user_mode(regs);
30 if (!is_user_mode) {
31 return;
32 }
34 /* entry preamble may not have executed */
35 gator_add_trace(cpu, lr);
37 /* check tail is valid */
38 if (fp == 0 || fp < sp) {
39 return;
40 }
42 tail = (struct frame_tail_eabi *)(fp - 4);
44 while (depth-- && tail && !((unsigned long) tail & 3)) {
45 /* Also check accessibility of one struct frame_tail beyond */
46 if (!access_ok(VERIFY_READ, tail, sizeof(struct frame_tail_eabi)))
47 return;
48 if (__copy_from_user_inatomic(&buftail, tail, sizeof(struct frame_tail_eabi)))
49 return;
50 ptrtail = &buftail;
52 lr = ptrtail[0].lr;
53 gator_add_trace(cpu, lr);
55 /* frame pointers should progress back up the stack, towards higher addresses */
56 next = (struct frame_tail_eabi *)(lr - 4);
57 if (tail >= next || lr == 0) {
58 fp = ptrtail[0].fp;
59 next = (struct frame_tail_eabi *)(fp - 4);
60 /* check tail is valid */
61 if (tail >= next || fp == 0) {
62 return;
63 }
64 }
66 tail = next;
67 }
68 #endif
69 }
71 #if defined(__arm__)
72 static int report_trace(struct stackframe *frame, void *d)
73 {
74 struct module *mod;
75 unsigned int *depth = d, cookie = NO_COOKIE, cpu = smp_processor_id();
76 unsigned long addr = frame->pc;
78 if (*depth) {
79 mod = __module_address(addr);
80 if (mod) {
81 cookie = get_cookie(cpu, current, NULL, mod, true);
82 addr = addr - (unsigned long)mod->module_core;
83 }
84 marshal_backtrace(addr & ~1, cookie);
85 (*depth)--;
86 }
88 return *depth == 0;
89 }
90 #endif
92 // Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile
93 // #define GATOR_KERNEL_STACK_UNWINDING
94 static void kernel_backtrace(int cpu, struct pt_regs * const regs)
95 {
96 #if defined(__arm__)
97 #ifdef GATOR_KERNEL_STACK_UNWINDING
98 int depth = gator_backtrace_depth;
99 #else
100 int depth = 1;
101 #endif
102 struct stackframe frame;
103 if (depth == 0)
104 depth = 1;
105 frame.fp = regs->ARM_fp;
106 frame.sp = regs->ARM_sp;
107 frame.lr = regs->ARM_lr;
108 frame.pc = regs->ARM_pc;
109 walk_stackframe(&frame, report_trace, &depth);
110 #else
111 marshal_backtrace(PC_REG & ~1, NO_COOKIE);
112 #endif
113 }