Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Paul Mundt and committed by
Paul Mundt
fa691511 45ed285b

+95 -102
+4
arch/sh/Kconfig
··· 22 22 config RWSEM_XCHGADD_ALGORITHM 23 23 bool 24 24 25 + config GENERIC_BUG 26 + def_bool y 27 + depends on BUG 28 + 25 29 config GENERIC_FIND_NEXT_BIT 26 30 bool 27 31 default y
+20 -34
arch/sh/kernel/traps.c
··· 18 18 #include <linux/module.h> 19 19 #include <linux/kallsyms.h> 20 20 #include <linux/io.h> 21 + #include <linux/bug.h> 21 22 #include <linux/debug_locks.h> 22 23 #include <linux/limits.h> 23 24 #include <asm/system.h> ··· 130 129 } 131 130 return -EFAULT; 132 131 } 133 - 134 - #ifdef CONFIG_BUG 135 - #ifdef CONFIG_DEBUG_BUGVERBOSE 136 - static inline void do_bug_verbose(struct pt_regs *regs) 137 - { 138 - struct bug_frame f; 139 - long len; 140 - 141 - if (__copy_from_user(&f, (const void __user *)regs->pc, 142 - sizeof(struct bug_frame))) 143 - return; 144 - 145 - len = __strnlen_user(f.file, PATH_MAX) - 1; 146 - if (unlikely(len < 0 || len >= PATH_MAX)) 147 - f.file = "<bad filename>"; 148 - len = __strnlen_user(f.func, PATH_MAX) - 1; 149 - if (unlikely(len < 0 || len >= PATH_MAX)) 150 - f.func = "<bad function>"; 151 - 152 - printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n", 153 - f.func, f.file, f.line); 154 - } 155 - #else 156 - static inline void do_bug_verbose(struct pt_regs *regs) 157 - { 158 - } 159 - #endif /* CONFIG_DEBUG_BUGVERBOSE */ 160 - 161 - void handle_BUG(struct pt_regs *regs) 162 - { 163 - do_bug_verbose(regs); 164 - die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); 165 - } 166 - #endif /* CONFIG_BUG */ 167 132 168 133 /* 169 134 * handle an instruction that does an unaligned memory access by emulating the ··· 854 887 /* Setup VBR for boot cpu */ 855 888 per_cpu_trap_init(); 856 889 } 890 + 891 + #ifdef CONFIG_BUG 892 + void handle_BUG(struct pt_regs *regs) 893 + { 894 + enum bug_trap_type tt; 895 + tt = report_bug(regs->pc); 896 + if (tt == BUG_TRAP_TYPE_WARN) { 897 + regs->pc += 2; 898 + return; 899 + } 900 + 901 + die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); 902 + } 903 + 904 + int is_valid_bugaddr(unsigned long addr) 905 + { 906 + return addr >= PAGE_OFFSET; 907 + } 908 + #endif 857 909 858 910 void show_trace(struct task_struct *tsk, unsigned long *sp, 859 911 struct pt_regs *regs)
+10 -37
arch/sh/kernel/vmlinux.lds.S
··· 34 34 __ex_table : { *(__ex_table) } 35 35 __stop___ex_table = .; 36 36 37 + _etext = .; /* End of text section */ 38 + 37 39 RODATA 38 40 39 - _etext = .; /* End of text section */ 41 + BUG_TABLE 40 42 41 43 .data : { /* Data */ 42 44 *(.data) ··· 55 53 56 54 . = ALIGN(PAGE_SIZE); 57 55 .data.page_aligned : { *(.data.page_aligned) } 56 + __nosave_begin = .; 57 + .data_nosave : { *(.data.nosave) } 58 + . = ALIGN(PAGE_SIZE); 59 + __nosave_end = .; 58 60 59 61 . = ALIGN(PAGE_SIZE); 60 62 __per_cpu_start = .; ··· 116 110 * it's a module. 117 111 */ 118 112 /DISCARD/ : { 119 - *(.exit.text) 120 - *(.exit.data) 121 113 *(.exitcall.exit) 122 114 } 123 115 124 - /* Stabs debugging sections. */ 125 - .stab 0 : { *(.stab) } 126 - .stabstr 0 : { *(.stabstr) } 127 - .stab.excl 0 : { *(.stab.excl) } 128 - .stab.exclstr 0 : { *(.stab.exclstr) } 129 - .stab.index 0 : { *(.stab.index) } 130 - .stab.indexstr 0 : { *(.stab.indexstr) } 131 - .comment 0 : { *(.comment) } 132 - /* DWARF debug sections. 133 - Symbols in the DWARF debugging section are relative to the beginning 134 - of the section so we begin .debug at 0. */ 135 - /* DWARF 1 */ 136 - .debug 0 : { *(.debug) } 137 - .line 0 : { *(.line) } 138 - /* GNU DWARF 1 extensions */ 139 - .debug_srcinfo 0 : { *(.debug_srcinfo) } 140 - .debug_sfnames 0 : { *(.debug_sfnames) } 141 - /* DWARF 1.1 and DWARF 2 */ 142 - .debug_aranges 0 : { *(.debug_aranges) } 143 - .debug_pubnames 0 : { *(.debug_pubnames) } 144 - /* DWARF 2 */ 145 - .debug_info 0 : { *(.debug_info) } 146 - .debug_abbrev 0 : { *(.debug_abbrev) } 147 - .debug_line 0 : { *(.debug_line) } 148 - .debug_frame 0 : { *(.debug_frame) } 149 - .debug_str 0 : { *(.debug_str) } 150 - .debug_loc 0 : { *(.debug_loc) } 151 - .debug_macinfo 0 : { *(.debug_macinfo) } 152 - /* SGI/MIPS DWARF 2 extensions */ 153 - .debug_weaknames 0 : { *(.debug_weaknames) } 154 - .debug_funcnames 0 : { *(.debug_funcnames) } 155 - .debug_typenames 0 : { *(.debug_typenames) } 156 - .debug_varnames 0 : { *(.debug_varnames) } 157 - /* These must appear regardless of . */ 116 + STABS_DEBUG 117 + 118 + DWARF_DEBUG 158 119 }
+61 -31
include/asm-sh/bug.h
··· 2 2 #define __ASM_SH_BUG_H 3 3 4 4 #ifdef CONFIG_BUG 5 - 6 - struct bug_frame { 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 *); 5 + #define HAVE_ARCH_BUG 6 + #define HAVE_ARCH_WARN_ON 16 7 17 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 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 38 #define BUG() \ 22 39 do { \ 23 40 __asm__ __volatile__ ( \ 24 - ".align 2\n\t" \ 25 - ".short %O0\n\t" \ 26 - ".short %O1\n\t" \ 27 - ".long %O2\n\t" \ 28 - ".long %O3\n\t" \ 29 - : \ 30 - : "n" (TRAPA_BUG_OPCODE), \ 31 - "i" (__LINE__), "X" (__FILE__), \ 32 - "X" (__FUNCTION__)); \ 41 + "1:\t.short %O0\n" \ 42 + _EMIT_BUG_ENTRY \ 43 + : \ 44 + : "n" (TRAPA_BUG_OPCODE), \ 45 + "i" (__FILE__), \ 46 + "i" (__LINE__), "i" (0), \ 47 + "i" (sizeof(struct bug_entry))); \ 33 48 } while (0) 34 49 35 - #else 36 - 37 - #define BUG() \ 38 - do { \ 39 - __asm__ __volatile__ ( \ 40 - ".align 2\n\t" \ 41 - ".short %O0\n\t" \ 42 - : \ 43 - : "n" (TRAPA_BUG_OPCODE)); \ 50 + #define __WARN() \ 51 + do { \ 52 + __asm__ __volatile__ ( \ 53 + "1:\t.short %O0\n" \ 54 + _EMIT_BUG_ENTRY \ 55 + : \ 56 + : "n" (TRAPA_BUG_OPCODE), \ 57 + "i" (__FILE__), \ 58 + "i" (__LINE__), \ 59 + "i" (BUGFLAG_WARNING), \ 60 + "i" (sizeof(struct bug_entry))); \ 44 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 80 #endif /* CONFIG_BUG */ 51 81