aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/kernel/traps.c')
-rw-r--r--arch/ppc/kernel/traps.c84
1 files changed, 17 insertions, 67 deletions
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index aafc8e8893d1..810f7aa72e92 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -28,6 +28,7 @@
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/prctl.h> 30#include <linux/prctl.h>
31#include <linux/bug.h>
31 32
32#include <asm/pgtable.h> 33#include <asm/pgtable.h>
33#include <asm/uaccess.h> 34#include <asm/uaccess.h>
@@ -316,7 +317,7 @@ void machine_check_exception(struct pt_regs *regs)
316 if (reason & MCSR_BUS_RBERR) 317 if (reason & MCSR_BUS_RBERR)
317 printk("Bus - Read Data Bus Error\n"); 318 printk("Bus - Read Data Bus Error\n");
318 if (reason & MCSR_BUS_WBERR) 319 if (reason & MCSR_BUS_WBERR)
319 printk("Bus - Read Data Bus Error\n"); 320 printk("Bus - Write Data Bus Error\n");
320 if (reason & MCSR_BUS_IPERR) 321 if (reason & MCSR_BUS_IPERR)
321 printk("Bus - Instruction Parity Error\n"); 322 printk("Bus - Instruction Parity Error\n");
322 if (reason & MCSR_BUS_RPERR) 323 if (reason & MCSR_BUS_RPERR)
@@ -559,64 +560,9 @@ static void emulate_single_step(struct pt_regs *regs)
559 } 560 }
560} 561}
561 562
562/* 563int is_valid_bugaddr(unsigned long addr)
563 * Look through the list of trap instructions that are used for BUG(),
564 * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
565 * that the exception was caused by a trap instruction of some kind.
566 * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
567 * otherwise.
568 */
569extern struct bug_entry __start___bug_table[], __stop___bug_table[];
570
571#ifndef CONFIG_MODULES
572#define module_find_bug(x) NULL
573#endif
574
575struct bug_entry *find_bug(unsigned long bugaddr)
576{ 564{
577 struct bug_entry *bug; 565 return addr >= PAGE_OFFSET;
578
579 for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
580 if (bugaddr == bug->bug_addr)
581 return bug;
582 return module_find_bug(bugaddr);
583}
584
585int check_bug_trap(struct pt_regs *regs)
586{
587 struct bug_entry *bug;
588 unsigned long addr;
589
590 if (regs->msr & MSR_PR)
591 return 0; /* not in kernel */
592 addr = regs->nip; /* address of trap instruction */
593 if (addr < PAGE_OFFSET)
594 return 0;
595 bug = find_bug(regs->nip);
596 if (bug == NULL)
597 return 0;
598 if (bug->line & BUG_WARNING_TRAP) {
599 /* this is a WARN_ON rather than BUG/BUG_ON */
600#ifdef CONFIG_XMON
601 xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n",
602 bug->function, bug->file,
603 bug->line & ~BUG_WARNING_TRAP);
604#endif /* CONFIG_XMON */
605 printk(KERN_ERR "Badness in %s at %s:%ld\n",
606 bug->function, bug->file,
607 bug->line & ~BUG_WARNING_TRAP);
608 dump_stack();
609 return 1;
610 }
611#ifdef CONFIG_XMON
612 xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
613 bug->function, bug->file, bug->line);
614 xmon(regs);
615#endif /* CONFIG_XMON */
616 printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
617 bug->function, bug->file, bug->line);
618
619 return 0;
620} 566}
621 567
622void program_check_exception(struct pt_regs *regs) 568void program_check_exception(struct pt_regs *regs)
@@ -671,7 +617,9 @@ void program_check_exception(struct pt_regs *regs)
671 /* trap exception */ 617 /* trap exception */
672 if (debugger_bpt(regs)) 618 if (debugger_bpt(regs))
673 return; 619 return;
674 if (check_bug_trap(regs)) { 620
621 if (!(regs->msr & MSR_PR) && /* not user-mode */
622 report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
675 regs->nip += 4; 623 regs->nip += 4;
676 return; 624 return;
677 } 625 }
@@ -708,7 +656,7 @@ void single_step_exception(struct pt_regs *regs)
708 656
709void alignment_exception(struct pt_regs *regs) 657void alignment_exception(struct pt_regs *regs)
710{ 658{
711 int fixed; 659 int sig, code, fixed = 0;
712 660
713 fixed = fix_alignment(regs); 661 fixed = fix_alignment(regs);
714 if (fixed == 1) { 662 if (fixed == 1) {
@@ -717,14 +665,16 @@ void alignment_exception(struct pt_regs *regs)
717 return; 665 return;
718 } 666 }
719 if (fixed == -EFAULT) { 667 if (fixed == -EFAULT) {
720 /* fixed == -EFAULT means the operand address was bad */ 668 sig = SIGSEGV;
721 if (user_mode(regs)) 669 code = SEGV_ACCERR;
722 _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); 670 } else {
723 else 671 sig = SIGBUS;
724 bad_page_fault(regs, regs->dar, SIGSEGV); 672 code = BUS_ADRALN;
725 return;
726 } 673 }
727 _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); 674 if (user_mode(regs))
675 _exception(sig, regs, code, regs->dar);
676 else
677 bad_page_fault(regs, regs->dar, sig);
728} 678}
729 679
730void StackOverflow(struct pt_regs *regs) 680void StackOverflow(struct pt_regs *regs)