diff options
-rw-r--r-- | arch/i386/Kconfig | 5 | ||||
-rw-r--r-- | arch/i386/kernel/module.c | 4 | ||||
-rw-r--r-- | arch/i386/kernel/traps.c | 41 | ||||
-rw-r--r-- | arch/i386/kernel/vmlinux.lds.S | 2 | ||||
-rw-r--r-- | include/asm-i386/bug.h | 28 | ||||
-rw-r--r-- | lib/Kconfig.debug | 2 |
6 files changed, 42 insertions, 40 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index ea70359b02d0..c2362c7ba749 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -49,6 +49,11 @@ config GENERIC_IOMAP | |||
49 | bool | 49 | bool |
50 | default y | 50 | default y |
51 | 51 | ||
52 | config GENERIC_BUG | ||
53 | bool | ||
54 | default y | ||
55 | depends on BUG | ||
56 | |||
52 | config GENERIC_HWEIGHT | 57 | config GENERIC_HWEIGHT |
53 | bool | 58 | bool |
54 | default y | 59 | default y |
diff --git a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c index d7d9c8b23f72..3db0a5442eb1 100644 --- a/arch/i386/kernel/module.c +++ b/arch/i386/kernel/module.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/bug.h> | ||
24 | 25 | ||
25 | #if 0 | 26 | #if 0 |
26 | #define DEBUGP printk | 27 | #define DEBUGP printk |
@@ -141,10 +142,11 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
141 | apply_paravirt(pseg, pseg + para->sh_size); | 142 | apply_paravirt(pseg, pseg + para->sh_size); |
142 | } | 143 | } |
143 | 144 | ||
144 | return 0; | 145 | return module_bug_finalize(hdr, sechdrs, me); |
145 | } | 146 | } |
146 | 147 | ||
147 | void module_arch_cleanup(struct module *mod) | 148 | void module_arch_cleanup(struct module *mod) |
148 | { | 149 | { |
149 | alternatives_smp_module_del(mod); | 150 | alternatives_smp_module_del(mod); |
151 | module_bug_cleanup(mod); | ||
150 | } | 152 | } |
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 68de48e498ca..2b30dbf8d117 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/unwind.h> | 30 | #include <linux/unwind.h> |
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <linux/nmi.h> | 32 | #include <linux/nmi.h> |
33 | #include <linux/bug.h> | ||
33 | 34 | ||
34 | #ifdef CONFIG_EISA | 35 | #ifdef CONFIG_EISA |
35 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
@@ -420,43 +421,22 @@ void show_registers(struct pt_regs *regs) | |||
420 | printk("\n"); | 421 | printk("\n"); |
421 | } | 422 | } |
422 | 423 | ||
423 | static void handle_BUG(struct pt_regs *regs) | 424 | int is_valid_bugaddr(unsigned long eip) |
424 | { | 425 | { |
425 | unsigned long eip = regs->eip; | ||
426 | unsigned short ud2; | 426 | unsigned short ud2; |
427 | 427 | ||
428 | if (eip < PAGE_OFFSET) | 428 | if (eip < PAGE_OFFSET) |
429 | return; | 429 | return 0; |
430 | if (probe_kernel_address((unsigned short *)eip, ud2)) | 430 | if (probe_kernel_address((unsigned short *)eip, ud2)) |
431 | return; | 431 | return 0; |
432 | if (ud2 != 0x0b0f) | ||
433 | return; | ||
434 | |||
435 | printk(KERN_EMERG "------------[ cut here ]------------\n"); | ||
436 | |||
437 | #ifdef CONFIG_DEBUG_BUGVERBOSE | ||
438 | do { | ||
439 | unsigned short line; | ||
440 | char *file; | ||
441 | char c; | ||
442 | |||
443 | if (probe_kernel_address((unsigned short *)(eip + 2), line)) | ||
444 | break; | ||
445 | if (probe_kernel_address((char **)(eip + 4), file) || | ||
446 | (unsigned long)file < PAGE_OFFSET || | ||
447 | probe_kernel_address(file, c)) | ||
448 | file = "<bad filename>"; | ||
449 | 432 | ||
450 | printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); | 433 | return ud2 == 0x0b0f; |
451 | return; | ||
452 | } while (0); | ||
453 | #endif | ||
454 | printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n"); | ||
455 | } | 434 | } |
456 | 435 | ||
457 | /* This is gone through when something in the kernel | 436 | /* |
458 | * has done something bad and is about to be terminated. | 437 | * This is gone through when something in the kernel has done something bad and |
459 | */ | 438 | * is about to be terminated. |
439 | */ | ||
460 | void die(const char * str, struct pt_regs * regs, long err) | 440 | void die(const char * str, struct pt_regs * regs, long err) |
461 | { | 441 | { |
462 | static struct { | 442 | static struct { |
@@ -488,7 +468,8 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
488 | unsigned long esp; | 468 | unsigned long esp; |
489 | unsigned short ss; | 469 | unsigned short ss; |
490 | 470 | ||
491 | handle_BUG(regs); | 471 | report_bug(regs->eip); |
472 | |||
492 | printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); | 473 | printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); |
493 | #ifdef CONFIG_PREEMPT | 474 | #ifdef CONFIG_PREEMPT |
494 | printk(KERN_EMERG "PREEMPT "); | 475 | printk(KERN_EMERG "PREEMPT "); |
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 56e6ad5cb045..16d3c7133ad7 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S | |||
@@ -57,6 +57,8 @@ SECTIONS | |||
57 | 57 | ||
58 | RODATA | 58 | RODATA |
59 | 59 | ||
60 | BUG_TABLE | ||
61 | |||
60 | . = ALIGN(4); | 62 | . = ALIGN(4); |
61 | .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { | 63 | .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { |
62 | __tracedata_start = .; | 64 | __tracedata_start = .; |
diff --git a/include/asm-i386/bug.h b/include/asm-i386/bug.h index 8062cdbf2587..b0fd78ca2619 100644 --- a/include/asm-i386/bug.h +++ b/include/asm-i386/bug.h | |||
@@ -4,20 +4,32 @@ | |||
4 | 4 | ||
5 | /* | 5 | /* |
6 | * Tell the user there is some problem. | 6 | * Tell the user there is some problem. |
7 | * The offending file and line are encoded after the "officially | 7 | * The offending file and line are encoded encoded in the __bug_table section. |
8 | * undefined" opcode for parsing in the trap handler. | ||
9 | */ | 8 | */ |
10 | 9 | ||
11 | #ifdef CONFIG_BUG | 10 | #ifdef CONFIG_BUG |
12 | #define HAVE_ARCH_BUG | 11 | #define HAVE_ARCH_BUG |
12 | |||
13 | #ifdef CONFIG_DEBUG_BUGVERBOSE | 13 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
14 | #define BUG() \ | 14 | #define BUG() \ |
15 | __asm__ __volatile__( "ud2\n" \ | 15 | do { \ |
16 | "\t.word %c0\n" \ | 16 | asm volatile("1:\tud2\n" \ |
17 | "\t.long %c1\n" \ | 17 | ".pushsection __bug_table,\"a\"\n" \ |
18 | : : "i" (__LINE__), "i" (__FILE__)) | 18 | "2:\t.long 1b, %c0\n" \ |
19 | "\t.word %c1, 0\n" \ | ||
20 | "\t.org 2b+%c2\n" \ | ||
21 | ".popsection" \ | ||
22 | : : "i" (__FILE__), "i" (__LINE__), \ | ||
23 | "i" (sizeof(struct bug_entry))); \ | ||
24 | for(;;) ; \ | ||
25 | } while(0) | ||
26 | |||
19 | #else | 27 | #else |
20 | #define BUG() __asm__ __volatile__("ud2\n") | 28 | #define BUG() \ |
29 | do { \ | ||
30 | asm volatile("ud2"); \ | ||
31 | for(;;) ; \ | ||
32 | } while(0) | ||
21 | #endif | 33 | #endif |
22 | #endif | 34 | #endif |
23 | 35 | ||
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ee46fb335d24..2c133c098607 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -285,7 +285,7 @@ config DEBUG_HIGHMEM | |||
285 | config DEBUG_BUGVERBOSE | 285 | config DEBUG_BUGVERBOSE |
286 | bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED | 286 | bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED |
287 | depends on BUG | 287 | depends on BUG |
288 | depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH || GENERIC_BUG | 288 | depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG |
289 | default !EMBEDDED | 289 | default !EMBEDDED |
290 | help | 290 | help |
291 | Say Y here to make BUG() panics output the file name and line number | 291 | Say Y here to make BUG() panics output the file name and line number |