aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2006-12-08 06:30:41 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-11 00:35:07 -0500
commit73c9ceab40b1269d6195e556773167c078ac8311 (patch)
treed1de1c286b58a8b1e8dcd0e690ac6e8724e990f5 /arch/powerpc/kernel
parent973c1fabc70deb10f12a0eaab2f50c2263784257 (diff)
[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: 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: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
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