diff options
Diffstat (limited to 'arch/microblaze/kernel/traps.c')
-rw-r--r-- | arch/microblaze/kernel/traps.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c new file mode 100644 index 000000000000..fbdc533c61e3 --- /dev/null +++ b/arch/microblaze/kernel/traps.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | ||
3 | * Copyright (C) 2007-2009 PetaLogix | ||
4 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/kallsyms.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/debug_locks.h> | ||
16 | |||
17 | #include <asm/exceptions.h> | ||
18 | #include <asm/system.h> | ||
19 | |||
20 | void trap_init(void) | ||
21 | { | ||
22 | __enable_hw_exceptions(); | ||
23 | } | ||
24 | |||
25 | void __bad_xchg(volatile void *ptr, int size) | ||
26 | { | ||
27 | printk(KERN_INFO "xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", | ||
28 | __builtin_return_address(0), ptr, size); | ||
29 | BUG(); | ||
30 | } | ||
31 | EXPORT_SYMBOL(__bad_xchg); | ||
32 | |||
33 | static int kstack_depth_to_print = 24; | ||
34 | |||
35 | static int __init kstack_setup(char *s) | ||
36 | { | ||
37 | kstack_depth_to_print = strict_strtoul(s, 0, 0); | ||
38 | |||
39 | return 1; | ||
40 | } | ||
41 | __setup("kstack=", kstack_setup); | ||
42 | |||
43 | void show_trace(struct task_struct *task, unsigned long *stack) | ||
44 | { | ||
45 | unsigned long addr; | ||
46 | |||
47 | if (!stack) | ||
48 | stack = (unsigned long *)&stack; | ||
49 | |||
50 | printk(KERN_NOTICE "Call Trace: "); | ||
51 | #ifdef CONFIG_KALLSYMS | ||
52 | printk(KERN_NOTICE "\n"); | ||
53 | #endif | ||
54 | while (!kstack_end(stack)) { | ||
55 | addr = *stack++; | ||
56 | /* | ||
57 | * If the address is either in the text segment of the | ||
58 | * kernel, or in the region which contains vmalloc'ed | ||
59 | * memory, it *may* be the address of a calling | ||
60 | * routine; if so, print it so that someone tracing | ||
61 | * down the cause of the crash will be able to figure | ||
62 | * out the call path that was taken. | ||
63 | */ | ||
64 | if (kernel_text_address(addr)) | ||
65 | print_ip_sym(addr); | ||
66 | } | ||
67 | printk(KERN_NOTICE "\n"); | ||
68 | |||
69 | if (!task) | ||
70 | task = current; | ||
71 | |||
72 | debug_show_held_locks(task); | ||
73 | } | ||
74 | |||
75 | void show_stack(struct task_struct *task, unsigned long *sp) | ||
76 | { | ||
77 | unsigned long *stack; | ||
78 | int i; | ||
79 | |||
80 | if (sp == NULL) { | ||
81 | if (task) | ||
82 | sp = (unsigned long *) ((struct thread_info *) | ||
83 | (task->stack))->cpu_context.r1; | ||
84 | else | ||
85 | sp = (unsigned long *)&sp; | ||
86 | } | ||
87 | |||
88 | stack = sp; | ||
89 | |||
90 | printk(KERN_INFO "\nStack:\n "); | ||
91 | |||
92 | for (i = 0; i < kstack_depth_to_print; i++) { | ||
93 | if (kstack_end(sp)) | ||
94 | break; | ||
95 | if (i && ((i % 8) == 0)) | ||
96 | printk("\n "); | ||
97 | printk("%08lx ", *sp++); | ||
98 | } | ||
99 | printk("\n"); | ||
100 | show_trace(task, stack); | ||
101 | } | ||
102 | |||
103 | void dump_stack(void) | ||
104 | { | ||
105 | show_stack(NULL, NULL); | ||
106 | } | ||
107 | EXPORT_SYMBOL(dump_stack); | ||