Merge branch 'linux-linaro-lsk' into linux-linaro-lsk-android
[firefly-linux-kernel-4.4.55.git] / drivers / staging / android / fiq_debugger / fiq_debugger_arm.c
1 /*
2  * Copyright (C) 2014 Google, Inc.
3  * Author: Colin Cross <ccross@android.com>
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/ptrace.h>
17 #include <linux/uaccess.h>
18
19 #include <asm/stacktrace.h>
20
21 #include "fiq_debugger_priv.h"
22
23 static char *mode_name(unsigned cpsr)
24 {
25         switch (cpsr & MODE_MASK) {
26         case USR_MODE: return "USR";
27         case FIQ_MODE: return "FIQ";
28         case IRQ_MODE: return "IRQ";
29         case SVC_MODE: return "SVC";
30         case ABT_MODE: return "ABT";
31         case UND_MODE: return "UND";
32         case SYSTEM_MODE: return "SYS";
33         default: return "???";
34         }
35 }
36
37 void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
38                 const struct pt_regs *regs)
39 {
40         output->printf(output, " pc %08x cpsr %08x mode %s\n",
41                 regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr));
42 }
43
44 void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
45                 const struct pt_regs *regs)
46 {
47         output->printf(output,
48                         " r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
49                         regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
50         output->printf(output,
51                         " r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
52                         regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);
53         output->printf(output,
54                         " r8 %08x  r9 %08x r10 %08x r11 %08x  mode %s\n",
55                         regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp,
56                         mode_name(regs->ARM_cpsr));
57         output->printf(output,
58                         " ip %08x  sp %08x  lr %08x  pc %08x cpsr %08x\n",
59                         regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc,
60                         regs->ARM_cpsr);
61 }
62
63 struct mode_regs {
64         unsigned long sp_svc;
65         unsigned long lr_svc;
66         unsigned long spsr_svc;
67
68         unsigned long sp_abt;
69         unsigned long lr_abt;
70         unsigned long spsr_abt;
71
72         unsigned long sp_und;
73         unsigned long lr_und;
74         unsigned long spsr_und;
75
76         unsigned long sp_irq;
77         unsigned long lr_irq;
78         unsigned long spsr_irq;
79
80         unsigned long r8_fiq;
81         unsigned long r9_fiq;
82         unsigned long r10_fiq;
83         unsigned long r11_fiq;
84         unsigned long r12_fiq;
85         unsigned long sp_fiq;
86         unsigned long lr_fiq;
87         unsigned long spsr_fiq;
88 };
89
90 static void __naked get_mode_regs(struct mode_regs *regs)
91 {
92         asm volatile (
93         "mrs    r1, cpsr\n"
94         "msr    cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n"
95         "stmia  r0!, {r13 - r14}\n"
96         "mrs    r2, spsr\n"
97         "msr    cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n"
98         "stmia  r0!, {r2, r13 - r14}\n"
99         "mrs    r2, spsr\n"
100         "msr    cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n"
101         "stmia  r0!, {r2, r13 - r14}\n"
102         "mrs    r2, spsr\n"
103         "msr    cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
104         "stmia  r0!, {r2, r13 - r14}\n"
105         "mrs    r2, spsr\n"
106         "msr    cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
107         "stmia  r0!, {r2, r8 - r14}\n"
108         "mrs    r2, spsr\n"
109         "stmia  r0!, {r2}\n"
110         "msr    cpsr_c, r1\n"
111         "bx     lr\n");
112 }
113
114
115 void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
116                 const struct pt_regs *regs)
117 {
118         struct mode_regs mode_regs;
119         unsigned long mode = regs->ARM_cpsr & MODE_MASK;
120
121         fiq_debugger_dump_regs(output, regs);
122         get_mode_regs(&mode_regs);
123
124         output->printf(output,
125                         "%csvc: sp %08x  lr %08x  spsr %08x\n",
126                         mode == SVC_MODE ? '*' : ' ',
127                         mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc);
128         output->printf(output,
129                         "%cabt: sp %08x  lr %08x  spsr %08x\n",
130                         mode == ABT_MODE ? '*' : ' ',
131                         mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt);
132         output->printf(output,
133                         "%cund: sp %08x  lr %08x  spsr %08x\n",
134                         mode == UND_MODE ? '*' : ' ',
135                         mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und);
136         output->printf(output,
137                         "%cirq: sp %08x  lr %08x  spsr %08x\n",
138                         mode == IRQ_MODE ? '*' : ' ',
139                         mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq);
140         output->printf(output,
141                         "%cfiq: r8 %08x  r9 %08x  r10 %08x  r11 %08x  r12 %08x\n",
142                         mode == FIQ_MODE ? '*' : ' ',
143                         mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq,
144                         mode_regs.r11_fiq, mode_regs.r12_fiq);
145         output->printf(output,
146                         " fiq: sp %08x  lr %08x  spsr %08x\n",
147                         mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq);
148 }
149
150 struct stacktrace_state {
151         struct fiq_debugger_output *output;
152         unsigned int depth;
153 };
154
155 static int report_trace(struct stackframe *frame, void *d)
156 {
157         struct stacktrace_state *sts = d;
158
159         if (sts->depth) {
160                 sts->output->printf(sts->output,
161                         "  pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
162                         frame->pc, frame->pc, frame->lr, frame->lr,
163                         frame->sp, frame->fp);
164                 sts->depth--;
165                 return 0;
166         }
167         sts->output->printf(sts->output, "  ...\n");
168
169         return sts->depth == 0;
170 }
171
172 struct frame_tail {
173         struct frame_tail *fp;
174         unsigned long sp;
175         unsigned long lr;
176 } __attribute__((packed));
177
178 static struct frame_tail *user_backtrace(struct fiq_debugger_output *output,
179                                         struct frame_tail *tail)
180 {
181         struct frame_tail buftail[2];
182
183         /* Also check accessibility of one struct frame_tail beyond */
184         if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) {
185                 output->printf(output, "  invalid frame pointer %p\n",
186                                 tail);
187                 return NULL;
188         }
189         if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) {
190                 output->printf(output,
191                         "  failed to copy frame pointer %p\n", tail);
192                 return NULL;
193         }
194
195         output->printf(output, "  %p\n", buftail[0].lr);
196
197         /* frame pointers should strictly progress back up the stack
198          * (towards higher addresses) */
199         if (tail >= buftail[0].fp)
200                 return NULL;
201
202         return buftail[0].fp-1;
203 }
204
205 void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
206                 const struct pt_regs *regs, unsigned int depth, void *ssp)
207 {
208         struct frame_tail *tail;
209         struct thread_info *real_thread_info = THREAD_INFO(ssp);
210         struct stacktrace_state sts;
211
212         sts.depth = depth;
213         sts.output = output;
214         *current_thread_info() = *real_thread_info;
215
216         if (!current)
217                 output->printf(output, "current NULL\n");
218         else
219                 output->printf(output, "pid: %d  comm: %s\n",
220                         current->pid, current->comm);
221         fiq_debugger_dump_regs(output, regs);
222
223         if (!user_mode(regs)) {
224                 struct stackframe frame;
225                 frame.fp = regs->ARM_fp;
226                 frame.sp = regs->ARM_sp;
227                 frame.lr = regs->ARM_lr;
228                 frame.pc = regs->ARM_pc;
229                 output->printf(output,
230                         "  pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
231                         regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr,
232                         regs->ARM_sp, regs->ARM_fp);
233                 walk_stackframe(&frame, report_trace, &sts);
234                 return;
235         }
236
237         tail = ((struct frame_tail *) regs->ARM_fp) - 1;
238         while (depth-- && tail && !((unsigned long) tail & 3))
239                 tail = user_backtrace(output, tail);
240 }