diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2006-12-08 05:36:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:39 -0500 |
commit | 91768d6c2bad0d2766a166f13f2f57e197de3458 (patch) | |
tree | 3857842d8635b2032c84c5e2e1b05181cd48ca65 /arch | |
parent | 7664c5a1da4711bb6383117f51b94c8dc8f3f1cd (diff) |
[PATCH] Generic BUG for i386
This makes i386 use the generic BUG machinery. There are no functional
changes from the old i386 implementation.
The main advantage in using the generic BUG machinery for i386 is that the
inlined overhead of BUG is just the ud2a instruction; the file+line(+function)
information are no longer inlined into the instruction stream. This reduces
cache pollution, and makes disassembly work properly.
Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Andi Kleen <ak@muc.de>
Cc: Hugh Dickens <hugh@veritas.com>
Cc: Michael Ellerman <michael@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-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 |
4 files changed, 21 insertions, 31 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 = .; |