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/bug.h>
17 #include <asm/special_insns.h>
18 #include <asm/traps.h>
20 int (*c6x_nmi_handler
)(struct pt_regs
*regs
);
22 void __init
trap_init(void)
24 ack_exception(EXCEPT_TYPE_NXF
);
25 ack_exception(EXCEPT_TYPE_EXC
);
26 ack_exception(EXCEPT_TYPE_IXF
);
27 ack_exception(EXCEPT_TYPE_SXF
);
31 void show_regs(struct pt_regs
*regs
)
34 show_regs_print_info(KERN_ERR
);
35 pr_err("PC: %08lx SP: %08lx\n", regs
->pc
, regs
->sp
);
36 pr_err("Status: %08lx ORIG_A4: %08lx\n", regs
->csr
, regs
->orig_a4
);
37 pr_err("A0: %08lx B0: %08lx\n", regs
->a0
, regs
->b0
);
38 pr_err("A1: %08lx B1: %08lx\n", regs
->a1
, regs
->b1
);
39 pr_err("A2: %08lx B2: %08lx\n", regs
->a2
, regs
->b2
);
40 pr_err("A3: %08lx B3: %08lx\n", regs
->a3
, regs
->b3
);
41 pr_err("A4: %08lx B4: %08lx\n", regs
->a4
, regs
->b4
);
42 pr_err("A5: %08lx B5: %08lx\n", regs
->a5
, regs
->b5
);
43 pr_err("A6: %08lx B6: %08lx\n", regs
->a6
, regs
->b6
);
44 pr_err("A7: %08lx B7: %08lx\n", regs
->a7
, regs
->b7
);
45 pr_err("A8: %08lx B8: %08lx\n", regs
->a8
, regs
->b8
);
46 pr_err("A9: %08lx B9: %08lx\n", regs
->a9
, regs
->b9
);
47 pr_err("A10: %08lx B10: %08lx\n", regs
->a10
, regs
->b10
);
48 pr_err("A11: %08lx B11: %08lx\n", regs
->a11
, regs
->b11
);
49 pr_err("A12: %08lx B12: %08lx\n", regs
->a12
, regs
->b12
);
50 pr_err("A13: %08lx B13: %08lx\n", regs
->a13
, regs
->b13
);
51 pr_err("A14: %08lx B14: %08lx\n", regs
->a14
, regs
->dp
);
52 pr_err("A15: %08lx B15: %08lx\n", regs
->a15
, regs
->sp
);
53 pr_err("A16: %08lx B16: %08lx\n", regs
->a16
, regs
->b16
);
54 pr_err("A17: %08lx B17: %08lx\n", regs
->a17
, regs
->b17
);
55 pr_err("A18: %08lx B18: %08lx\n", regs
->a18
, regs
->b18
);
56 pr_err("A19: %08lx B19: %08lx\n", regs
->a19
, regs
->b19
);
57 pr_err("A20: %08lx B20: %08lx\n", regs
->a20
, regs
->b20
);
58 pr_err("A21: %08lx B21: %08lx\n", regs
->a21
, regs
->b21
);
59 pr_err("A22: %08lx B22: %08lx\n", regs
->a22
, regs
->b22
);
60 pr_err("A23: %08lx B23: %08lx\n", regs
->a23
, regs
->b23
);
61 pr_err("A24: %08lx B24: %08lx\n", regs
->a24
, regs
->b24
);
62 pr_err("A25: %08lx B25: %08lx\n", regs
->a25
, regs
->b25
);
63 pr_err("A26: %08lx B26: %08lx\n", regs
->a26
, regs
->b26
);
64 pr_err("A27: %08lx B27: %08lx\n", regs
->a27
, regs
->b27
);
65 pr_err("A28: %08lx B28: %08lx\n", regs
->a28
, regs
->b28
);
66 pr_err("A29: %08lx B29: %08lx\n", regs
->a29
, regs
->b29
);
67 pr_err("A30: %08lx B30: %08lx\n", regs
->a30
, regs
->b30
);
68 pr_err("A31: %08lx B31: %08lx\n", regs
->a31
, regs
->b31
);
71 void die(char *str
, struct pt_regs
*fp
, int nr
)
74 pr_err("%s: %08x\n", str
, nr
);
77 pr_err("Process %s (pid: %d, stackpage=%08lx)\n",
78 current
->comm
, current
->pid
, (PAGE_SIZE
+
79 (unsigned long) current
));
86 static void die_if_kernel(char *str
, struct pt_regs
*fp
, int nr
)
95 /* Internal exceptions */
96 static struct exception_info iexcept_table
[10] = {
97 { "Oops - instruction fetch", SIGBUS
, BUS_ADRERR
},
98 { "Oops - fetch packet", SIGBUS
, BUS_ADRERR
},
99 { "Oops - execute packet", SIGILL
, ILL_ILLOPC
},
100 { "Oops - undefined instruction", SIGILL
, ILL_ILLOPC
},
101 { "Oops - resource conflict", SIGILL
, ILL_ILLOPC
},
102 { "Oops - resource access", SIGILL
, ILL_PRVREG
},
103 { "Oops - privilege", SIGILL
, ILL_PRVOPC
},
104 { "Oops - loops buffer", SIGILL
, ILL_ILLOPC
},
105 { "Oops - software exception", SIGILL
, ILL_ILLTRP
},
106 { "Oops - unknown exception", SIGILL
, ILL_ILLOPC
}
109 /* External exceptions */
110 static struct exception_info eexcept_table
[128] = {
111 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
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
},
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
},
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
},
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
},
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
},
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
},
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 - CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
234 { "Oops - CPU memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
235 { "Oops - DMA memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
236 { "Oops - CPU memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
237 { "Oops - DMA memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
238 { "Oops - CPU memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
239 { "Oops - DMA memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
240 { "Oops - EMC CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
241 { "Oops - EMC bus error", SIGBUS
, BUS_ADRERR
}
244 static void do_trap(struct exception_info
*except_info
, struct pt_regs
*regs
)
246 unsigned long addr
= instruction_pointer(regs
);
249 if (except_info
->code
!= TRAP_BRKPT
)
250 pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
251 except_info
->kernel_str
, regs
->pc
,
252 except_info
->signo
, except_info
->code
);
254 die_if_kernel(except_info
->kernel_str
, regs
, addr
);
256 info
.si_signo
= except_info
->signo
;
258 info
.si_code
= except_info
->code
;
259 info
.si_addr
= (void __user
*)addr
;
261 force_sig_info(except_info
->signo
, &info
, current
);
265 * Process an internal exception (non maskable)
267 static int process_iexcept(struct pt_regs
*regs
)
269 unsigned int iexcept_report
= get_iexcept();
270 unsigned int iexcept_num
;
272 ack_exception(EXCEPT_TYPE_IXF
);
274 pr_err("IEXCEPT: PC[0x%lx]\n", regs
->pc
);
276 while (iexcept_report
) {
277 iexcept_num
= __ffs(iexcept_report
);
278 iexcept_report
&= ~(1 << iexcept_num
);
279 set_iexcept(iexcept_report
);
280 if (*(unsigned int *)regs
->pc
== BKPT_OPCODE
) {
281 /* This is a breakpoint */
282 struct exception_info bkpt_exception
= {
283 "Oops - undefined instruction",
286 do_trap(&bkpt_exception
, regs
);
287 iexcept_report
&= ~(0xFF);
288 set_iexcept(iexcept_report
);
292 do_trap(&iexcept_table
[iexcept_num
], regs
);
298 * Process an external exception (maskable)
300 static void process_eexcept(struct pt_regs
*regs
)
304 pr_err("EEXCEPT: PC[0x%lx]\n", regs
->pc
);
306 while ((evt
= soc_get_exception()) >= 0)
307 do_trap(&eexcept_table
[evt
], regs
);
309 ack_exception(EXCEPT_TYPE_EXC
);
313 * Main exception processing
315 asmlinkage
int process_exception(struct pt_regs
*regs
)
318 unsigned int type_num
;
319 unsigned int ie_num
= 9; /* default is unknown exception */
321 while ((type
= get_except_type()) != 0) {
322 type_num
= fls(type
) - 1;
325 case EXCEPT_TYPE_NXF
:
326 ack_exception(EXCEPT_TYPE_NXF
);
328 (c6x_nmi_handler
)(regs
);
330 pr_alert("NMI interrupt!\n");
333 case EXCEPT_TYPE_IXF
:
334 if (process_iexcept(regs
))
338 case EXCEPT_TYPE_EXC
:
339 process_eexcept(regs
);
342 case EXCEPT_TYPE_SXF
:
345 ack_exception(type_num
);
346 do_trap(&iexcept_table
[ie_num
], regs
);
353 static int kstack_depth_to_print
= 48;
355 static void show_trace(unsigned long *stack
, unsigned long *endstack
)
360 pr_debug("Call trace:");
362 while (stack
+ 1 <= endstack
) {
365 * If the address is either in the text segment of the
366 * kernel, or in the region which contains vmalloc'ed
367 * memory, it *may* be the address of a calling
368 * routine; if so, print it so that someone tracing
369 * down the cause of the crash will be able to figure
370 * out the call path that was taken.
372 if (__kernel_text_address(addr
)) {
373 #ifndef CONFIG_KALLSYMS
377 pr_debug(" [<%08lx>] %pS\n", addr
, (void *)addr
);
384 void show_stack(struct task_struct
*task
, unsigned long *stack
)
386 unsigned long *p
, *endstack
;
390 if (task
&& task
!= current
)
391 /* We know this is a kernel stack,
392 so this is the start/end */
393 stack
= (unsigned long *)thread_saved_ksp(task
);
395 stack
= (unsigned long *)&stack
;
397 endstack
= (unsigned long *)(((unsigned long)stack
+ THREAD_SIZE
- 1)
400 pr_debug("Stack from %08lx:", (unsigned long)stack
);
401 for (i
= 0, p
= stack
; i
< kstack_depth_to_print
; i
++) {
402 if (p
+ 1 > endstack
)
406 pr_cont(" %08lx", *p
++);
409 show_trace(stack
, endstack
);
412 int is_valid_bugaddr(unsigned long addr
)
414 return __kernel_text_address(addr
);