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/kallsyms.h>
14 #include <linux/bug.h>
17 #include <asm/traps.h>
19 int (*c6x_nmi_handler
)(struct pt_regs
*regs
);
21 void __init
trap_init(void)
23 ack_exception(EXCEPT_TYPE_NXF
);
24 ack_exception(EXCEPT_TYPE_EXC
);
25 ack_exception(EXCEPT_TYPE_IXF
);
26 ack_exception(EXCEPT_TYPE_SXF
);
30 void show_regs(struct pt_regs
*regs
)
33 pr_err("PC: %08lx SP: %08lx\n", regs
->pc
, regs
->sp
);
34 pr_err("Status: %08lx ORIG_A4: %08lx\n", regs
->csr
, regs
->orig_a4
);
35 pr_err("A0: %08lx B0: %08lx\n", regs
->a0
, regs
->b0
);
36 pr_err("A1: %08lx B1: %08lx\n", regs
->a1
, regs
->b1
);
37 pr_err("A2: %08lx B2: %08lx\n", regs
->a2
, regs
->b2
);
38 pr_err("A3: %08lx B3: %08lx\n", regs
->a3
, regs
->b3
);
39 pr_err("A4: %08lx B4: %08lx\n", regs
->a4
, regs
->b4
);
40 pr_err("A5: %08lx B5: %08lx\n", regs
->a5
, regs
->b5
);
41 pr_err("A6: %08lx B6: %08lx\n", regs
->a6
, regs
->b6
);
42 pr_err("A7: %08lx B7: %08lx\n", regs
->a7
, regs
->b7
);
43 pr_err("A8: %08lx B8: %08lx\n", regs
->a8
, regs
->b8
);
44 pr_err("A9: %08lx B9: %08lx\n", regs
->a9
, regs
->b9
);
45 pr_err("A10: %08lx B10: %08lx\n", regs
->a10
, regs
->b10
);
46 pr_err("A11: %08lx B11: %08lx\n", regs
->a11
, regs
->b11
);
47 pr_err("A12: %08lx B12: %08lx\n", regs
->a12
, regs
->b12
);
48 pr_err("A13: %08lx B13: %08lx\n", regs
->a13
, regs
->b13
);
49 pr_err("A14: %08lx B14: %08lx\n", regs
->a14
, regs
->dp
);
50 pr_err("A15: %08lx B15: %08lx\n", regs
->a15
, regs
->sp
);
51 pr_err("A16: %08lx B16: %08lx\n", regs
->a16
, regs
->b16
);
52 pr_err("A17: %08lx B17: %08lx\n", regs
->a17
, regs
->b17
);
53 pr_err("A18: %08lx B18: %08lx\n", regs
->a18
, regs
->b18
);
54 pr_err("A19: %08lx B19: %08lx\n", regs
->a19
, regs
->b19
);
55 pr_err("A20: %08lx B20: %08lx\n", regs
->a20
, regs
->b20
);
56 pr_err("A21: %08lx B21: %08lx\n", regs
->a21
, regs
->b21
);
57 pr_err("A22: %08lx B22: %08lx\n", regs
->a22
, regs
->b22
);
58 pr_err("A23: %08lx B23: %08lx\n", regs
->a23
, regs
->b23
);
59 pr_err("A24: %08lx B24: %08lx\n", regs
->a24
, regs
->b24
);
60 pr_err("A25: %08lx B25: %08lx\n", regs
->a25
, regs
->b25
);
61 pr_err("A26: %08lx B26: %08lx\n", regs
->a26
, regs
->b26
);
62 pr_err("A27: %08lx B27: %08lx\n", regs
->a27
, regs
->b27
);
63 pr_err("A28: %08lx B28: %08lx\n", regs
->a28
, regs
->b28
);
64 pr_err("A29: %08lx B29: %08lx\n", regs
->a29
, regs
->b29
);
65 pr_err("A30: %08lx B30: %08lx\n", regs
->a30
, regs
->b30
);
66 pr_err("A31: %08lx B31: %08lx\n", regs
->a31
, regs
->b31
);
73 show_stack(current
, &stack
);
75 EXPORT_SYMBOL(dump_stack
);
78 void die(char *str
, struct pt_regs
*fp
, int nr
)
81 pr_err("%s: %08x\n", str
, nr
);
84 pr_err("Process %s (pid: %d, stackpage=%08lx)\n",
85 current
->comm
, current
->pid
, (PAGE_SIZE
+
86 (unsigned long) current
));
93 static void die_if_kernel(char *str
, struct pt_regs
*fp
, int nr
)
102 /* Internal exceptions */
103 static struct exception_info iexcept_table
[10] = {
104 { "Oops - instruction fetch", SIGBUS
, BUS_ADRERR
},
105 { "Oops - fetch packet", SIGBUS
, BUS_ADRERR
},
106 { "Oops - execute packet", SIGILL
, ILL_ILLOPC
},
107 { "Oops - undefined instruction", SIGILL
, ILL_ILLOPC
},
108 { "Oops - resource conflict", SIGILL
, ILL_ILLOPC
},
109 { "Oops - resource access", SIGILL
, ILL_PRVREG
},
110 { "Oops - privilege", SIGILL
, ILL_PRVOPC
},
111 { "Oops - loops buffer", SIGILL
, ILL_ILLOPC
},
112 { "Oops - software exception", SIGILL
, ILL_ILLTRP
},
113 { "Oops - unknown exception", SIGILL
, ILL_ILLOPC
}
116 /* External exceptions */
117 static struct exception_info eexcept_table
[128] = {
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
},
144 { "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
},
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
},
177 { "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
},
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
},
210 { "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
},
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 - external exception", SIGBUS
, BUS_ADRERR
},
235 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
236 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
237 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
238 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
239 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
240 { "Oops - CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
241 { "Oops - CPU memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
242 { "Oops - DMA memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
243 { "Oops - CPU memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
244 { "Oops - DMA memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
245 { "Oops - CPU memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
246 { "Oops - DMA memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
247 { "Oops - EMC CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
248 { "Oops - EMC bus error", SIGBUS
, BUS_ADRERR
}
251 static void do_trap(struct exception_info
*except_info
, struct pt_regs
*regs
)
253 unsigned long addr
= instruction_pointer(regs
);
256 if (except_info
->code
!= TRAP_BRKPT
)
257 pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
258 except_info
->kernel_str
, regs
->pc
,
259 except_info
->signo
, except_info
->code
);
261 die_if_kernel(except_info
->kernel_str
, regs
, addr
);
263 info
.si_signo
= except_info
->signo
;
265 info
.si_code
= except_info
->code
;
266 info
.si_addr
= (void __user
*)addr
;
268 force_sig_info(except_info
->signo
, &info
, current
);
272 * Process an internal exception (non maskable)
274 static int process_iexcept(struct pt_regs
*regs
)
276 unsigned int iexcept_report
= get_iexcept();
277 unsigned int iexcept_num
;
279 ack_exception(EXCEPT_TYPE_IXF
);
281 pr_err("IEXCEPT: PC[0x%lx]\n", regs
->pc
);
283 while (iexcept_report
) {
284 iexcept_num
= __ffs(iexcept_report
);
285 iexcept_report
&= ~(1 << iexcept_num
);
286 set_iexcept(iexcept_report
);
287 if (*(unsigned int *)regs
->pc
== BKPT_OPCODE
) {
288 /* This is a breakpoint */
289 struct exception_info bkpt_exception
= {
290 "Oops - undefined instruction",
293 do_trap(&bkpt_exception
, regs
);
294 iexcept_report
&= ~(0xFF);
295 set_iexcept(iexcept_report
);
299 do_trap(&iexcept_table
[iexcept_num
], regs
);
305 * Process an external exception (maskable)
307 static void process_eexcept(struct pt_regs
*regs
)
311 pr_err("EEXCEPT: PC[0x%lx]\n", regs
->pc
);
313 while ((evt
= soc_get_exception()) >= 0)
314 do_trap(&eexcept_table
[evt
], regs
);
316 ack_exception(EXCEPT_TYPE_EXC
);
320 * Main exception processing
322 asmlinkage
int process_exception(struct pt_regs
*regs
)
325 unsigned int type_num
;
326 unsigned int ie_num
= 9; /* default is unknown exception */
328 while ((type
= get_except_type()) != 0) {
329 type_num
= fls(type
) - 1;
332 case EXCEPT_TYPE_NXF
:
333 ack_exception(EXCEPT_TYPE_NXF
);
335 (c6x_nmi_handler
)(regs
);
337 pr_alert("NMI interrupt!\n");
340 case EXCEPT_TYPE_IXF
:
341 if (process_iexcept(regs
))
345 case EXCEPT_TYPE_EXC
:
346 process_eexcept(regs
);
349 case EXCEPT_TYPE_SXF
:
352 ack_exception(type_num
);
353 do_trap(&iexcept_table
[ie_num
], regs
);
360 static int kstack_depth_to_print
= 48;
362 static void show_trace(unsigned long *stack
, unsigned long *endstack
)
367 pr_debug("Call trace:");
369 while (stack
+ 1 <= endstack
) {
372 * If the address is either in the text segment of the
373 * kernel, or in the region which contains vmalloc'ed
374 * memory, it *may* be the address of a calling
375 * routine; if so, print it so that someone tracing
376 * down the cause of the crash will be able to figure
377 * out the call path that was taken.
379 if (__kernel_text_address(addr
)) {
380 #ifndef CONFIG_KALLSYMS
384 pr_debug(" [<%08lx>]", addr
);
385 print_symbol(" %s\n", addr
);
392 void show_stack(struct task_struct
*task
, unsigned long *stack
)
394 unsigned long *p
, *endstack
;
398 if (task
&& task
!= current
)
399 /* We know this is a kernel stack,
400 so this is the start/end */
401 stack
= (unsigned long *)thread_saved_ksp(task
);
403 stack
= (unsigned long *)&stack
;
405 endstack
= (unsigned long *)(((unsigned long)stack
+ THREAD_SIZE
- 1)
408 pr_debug("Stack from %08lx:", (unsigned long)stack
);
409 for (i
= 0, p
= stack
; i
< kstack_depth_to_print
; i
++) {
410 if (p
+ 1 > endstack
)
414 pr_cont(" %08lx", *p
++);
417 show_trace(stack
, endstack
);
420 int is_valid_bugaddr(unsigned long addr
)
422 return __kernel_text_address(addr
);