gator: ARM DS-5.4 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_backtrace.c
1 /**
2  * Copyright (C) ARM Limited 2010-2011. 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 lr = regs->ARM_lr;
27         int is_user_mode = user_mode(regs);
29         if (!is_user_mode) {
30                 return;
31         }
33         /* entry preamble may not have executed */
34         gator_add_trace(cpu, lr);
36         /* check tail is valid */
37         if (fp == 0) {
38                 return;
39         }
41         tail = (struct frame_tail_eabi *)(fp - 4);
43         while (depth-- && tail && !((unsigned long) tail & 3)) {
44                 /* Also check accessibility of one struct frame_tail beyond */
45                 if (!access_ok(VERIFY_READ, tail, sizeof(struct frame_tail_eabi)))
46                         return;
47                 if (__copy_from_user_inatomic(&buftail, tail, sizeof(struct frame_tail_eabi)))
48                         return;
49                 ptrtail = &buftail;
51                 lr = ptrtail[0].lr;
52                 gator_add_trace(cpu, lr);
54                 /* frame pointers should progress back up the stack, towards higher addresses */
55                 next = (struct frame_tail_eabi *)(lr - 4);
56                 if (tail >= next || lr == 0) {
57                         fp = ptrtail[0].fp;
58                         next = (struct frame_tail_eabi *)(fp - 4);
59                         /* check tail is valid */
60                         if (tail >= next || fp == 0) {
61                                 return;
62                         }
63                 }
65                 tail = next;
66         }
67 #endif
68 }