Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -96,6 +96,11 @@ config AUDIT_ARCH
	bool
	default y

config GENERIC_BUG
	bool
	default y
	depends on BUG

source "init/Kconfig"


+4 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/bug.h>

#include <asm/system.h>
#include <asm/page.h>
@@ -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);
}
+12 −24
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/kexec.h>
#include <linux/unwind.h>
#include <linux/uaccess.h>
#include <linux/bug.h>

#include <asm/system.h>
#include <asm/io.h>
@@ -524,29 +525,14 @@ bad:
	printk("\n");
}	

void handle_BUG(struct pt_regs *regs)
int is_valid_bugaddr(unsigned long rip)
{
	struct bug_frame f;
	long len;
	const char *prefix = "";
	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
@@ -627,7 +613,9 @@ void die(const char * str, struct pt_regs * regs, long err)
{
	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); 
+2 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ SECTIONS

  RODATA

  BUG_TABLE

  . = ALIGN(PAGE_SIZE);        /* Align data segment to page size boundary */
				/* Data */
  .data : AT(ADDR(.data) - LOAD_OFFSET) {
+22 −22
Original line number Diff line number Diff line
#ifndef __ASM_X8664_BUG_H
#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
#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. */

#ifdef CONFIG_DEBUG_BUGVERBOSE
#define BUG()								\
	asm volatile(							\
	"ud2 ; pushq $%c1 ; ret $%c0" :: 				\
		     "i"(__LINE__), "i" (__FILE__))
	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) { }