diff options
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 56 |
1 files changed, 8 insertions, 48 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 0d4e203fa7a0..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 | /* | 731 | int 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 | */ | ||
| 737 | extern struct bug_entry __start___bug_table[], __stop___bug_table[]; | ||
| 738 | |||
| 739 | #ifndef CONFIG_MODULES | ||
| 740 | #define module_find_bug(x) NULL | ||
| 741 | #endif | ||
| 742 | |||
| 743 | struct 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 | |||
| 753 | static 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 | ||
| 780 | void __kprobes program_check_exception(struct pt_regs *regs) | 736 | void __kprobes program_check_exception(struct pt_regs *regs) |
| @@ -782,6 +738,8 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
| 782 | unsigned int reason = get_reason(regs); | 738 | unsigned int reason = get_reason(regs); |
| 783 | extern int do_mathemu(struct pt_regs *regs); | 739 | extern int do_mathemu(struct pt_regs *regs); |
| 784 | 740 | ||
| 741 | /* We can now get here via a FP Unavailable exception if the core | ||
| 742 | * has no FPU, in that case no reason flags will be set */ | ||
| 785 | #ifdef CONFIG_MATH_EMULATION | 743 | #ifdef CONFIG_MATH_EMULATION |
| 786 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, | 744 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, |
| 787 | * but there seems to be a hardware bug on the 405GP (RevD) | 745 | * but there seems to be a hardware bug on the 405GP (RevD) |
| @@ -808,7 +766,9 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
| 808 | return; | 766 | return; |
| 809 | if (debugger_bpt(regs)) | 767 | if (debugger_bpt(regs)) |
| 810 | return; | 768 | return; |
| 811 | if (check_bug_trap(regs)) { | 769 | |
| 770 | if (!(regs->msr & MSR_PR) && /* not user-mode */ | ||
| 771 | report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) { | ||
| 812 | regs->nip += 4; | 772 | regs->nip += 4; |
| 813 | return; | 773 | return; |
| 814 | } | 774 | } |
