From: Jeremy Fitzhardinge This makes x86-64 use the generic BUG machinery. The most significant The main advantage in using the generic BUG machinery for x86-64 is that the inlined overhead of BUG is just the ud2a instruction; the file+line information are no longer inlined into the instruction stream. This reduces cache pollution. Signed-off-by: Jeremy Fitzhardinge Cc: Andi Kleen Cc: Hugh Dickens Cc: Michael Ellerman Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Rusty Russell Signed-off-by: Andrew Morton --- arch/x86_64/Kconfig | 5 +++ arch/x86_64/kernel/module.c | 5 ++- arch/x86_64/kernel/traps.c | 36 +++++++---------------- arch/x86_64/kernel/vmlinux.lds.S | 2 + include/asm-x86_64/bug.h | 44 ++++++++++++++--------------- 5 files changed, 45 insertions(+), 47 deletions(-) diff -puN arch/x86_64/Kconfig~generic-bug-for-x86-64 arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig~generic-bug-for-x86-64 +++ a/arch/x86_64/Kconfig @@ -100,6 +100,11 @@ config AUDIT_ARCH bool default y +config GENERIC_BUG + bool + default y + depends on BUG + source "init/Kconfig" diff -puN arch/x86_64/kernel/module.c~generic-bug-for-x86-64 arch/x86_64/kernel/module.c --- a/arch/x86_64/kernel/module.c~generic-bug-for-x86-64 +++ a/arch/x86_64/kernel/module.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -173,10 +174,12 @@ int module_finalize(const Elf_Ehdr *hdr, lseg, lseg + locks->sh_size, tseg, tseg + text->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); } diff -puN arch/x86_64/kernel/traps.c~generic-bug-for-x86-64 arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c~generic-bug-for-x86-64 +++ a/arch/x86_64/kernel/traps.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -525,30 +526,15 @@ bad: printk("\n"); } -void handle_BUG(struct pt_regs *regs) -{ - struct bug_frame f; - long len; - const char *prefix = ""; +int is_valid_bugaddr(unsigned long rip) +{ + unsigned short ud2; - if (user_mode(regs)) - return; - if (__copy_from_user(&f, (const void __user *) regs->rip, - sizeof(struct bug_frame))) - return; - if (f.filename >= 0 || - f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) - return; - len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1; - if (len < 0 || len >= PATH_MAX) - f.filename = (int)(long)"unmapped filename"; - else if (len > 50) { - f.filename += len - 50; - prefix = "..."; - } - printk("----------- [cut here ] --------- [please bite here ] ---------\n"); - printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line); -} + if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2))) + return 0; + + return ud2 == 0x0b0f; +} #ifdef CONFIG_BUG void out_of_line_bug(void) @@ -629,7 +615,9 @@ void die(const char * str, struct pt_reg { unsigned long flags = oops_begin(); - handle_BUG(regs); + if (!user_mode(regs)) + report_bug(regs->rip); + __die(str, regs, err); oops_end(flags); do_exit(SIGSEGV); diff -puN arch/x86_64/kernel/vmlinux.lds.S~generic-bug-for-x86-64 arch/x86_64/kernel/vmlinux.lds.S --- a/arch/x86_64/kernel/vmlinux.lds.S~generic-bug-for-x86-64 +++ a/arch/x86_64/kernel/vmlinux.lds.S @@ -51,6 +51,8 @@ SECTIONS RODATA + BUG_TABLE + #ifdef CONFIG_STACK_UNWIND . = ALIGN(8); .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { diff -puN include/asm-x86_64/bug.h~generic-bug-for-x86-64 include/asm-x86_64/bug.h --- a/include/asm-x86_64/bug.h~generic-bug-for-x86-64 +++ a/include/asm-x86_64/bug.h @@ -1,30 +1,30 @@ #ifndef __ASM_X8664_BUG_H #define __ASM_X8664_BUG_H 1 -#include - -/* - * Tell the user there is some problem. The exception handler decodes - * this frame. - */ -struct bug_frame { - unsigned char ud2[2]; - unsigned char push; - signed int filename; - unsigned char ret; - unsigned short line; -} __attribute__((packed)); - #ifdef CONFIG_BUG #define HAVE_ARCH_BUG -/* We turn the bug frame into valid instructions to not confuse - the disassembler. Thanks to Jan Beulich & Suresh Siddha - for nice instruction selection. - The magic numbers generate mov $64bitimm,%eax ; ret $offset. */ -#define BUG() \ - asm volatile( \ - "ud2 ; pushq $%c1 ; ret $%c0" :: \ - "i"(__LINE__), "i" (__FILE__)) + +#ifdef CONFIG_DEBUG_BUGVERBOSE +#define BUG() \ + do { \ + asm volatile("1:\tud2\n" \ + ".pushsection __bug_table,\"a\"\n" \ + "2:\t.quad 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() \ + do { \ + asm volatile("ud2"); \ + for(;;) ; \ + } while(0) +#endif + void out_of_line_bug(void); #else static inline void out_of_line_bug(void) { } _