aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c79
1 files changed, 39 insertions, 40 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5457e9575685..678fbff0d206 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -52,6 +52,10 @@
52#include <asm/processor.h> 52#include <asm/processor.h>
53#endif 53#endif
54#include <asm/kexec.h> 54#include <asm/kexec.h>
55#include <asm/ppc-opcode.h>
56#ifdef CONFIG_FSL_BOOKE
57#include <asm/dbell.h>
58#endif
55 59
56#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) 60#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
57int (*__debugger)(struct pt_regs *regs); 61int (*__debugger)(struct pt_regs *regs);
@@ -637,29 +641,6 @@ static void parse_fpe(struct pt_regs *regs)
637 * bits is faster and easier. 641 * bits is faster and easier.
638 * 642 *
639 */ 643 */
640#define INST_MFSPR_PVR 0x7c1f42a6
641#define INST_MFSPR_PVR_MASK 0xfc1fffff
642
643#define INST_DCBA 0x7c0005ec
644#define INST_DCBA_MASK 0xfc0007fe
645
646#define INST_MCRXR 0x7c000400
647#define INST_MCRXR_MASK 0xfc0007fe
648
649#define INST_STRING 0x7c00042a
650#define INST_STRING_MASK 0xfc0007fe
651#define INST_STRING_GEN_MASK 0xfc00067e
652#define INST_LSWI 0x7c0004aa
653#define INST_LSWX 0x7c00042a
654#define INST_STSWI 0x7c0005aa
655#define INST_STSWX 0x7c00052a
656
657#define INST_POPCNTB 0x7c0000f4
658#define INST_POPCNTB_MASK 0xfc0007fe
659
660#define INST_ISEL 0x7c00001e
661#define INST_ISEL_MASK 0xfc00003e
662
663static int emulate_string_inst(struct pt_regs *regs, u32 instword) 644static int emulate_string_inst(struct pt_regs *regs, u32 instword)
664{ 645{
665 u8 rT = (instword >> 21) & 0x1f; 646 u8 rT = (instword >> 21) & 0x1f;
@@ -670,20 +651,20 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
670 int pos = 0; 651 int pos = 0;
671 652
672 /* Early out if we are an invalid form of lswx */ 653 /* Early out if we are an invalid form of lswx */
673 if ((instword & INST_STRING_MASK) == INST_LSWX) 654 if ((instword & PPC_INST_STRING_MASK) == PPC_INST_LSWX)
674 if ((rT == rA) || (rT == NB_RB)) 655 if ((rT == rA) || (rT == NB_RB))
675 return -EINVAL; 656 return -EINVAL;
676 657
677 EA = (rA == 0) ? 0 : regs->gpr[rA]; 658 EA = (rA == 0) ? 0 : regs->gpr[rA];
678 659
679 switch (instword & INST_STRING_MASK) { 660 switch (instword & PPC_INST_STRING_MASK) {
680 case INST_LSWX: 661 case PPC_INST_LSWX:
681 case INST_STSWX: 662 case PPC_INST_STSWX:
682 EA += NB_RB; 663 EA += NB_RB;
683 num_bytes = regs->xer & 0x7f; 664 num_bytes = regs->xer & 0x7f;
684 break; 665 break;
685 case INST_LSWI: 666 case PPC_INST_LSWI:
686 case INST_STSWI: 667 case PPC_INST_STSWI:
687 num_bytes = (NB_RB == 0) ? 32 : NB_RB; 668 num_bytes = (NB_RB == 0) ? 32 : NB_RB;
688 break; 669 break;
689 default: 670 default:
@@ -695,9 +676,9 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
695 u8 val; 676 u8 val;
696 u32 shift = 8 * (3 - (pos & 0x3)); 677 u32 shift = 8 * (3 - (pos & 0x3));
697 678
698 switch ((instword & INST_STRING_MASK)) { 679 switch ((instword & PPC_INST_STRING_MASK)) {
699 case INST_LSWX: 680 case PPC_INST_LSWX:
700 case INST_LSWI: 681 case PPC_INST_LSWI:
701 if (get_user(val, (u8 __user *)EA)) 682 if (get_user(val, (u8 __user *)EA))
702 return -EFAULT; 683 return -EFAULT;
703 /* first time updating this reg, 684 /* first time updating this reg,
@@ -706,8 +687,8 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
706 regs->gpr[rT] = 0; 687 regs->gpr[rT] = 0;
707 regs->gpr[rT] |= val << shift; 688 regs->gpr[rT] |= val << shift;
708 break; 689 break;
709 case INST_STSWI: 690 case PPC_INST_STSWI:
710 case INST_STSWX: 691 case PPC_INST_STSWX:
711 val = regs->gpr[rT] >> shift; 692 val = regs->gpr[rT] >> shift;
712 if (put_user(val, (u8 __user *)EA)) 693 if (put_user(val, (u8 __user *)EA))
713 return -EFAULT; 694 return -EFAULT;
@@ -775,18 +756,18 @@ static int emulate_instruction(struct pt_regs *regs)
775 return -EFAULT; 756 return -EFAULT;
776 757
777 /* Emulate the mfspr rD, PVR. */ 758 /* Emulate the mfspr rD, PVR. */
778 if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) { 759 if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) {
779 rd = (instword >> 21) & 0x1f; 760 rd = (instword >> 21) & 0x1f;
780 regs->gpr[rd] = mfspr(SPRN_PVR); 761 regs->gpr[rd] = mfspr(SPRN_PVR);
781 return 0; 762 return 0;
782 } 763 }
783 764
784 /* Emulating the dcba insn is just a no-op. */ 765 /* Emulating the dcba insn is just a no-op. */
785 if ((instword & INST_DCBA_MASK) == INST_DCBA) 766 if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA)
786 return 0; 767 return 0;
787 768
788 /* Emulate the mcrxr insn. */ 769 /* Emulate the mcrxr insn. */
789 if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { 770 if ((instword & PPC_INST_MCRXR_MASK) == PPC_INST_MCRXR) {
790 int shift = (instword >> 21) & 0x1c; 771 int shift = (instword >> 21) & 0x1c;
791 unsigned long msk = 0xf0000000UL >> shift; 772 unsigned long msk = 0xf0000000UL >> shift;
792 773
@@ -796,16 +777,16 @@ static int emulate_instruction(struct pt_regs *regs)
796 } 777 }
797 778
798 /* Emulate load/store string insn. */ 779 /* Emulate load/store string insn. */
799 if ((instword & INST_STRING_GEN_MASK) == INST_STRING) 780 if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING)
800 return emulate_string_inst(regs, instword); 781 return emulate_string_inst(regs, instword);
801 782
802 /* Emulate the popcntb (Population Count Bytes) instruction. */ 783 /* Emulate the popcntb (Population Count Bytes) instruction. */
803 if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) { 784 if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) {
804 return emulate_popcntb_inst(regs, instword); 785 return emulate_popcntb_inst(regs, instword);
805 } 786 }
806 787
807 /* Emulate isel (Integer Select) instruction */ 788 /* Emulate isel (Integer Select) instruction */
808 if ((instword & INST_ISEL_MASK) == INST_ISEL) { 789 if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) {
809 return emulate_isel(regs, instword); 790 return emulate_isel(regs, instword);
810 } 791 }
811 792
@@ -1144,6 +1125,24 @@ void vsx_assist_exception(struct pt_regs *regs)
1144#endif /* CONFIG_VSX */ 1125#endif /* CONFIG_VSX */
1145 1126
1146#ifdef CONFIG_FSL_BOOKE 1127#ifdef CONFIG_FSL_BOOKE
1128
1129void doorbell_exception(struct pt_regs *regs)
1130{
1131#ifdef CONFIG_SMP
1132 int cpu = smp_processor_id();
1133 int msg;
1134
1135 if (num_online_cpus() < 2)
1136 return;
1137
1138 for (msg = 0; msg < 4; msg++)
1139 if (test_and_clear_bit(msg, &dbell_smp_message[cpu]))
1140 smp_message_recv(msg);
1141#else
1142 printk(KERN_WARNING "Received doorbell on non-smp system\n");
1143#endif
1144}
1145
1147void CacheLockingException(struct pt_regs *regs, unsigned long address, 1146void CacheLockingException(struct pt_regs *regs, unsigned long address,
1148 unsigned long error_code) 1147 unsigned long error_code)
1149{ 1148{