traps.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * linux/arch/cris/traps.c
  3. *
  4. * Here we handle the break vectors not used by the system call
  5. * mechanism, as well as some general stack/register dumping
  6. * things.
  7. *
  8. * Copyright (C) 2000-2007 Axis Communications AB
  9. *
  10. * Authors: Bjorn Wesen
  11. * Hans-Peter Nilsson
  12. *
  13. */
  14. #include <linux/init.h>
  15. #include <linux/module.h>
  16. #include <asm/pgtable.h>
  17. #include <asm/uaccess.h>
  18. #include <arch/system.h>
  19. extern void arch_enable_nmi(void);
  20. extern void stop_watchdog(void);
  21. extern void reset_watchdog(void);
  22. extern void show_registers(struct pt_regs *regs);
  23. #ifdef CONFIG_DEBUG_BUGVERBOSE
  24. extern void handle_BUG(struct pt_regs *regs);
  25. #else
  26. #define handle_BUG(regs)
  27. #endif
  28. static int kstack_depth_to_print = 24;
  29. void (*nmi_handler)(struct pt_regs *);
  30. void
  31. show_trace(unsigned long *stack)
  32. {
  33. unsigned long addr, module_start, module_end;
  34. extern char _stext, _etext;
  35. int i;
  36. printk("\nCall Trace: ");
  37. i = 1;
  38. module_start = VMALLOC_START;
  39. module_end = VMALLOC_END;
  40. while (((long)stack & (THREAD_SIZE-1)) != 0) {
  41. if (__get_user(addr, stack)) {
  42. /* This message matches "failing address" marked
  43. s390 in ksymoops, so lines containing it will
  44. not be filtered out by ksymoops. */
  45. printk("Failing address 0x%lx\n", (unsigned long)stack);
  46. break;
  47. }
  48. stack++;
  49. /*
  50. * If the address is either in the text segment of the
  51. * kernel, or in the region which contains vmalloc'ed
  52. * memory, it *may* be the address of a calling
  53. * routine; if so, print it so that someone tracing
  54. * down the cause of the crash will be able to figure
  55. * out the call path that was taken.
  56. */
  57. if (((addr >= (unsigned long)&_stext) &&
  58. (addr <= (unsigned long)&_etext)) ||
  59. ((addr >= module_start) && (addr <= module_end))) {
  60. if (i && ((i % 8) == 0))
  61. printk("\n ");
  62. printk("[<%08lx>] ", addr);
  63. i++;
  64. }
  65. }
  66. }
  67. /*
  68. * These constants are for searching for possible module text
  69. * segments. MODULE_RANGE is a guess of how much space is likely
  70. * to be vmalloced.
  71. */
  72. #define MODULE_RANGE (8*1024*1024)
  73. /*
  74. * The output (format, strings and order) is adjusted to be usable with
  75. * ksymoops-2.4.1 with some necessary CRIS-specific patches. Please don't
  76. * change it unless you're serious about adjusting ksymoops and syncing
  77. * with the ksymoops maintainer.
  78. */
  79. void
  80. show_stack(struct task_struct *task, unsigned long *sp)
  81. {
  82. unsigned long *stack, addr;
  83. int i;
  84. /*
  85. * debugging aid: "show_stack(NULL);" prints a
  86. * back trace.
  87. */
  88. if (sp == NULL) {
  89. if (task)
  90. sp = (unsigned long*)task->thread.ksp;
  91. else
  92. sp = (unsigned long*)rdsp();
  93. }
  94. stack = sp;
  95. printk("\nStack from %08lx:\n ", (unsigned long)stack);
  96. for (i = 0; i < kstack_depth_to_print; i++) {
  97. if (((long)stack & (THREAD_SIZE-1)) == 0)
  98. break;
  99. if (i && ((i % 8) == 0))
  100. printk("\n ");
  101. if (__get_user(addr, stack)) {
  102. /* This message matches "failing address" marked
  103. s390 in ksymoops, so lines containing it will
  104. not be filtered out by ksymoops. */
  105. printk("Failing address 0x%lx\n", (unsigned long)stack);
  106. break;
  107. }
  108. stack++;
  109. printk("%08lx ", addr);
  110. }
  111. show_trace(sp);
  112. }
  113. #if 0
  114. /* displays a short stack trace */
  115. int
  116. show_stack(void)
  117. {
  118. unsigned long *sp = (unsigned long *)rdusp();
  119. int i;
  120. printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
  121. for (i = 0; i < 16; i++)
  122. printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
  123. return 0;
  124. }
  125. #endif
  126. void
  127. dump_stack(void)
  128. {
  129. show_stack(NULL, NULL);
  130. }
  131. EXPORT_SYMBOL(dump_stack);
  132. void
  133. set_nmi_handler(void (*handler)(struct pt_regs *))
  134. {
  135. nmi_handler = handler;
  136. arch_enable_nmi();
  137. }
  138. #ifdef CONFIG_DEBUG_NMI_OOPS
  139. void
  140. oops_nmi_handler(struct pt_regs *regs)
  141. {
  142. stop_watchdog();
  143. oops_in_progress = 1;
  144. printk("NMI!\n");
  145. show_registers(regs);
  146. oops_in_progress = 0;
  147. }
  148. static int __init
  149. oops_nmi_register(void)
  150. {
  151. set_nmi_handler(oops_nmi_handler);
  152. return 0;
  153. }
  154. __initcall(oops_nmi_register);
  155. #endif
  156. /*
  157. * This gets called from entry.S when the watchdog has bitten. Show something
  158. * similar to an Oops dump, and if the kernel is configured to be a nice
  159. * doggy, then halt instead of reboot.
  160. */
  161. void
  162. watchdog_bite_hook(struct pt_regs *regs)
  163. {
  164. #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
  165. local_irq_disable();
  166. stop_watchdog();
  167. show_registers(regs);
  168. while (1)
  169. ; /* Do nothing. */
  170. #else
  171. show_registers(regs);
  172. #endif
  173. }
  174. /* This is normally the Oops function. */
  175. void
  176. die_if_kernel(const char *str, struct pt_regs *regs, long err)
  177. {
  178. if (user_mode(regs))
  179. return;
  180. #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
  181. /*
  182. * This printout might take too long and could trigger
  183. * the watchdog normally. If NICE_DOGGY is set, simply
  184. * stop the watchdog during the printout.
  185. */
  186. stop_watchdog();
  187. #endif
  188. handle_BUG(regs);
  189. printk("%s: %04lx\n", str, err & 0xffff);
  190. show_registers(regs);
  191. oops_in_progress = 0;
  192. #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
  193. reset_watchdog();
  194. #endif
  195. do_exit(SIGSEGV);
  196. }
  197. void __init
  198. trap_init(void)
  199. {
  200. /* Nothing needs to be done */
  201. }