1 // SPDX-License-Identifier: GPL-2.0-only
3 * Port on Texas Instruments TMS320C6x architecture
5 * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
6 * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
8 #include <linux/module.h>
9 #include <linux/ptrace.h>
10 #include <linux/sched/debug.h>
11 #include <linux/bug.h>
14 #include <asm/special_insns.h>
15 #include <asm/traps.h>
17 int (*c6x_nmi_handler
)(struct pt_regs
*regs
);
19 void __init
trap_init(void)
21 ack_exception(EXCEPT_TYPE_NXF
);
22 ack_exception(EXCEPT_TYPE_EXC
);
23 ack_exception(EXCEPT_TYPE_IXF
);
24 ack_exception(EXCEPT_TYPE_SXF
);
28 void show_regs(struct pt_regs
*regs
)
31 show_regs_print_info(KERN_ERR
);
32 pr_err("PC: %08lx SP: %08lx\n", regs
->pc
, regs
->sp
);
33 pr_err("Status: %08lx ORIG_A4: %08lx\n", regs
->csr
, regs
->orig_a4
);
34 pr_err("A0: %08lx B0: %08lx\n", regs
->a0
, regs
->b0
);
35 pr_err("A1: %08lx B1: %08lx\n", regs
->a1
, regs
->b1
);
36 pr_err("A2: %08lx B2: %08lx\n", regs
->a2
, regs
->b2
);
37 pr_err("A3: %08lx B3: %08lx\n", regs
->a3
, regs
->b3
);
38 pr_err("A4: %08lx B4: %08lx\n", regs
->a4
, regs
->b4
);
39 pr_err("A5: %08lx B5: %08lx\n", regs
->a5
, regs
->b5
);
40 pr_err("A6: %08lx B6: %08lx\n", regs
->a6
, regs
->b6
);
41 pr_err("A7: %08lx B7: %08lx\n", regs
->a7
, regs
->b7
);
42 pr_err("A8: %08lx B8: %08lx\n", regs
->a8
, regs
->b8
);
43 pr_err("A9: %08lx B9: %08lx\n", regs
->a9
, regs
->b9
);
44 pr_err("A10: %08lx B10: %08lx\n", regs
->a10
, regs
->b10
);
45 pr_err("A11: %08lx B11: %08lx\n", regs
->a11
, regs
->b11
);
46 pr_err("A12: %08lx B12: %08lx\n", regs
->a12
, regs
->b12
);
47 pr_err("A13: %08lx B13: %08lx\n", regs
->a13
, regs
->b13
);
48 pr_err("A14: %08lx B14: %08lx\n", regs
->a14
, regs
->dp
);
49 pr_err("A15: %08lx B15: %08lx\n", regs
->a15
, regs
->sp
);
50 pr_err("A16: %08lx B16: %08lx\n", regs
->a16
, regs
->b16
);
51 pr_err("A17: %08lx B17: %08lx\n", regs
->a17
, regs
->b17
);
52 pr_err("A18: %08lx B18: %08lx\n", regs
->a18
, regs
->b18
);
53 pr_err("A19: %08lx B19: %08lx\n", regs
->a19
, regs
->b19
);
54 pr_err("A20: %08lx B20: %08lx\n", regs
->a20
, regs
->b20
);
55 pr_err("A21: %08lx B21: %08lx\n", regs
->a21
, regs
->b21
);
56 pr_err("A22: %08lx B22: %08lx\n", regs
->a22
, regs
->b22
);
57 pr_err("A23: %08lx B23: %08lx\n", regs
->a23
, regs
->b23
);
58 pr_err("A24: %08lx B24: %08lx\n", regs
->a24
, regs
->b24
);
59 pr_err("A25: %08lx B25: %08lx\n", regs
->a25
, regs
->b25
);
60 pr_err("A26: %08lx B26: %08lx\n", regs
->a26
, regs
->b26
);
61 pr_err("A27: %08lx B27: %08lx\n", regs
->a27
, regs
->b27
);
62 pr_err("A28: %08lx B28: %08lx\n", regs
->a28
, regs
->b28
);
63 pr_err("A29: %08lx B29: %08lx\n", regs
->a29
, regs
->b29
);
64 pr_err("A30: %08lx B30: %08lx\n", regs
->a30
, regs
->b30
);
65 pr_err("A31: %08lx B31: %08lx\n", regs
->a31
, regs
->b31
);
68 void die(char *str
, struct pt_regs
*fp
, int nr
)
71 pr_err("%s: %08x\n", str
, nr
);
74 pr_err("Process %s (pid: %d, stackpage=%08lx)\n",
75 current
->comm
, current
->pid
, (PAGE_SIZE
+
76 (unsigned long) current
));
83 static void die_if_kernel(char *str
, struct pt_regs
*fp
, int nr
)
92 /* Internal exceptions */
93 static struct exception_info iexcept_table
[10] = {
94 { "Oops - instruction fetch", SIGBUS
, BUS_ADRERR
},
95 { "Oops - fetch packet", SIGBUS
, BUS_ADRERR
},
96 { "Oops - execute packet", SIGILL
, ILL_ILLOPC
},
97 { "Oops - undefined instruction", SIGILL
, ILL_ILLOPC
},
98 { "Oops - resource conflict", SIGILL
, ILL_ILLOPC
},
99 { "Oops - resource access", SIGILL
, ILL_PRVREG
},
100 { "Oops - privilege", SIGILL
, ILL_PRVOPC
},
101 { "Oops - loops buffer", SIGILL
, ILL_ILLOPC
},
102 { "Oops - software exception", SIGILL
, ILL_ILLTRP
},
103 { "Oops - unknown exception", SIGILL
, ILL_ILLOPC
}
106 /* External exceptions */
107 static struct exception_info eexcept_table
[128] = {
108 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
109 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
110 { "Oops - external exception", SIGBUS
, BUS_ADRERR
},
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
},
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
},
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
},
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
},
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
},
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
},
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 - CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
231 { "Oops - CPU memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
232 { "Oops - DMA memory protection fault in L1P", SIGSEGV
, SEGV_ACCERR
},
233 { "Oops - CPU memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
234 { "Oops - DMA memory protection fault in L1D", SIGSEGV
, SEGV_ACCERR
},
235 { "Oops - CPU memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
236 { "Oops - DMA memory protection fault in L2", SIGSEGV
, SEGV_ACCERR
},
237 { "Oops - EMC CPU memory protection fault", SIGSEGV
, SEGV_ACCERR
},
238 { "Oops - EMC bus error", SIGBUS
, BUS_ADRERR
}
241 static void do_trap(struct exception_info
*except_info
, struct pt_regs
*regs
)
243 unsigned long addr
= instruction_pointer(regs
);
245 if (except_info
->code
!= TRAP_BRKPT
)
246 pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
247 except_info
->kernel_str
, regs
->pc
,
248 except_info
->signo
, except_info
->code
);
250 die_if_kernel(except_info
->kernel_str
, regs
, addr
);
252 force_sig_fault(except_info
->signo
, except_info
->code
,
253 (void __user
*)addr
);
257 * Process an internal exception (non maskable)
259 static int process_iexcept(struct pt_regs
*regs
)
261 unsigned int iexcept_report
= get_iexcept();
262 unsigned int iexcept_num
;
264 ack_exception(EXCEPT_TYPE_IXF
);
266 pr_err("IEXCEPT: PC[0x%lx]\n", regs
->pc
);
268 while (iexcept_report
) {
269 iexcept_num
= __ffs(iexcept_report
);
270 iexcept_report
&= ~(1 << iexcept_num
);
271 set_iexcept(iexcept_report
);
272 if (*(unsigned int *)regs
->pc
== BKPT_OPCODE
) {
273 /* This is a breakpoint */
274 struct exception_info bkpt_exception
= {
275 "Oops - undefined instruction",
278 do_trap(&bkpt_exception
, regs
);
279 iexcept_report
&= ~(0xFF);
280 set_iexcept(iexcept_report
);
284 do_trap(&iexcept_table
[iexcept_num
], regs
);
290 * Process an external exception (maskable)
292 static void process_eexcept(struct pt_regs
*regs
)
296 pr_err("EEXCEPT: PC[0x%lx]\n", regs
->pc
);
298 while ((evt
= soc_get_exception()) >= 0)
299 do_trap(&eexcept_table
[evt
], regs
);
301 ack_exception(EXCEPT_TYPE_EXC
);
305 * Main exception processing
307 asmlinkage
int process_exception(struct pt_regs
*regs
)
310 unsigned int type_num
;
311 unsigned int ie_num
= 9; /* default is unknown exception */
313 while ((type
= get_except_type()) != 0) {
314 type_num
= fls(type
) - 1;
317 case EXCEPT_TYPE_NXF
:
318 ack_exception(EXCEPT_TYPE_NXF
);
320 (c6x_nmi_handler
)(regs
);
322 pr_alert("NMI interrupt!\n");
325 case EXCEPT_TYPE_IXF
:
326 if (process_iexcept(regs
))
330 case EXCEPT_TYPE_EXC
:
331 process_eexcept(regs
);
334 case EXCEPT_TYPE_SXF
:
337 ack_exception(type_num
);
338 do_trap(&iexcept_table
[ie_num
], regs
);
345 static int kstack_depth_to_print
= 48;
347 static void show_trace(unsigned long *stack
, unsigned long *endstack
)
352 pr_debug("Call trace:");
354 while (stack
+ 1 <= endstack
) {
357 * If the address is either in the text segment of the
358 * kernel, or in the region which contains vmalloc'ed
359 * memory, it *may* be the address of a calling
360 * routine; if so, print it so that someone tracing
361 * down the cause of the crash will be able to figure
362 * out the call path that was taken.
364 if (__kernel_text_address(addr
)) {
365 #ifndef CONFIG_KALLSYMS
369 pr_debug(" [<%08lx>] %pS\n", addr
, (void *)addr
);
376 void show_stack(struct task_struct
*task
, unsigned long *stack
)
378 unsigned long *p
, *endstack
;
382 if (task
&& task
!= current
)
383 /* We know this is a kernel stack,
384 so this is the start/end */
385 stack
= (unsigned long *)thread_saved_ksp(task
);
387 stack
= (unsigned long *)&stack
;
389 endstack
= (unsigned long *)(((unsigned long)stack
+ THREAD_SIZE
- 1)
392 pr_debug("Stack from %08lx:", (unsigned long)stack
);
393 for (i
= 0, p
= stack
; i
< kstack_depth_to_print
; i
++) {
394 if (p
+ 1 > endstack
)
398 pr_cont(" %08lx", *p
++);
401 show_trace(stack
, endstack
);
404 int is_valid_bugaddr(unsigned long addr
)
406 return __kernel_text_address(addr
);