aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
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 /arch/i386/kernel/traps.c
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>
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r--arch/i386/kernel/traps.c41
1 files changed, 11 insertions, 30 deletions
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 ");