aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2006-12-08 05:36:21 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 11:28:39 -0500
commit91768d6c2bad0d2766a166f13f2f57e197de3458 (patch)
tree3857842d8635b2032c84c5e2e1b05181cd48ca65
parent7664c5a1da4711bb6383117f51b94c8dc8f3f1cd (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>
-rw-r--r--arch/i386/Kconfig5
-rw-r--r--arch/i386/kernel/module.c4
-rw-r--r--arch/i386/kernel/traps.c41
-rw-r--r--arch/i386/kernel/vmlinux.lds.S2
-rw-r--r--include/asm-i386/bug.h28
-rw-r--r--lib/Kconfig.debug2
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
52config GENERIC_BUG
53 bool
54 default y
55 depends on BUG
56
52config GENERIC_HWEIGHT 57config 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
147void module_arch_cleanup(struct module *mod) 148void 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
423static void handle_BUG(struct pt_regs *regs) 424int 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 */
460void die(const char * str, struct pt_regs * regs, long err) 440void 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
285config DEBUG_BUGVERBOSE 285config 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