Commit c31a0bf3 authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Linus Torvalds

[PATCH] Generic BUG for x86-64

This makes x86-64 use the generic BUG machinery.

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: default avatarJeremy 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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 91768d6c
...@@ -96,6 +96,11 @@ config AUDIT_ARCH ...@@ -96,6 +96,11 @@ config AUDIT_ARCH
bool bool
default y default y
config GENERIC_BUG
bool
default y
depends on BUG
source "init/Kconfig" source "init/Kconfig"
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/bug.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -173,10 +174,12 @@ int module_finalize(const Elf_Ehdr *hdr, ...@@ -173,10 +174,12 @@ int module_finalize(const Elf_Ehdr *hdr,
lseg, lseg + locks->sh_size, lseg, lseg + locks->sh_size,
tseg, tseg + text->sh_size); tseg, tseg + text->sh_size);
} }
return 0;
return module_bug_finalize(hdr, sechdrs, me);
} }
void module_arch_cleanup(struct module *mod) void module_arch_cleanup(struct module *mod)
{ {
alternatives_smp_module_del(mod); alternatives_smp_module_del(mod);
module_bug_cleanup(mod);
} }
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/unwind.h> #include <linux/unwind.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/bug.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -524,29 +525,14 @@ bad: ...@@ -524,29 +525,14 @@ bad:
printk("\n"); printk("\n");
} }
void handle_BUG(struct pt_regs *regs) int is_valid_bugaddr(unsigned long rip)
{ {
struct bug_frame f; unsigned short ud2;
long len;
const char *prefix = "";
if (user_mode(regs)) if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2)))
return; return 0;
if (__copy_from_user(&f, (const void __user *) regs->rip,
sizeof(struct bug_frame))) return ud2 == 0x0b0f;
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);
} }
#ifdef CONFIG_BUG #ifdef CONFIG_BUG
...@@ -627,7 +613,9 @@ void die(const char * str, struct pt_regs * regs, long err) ...@@ -627,7 +613,9 @@ void die(const char * str, struct pt_regs * regs, long err)
{ {
unsigned long flags = oops_begin(); unsigned long flags = oops_begin();
handle_BUG(regs); if (!user_mode(regs))
report_bug(regs->rip);
__die(str, regs, err); __die(str, regs, err);
oops_end(flags); oops_end(flags);
do_exit(SIGSEGV); do_exit(SIGSEGV);
......
...@@ -51,6 +51,8 @@ SECTIONS ...@@ -51,6 +51,8 @@ SECTIONS
RODATA RODATA
BUG_TABLE
. = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */
/* Data */ /* Data */
.data : AT(ADDR(.data) - LOAD_OFFSET) { .data : AT(ADDR(.data) - LOAD_OFFSET) {
......
#ifndef __ASM_X8664_BUG_H #ifndef __ASM_X8664_BUG_H
#define __ASM_X8664_BUG_H 1 #define __ASM_X8664_BUG_H 1
#include <linux/stringify.h>
/*
* 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 #ifdef CONFIG_BUG
#define HAVE_ARCH_BUG #define HAVE_ARCH_BUG
/* We turn the bug frame into valid instructions to not confuse
the disassembler. Thanks to Jan Beulich & Suresh Siddha #ifdef CONFIG_DEBUG_BUGVERBOSE
for nice instruction selection.
The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
#define BUG() \ #define BUG() \
asm volatile( \ do { \
"ud2 ; pushq $%c1 ; ret $%c0" :: \ asm volatile("1:\tud2\n" \
"i"(__LINE__), "i" (__FILE__)) ".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); void out_of_line_bug(void);
#else #else
static inline void out_of_line_bug(void) { } static inline void out_of_line_bug(void) { }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment