Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 44247
b: refs/heads/master
c: 73c9cea
h: refs/heads/master
i:
  44245: 611bea0
  44243: 5338519
  44239: 596e8c6
v: v3
  • Loading branch information
Jeremy Fitzhardinge authored and Paul Mackerras committed Dec 11, 2006
1 parent 86f8883 commit 0367501
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 135 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 973c1fabc70deb10f12a0eaab2f50c2263784257
refs/heads/master: 73c9ceab40b1269d6195e556773167c078ac8311
5 changes: 5 additions & 0 deletions trunk/arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ config AUDIT_ARCH
bool
default y

config GENERIC_BUG
bool
default y
depends on BUG

config DEFAULT_UIMAGE
bool
help
Expand Down
23 changes: 6 additions & 17 deletions trunk/arch/powerpc/kernel/module_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/cache.h>
#include <linux/bug.h>

#include "setup.h"

Expand Down Expand Up @@ -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");
Expand All @@ -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)
Expand Down
23 changes: 6 additions & 17 deletions trunk/arch/powerpc/kernel/module_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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");
Expand All @@ -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)
Expand Down
54 changes: 6 additions & 48 deletions trunk/arch/powerpc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 1 addition & 5 deletions trunk/arch/powerpc/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions trunk/arch/powerpc/xmon/xmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/sysrq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/bug.h>

#include <asm/ptrace.h>
#include <asm/string.h>
Expand All @@ -35,7 +36,6 @@
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/sstep.h>
#include <asm/bug.h>
#include <asm/irq_regs.h>
#include <asm/spu.h>
#include <asm/spu_priv1.h>
Expand Down Expand Up @@ -1346,7 +1346,7 @@ static void backtrace(struct pt_regs *excp)

static void print_bug_trap(struct pt_regs *regs)
{
struct bug_entry *bug;
const struct bug_entry *bug;
unsigned long addr;

if (regs->msr & MSR_PR)
Expand All @@ -1357,11 +1357,11 @@ static void print_bug_trap(struct pt_regs *regs)
bug = find_bug(regs->nip);
if (bug == NULL)
return;
if (bug->line & BUG_WARNING_TRAP)
if (is_warning_bug(bug))
return;

printf("kernel BUG in %s at %s:%d!\n",
bug->function, bug->file, (unsigned int)bug->line);
printf("kernel BUG at %s:%u!\n",
bug->file, bug->line);
}

void excprint(struct pt_regs *fp)
Expand Down
80 changes: 40 additions & 40 deletions trunk/include/asm-powerpc/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,39 @@

#ifndef __ASSEMBLY__

struct bug_entry {
unsigned long bug_addr;
long line;
const char *file;
const char *function;
};

struct bug_entry *find_bug(unsigned long bugaddr);

/*
* If this bit is set in the line number it means that the trap
* is for WARN_ON rather than BUG or BUG_ON.
*/
#define BUG_WARNING_TRAP 0x1000000

#ifdef CONFIG_BUG

/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
sizeof(struct bug_entry), respectively */
#ifdef CONFIG_DEBUG_BUGVERBOSE
#define _EMIT_BUG_ENTRY \
".section __bug_table,\"a\"\n" \
"2:\t" PPC_LONG "1b, %0\n" \
"\t.short %1, %2\n" \
".org 2b+%3\n" \
".previous\n"
#else
#define _EMIT_BUG_ENTRY \
".section __bug_table,\"a\"\n" \
"2:\t" PPC_LONG "1b\n" \
"\t.short %2\n" \
".org 2b+%3\n" \
".previous\n"
#endif

/*
* BUG_ON() and WARN_ON() do their best to cooperate with compile-time
* optimisations. However depending on the complexity of the condition
* some compiler versions may not produce optimal results.
*/

#define BUG() do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%0,%1,%2\n" \
".previous" \
: : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
#define BUG() do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
_EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (0), "i" (sizeof(struct bug_entry))); \
for(;;) ; \
} while (0)

#define BUG_ON(x) do { \
Expand All @@ -51,23 +54,21 @@ struct bug_entry *find_bug(unsigned long bugaddr);
BUG(); \
} else { \
__asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" ((long)(x)), "i" (__LINE__), \
"i" (__FILE__), "i" (__FUNCTION__)); \
"1: "PPC_TLNEI" %4,0\n" \
_EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), "i" (0), \
"i" (sizeof(struct bug_entry)), \
"r" ((long)(x))); \
} \
} while (0)

#define __WARN() do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%0,%1,%2\n" \
".previous" \
: : "i" (__LINE__ + BUG_WARNING_TRAP), \
"i" (__FILE__), "i" (__FUNCTION__)); \
_EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \
"i" (sizeof(struct bug_entry))); \
} while (0)

#define WARN_ON(x) ({ \
Expand All @@ -77,13 +78,12 @@ struct bug_entry *find_bug(unsigned long bugaddr);
__WARN(); \
} else { \
__asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" (__ret_warn_on), \
"i" (__LINE__ + BUG_WARNING_TRAP), \
"i" (__FILE__), "i" (__FUNCTION__)); \
"1: "PPC_TLNEI" %4,0\n" \
_EMIT_BUG_ENTRY \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING), \
"i" (sizeof(struct bug_entry)), \
"r" (__ret_warn_on)); \
} \
unlikely(__ret_warn_on); \
})
Expand Down
2 changes: 0 additions & 2 deletions trunk/include/asm-powerpc/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ struct mod_arch_specific {
unsigned int num_bugs;
};

extern struct bug_entry *module_find_bug(unsigned long bugaddr);

/*
* Select ELF headers.
* Make empty section for module_frob_arch_sections to expand.
Expand Down

0 comments on commit 0367501

Please sign in to comment.