Skip to content

Commit

Permalink
[PATCH] Generic BUG for i386
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jeremy Fitzhardinge authored and Linus Torvalds committed Dec 8, 2006
1 parent 7664c5a commit 91768d6
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 40 deletions.
5 changes: 5 additions & 0 deletions arch/i386/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ config GENERIC_IOMAP
bool
default y

config GENERIC_BUG
bool
default y
depends on BUG

config GENERIC_HWEIGHT
bool
default y
Expand Down
4 changes: 3 additions & 1 deletion arch/i386/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/bug.h>

#if 0
#define DEBUGP printk
Expand Down Expand Up @@ -141,10 +142,11 @@ int module_finalize(const Elf_Ehdr *hdr,
apply_paravirt(pseg, pseg + para->sh_size);
}

return 0;
return module_bug_finalize(hdr, sechdrs, me);
}

void module_arch_cleanup(struct module *mod)
{
alternatives_smp_module_del(mod);
module_bug_cleanup(mod);
}
41 changes: 11 additions & 30 deletions arch/i386/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <linux/unwind.h>
#include <linux/uaccess.h>
#include <linux/nmi.h>
#include <linux/bug.h>

#ifdef CONFIG_EISA
#include <linux/ioport.h>
Expand Down Expand Up @@ -420,43 +421,22 @@ void show_registers(struct pt_regs *regs)
printk("\n");
}

static void handle_BUG(struct pt_regs *regs)
int is_valid_bugaddr(unsigned long eip)
{
unsigned long eip = regs->eip;
unsigned short ud2;

if (eip < PAGE_OFFSET)
return;
return 0;
if (probe_kernel_address((unsigned short *)eip, ud2))
return;
if (ud2 != 0x0b0f)
return;

printk(KERN_EMERG "------------[ cut here ]------------\n");

#ifdef CONFIG_DEBUG_BUGVERBOSE
do {
unsigned short line;
char *file;
char c;

if (probe_kernel_address((unsigned short *)(eip + 2), line))
break;
if (probe_kernel_address((char **)(eip + 4), file) ||
(unsigned long)file < PAGE_OFFSET ||
probe_kernel_address(file, c))
file = "<bad filename>";
return 0;

printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
return;
} while (0);
#endif
printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n");
return ud2 == 0x0b0f;
}

/* This is gone through when something in the kernel
* has done something bad and is about to be terminated.
*/
/*
* This is gone through when something in the kernel has done something bad and
* is about to be terminated.
*/
void die(const char * str, struct pt_regs * regs, long err)
{
static struct {
Expand Down Expand Up @@ -488,7 +468,8 @@ void die(const char * str, struct pt_regs * regs, long err)
unsigned long esp;
unsigned short ss;

handle_BUG(regs);
report_bug(regs->eip);

printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
printk(KERN_EMERG "PREEMPT ");
Expand Down
2 changes: 2 additions & 0 deletions arch/i386/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ SECTIONS

RODATA

BUG_TABLE

. = ALIGN(4);
.tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
__tracedata_start = .;
Expand Down
28 changes: 20 additions & 8 deletions include/asm-i386/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,32 @@

/*
* Tell the user there is some problem.
* The offending file and line are encoded after the "officially
* undefined" opcode for parsing in the trap handler.
* The offending file and line are encoded encoded in the __bug_table section.
*/

#ifdef CONFIG_BUG
#define HAVE_ARCH_BUG

#ifdef CONFIG_DEBUG_BUGVERBOSE
#define BUG() \
__asm__ __volatile__( "ud2\n" \
"\t.word %c0\n" \
"\t.long %c1\n" \
: : "i" (__LINE__), "i" (__FILE__))
#define BUG() \
do { \
asm volatile("1:\tud2\n" \
".pushsection __bug_table,\"a\"\n" \
"2:\t.long 1b, %c0\n" \
"\t.word %c1, 0\n" \
"\t.org 2b+%c2\n" \
".popsection" \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (sizeof(struct bug_entry))); \
for(;;) ; \
} while(0)

#else
#define BUG() __asm__ __volatile__("ud2\n")
#define BUG() \
do { \
asm volatile("ud2"); \
for(;;) ; \
} while(0)
#endif
#endif

Expand Down
2 changes: 1 addition & 1 deletion lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ config DEBUG_HIGHMEM
config DEBUG_BUGVERBOSE
bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
depends on BUG
depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH || GENERIC_BUG
depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG
default !EMBEDDED
help
Say Y here to make BUG() panics output the file name and line number
Expand Down

0 comments on commit 91768d6

Please sign in to comment.