aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/module_32.c23
-rw-r--r--arch/powerpc/kernel/module_64.c23
-rw-r--r--arch/powerpc/kernel/traps.c54
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S6
4 files changed, 19 insertions, 87 deletions
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index e2c3c6a85f33..8339fd609de0 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -23,6 +23,7 @@
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/cache.h> 25#include <linux/cache.h>
26#include <linux/bug.h>
26 27
27#include "setup.h" 28#include "setup.h"
28 29
@@ -290,23 +291,11 @@ int module_finalize(const Elf_Ehdr *hdr,
290 struct module *me) 291 struct module *me)
291{ 292{
292 const Elf_Shdr *sect; 293 const Elf_Shdr *sect;
294 int err;
293 295
294 me->arch.bug_table = NULL; 296 err = module_bug_finalize(hdr, sechdrs, me);
295 me->arch.num_bugs = 0; 297 if (err) /* never true, currently */
296 298 return err;
297 /* Find the __bug_table section, if present */
298 sect = find_section(hdr, sechdrs, "__bug_table");
299 if (sect != NULL) {
300 me->arch.bug_table = (void *) sect->sh_addr;
301 me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
302 }
303
304 /*
305 * Strictly speaking this should have a spinlock to protect against
306 * traversals, but since we only traverse on BUG()s, a spinlock
307 * could potentially lead to deadlock and thus be counter-productive.
308 */
309 list_add(&me->arch.bug_list, &module_bug_list);
310 299
311 /* Apply feature fixups */ 300 /* Apply feature fixups */
312 sect = find_section(hdr, sechdrs, "__ftr_fixup"); 301 sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -320,7 +309,7 @@ int module_finalize(const Elf_Ehdr *hdr,
320 309
321void module_arch_cleanup(struct module *mod) 310void module_arch_cleanup(struct module *mod)
322{ 311{
323 list_del(&mod->arch.bug_list); 312 module_bug_cleanup(mod);
324} 313}
325 314
326struct bug_entry *module_find_bug(unsigned long bugaddr) 315struct bug_entry *module_find_bug(unsigned long bugaddr)
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 8dd1f0aae5d6..75c7c4f19280 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -20,6 +20,7 @@
20#include <linux/moduleloader.h> 20#include <linux/moduleloader.h>
21#include <linux/err.h> 21#include <linux/err.h>
22#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
23#include <linux/bug.h>
23#include <asm/module.h> 24#include <asm/module.h>
24#include <asm/uaccess.h> 25#include <asm/uaccess.h>
25#include <asm/firmware.h> 26#include <asm/firmware.h>
@@ -439,23 +440,11 @@ int module_finalize(const Elf_Ehdr *hdr,
439 const Elf_Shdr *sechdrs, struct module *me) 440 const Elf_Shdr *sechdrs, struct module *me)
440{ 441{
441 const Elf_Shdr *sect; 442 const Elf_Shdr *sect;
443 int err;
442 444
443 me->arch.bug_table = NULL; 445 err = module_bug_finalize(hdr, sechdrs, me);
444 me->arch.num_bugs = 0; 446 if (err)
445 447 return err;
446 /* Find the __bug_table section, if present */
447 sect = find_section(hdr, sechdrs, "__bug_table");
448 if (sect != NULL) {
449 me->arch.bug_table = (void *) sect->sh_addr;
450 me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
451 }
452
453 /*
454 * Strictly speaking this should have a spinlock to protect against
455 * traversals, but since we only traverse on BUG()s, a spinlock
456 * could potentially lead to deadlock and thus be counter-productive.
457 */
458 list_add(&me->arch.bug_list, &module_bug_list);
459 448
460 /* Apply feature fixups */ 449 /* Apply feature fixups */
461 sect = find_section(hdr, sechdrs, "__ftr_fixup"); 450 sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -475,7 +464,7 @@ int module_finalize(const Elf_Ehdr *hdr,
475 464
476void module_arch_cleanup(struct module *mod) 465void module_arch_cleanup(struct module *mod)
477{ 466{
478 list_del(&mod->arch.bug_list); 467 module_bug_cleanup(mod);
479} 468}
480 469
481struct bug_entry *module_find_bug(unsigned long bugaddr) 470struct bug_entry *module_find_bug(unsigned long bugaddr)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index fde820e52d03..535f50665647 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -32,6 +32,7 @@
32#include <linux/kprobes.h> 32#include <linux/kprobes.h>
33#include <linux/kexec.h> 33#include <linux/kexec.h>
34#include <linux/backlight.h> 34#include <linux/backlight.h>
35#include <linux/bug.h>
35 36
36#include <asm/kdebug.h> 37#include <asm/kdebug.h>
37#include <asm/pgtable.h> 38#include <asm/pgtable.h>
@@ -727,54 +728,9 @@ static int emulate_instruction(struct pt_regs *regs)
727 return -EINVAL; 728 return -EINVAL;
728} 729}
729 730
730/* 731int is_valid_bugaddr(unsigned long addr)
731 * Look through the list of trap instructions that are used for BUG(),
732 * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
733 * that the exception was caused by a trap instruction of some kind.
734 * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
735 * otherwise.
736 */
737extern struct bug_entry __start___bug_table[], __stop___bug_table[];
738
739#ifndef CONFIG_MODULES
740#define module_find_bug(x) NULL
741#endif
742
743struct bug_entry *find_bug(unsigned long bugaddr)
744{ 732{
745 struct bug_entry *bug; 733 return is_kernel_addr(addr);
746
747 for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
748 if (bugaddr == bug->bug_addr)
749 return bug;
750 return module_find_bug(bugaddr);
751}
752
753static int check_bug_trap(struct pt_regs *regs)
754{
755 struct bug_entry *bug;
756 unsigned long addr;
757
758 if (regs->msr & MSR_PR)
759 return 0; /* not in kernel */
760 addr = regs->nip; /* address of trap instruction */
761 if (addr < PAGE_OFFSET)
762 return 0;
763 bug = find_bug(regs->nip);
764 if (bug == NULL)
765 return 0;
766 if (bug->line & BUG_WARNING_TRAP) {
767 /* this is a WARN_ON rather than BUG/BUG_ON */
768 printk(KERN_ERR "Badness in %s at %s:%ld\n",
769 bug->function, bug->file,
770 bug->line & ~BUG_WARNING_TRAP);
771 dump_stack();
772 return 1;
773 }
774 printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
775 bug->function, bug->file, bug->line);
776
777 return 0;
778} 734}
779 735
780void __kprobes program_check_exception(struct pt_regs *regs) 736void __kprobes program_check_exception(struct pt_regs *regs)
@@ -810,7 +766,9 @@ void __kprobes program_check_exception(struct pt_regs *regs)
810 return; 766 return;
811 if (debugger_bpt(regs)) 767 if (debugger_bpt(regs))
812 return; 768 return;
813 if (check_bug_trap(regs)) { 769
770 if (!(regs->msr & MSR_PR) && /* not user-mode */
771 report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
814 regs->nip += 4; 772 regs->nip += 4;
815 return; 773 return;
816 } 774 }
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 04b98671a060..04b8e71bf5b0 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -62,11 +62,7 @@ SECTIONS
62 __stop___ex_table = .; 62 __stop___ex_table = .;
63 } 63 }
64 64
65 __bug_table : { 65 BUG_TABLE
66 __start___bug_table = .;
67 *(__bug_table)
68 __stop___bug_table = .;
69 }
70 66
71/* 67/*
72 * Init sections discarded at runtime 68 * Init sections discarded at runtime