diff options
author | Paul Mundt <lethal@linux-sh.org> | 2007-03-08 05:41:21 -0500 |
---|---|---|
committer | Paul Mundt <lethal@hera.kernel.org> | 2007-05-06 22:10:53 -0400 |
commit | fa69151173b1fc6fa3ced0edd5c2ea83b5d32bc1 (patch) | |
tree | e7af97ccddc06d54dd6d6982a64cbf4982693379 | |
parent | 45ed285b54930767937deb0eaf718b1d08c3c475 (diff) |
sh: generic BUG() support.
Wire up GENERIC_BUG for SH. This moves off of the special bug
frame and on to the generic struct bug_entry. Roughly the same
semantics are retained, and we can kill off some of the verbose
BUG() reporting code.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/Kconfig | 4 | ||||
-rw-r--r-- | arch/sh/kernel/traps.c | 54 | ||||
-rw-r--r-- | arch/sh/kernel/vmlinux.lds.S | 47 | ||||
-rw-r--r-- | include/asm-sh/bug.h | 92 |
4 files changed, 95 insertions, 102 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 2715834f72be..51d9d0ab39c6 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -22,6 +22,10 @@ config RWSEM_GENERIC_SPINLOCK | |||
22 | config RWSEM_XCHGADD_ALGORITHM | 22 | config RWSEM_XCHGADD_ALGORITHM |
23 | bool | 23 | bool |
24 | 24 | ||
25 | config GENERIC_BUG | ||
26 | def_bool y | ||
27 | depends on BUG | ||
28 | |||
25 | config GENERIC_FIND_NEXT_BIT | 29 | config GENERIC_FIND_NEXT_BIT |
26 | bool | 30 | bool |
27 | default y | 31 | default y |
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index e9f168f60f95..77107838271f 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/kallsyms.h> | 19 | #include <linux/kallsyms.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/bug.h> | ||
21 | #include <linux/debug_locks.h> | 22 | #include <linux/debug_locks.h> |
22 | #include <linux/limits.h> | 23 | #include <linux/limits.h> |
23 | #include <asm/system.h> | 24 | #include <asm/system.h> |
@@ -130,40 +131,6 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) | |||
130 | return -EFAULT; | 131 | return -EFAULT; |
131 | } | 132 | } |
132 | 133 | ||
133 | #ifdef CONFIG_BUG | ||
134 | #ifdef CONFIG_DEBUG_BUGVERBOSE | ||
135 | static inline void do_bug_verbose(struct pt_regs *regs) | ||
136 | { | ||
137 | struct bug_frame f; | ||
138 | long len; | ||
139 | |||
140 | if (__copy_from_user(&f, (const void __user *)regs->pc, | ||
141 | sizeof(struct bug_frame))) | ||
142 | return; | ||
143 | |||
144 | len = __strnlen_user(f.file, PATH_MAX) - 1; | ||
145 | if (unlikely(len < 0 || len >= PATH_MAX)) | ||
146 | f.file = "<bad filename>"; | ||
147 | len = __strnlen_user(f.func, PATH_MAX) - 1; | ||
148 | if (unlikely(len < 0 || len >= PATH_MAX)) | ||
149 | f.func = "<bad function>"; | ||
150 | |||
151 | printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n", | ||
152 | f.func, f.file, f.line); | ||
153 | } | ||
154 | #else | ||
155 | static inline void do_bug_verbose(struct pt_regs *regs) | ||
156 | { | ||
157 | } | ||
158 | #endif /* CONFIG_DEBUG_BUGVERBOSE */ | ||
159 | |||
160 | void handle_BUG(struct pt_regs *regs) | ||
161 | { | ||
162 | do_bug_verbose(regs); | ||
163 | die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); | ||
164 | } | ||
165 | #endif /* CONFIG_BUG */ | ||
166 | |||
167 | /* | 134 | /* |
168 | * handle an instruction that does an unaligned memory access by emulating the | 135 | * handle an instruction that does an unaligned memory access by emulating the |
169 | * desired behaviour | 136 | * desired behaviour |
@@ -888,6 +855,25 @@ void __init trap_init(void) | |||
888 | per_cpu_trap_init(); | 855 | per_cpu_trap_init(); |
889 | } | 856 | } |
890 | 857 | ||
858 | #ifdef CONFIG_BUG | ||
859 | void handle_BUG(struct pt_regs *regs) | ||
860 | { | ||
861 | enum bug_trap_type tt; | ||
862 | tt = report_bug(regs->pc); | ||
863 | if (tt == BUG_TRAP_TYPE_WARN) { | ||
864 | regs->pc += 2; | ||
865 | return; | ||
866 | } | ||
867 | |||
868 | die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); | ||
869 | } | ||
870 | |||
871 | int is_valid_bugaddr(unsigned long addr) | ||
872 | { | ||
873 | return addr >= PAGE_OFFSET; | ||
874 | } | ||
875 | #endif | ||
876 | |||
891 | void show_trace(struct task_struct *tsk, unsigned long *sp, | 877 | void show_trace(struct task_struct *tsk, unsigned long *sp, |
892 | struct pt_regs *regs) | 878 | struct pt_regs *regs) |
893 | { | 879 | { |
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 2f606d0ce1f6..d83143cc5ca9 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S | |||
@@ -34,9 +34,11 @@ SECTIONS | |||
34 | __ex_table : { *(__ex_table) } | 34 | __ex_table : { *(__ex_table) } |
35 | __stop___ex_table = .; | 35 | __stop___ex_table = .; |
36 | 36 | ||
37 | _etext = .; /* End of text section */ | ||
38 | |||
37 | RODATA | 39 | RODATA |
38 | 40 | ||
39 | _etext = .; /* End of text section */ | 41 | BUG_TABLE |
40 | 42 | ||
41 | .data : { /* Data */ | 43 | .data : { /* Data */ |
42 | *(.data) | 44 | *(.data) |
@@ -53,6 +55,10 @@ SECTIONS | |||
53 | 55 | ||
54 | . = ALIGN(PAGE_SIZE); | 56 | . = ALIGN(PAGE_SIZE); |
55 | .data.page_aligned : { *(.data.page_aligned) } | 57 | .data.page_aligned : { *(.data.page_aligned) } |
58 | __nosave_begin = .; | ||
59 | .data_nosave : { *(.data.nosave) } | ||
60 | . = ALIGN(PAGE_SIZE); | ||
61 | __nosave_end = .; | ||
56 | 62 | ||
57 | . = ALIGN(PAGE_SIZE); | 63 | . = ALIGN(PAGE_SIZE); |
58 | __per_cpu_start = .; | 64 | __per_cpu_start = .; |
@@ -110,43 +116,10 @@ SECTIONS | |||
110 | * it's a module. | 116 | * it's a module. |
111 | */ | 117 | */ |
112 | /DISCARD/ : { | 118 | /DISCARD/ : { |
113 | *(.exit.text) | ||
114 | *(.exit.data) | ||
115 | *(.exitcall.exit) | 119 | *(.exitcall.exit) |
116 | } | 120 | } |
117 | 121 | ||
118 | /* Stabs debugging sections. */ | 122 | STABS_DEBUG |
119 | .stab 0 : { *(.stab) } | 123 | |
120 | .stabstr 0 : { *(.stabstr) } | 124 | DWARF_DEBUG |
121 | .stab.excl 0 : { *(.stab.excl) } | ||
122 | .stab.exclstr 0 : { *(.stab.exclstr) } | ||
123 | .stab.index 0 : { *(.stab.index) } | ||
124 | .stab.indexstr 0 : { *(.stab.indexstr) } | ||
125 | .comment 0 : { *(.comment) } | ||
126 | /* DWARF debug sections. | ||
127 | Symbols in the DWARF debugging section are relative to the beginning | ||
128 | of the section so we begin .debug at 0. */ | ||
129 | /* DWARF 1 */ | ||
130 | .debug 0 : { *(.debug) } | ||
131 | .line 0 : { *(.line) } | ||
132 | /* GNU DWARF 1 extensions */ | ||
133 | .debug_srcinfo 0 : { *(.debug_srcinfo) } | ||
134 | .debug_sfnames 0 : { *(.debug_sfnames) } | ||
135 | /* DWARF 1.1 and DWARF 2 */ | ||
136 | .debug_aranges 0 : { *(.debug_aranges) } | ||
137 | .debug_pubnames 0 : { *(.debug_pubnames) } | ||
138 | /* DWARF 2 */ | ||
139 | .debug_info 0 : { *(.debug_info) } | ||
140 | .debug_abbrev 0 : { *(.debug_abbrev) } | ||
141 | .debug_line 0 : { *(.debug_line) } | ||
142 | .debug_frame 0 : { *(.debug_frame) } | ||
143 | .debug_str 0 : { *(.debug_str) } | ||
144 | .debug_loc 0 : { *(.debug_loc) } | ||
145 | .debug_macinfo 0 : { *(.debug_macinfo) } | ||
146 | /* SGI/MIPS DWARF 2 extensions */ | ||
147 | .debug_weaknames 0 : { *(.debug_weaknames) } | ||
148 | .debug_funcnames 0 : { *(.debug_funcnames) } | ||
149 | .debug_typenames 0 : { *(.debug_typenames) } | ||
150 | .debug_varnames 0 : { *(.debug_varnames) } | ||
151 | /* These must appear regardless of . */ | ||
152 | } | 125 | } |
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h index 2f89dd06d0cd..794c36daf06d 100644 --- a/include/asm-sh/bug.h +++ b/include/asm-sh/bug.h | |||
@@ -2,50 +2,80 @@ | |||
2 | #define __ASM_SH_BUG_H | 2 | #define __ASM_SH_BUG_H |
3 | 3 | ||
4 | #ifdef CONFIG_BUG | 4 | #ifdef CONFIG_BUG |
5 | 5 | #define HAVE_ARCH_BUG | |
6 | struct bug_frame { | 6 | #define HAVE_ARCH_WARN_ON |
7 | unsigned short opcode; | ||
8 | unsigned short line; | ||
9 | const char *file; | ||
10 | const char *func; | ||
11 | }; | ||
12 | |||
13 | struct pt_regs; | ||
14 | |||
15 | extern void handle_BUG(struct pt_regs *); | ||
16 | 7 | ||
17 | #define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */ | 8 | #define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */ |
18 | 9 | ||
10 | /** | ||
11 | * _EMIT_BUG_ENTRY | ||
12 | * %1 - __FILE__ | ||
13 | * %2 - __LINE__ | ||
14 | * %3 - trap type | ||
15 | * %4 - sizeof(struct bug_entry) | ||
16 | * | ||
17 | * The trapa opcode itself sits in %0. | ||
18 | * The %O notation is used to avoid # generation. | ||
19 | * | ||
20 | * The offending file and line are encoded in the __bug_table section. | ||
21 | */ | ||
19 | #ifdef CONFIG_DEBUG_BUGVERBOSE | 22 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
23 | #define _EMIT_BUG_ENTRY \ | ||
24 | "\t.pushsection __bug_table,\"a\"\n" \ | ||
25 | "2:\t.long 1b, %O1\n" \ | ||
26 | "\t.short %O2, %O3\n" \ | ||
27 | "\t.org 2b+%O4\n" \ | ||
28 | "\t.popsection\n" | ||
29 | #else | ||
30 | #define _EMIT_BUG_ENTRY \ | ||
31 | "\t.pushsection __bug_table,\"a\"\n" \ | ||
32 | "2:\t.long 1b\n" \ | ||
33 | "\t.short %O3\n" \ | ||
34 | "\t.org 2b+%O4\n" \ | ||
35 | "\t.popsection\n" | ||
36 | #endif | ||
20 | 37 | ||
21 | #define BUG() \ | 38 | #define BUG() \ |
22 | do { \ | 39 | do { \ |
23 | __asm__ __volatile__ ( \ | 40 | __asm__ __volatile__ ( \ |
24 | ".align 2\n\t" \ | 41 | "1:\t.short %O0\n" \ |
25 | ".short %O0\n\t" \ | 42 | _EMIT_BUG_ENTRY \ |
26 | ".short %O1\n\t" \ | 43 | : \ |
27 | ".long %O2\n\t" \ | 44 | : "n" (TRAPA_BUG_OPCODE), \ |
28 | ".long %O3\n\t" \ | 45 | "i" (__FILE__), \ |
29 | : \ | 46 | "i" (__LINE__), "i" (0), \ |
30 | : "n" (TRAPA_BUG_OPCODE), \ | 47 | "i" (sizeof(struct bug_entry))); \ |
31 | "i" (__LINE__), "X" (__FILE__), \ | ||
32 | "X" (__FUNCTION__)); \ | ||
33 | } while (0) | 48 | } while (0) |
34 | 49 | ||
35 | #else | 50 | #define __WARN() \ |
36 | 51 | do { \ | |
37 | #define BUG() \ | 52 | __asm__ __volatile__ ( \ |
38 | do { \ | 53 | "1:\t.short %O0\n" \ |
39 | __asm__ __volatile__ ( \ | 54 | _EMIT_BUG_ENTRY \ |
40 | ".align 2\n\t" \ | 55 | : \ |
41 | ".short %O0\n\t" \ | 56 | : "n" (TRAPA_BUG_OPCODE), \ |
42 | : \ | 57 | "i" (__FILE__), \ |
43 | : "n" (TRAPA_BUG_OPCODE)); \ | 58 | "i" (__LINE__), \ |
59 | "i" (BUGFLAG_WARNING), \ | ||
60 | "i" (sizeof(struct bug_entry))); \ | ||
44 | } while (0) | 61 | } while (0) |
45 | 62 | ||
46 | #endif /* CONFIG_DEBUG_BUGVERBOSE */ | 63 | #define WARN_ON(x) ({ \ |
64 | typeof(x) __ret_warn_on = (x); \ | ||
65 | if (__builtin_constant_p(__ret_warn_on)) { \ | ||
66 | if (__ret_warn_on) \ | ||
67 | __WARN(); \ | ||
68 | } else { \ | ||
69 | if (unlikely(__ret_warn_on)) \ | ||
70 | __WARN(); \ | ||
71 | } \ | ||
72 | unlikely(__ret_warn_on); \ | ||
73 | }) | ||
47 | 74 | ||
48 | #define HAVE_ARCH_BUG | 75 | struct pt_regs; |
76 | |||
77 | /* arch/sh/kernel/traps.c */ | ||
78 | void handle_BUG(struct pt_regs *); | ||
49 | 79 | ||
50 | #endif /* CONFIG_BUG */ | 80 | #endif /* CONFIG_BUG */ |
51 | 81 | ||