mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
[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: 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>
This commit is contained in:
parent
91768d6c2b
commit
c31a0bf3e1
5 changed files with 45 additions and 47 deletions
|
@ -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 @@
|
||||||
#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,
|
||||||
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 @@
|
||||||
#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 @@ void show_registers(struct pt_regs *regs)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
#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.
|
#define BUG() \
|
||||||
The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
|
do { \
|
||||||
#define BUG() \
|
asm volatile("1:\tud2\n" \
|
||||||
asm volatile( \
|
".pushsection __bug_table,\"a\"\n" \
|
||||||
"ud2 ; pushq $%c1 ; ret $%c0" :: \
|
"2:\t.quad 1b, %c0\n" \
|
||||||
"i"(__LINE__), "i" (__FILE__))
|
"\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) { }
|
||||||
|
|
Loading…
Reference in a new issue