Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
traps.c
Go to the documentation of this file.
1 /*
2  * Port on Texas Instruments TMS320C6x architecture
3  *
4  * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
5  * Author: Aurelien Jacquiot ([email protected])
6  *
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.
10  */
11 #include <linux/module.h>
12 #include <linux/ptrace.h>
13 #include <linux/kallsyms.h>
14 #include <linux/bug.h>
15 
16 #include <asm/soc.h>
17 #include <asm/special_insns.h>
18 #include <asm/traps.h>
19 
21 
22 void __init trap_init(void)
23 {
29 }
30 
31 void show_regs(struct pt_regs *regs)
32 {
33  pr_err("\n");
34  pr_err("PC: %08lx SP: %08lx\n", regs->pc, regs->sp);
35  pr_err("Status: %08lx ORIG_A4: %08lx\n", regs->csr, regs->orig_a4);
36  pr_err("A0: %08lx B0: %08lx\n", regs->a0, regs->b0);
37  pr_err("A1: %08lx B1: %08lx\n", regs->a1, regs->b1);
38  pr_err("A2: %08lx B2: %08lx\n", regs->a2, regs->b2);
39  pr_err("A3: %08lx B3: %08lx\n", regs->a3, regs->b3);
40  pr_err("A4: %08lx B4: %08lx\n", regs->a4, regs->b4);
41  pr_err("A5: %08lx B5: %08lx\n", regs->a5, regs->b5);
42  pr_err("A6: %08lx B6: %08lx\n", regs->a6, regs->b6);
43  pr_err("A7: %08lx B7: %08lx\n", regs->a7, regs->b7);
44  pr_err("A8: %08lx B8: %08lx\n", regs->a8, regs->b8);
45  pr_err("A9: %08lx B9: %08lx\n", regs->a9, regs->b9);
46  pr_err("A10: %08lx B10: %08lx\n", regs->a10, regs->b10);
47  pr_err("A11: %08lx B11: %08lx\n", regs->a11, regs->b11);
48  pr_err("A12: %08lx B12: %08lx\n", regs->a12, regs->b12);
49  pr_err("A13: %08lx B13: %08lx\n", regs->a13, regs->b13);
50  pr_err("A14: %08lx B14: %08lx\n", regs->a14, regs->dp);
51  pr_err("A15: %08lx B15: %08lx\n", regs->a15, regs->sp);
52  pr_err("A16: %08lx B16: %08lx\n", regs->a16, regs->b16);
53  pr_err("A17: %08lx B17: %08lx\n", regs->a17, regs->b17);
54  pr_err("A18: %08lx B18: %08lx\n", regs->a18, regs->b18);
55  pr_err("A19: %08lx B19: %08lx\n", regs->a19, regs->b19);
56  pr_err("A20: %08lx B20: %08lx\n", regs->a20, regs->b20);
57  pr_err("A21: %08lx B21: %08lx\n", regs->a21, regs->b21);
58  pr_err("A22: %08lx B22: %08lx\n", regs->a22, regs->b22);
59  pr_err("A23: %08lx B23: %08lx\n", regs->a23, regs->b23);
60  pr_err("A24: %08lx B24: %08lx\n", regs->a24, regs->b24);
61  pr_err("A25: %08lx B25: %08lx\n", regs->a25, regs->b25);
62  pr_err("A26: %08lx B26: %08lx\n", regs->a26, regs->b26);
63  pr_err("A27: %08lx B27: %08lx\n", regs->a27, regs->b27);
64  pr_err("A28: %08lx B28: %08lx\n", regs->a28, regs->b28);
65  pr_err("A29: %08lx B29: %08lx\n", regs->a29, regs->b29);
66  pr_err("A30: %08lx B30: %08lx\n", regs->a30, regs->b30);
67  pr_err("A31: %08lx B31: %08lx\n", regs->a31, regs->b31);
68 }
69 
70 void dump_stack(void)
71 {
72  unsigned long stack;
73 
74  show_stack(current, &stack);
75 }
77 
78 
79 void die(char *str, struct pt_regs *fp, int nr)
80 {
81  console_verbose();
82  pr_err("%s: %08x\n", str, nr);
83  show_regs(fp);
84 
85  pr_err("Process %s (pid: %d, stackpage=%08lx)\n",
86  current->comm, current->pid, (PAGE_SIZE +
87  (unsigned long) current));
88 
89  dump_stack();
90  while (1)
91  ;
92 }
93 
94 static void die_if_kernel(char *str, struct pt_regs *fp, int nr)
95 {
96  if (user_mode(fp))
97  return;
98 
99  die(str, fp, nr);
100 }
101 
102 
103 /* Internal exceptions */
104 static struct exception_info iexcept_table[10] = {
105  { "Oops - instruction fetch", SIGBUS, BUS_ADRERR },
106  { "Oops - fetch packet", SIGBUS, BUS_ADRERR },
107  { "Oops - execute packet", SIGILL, ILL_ILLOPC },
108  { "Oops - undefined instruction", SIGILL, ILL_ILLOPC },
109  { "Oops - resource conflict", SIGILL, ILL_ILLOPC },
110  { "Oops - resource access", SIGILL, ILL_PRVREG },
111  { "Oops - privilege", SIGILL, ILL_PRVOPC },
112  { "Oops - loops buffer", SIGILL, ILL_ILLOPC },
113  { "Oops - software exception", SIGILL, ILL_ILLTRP },
114  { "Oops - unknown exception", SIGILL, ILL_ILLOPC }
115 };
116 
117 /* External exceptions */
118 static struct exception_info eexcept_table[128] = {
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 },
150  { "Oops - external exception", SIGBUS, BUS_ADRERR },
151 
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 },
183  { "Oops - external exception", SIGBUS, BUS_ADRERR },
184 
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 },
216  { "Oops - external exception", SIGBUS, BUS_ADRERR },
217 
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 - external exception", SIGBUS, BUS_ADRERR },
241  { "Oops - CPU memory protection fault", SIGSEGV, SEGV_ACCERR },
242  { "Oops - CPU memory protection fault in L1P", SIGSEGV, SEGV_ACCERR },
243  { "Oops - DMA memory protection fault in L1P", SIGSEGV, SEGV_ACCERR },
244  { "Oops - CPU memory protection fault in L1D", SIGSEGV, SEGV_ACCERR },
245  { "Oops - DMA memory protection fault in L1D", SIGSEGV, SEGV_ACCERR },
246  { "Oops - CPU memory protection fault in L2", SIGSEGV, SEGV_ACCERR },
247  { "Oops - DMA memory protection fault in L2", SIGSEGV, SEGV_ACCERR },
248  { "Oops - EMC CPU memory protection fault", SIGSEGV, SEGV_ACCERR },
249  { "Oops - EMC bus error", SIGBUS, BUS_ADRERR }
250 };
251 
252 static void do_trap(struct exception_info *except_info, struct pt_regs *regs)
253 {
254  unsigned long addr = instruction_pointer(regs);
255  siginfo_t info;
256 
257  if (except_info->code != TRAP_BRKPT)
258  pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
259  except_info->kernel_str, regs->pc,
260  except_info->signo, except_info->code);
261 
262  die_if_kernel(except_info->kernel_str, regs, addr);
263 
264  info.si_signo = except_info->signo;
265  info.si_errno = 0;
266  info.si_code = except_info->code;
267  info.si_addr = (void __user *)addr;
268 
269  force_sig_info(except_info->signo, &info, current);
270 }
271 
272 /*
273  * Process an internal exception (non maskable)
274  */
275 static int process_iexcept(struct pt_regs *regs)
276 {
277  unsigned int iexcept_report = get_iexcept();
278  unsigned int iexcept_num;
279 
281 
282  pr_err("IEXCEPT: PC[0x%lx]\n", regs->pc);
283 
284  while (iexcept_report) {
285  iexcept_num = __ffs(iexcept_report);
286  iexcept_report &= ~(1 << iexcept_num);
287  set_iexcept(iexcept_report);
288  if (*(unsigned int *)regs->pc == BKPT_OPCODE) {
289  /* This is a breakpoint */
290  struct exception_info bkpt_exception = {
291  "Oops - undefined instruction",
293  };
294  do_trap(&bkpt_exception, regs);
295  iexcept_report &= ~(0xFF);
296  set_iexcept(iexcept_report);
297  continue;
298  }
299 
300  do_trap(&iexcept_table[iexcept_num], regs);
301  }
302  return 0;
303 }
304 
305 /*
306  * Process an external exception (maskable)
307  */
308 static void process_eexcept(struct pt_regs *regs)
309 {
310  int evt;
311 
312  pr_err("EEXCEPT: PC[0x%lx]\n", regs->pc);
313 
314  while ((evt = soc_get_exception()) >= 0)
315  do_trap(&eexcept_table[evt], regs);
316 
318 }
319 
320 /*
321  * Main exception processing
322  */
324 {
325  unsigned int type;
326  unsigned int type_num;
327  unsigned int ie_num = 9; /* default is unknown exception */
328 
329  while ((type = get_except_type()) != 0) {
330  type_num = fls(type) - 1;
331 
332  switch (type_num) {
333  case EXCEPT_TYPE_NXF:
335  if (c6x_nmi_handler)
336  (c6x_nmi_handler)(regs);
337  else
338  pr_alert("NMI interrupt!\n");
339  break;
340 
341  case EXCEPT_TYPE_IXF:
342  if (process_iexcept(regs))
343  return 1;
344  break;
345 
346  case EXCEPT_TYPE_EXC:
347  process_eexcept(regs);
348  break;
349 
350  case EXCEPT_TYPE_SXF:
351  ie_num = 8;
352  default:
353  ack_exception(type_num);
354  do_trap(&iexcept_table[ie_num], regs);
355  break;
356  }
357  }
358  return 0;
359 }
360 
361 static int kstack_depth_to_print = 48;
362 
363 static void show_trace(unsigned long *stack, unsigned long *endstack)
364 {
365  unsigned long addr;
366  int i;
367 
368  pr_debug("Call trace:");
369  i = 0;
370  while (stack + 1 <= endstack) {
371  addr = *stack++;
372  /*
373  * If the address is either in the text segment of the
374  * kernel, or in the region which contains vmalloc'ed
375  * memory, it *may* be the address of a calling
376  * routine; if so, print it so that someone tracing
377  * down the cause of the crash will be able to figure
378  * out the call path that was taken.
379  */
380  if (__kernel_text_address(addr)) {
381 #ifndef CONFIG_KALLSYMS
382  if (i % 5 == 0)
383  pr_debug("\n ");
384 #endif
385  pr_debug(" [<%08lx>]", addr);
386  print_symbol(" %s\n", addr);
387  i++;
388  }
389  }
390  pr_debug("\n");
391 }
392 
393 void show_stack(struct task_struct *task, unsigned long *stack)
394 {
395  unsigned long *p, *endstack;
396  int i;
397 
398  if (!stack) {
399  if (task && task != current)
400  /* We know this is a kernel stack,
401  so this is the start/end */
402  stack = (unsigned long *)thread_saved_ksp(task);
403  else
404  stack = (unsigned long *)&stack;
405  }
406  endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1)
407  & -THREAD_SIZE);
408 
409  pr_debug("Stack from %08lx:", (unsigned long)stack);
410  for (i = 0, p = stack; i < kstack_depth_to_print; i++) {
411  if (p + 1 > endstack)
412  break;
413  if (i % 8 == 0)
414  pr_cont("\n ");
415  pr_cont(" %08lx", *p++);
416  }
417  pr_cont("\n");
418  show_trace(stack, endstack);
419 }
420 
421 int is_valid_bugaddr(unsigned long addr)
422 {
423  return __kernel_text_address(addr);
424 }