]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blob - driver/gator_backtrace.c
gator-driver: Default GATOR_MALI_INTERFACE_STYLE to '2'
[android-sdk/arm-ds5-gator.git] / driver / gator_backtrace.c
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)
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