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

Commit 73c9ceab authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Paul Mackerras
Browse files

[POWERPC] Generic BUG for powerpc



This makes powerpc use the generic BUG machinery.  The biggest reports the
function name, since it is redundant with kallsyms, and not needed in general.

There is an overall reduction of code, since module_32/64 duplicated several
functions.

Unfortunately there's no way to tell gcc that BUG won't return, so the BUG
macro includes a goto loop.  This will generate a real jmp instruction, which
is never used.

[akpm@osdl.org: build fix]
[paulus@samba.org: remove infinite loop in BUG_ON]
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: 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 avatarPaul Mackerras <paulus@samba.org>
parent 973c1fab
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -99,6 +99,11 @@ config AUDIT_ARCH
	bool
	default y

config GENERIC_BUG
	bool
	default y
	depends on BUG

config DEFAULT_UIMAGE
	bool
	help
+6 −17
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/cache.h>
#include <linux/bug.h>

#include "setup.h"

@@ -290,23 +291,11 @@ int module_finalize(const Elf_Ehdr *hdr,
		    struct module *me)
{
	const Elf_Shdr *sect;
	int err;

	me->arch.bug_table = NULL;
	me->arch.num_bugs = 0;

	/* Find the __bug_table section, if present */
	sect = find_section(hdr, sechdrs, "__bug_table");
	if (sect != NULL) {
		me->arch.bug_table = (void *) sect->sh_addr;
		me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
	}

 	/*
	 * Strictly speaking this should have a spinlock to protect against
	 * traversals, but since we only traverse on BUG()s, a spinlock
	 * could potentially lead to deadlock and thus be counter-productive.
	 */
	list_add(&me->arch.bug_list, &module_bug_list);
	err = module_bug_finalize(hdr, sechdrs, me);
	if (err)		/* never true, currently */
		return err;

	/* Apply feature fixups */
	sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -320,7 +309,7 @@ int module_finalize(const Elf_Ehdr *hdr,

void module_arch_cleanup(struct module *mod)
{
	list_del(&mod->arch.bug_list);
	module_bug_cleanup(mod);
}

struct bug_entry *module_find_bug(unsigned long bugaddr)
+6 −17
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/moduleloader.h>
#include <linux/err.h>
#include <linux/vmalloc.h>
#include <linux/bug.h>
#include <asm/module.h>
#include <asm/uaccess.h>
#include <asm/firmware.h>
@@ -439,23 +440,11 @@ int module_finalize(const Elf_Ehdr *hdr,
		const Elf_Shdr *sechdrs, struct module *me)
{
	const Elf_Shdr *sect;
	int err;

	me->arch.bug_table = NULL;
	me->arch.num_bugs = 0;

	/* Find the __bug_table section, if present */
	sect = find_section(hdr, sechdrs, "__bug_table");
	if (sect != NULL) {
		me->arch.bug_table = (void *) sect->sh_addr;
		me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
	}

	/*
	 * Strictly speaking this should have a spinlock to protect against
	 * traversals, but since we only traverse on BUG()s, a spinlock
	 * could potentially lead to deadlock and thus be counter-productive.
	 */
	list_add(&me->arch.bug_list, &module_bug_list);
	err = module_bug_finalize(hdr, sechdrs, me);
	if (err)
		return err;

	/* Apply feature fixups */
	sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -475,7 +464,7 @@ int module_finalize(const Elf_Ehdr *hdr,

void module_arch_cleanup(struct module *mod)
{
	list_del(&mod->arch.bug_list);
	module_bug_cleanup(mod);
}

struct bug_entry *module_find_bug(unsigned long bugaddr)
+6 −48
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/kprobes.h>
#include <linux/kexec.h>
#include <linux/backlight.h>
#include <linux/bug.h>

#include <asm/kdebug.h>
#include <asm/pgtable.h>
@@ -727,54 +728,9 @@ static int emulate_instruction(struct pt_regs *regs)
	return -EINVAL;
}

/*
 * Look through the list of trap instructions that are used for BUG(),
 * BUG_ON() and WARN_ON() and see if we hit one.  At this point we know
 * that the exception was caused by a trap instruction of some kind.
 * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
 * otherwise.
 */
extern struct bug_entry __start___bug_table[], __stop___bug_table[];

#ifndef CONFIG_MODULES
#define module_find_bug(x)	NULL
#endif

struct bug_entry *find_bug(unsigned long bugaddr)
int is_valid_bugaddr(unsigned long addr)
{
	struct bug_entry *bug;

	for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
		if (bugaddr == bug->bug_addr)
			return bug;
	return module_find_bug(bugaddr);
}

static int check_bug_trap(struct pt_regs *regs)
{
	struct bug_entry *bug;
	unsigned long addr;

	if (regs->msr & MSR_PR)
		return 0;	/* not in kernel */
	addr = regs->nip;	/* address of trap instruction */
	if (addr < PAGE_OFFSET)
		return 0;
	bug = find_bug(regs->nip);
	if (bug == NULL)
		return 0;
	if (bug->line & BUG_WARNING_TRAP) {
		/* this is a WARN_ON rather than BUG/BUG_ON */
		printk(KERN_ERR "Badness in %s at %s:%ld\n",
		       bug->function, bug->file,
		       bug->line & ~BUG_WARNING_TRAP);
		dump_stack();
		return 1;
	}
	printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
	       bug->function, bug->file, bug->line);

	return 0;
	return is_kernel_addr(addr);
}

void __kprobes program_check_exception(struct pt_regs *regs)
@@ -810,7 +766,9 @@ void __kprobes program_check_exception(struct pt_regs *regs)
			return;
		if (debugger_bpt(regs))
			return;
		if (check_bug_trap(regs)) {

		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
		    report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
			regs->nip += 4;
			return;
		}
+1 −5
Original line number Diff line number Diff line
@@ -62,11 +62,7 @@ SECTIONS
		__stop___ex_table = .;
	}

	__bug_table : {
		__start___bug_table = .;
		*(__bug_table)
		__stop___bug_table = .;
	}
	BUG_TABLE

/*
 * Init sections discarded at runtime
Loading