]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - arch/arm/common/fiq_debugger_arm64.c
FIQ: Implement WDT FIQ debugger
[sojka/nv-tegra/linux-3.10.git] / arch / arm / common / fiq_debugger_arm64.c
1 /*
2  * Copyright (C) 2014 Google, Inc.
3  * Author: Colin Cross <ccross@android.com>
4  * Copyright (C) 2010-2015 NVIDIA Corporation.  All rights reserved.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/ptrace.h>
18 #include <asm/stacktrace.h>
19
20 #include "fiq_debugger_priv.h"
21
22 static char *mode_name(const struct pt_regs *regs)
23 {
24         if (compat_user_mode(regs)) {
25                 return "USR";
26         } else {
27                 switch (processor_mode(regs)) {
28                 case PSR_MODE_EL0t: return "EL0t";
29                 case PSR_MODE_EL1t: return "EL1t";
30                 case PSR_MODE_EL1h: return "EL1h";
31                 case PSR_MODE_EL2t: return "EL2t";
32                 case PSR_MODE_EL2h: return "EL2h";
33                 default: return "???";
34                 }
35         }
36 }
37
38 void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
39                 const struct pt_regs *regs)
40 {
41         output->printf(output, " pc %016lx cpsr %08lx mode %s\n",
42                 regs->pc, regs->pstate, mode_name(regs));
43 }
44
45 void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output *output,
46                 const struct pt_regs *regs)
47 {
48         output->printf(output, " r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
49                         regs->compat_usr(0), regs->compat_usr(1),
50                         regs->compat_usr(2), regs->compat_usr(3));
51         output->printf(output, " r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
52                         regs->compat_usr(4), regs->compat_usr(5),
53                         regs->compat_usr(6), regs->compat_usr(7));
54         output->printf(output, " r8 %08x  r9 %08x r10 %08x r11 %08x\n",
55                         regs->compat_usr(8), regs->compat_usr(9),
56                         regs->compat_usr(10), regs->compat_usr(11));
57         output->printf(output, " ip %08x  sp %08x  lr %08x  pc %08x\n",
58                         regs->compat_usr(12), regs->compat_sp,
59                         regs->compat_lr, regs->pc);
60         output->printf(output, " cpsr %08x (%s)\n",
61                         regs->pstate, mode_name(regs));
62 }
63
64 void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output *output,
65                 const struct pt_regs *regs)
66 {
67
68         output->printf(output, "  x0 %016lx   x1 %016lx\n",
69                         regs->regs[0], regs->regs[1]);
70         output->printf(output, "  x2 %016lx   x3 %016lx\n",
71                         regs->regs[2], regs->regs[3]);
72         output->printf(output, "  x4 %016lx   x5 %016lx\n",
73                         regs->regs[4], regs->regs[5]);
74         output->printf(output, "  x6 %016lx   x7 %016lx\n",
75                         regs->regs[6], regs->regs[7]);
76         output->printf(output, "  x8 %016lx   x9 %016lx\n",
77                         regs->regs[8], regs->regs[9]);
78         output->printf(output, " x10 %016lx  x11 %016lx\n",
79                         regs->regs[10], regs->regs[11]);
80         output->printf(output, " x12 %016lx  x13 %016lx\n",
81                         regs->regs[12], regs->regs[13]);
82         output->printf(output, " x14 %016lx  x15 %016lx\n",
83                         regs->regs[14], regs->regs[15]);
84         output->printf(output, " x16 %016lx  x17 %016lx\n",
85                         regs->regs[16], regs->regs[17]);
86         output->printf(output, " x18 %016lx  x19 %016lx\n",
87                         regs->regs[18], regs->regs[19]);
88         output->printf(output, " x20 %016lx  x21 %016lx\n",
89                         regs->regs[20], regs->regs[21]);
90         output->printf(output, " x22 %016lx  x23 %016lx\n",
91                         regs->regs[22], regs->regs[23]);
92         output->printf(output, " x24 %016lx  x25 %016lx\n",
93                         regs->regs[24], regs->regs[25]);
94         output->printf(output, " x26 %016lx  x27 %016lx\n",
95                         regs->regs[26], regs->regs[27]);
96         output->printf(output, " x28 %016lx  x29 %016lx\n",
97                         regs->regs[28], regs->regs[29]);
98         output->printf(output, " x30 %016lx   sp %016lx\n",
99                         regs->regs[30], regs->sp);
100         output->printf(output, "  pc %016lx cpsr %08x (%s)\n",
101                         regs->pc, regs->pstate, mode_name(regs));
102 }
103
104 void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
105                 const struct pt_regs *regs)
106 {
107         if (compat_user_mode(regs))
108                 fiq_debugger_dump_regs_aarch32(output, regs);
109         else
110                 fiq_debugger_dump_regs_aarch64(output, regs);
111 }
112
113 #define READ_SPECIAL_REG(x) ({ \
114         u64 val; \
115         asm volatile ("mrs %0, " # x : "=r"(val)); \
116         val; \
117 })
118
119 void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
120                 const struct pt_regs *regs)
121 {
122         u32 pstate = READ_SPECIAL_REG(CurrentEl);
123         bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t;
124
125         fiq_debugger_dump_regs(output, regs);
126
127         output->printf(output, " sp_el0   %016lx\n",
128                         READ_SPECIAL_REG(sp_el0));
129
130         if (in_el2)
131                 output->printf(output, " sp_el1   %016lx\n",
132                                 READ_SPECIAL_REG(sp_el1));
133
134         output->printf(output, " elr_el1  %016lx\n",
135                         READ_SPECIAL_REG(elr_el1));
136
137         output->printf(output, " spsr_el1 %08lx\n",
138                         READ_SPECIAL_REG(spsr_el1));
139
140         if (in_el2) {
141                 output->printf(output, " spsr_irq %08lx\n",
142                                 READ_SPECIAL_REG(spsr_irq));
143                 output->printf(output, " spsr_abt %08lx\n",
144                                 READ_SPECIAL_REG(spsr_abt));
145                 output->printf(output, " spsr_und %08lx\n",
146                                 READ_SPECIAL_REG(spsr_und));
147                 output->printf(output, " spsr_fiq %08lx\n",
148                                 READ_SPECIAL_REG(spsr_fiq));
149                 output->printf(output, " spsr_el2 %08lx\n",
150                                 READ_SPECIAL_REG(elr_el2));
151                 output->printf(output, " spsr_el2 %08lx\n",
152                                 READ_SPECIAL_REG(spsr_el2));
153         }
154 }
155
156 struct stacktrace_state {
157         struct fiq_debugger_output *output;
158         unsigned int depth;
159 };
160
161 static int report_trace(struct stackframe *frame, void *d)
162 {
163         struct stacktrace_state *sts = d;
164
165         if (sts->depth) {
166                 sts->output->printf(sts->output, "%pF:\n", frame->pc);
167                 sts->output->printf(sts->output,
168                                 "  pc %016lx   sp %016lx   fp %016lx\n",
169                                 frame->pc, frame->sp, frame->fp);
170                 sts->depth--;
171                 return 0;
172         }
173         sts->output->printf(sts->output, "  ...\n");
174
175         return sts->depth == 0;
176 }
177
178 void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
179                 const struct pt_regs *regs, unsigned int depth, void *ssp)
180 {
181         struct thread_info *real_thread_info = THREAD_INFO(ssp);
182         struct stacktrace_state sts;
183
184         sts.depth = depth;
185         sts.output = output;
186         *current_thread_info() = *real_thread_info;
187
188         if (!current)
189                 output->printf(output, "current NULL\n");
190         else
191                 output->printf(output, "pid: %d  comm: %s\n",
192                         current->pid, current->comm);
193         fiq_debugger_dump_regs(output, regs);
194
195         if (!user_mode(regs)) {
196                 struct stackframe frame;
197                 frame.fp = regs->regs[29];
198                 frame.sp = regs->sp;
199                 frame.pc = regs->pc;
200                 output->printf(output, "\n");
201                 walk_stackframe(&frame, report_trace, &sts);
202         }
203 }