]> 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__)
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