diff options
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 58 |
1 files changed, 17 insertions, 41 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index a2e4ad3f5a75..6a881e3ea01d 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -31,29 +31,33 @@ | |||
31 | #include <linux/prctl.h> | 31 | #include <linux/prctl.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/kprobes.h> | 33 | #include <linux/kprobes.h> |
34 | #include <asm/kdebug.h> | ||
35 | 34 | ||
35 | #include <asm/kdebug.h> | ||
36 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | #include <asm/system.h> | 38 | #include <asm/system.h> |
39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
40 | #include <asm/machdep.h> | ||
41 | #include <asm/rtas.h> | ||
42 | #include <asm/xmon.h> | ||
40 | #ifdef CONFIG_PPC32 | 43 | #ifdef CONFIG_PPC32 |
41 | #include <asm/reg.h> | 44 | #include <asm/reg.h> |
42 | #include <asm/xmon.h> | 45 | #include <asm/perfmon.h> |
46 | #endif | ||
43 | #ifdef CONFIG_PMAC_BACKLIGHT | 47 | #ifdef CONFIG_PMAC_BACKLIGHT |
44 | #include <asm/backlight.h> | 48 | #include <asm/backlight.h> |
45 | #endif | 49 | #endif |
46 | #include <asm/perfmon.h> | ||
47 | #endif | ||
48 | #ifdef CONFIG_PPC64 | 50 | #ifdef CONFIG_PPC64 |
51 | #include <asm/firmware.h> | ||
49 | #include <asm/processor.h> | 52 | #include <asm/processor.h> |
50 | #include <asm/ppcdebug.h> | ||
51 | #include <asm/rtas.h> | ||
52 | #include <asm/systemcfg.h> | 53 | #include <asm/systemcfg.h> |
53 | #include <asm/machdep.h> | ||
54 | #include <asm/pmc.h> | 54 | #include <asm/pmc.h> |
55 | #endif | 55 | #endif |
56 | 56 | ||
57 | #ifdef CONFIG_PPC64 /* XXX */ | ||
58 | #define _IO_BASE pci_io_base | ||
59 | #endif | ||
60 | |||
57 | #ifdef CONFIG_DEBUGGER | 61 | #ifdef CONFIG_DEBUGGER |
58 | int (*__debugger)(struct pt_regs *regs); | 62 | int (*__debugger)(struct pt_regs *regs); |
59 | int (*__debugger_ipi)(struct pt_regs *regs); | 63 | int (*__debugger_ipi)(struct pt_regs *regs); |
@@ -277,7 +281,6 @@ static inline int check_io_access(struct pt_regs *regs) | |||
277 | } | 281 | } |
278 | 282 | ||
279 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 283 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
280 | |||
281 | /* On 4xx, the reason for the machine check or program exception | 284 | /* On 4xx, the reason for the machine check or program exception |
282 | is in the ESR. */ | 285 | is in the ESR. */ |
283 | #define get_reason(regs) ((regs)->dsisr) | 286 | #define get_reason(regs) ((regs)->dsisr) |
@@ -296,7 +299,6 @@ static inline int check_io_access(struct pt_regs *regs) | |||
296 | #define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC) | 299 | #define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC) |
297 | 300 | ||
298 | #else | 301 | #else |
299 | |||
300 | /* On non-4xx, the reason for the machine check or program | 302 | /* On non-4xx, the reason for the machine check or program |
301 | exception is in the MSR. */ | 303 | exception is in the MSR. */ |
302 | #define get_reason(regs) ((regs)->msr) | 304 | #define get_reason(regs) ((regs)->msr) |
@@ -475,7 +477,7 @@ void machine_check_exception(struct pt_regs *regs) | |||
475 | * additional info, e.g. bus error registers. | 477 | * additional info, e.g. bus error registers. |
476 | */ | 478 | */ |
477 | platform_machine_check(regs); | 479 | platform_machine_check(regs); |
478 | #endif /* CONFIG_PPC32 */ | 480 | #endif /* CONFIG_PPC64 */ |
479 | 481 | ||
480 | if (debugger_fault_handler(regs)) | 482 | if (debugger_fault_handler(regs)) |
481 | return; | 483 | return; |
@@ -486,12 +488,10 @@ void machine_check_exception(struct pt_regs *regs) | |||
486 | panic("Unrecoverable Machine check"); | 488 | panic("Unrecoverable Machine check"); |
487 | } | 489 | } |
488 | 490 | ||
489 | #ifdef CONFIG_PPC32 | ||
490 | void SMIException(struct pt_regs *regs) | 491 | void SMIException(struct pt_regs *regs) |
491 | { | 492 | { |
492 | die("System Management Interrupt", regs, SIGABRT); | 493 | die("System Management Interrupt", regs, SIGABRT); |
493 | } | 494 | } |
494 | #endif | ||
495 | 495 | ||
496 | void unknown_exception(struct pt_regs *regs) | 496 | void unknown_exception(struct pt_regs *regs) |
497 | { | 497 | { |
@@ -511,12 +511,10 @@ void instruction_breakpoint_exception(struct pt_regs *regs) | |||
511 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); | 511 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); |
512 | } | 512 | } |
513 | 513 | ||
514 | #ifdef CONFIG_PPC32 | ||
515 | void RunModeException(struct pt_regs *regs) | 514 | void RunModeException(struct pt_regs *regs) |
516 | { | 515 | { |
517 | _exception(SIGTRAP, regs, 0, 0); | 516 | _exception(SIGTRAP, regs, 0, 0); |
518 | } | 517 | } |
519 | #endif | ||
520 | 518 | ||
521 | void __kprobes single_step_exception(struct pt_regs *regs) | 519 | void __kprobes single_step_exception(struct pt_regs *regs) |
522 | { | 520 | { |
@@ -542,7 +540,6 @@ static void emulate_single_step(struct pt_regs *regs) | |||
542 | if (single_stepping(regs)) { | 540 | if (single_stepping(regs)) { |
543 | clear_single_step(regs); | 541 | clear_single_step(regs); |
544 | _exception(SIGTRAP, regs, TRAP_TRACE, 0); | 542 | _exception(SIGTRAP, regs, TRAP_TRACE, 0); |
545 | single_step_exception(regs); | ||
546 | } | 543 | } |
547 | } | 544 | } |
548 | 545 | ||
@@ -587,6 +584,7 @@ static void parse_fpe(struct pt_regs *regs) | |||
587 | * There are a couple of ways to do this, either "decode" the instruction | 584 | * There are a couple of ways to do this, either "decode" the instruction |
588 | * or directly match lots of bits. In this case, matching lots of | 585 | * or directly match lots of bits. In this case, matching lots of |
589 | * bits is faster and easier. | 586 | * bits is faster and easier. |
587 | * | ||
590 | */ | 588 | */ |
591 | #define INST_MFSPR_PVR 0x7c1f42a6 | 589 | #define INST_MFSPR_PVR 0x7c1f42a6 |
592 | #define INST_MFSPR_PVR_MASK 0xfc1fffff | 590 | #define INST_MFSPR_PVR_MASK 0xfc1fffff |
@@ -597,8 +595,6 @@ static void parse_fpe(struct pt_regs *regs) | |||
597 | #define INST_MCRXR 0x7c000400 | 595 | #define INST_MCRXR 0x7c000400 |
598 | #define INST_MCRXR_MASK 0x7c0007fe | 596 | #define INST_MCRXR_MASK 0x7c0007fe |
599 | 597 | ||
600 | #ifdef CONFIG_PPC32 | ||
601 | |||
602 | #define INST_STRING 0x7c00042a | 598 | #define INST_STRING 0x7c00042a |
603 | #define INST_STRING_MASK 0x7c0007fe | 599 | #define INST_STRING_MASK 0x7c0007fe |
604 | #define INST_STRING_GEN_MASK 0x7c00067e | 600 | #define INST_STRING_GEN_MASK 0x7c00067e |
@@ -674,7 +670,6 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword) | |||
674 | 670 | ||
675 | return 0; | 671 | return 0; |
676 | } | 672 | } |
677 | #endif /* CONFIG_PPC32 */ | ||
678 | 673 | ||
679 | static int emulate_instruction(struct pt_regs *regs) | 674 | static int emulate_instruction(struct pt_regs *regs) |
680 | { | 675 | { |
@@ -701,28 +696,17 @@ static int emulate_instruction(struct pt_regs *regs) | |||
701 | 696 | ||
702 | /* Emulate the mcrxr insn. */ | 697 | /* Emulate the mcrxr insn. */ |
703 | if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { | 698 | if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { |
704 | unsigned int shift = (instword >> 21) & 0x1c; | 699 | int shift = (instword >> 21) & 0x1c; |
705 | unsigned long msk = 0xf0000000UL >> shift; | 700 | unsigned long msk = 0xf0000000UL >> shift; |
706 | #ifdef CONFIG_PPC64 | ||
707 | static int warned; | ||
708 | 701 | ||
709 | if (!warned) { | ||
710 | printk(KERN_WARNING | ||
711 | "process %d (%s) uses obsolete 'mcrxr' insn\n", | ||
712 | current->pid, current->comm); | ||
713 | warned = 1; | ||
714 | } | ||
715 | #endif | ||
716 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); | 702 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); |
717 | regs->xer &= ~0xf0000000UL; | 703 | regs->xer &= ~0xf0000000UL; |
718 | return 0; | 704 | return 0; |
719 | } | 705 | } |
720 | 706 | ||
721 | #ifdef CONFIG_PPC32 | ||
722 | /* Emulate load/store string insn. */ | 707 | /* Emulate load/store string insn. */ |
723 | if ((instword & INST_STRING_GEN_MASK) == INST_STRING) | 708 | if ((instword & INST_STRING_GEN_MASK) == INST_STRING) |
724 | return emulate_string_inst(regs, instword); | 709 | return emulate_string_inst(regs, instword); |
725 | #endif | ||
726 | 710 | ||
727 | return -EINVAL; | 711 | return -EINVAL; |
728 | } | 712 | } |
@@ -769,22 +753,18 @@ static int check_bug_trap(struct pt_regs *regs) | |||
769 | xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", | 753 | xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", |
770 | bug->function, bug->file, | 754 | bug->function, bug->file, |
771 | bug->line & ~BUG_WARNING_TRAP); | 755 | bug->line & ~BUG_WARNING_TRAP); |
772 | #endif | 756 | #endif /* CONFIG_XMON */ |
773 | printk(KERN_ERR "Badness in %s at %s:%d\n", | 757 | printk(KERN_ERR "Badness in %s at %s:%d\n", |
774 | bug->function, bug->file, | 758 | bug->function, bug->file, |
775 | bug->line & ~BUG_WARNING_TRAP); | 759 | bug->line & ~BUG_WARNING_TRAP); |
776 | #ifdef CONFIG_PPC32 | ||
777 | dump_stack(); | 760 | dump_stack(); |
778 | #else | ||
779 | show_stack(current, (void *)regs->gpr[1]); | ||
780 | #endif | ||
781 | return 1; | 761 | return 1; |
782 | } | 762 | } |
783 | #if defined(CONFIG_PPC32) && defined(CONFIG_XMON) | 763 | #ifdef CONFIG_XMON |
784 | xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n", | 764 | xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n", |
785 | bug->function, bug->file, bug->line); | 765 | bug->function, bug->file, bug->line); |
786 | xmon(regs); | 766 | xmon(regs); |
787 | #endif | 767 | #endif /* CONFIG_XMON */ |
788 | printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", | 768 | printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", |
789 | bug->function, bug->file, bug->line); | 769 | bug->function, bug->file, bug->line); |
790 | 770 | ||
@@ -873,7 +853,6 @@ void alignment_exception(struct pt_regs *regs) | |||
873 | _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); | 853 | _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); |
874 | } | 854 | } |
875 | 855 | ||
876 | #ifdef CONFIG_PPC32 | ||
877 | void StackOverflow(struct pt_regs *regs) | 856 | void StackOverflow(struct pt_regs *regs) |
878 | { | 857 | { |
879 | printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n", | 858 | printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n", |
@@ -897,7 +876,6 @@ void trace_syscall(struct pt_regs *regs) | |||
897 | current, current->pid, regs->nip, regs->link, regs->gpr[0], | 876 | current, current->pid, regs->nip, regs->link, regs->gpr[0], |
898 | regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted()); | 877 | regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted()); |
899 | } | 878 | } |
900 | #endif /* CONFIG_PPC32 */ | ||
901 | 879 | ||
902 | void kernel_fp_unavailable_exception(struct pt_regs *regs) | 880 | void kernel_fp_unavailable_exception(struct pt_regs *regs) |
903 | { | 881 | { |
@@ -963,7 +941,6 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
963 | } | 941 | } |
964 | #endif /* CONFIG_8xx */ | 942 | #endif /* CONFIG_8xx */ |
965 | 943 | ||
966 | #ifdef CONFIG_PPC32 | ||
967 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 944 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) |
968 | 945 | ||
969 | void DebugException(struct pt_regs *regs, unsigned long debug_status) | 946 | void DebugException(struct pt_regs *regs, unsigned long debug_status) |
@@ -992,7 +969,6 @@ void TAUException(struct pt_regs *regs) | |||
992 | regs->nip, regs->msr, regs->trap, print_tainted()); | 969 | regs->nip, regs->msr, regs->trap, print_tainted()); |
993 | } | 970 | } |
994 | #endif /* CONFIG_INT_TAU */ | 971 | #endif /* CONFIG_INT_TAU */ |
995 | #endif /* CONFIG_PPC32*/ | ||
996 | 972 | ||
997 | #ifdef CONFIG_ALTIVEC | 973 | #ifdef CONFIG_ALTIVEC |
998 | void altivec_assist_exception(struct pt_regs *regs) | 974 | void altivec_assist_exception(struct pt_regs *regs) |