2 * Port on Texas Instruments TMS320C6x architecture
4 * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
5 * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #include <linux/module.h>
12 #include <linux/ptrace.h>
13 #include <linux/sched/debug.h>
14 #include <linux/kallsyms.h>
15 #include <linux/bug.h>
18 #include <asm/special_insns.h>
19 #include <asm/traps.h>
21 int (*c6x_nmi_handler
)(struct pt_regs
*regs
);
23 void __init
trap_init(void)
25 ack_exception(EXCEPT_TYPE_NXF
);
26 ack_exception(EXCEPT_TYPE_EXC
);
27 ack_exception(EXCEPT_TYPE_IXF
);
28 ack_exception(EXCEPT_TYPE_SXF
);
32 void show_regs(struct pt_regs
*regs
)
35 show_regs_print_info(KERN_ERR
);
36 pr_err("PC: %08lx SP: %08lx\n", regs
->pc
, regs
->sp
);
37 pr_err("Status: %08lx ORIG_A4: %08lx\n", regs
->csr
, regs
->orig_a4
);
38 pr_err("A0: %08lx B0: %08lx\n", regs
->a0
, regs
->b0
);
39 pr_err("A1: %08lx B1: %08lx\n", regs
->a1
, regs
->b1
);
40 pr_err("A2: %08lx B2: %08lx\n", regs
->a2
, regs
->b2
);
41 pr_err("A3: %08lx B3: %08lx\n", regs
->a3
, regs
->b3
);
42 pr_err("A4: %08lx B4: %08lx\n", regs
->a4
, regs
->b4
);
43 pr_err("A5: %08lx B5: %08lx\n", regs
->a5
, regs
->b5
);
44 pr_err("A6: %08lx B6: %08lx\n", regs
->a6
, regs
->b6
);
45 pr_err("A7: %08lx B7: %08lx\n", regs
->a7
, regs
->b7
);
46 pr_err("A8: %08lx B8: %08lx\n", regs
->a8
, regs
->b8
);
47 pr_err("A9: %08lx B9: %08lx\n", regs
->a9
, regs
->b9
);
48 pr_err("A10: %08lx B10: %08lx\n", regs
->a10
, regs
->b10
);
49 pr_err("A11: %08lx B11: %08lx\n", regs
->a11
, regs
->b11
);
50 pr_err("A12: %08lx B12: %08lx\n", regs
->a12
, regs
->b12
);
51 pr_err("A13: %08lx B13: %08lx\n", regs
->a13
, regs
->b13
);
52 pr_err("A14: %08lx B14: %08lx\n", regs
->a14
, regs
->dp
);
53 pr_err("A15: %08lx B15: %08lx\n", regs
->a15
, regs
->sp
);
54 pr_err("A16: %08lx B16: %08lx\n", regs
->a16
, regs
->b16
);
55 pr_err("A17: %08lx B17: %08lx\n", regs
->a17
, regs
->b17
);
56 pr_err("A18: %08lx B18: %08lx\n", regs
->a18
, regs
->b18
);
57 pr_err("A19: %08lx B19: %08lx\n", regs
->a19
, regs
->b19
);
58 pr_err("A20: %08lx B20: %08lx\n", regs
->a20
, regs
->b20
);
59 pr_err("A21: %08lx B21: %08lx\n", regs
->a21
, regs
->b21
);
60 pr_err("A22: %08lx B22: %08lx\n", regs
->a22
, regs
->b22
);
61 pr_err("A23: %08lx B23: %08lx\n", regs
->a23
, regs
->b23
);
62 pr_err("A24: %08lx B24: %08lx\n", regs
->a24
, regs
->b24
);
63 pr_err("A25: %08lx B25: %08lx\n", regs
->a25
, regs
->b25
);
64 pr_err("A26: %08lx B26: %08lx\n", regs
->a26
, regs
->b26
);
65 pr_err("A27: %08lx B27: %08lx\n", regs
->a27
, regs
->b27
);
66 pr_err("A28: %08lx B28: %08lx\n", regs
->a28
, regs
->b28
);
67 pr_err("A29: %08lx B29: %08lx\n", regs
->a29
, regs
->b29
);
68 pr_err("A30: %08lx B30: %08lx\n", regs
->a30
, regs
->b30
);
69 pr_err("A31: %08lx B31: %08lx\n", regs
->a31
, regs
->b31
);
72 void die(char *str
, struct pt_regs
*fp
, int nr
)
75 pr_err("%s: %08x\n", str
, nr
);
78 pr_err("Process %s (pid: %d, stackpage=%08lx)\n",
79 current
->comm
, current
->pid
, (PAGE_SIZE
+
80 (unsigned long) current
));
87 static void die_if_kernel(char *str
, struct pt_regs
*fp
, int nr
)
96 /* Internal exceptions */
97 static struct exception_info iexcept_table
[10] = {
98 { "Oops - instruction fetch", SIGBUS
, BUS_ADRERR
},
99 { "Oops - fetch packet", SIGBUS
, BUS_ADRERR
},
100 { "Oops - execute packet", SIGILL
, ILL_ILLOPC
},
101 { "Oops - undefined instruction", SIGILL
, ILL_ILLOPC
},
102 { "Oops - resource conflict", SIGILL
, ILL_ILLOPC
},
103 { "Oops - resource access", SIGILL
, ILL_PRVREG
},
104 { "Oops - privilege", SIGILL
, ILL_PRVOPC
},
105 { "Oops - loops buffer", SIGILL
, ILL_ILLOPC
},
106 { "Oops - software exception", SIGILL
, ILL_ILLTRP
},
107 { "Oops - unknown exception", SIGILL
, ILL_ILLOPC
}
110 /* External exceptions */
111 static struct exception_info eexcept_table
[128] = {
112 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
113 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
114 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
115 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
116 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
117 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
118 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
119 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
120 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
121 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
122 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
123 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
124 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
125 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
126 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
127 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
128 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
129 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
130 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
131 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
132 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
133 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
134 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
135 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
136 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
137 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
138 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
139 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
140 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
141 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
142 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
143 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
145 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
146 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
147 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
148 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
149 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
150 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
151 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
152 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
153 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
154 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
155 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
156 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
157 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
158 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
159 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
160 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
161 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
162 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
163 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
164 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
165 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
166 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
167 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
168 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
169 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
170 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
171 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
172 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
173 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
174 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
175 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
176 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
178 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
179 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
180 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
181 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
182 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
183 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
184 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
185 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
186 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
187 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
188 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
189 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
190 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
191 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
192 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
193 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
194 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
195 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
196 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
197 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
198 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
199 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
200 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
201 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
202 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
203 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
204 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
205 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
206 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
207 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
208 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
209 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
211 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
212 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
213 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
214 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
215 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
216 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
217 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
218 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
219 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
220 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
221 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
222 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
223 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
224 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
225 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
226 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
227 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
228 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
229 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
230 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
231 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
232 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
233 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
234 { "Oops - CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
235 { "Oops - CPU memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
236 { "Oops - DMA memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
237 { "Oops - CPU memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
238 { "Oops - DMA memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
239 { "Oops - CPU memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
240 { "Oops - DMA memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
241 { "Oops - EMC CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
242 { "Oops - EMC bus error", SIGBUS
, BUS_ADRERR
}
245 static void do_trap(struct exception_info
*except_info
, struct pt_regs
*regs
)
247 unsigned long addr
= instruction_pointer(regs
);
250 if (except_info
->code
!= TRAP_BRKPT
)
251 pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
252 except_info
->kernel_str
, regs
->pc
,
253 except_info
->signo
, except_info
->code
);
255 die_if_kernel(except_info
->kernel_str
, regs
, addr
);
257 info
.si_signo
= except_info
->signo
;
259 info
.si_code
= except_info
->code
;
260 info
.si_addr
= (void __user
*)addr
;
262 force_sig_info(except_info
->signo
, &info
, current
);
266 * Process an internal exception (non maskable)
268 static int process_iexcept(struct pt_regs
*regs
)
270 unsigned int iexcept_report
= get_iexcept();
271 unsigned int iexcept_num
;
273 ack_exception(EXCEPT_TYPE_IXF
);
275 pr_err("IEXCEPT: PC[0x%lx]\n", regs
->pc
);
277 while (iexcept_report
) {
278 iexcept_num
= __ffs(iexcept_report
);
279 iexcept_report
&= ~(1 << iexcept_num
);
280 set_iexcept(iexcept_report
);
281 if (*(unsigned int *)regs
->pc
== BKPT_OPCODE
) {
282 /* This is a breakpoint */
283 struct exception_info bkpt_exception
= {
284 "Oops - undefined instruction",
287 do_trap(&bkpt_exception
, regs
);
288 iexcept_report
&= ~(0xFF);
289 set_iexcept(iexcept_report
);
293 do_trap(&iexcept_table
[iexcept_num
], regs
);
299 * Process an external exception (maskable)
301 static void process_eexcept(struct pt_regs
*regs
)
305 pr_err("EEXCEPT: PC[0x%lx]\n", regs
->pc
);
307 while ((evt
= soc_get_exception()) >= 0)
308 do_trap(&eexcept_table
[evt
], regs
);
310 ack_exception(EXCEPT_TYPE_EXC
);
314 * Main exception processing
316 asmlinkage
int process_exception(struct pt_regs
*regs
)
319 unsigned int type_num
;
320 unsigned int ie_num
= 9; /* default is unknown exception */
322 while ((type
= get_except_type()) != 0) {
323 type_num
= fls(type
) - 1;
326 case EXCEPT_TYPE_NXF
:
327 ack_exception(EXCEPT_TYPE_NXF
);
329 (c6x_nmi_handler
)(regs
);
331 pr_alert("NMI interrupt!\n");
334 case EXCEPT_TYPE_IXF
:
335 if (process_iexcept(regs
))
339 case EXCEPT_TYPE_EXC
:
340 process_eexcept(regs
);
343 case EXCEPT_TYPE_SXF
:
346 ack_exception(type_num
);
347 do_trap(&iexcept_table
[ie_num
], regs
);
354 static int kstack_depth_to_print
= 48;
356 static void show_trace(unsigned long *stack
, unsigned long *endstack
)
361 pr_debug("Call trace:");
363 while (stack
+ 1 <= endstack
) {
366 * If the address is either in the text segment of the
367 * kernel, or in the region which contains vmalloc'ed
368 * memory, it *may* be the address of a calling
369 * routine; if so, print it so that someone tracing
370 * down the cause of the crash will be able to figure
371 * out the call path that was taken.
373 if (__kernel_text_address(addr
)) {
374 #ifndef CONFIG_KALLSYMS
378 pr_debug(" [<%08lx>]", addr
);
379 print_symbol(" %s\n", addr
);
386 void show_stack(struct task_struct
*task
, unsigned long *stack
)
388 unsigned long *p
, *endstack
;
392 if (task
&& task
!= current
)
393 /* We know this is a kernel stack,
394 so this is the start/end */
395 stack
= (unsigned long *)thread_saved_ksp(task
);
397 stack
= (unsigned long *)&stack
;
399 endstack
= (unsigned long *)(((unsigned long)stack
+ THREAD_SIZE
- 1)
402 pr_debug("Stack from %08lx:", (unsigned long)stack
);
403 for (i
= 0, p
= stack
; i
< kstack_depth_to_print
; i
++) {
404 if (p
+ 1 > endstack
)
408 pr_cont(" %08lx", *p
++);
411 show_trace(stack
, endstack
);
414 int is_valid_bugaddr(unsigned long addr
)
416 return __kernel_text_address(addr
);