diff options
author | Anton Blanchard <anton@samba.org> | 2009-10-27 14:46:55 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2009-10-28 01:13:03 -0400 |
commit | eecff81d1fcda22cd0029d11fe2a71dceed11dad (patch) | |
tree | 9cbccbfc76a7336aa1d309b89407e31a76110784 | |
parent | f7d7986060b2890fc26db6ab5203efbd33aa2497 (diff) |
powerpc: Create PPC_WARN_ALIGNMENT to match PPC_WARN_EMULATED
perf_event wants a separate event for alignment and emulation faults,
so create another emulation event. This will make it easy to hook in
perf_event at one spot.
We pass in regs which will be required for these events.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/include/asm/emulated_ops.h | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/align.c | 12 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 18 |
3 files changed, 20 insertions, 17 deletions
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h index 9154e8526732..640c4e456aa5 100644 --- a/arch/powerpc/include/asm/emulated_ops.h +++ b/arch/powerpc/include/asm/emulated_ops.h | |||
@@ -57,7 +57,7 @@ extern u32 ppc_warn_emulated; | |||
57 | 57 | ||
58 | extern void ppc_warn_emulated_print(const char *type); | 58 | extern void ppc_warn_emulated_print(const char *type); |
59 | 59 | ||
60 | #define PPC_WARN_EMULATED(type) \ | 60 | #define __PPC_WARN_EMULATED(type) \ |
61 | do { \ | 61 | do { \ |
62 | atomic_inc(&ppc_emulated.type.val); \ | 62 | atomic_inc(&ppc_emulated.type.val); \ |
63 | if (ppc_warn_emulated) \ | 63 | if (ppc_warn_emulated) \ |
@@ -66,8 +66,11 @@ extern void ppc_warn_emulated_print(const char *type); | |||
66 | 66 | ||
67 | #else /* !CONFIG_PPC_EMULATED_STATS */ | 67 | #else /* !CONFIG_PPC_EMULATED_STATS */ |
68 | 68 | ||
69 | #define PPC_WARN_EMULATED(type) do { } while (0) | 69 | #define __PPC_WARN_EMULATED(type) do { } while (0) |
70 | 70 | ||
71 | #endif /* !CONFIG_PPC_EMULATED_STATS */ | 71 | #endif /* !CONFIG_PPC_EMULATED_STATS */ |
72 | 72 | ||
73 | #define PPC_WARN_EMULATED(type, regs) __PPC_WARN_EMULATED(type) | ||
74 | #define PPC_WARN_ALIGNMENT(type, regs) __PPC_WARN_EMULATED(type) | ||
75 | |||
73 | #endif /* _ASM_POWERPC_EMULATED_OPS_H */ | 76 | #endif /* _ASM_POWERPC_EMULATED_OPS_H */ |
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index a5b632e52fae..3839839f83c7 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -732,7 +732,7 @@ int fix_alignment(struct pt_regs *regs) | |||
732 | 732 | ||
733 | #ifdef CONFIG_SPE | 733 | #ifdef CONFIG_SPE |
734 | if ((instr >> 26) == 0x4) { | 734 | if ((instr >> 26) == 0x4) { |
735 | PPC_WARN_EMULATED(spe); | 735 | PPC_WARN_ALIGNMENT(spe, regs); |
736 | return emulate_spe(regs, reg, instr); | 736 | return emulate_spe(regs, reg, instr); |
737 | } | 737 | } |
738 | #endif | 738 | #endif |
@@ -786,7 +786,7 @@ int fix_alignment(struct pt_regs *regs) | |||
786 | flags |= SPLT; | 786 | flags |= SPLT; |
787 | nb = 8; | 787 | nb = 8; |
788 | } | 788 | } |
789 | PPC_WARN_EMULATED(vsx); | 789 | PPC_WARN_ALIGNMENT(vsx, regs); |
790 | return emulate_vsx(addr, reg, areg, regs, flags, nb); | 790 | return emulate_vsx(addr, reg, areg, regs, flags, nb); |
791 | } | 791 | } |
792 | #endif | 792 | #endif |
@@ -794,7 +794,7 @@ int fix_alignment(struct pt_regs *regs) | |||
794 | * the exception of DCBZ which is handled as a special case here | 794 | * the exception of DCBZ which is handled as a special case here |
795 | */ | 795 | */ |
796 | if (instr == DCBZ) { | 796 | if (instr == DCBZ) { |
797 | PPC_WARN_EMULATED(dcbz); | 797 | PPC_WARN_ALIGNMENT(dcbz, regs); |
798 | return emulate_dcbz(regs, addr); | 798 | return emulate_dcbz(regs, addr); |
799 | } | 799 | } |
800 | if (unlikely(nb == 0)) | 800 | if (unlikely(nb == 0)) |
@@ -804,7 +804,7 @@ int fix_alignment(struct pt_regs *regs) | |||
804 | * function | 804 | * function |
805 | */ | 805 | */ |
806 | if (flags & M) { | 806 | if (flags & M) { |
807 | PPC_WARN_EMULATED(multiple); | 807 | PPC_WARN_ALIGNMENT(multiple, regs); |
808 | return emulate_multiple(regs, addr, reg, nb, | 808 | return emulate_multiple(regs, addr, reg, nb, |
809 | flags, instr, swiz); | 809 | flags, instr, swiz); |
810 | } | 810 | } |
@@ -825,11 +825,11 @@ int fix_alignment(struct pt_regs *regs) | |||
825 | 825 | ||
826 | /* Special case for 16-byte FP loads and stores */ | 826 | /* Special case for 16-byte FP loads and stores */ |
827 | if (nb == 16) { | 827 | if (nb == 16) { |
828 | PPC_WARN_EMULATED(fp_pair); | 828 | PPC_WARN_ALIGNMENT(fp_pair, regs); |
829 | return emulate_fp_pair(addr, reg, flags); | 829 | return emulate_fp_pair(addr, reg, flags); |
830 | } | 830 | } |
831 | 831 | ||
832 | PPC_WARN_EMULATED(unaligned); | 832 | PPC_WARN_ALIGNMENT(unaligned, regs); |
833 | 833 | ||
834 | /* If we are loading, get the data from user space, else | 834 | /* If we are loading, get the data from user space, else |
835 | * get it from register values | 835 | * get it from register values |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6f0ae1a9bfae..9d1f9354d6ca 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -759,7 +759,7 @@ static int emulate_instruction(struct pt_regs *regs) | |||
759 | 759 | ||
760 | /* Emulate the mfspr rD, PVR. */ | 760 | /* Emulate the mfspr rD, PVR. */ |
761 | if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) { | 761 | if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) { |
762 | PPC_WARN_EMULATED(mfpvr); | 762 | PPC_WARN_EMULATED(mfpvr, regs); |
763 | rd = (instword >> 21) & 0x1f; | 763 | rd = (instword >> 21) & 0x1f; |
764 | regs->gpr[rd] = mfspr(SPRN_PVR); | 764 | regs->gpr[rd] = mfspr(SPRN_PVR); |
765 | return 0; | 765 | return 0; |
@@ -767,7 +767,7 @@ static int emulate_instruction(struct pt_regs *regs) | |||
767 | 767 | ||
768 | /* Emulating the dcba insn is just a no-op. */ | 768 | /* Emulating the dcba insn is just a no-op. */ |
769 | if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) { | 769 | if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) { |
770 | PPC_WARN_EMULATED(dcba); | 770 | PPC_WARN_EMULATED(dcba, regs); |
771 | return 0; | 771 | return 0; |
772 | } | 772 | } |
773 | 773 | ||
@@ -776,7 +776,7 @@ static int emulate_instruction(struct pt_regs *regs) | |||
776 | int shift = (instword >> 21) & 0x1c; | 776 | int shift = (instword >> 21) & 0x1c; |
777 | unsigned long msk = 0xf0000000UL >> shift; | 777 | unsigned long msk = 0xf0000000UL >> shift; |
778 | 778 | ||
779 | PPC_WARN_EMULATED(mcrxr); | 779 | PPC_WARN_EMULATED(mcrxr, regs); |
780 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); | 780 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); |
781 | regs->xer &= ~0xf0000000UL; | 781 | regs->xer &= ~0xf0000000UL; |
782 | return 0; | 782 | return 0; |
@@ -784,19 +784,19 @@ static int emulate_instruction(struct pt_regs *regs) | |||
784 | 784 | ||
785 | /* Emulate load/store string insn. */ | 785 | /* Emulate load/store string insn. */ |
786 | if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) { | 786 | if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) { |
787 | PPC_WARN_EMULATED(string); | 787 | PPC_WARN_EMULATED(string, regs); |
788 | return emulate_string_inst(regs, instword); | 788 | return emulate_string_inst(regs, instword); |
789 | } | 789 | } |
790 | 790 | ||
791 | /* Emulate the popcntb (Population Count Bytes) instruction. */ | 791 | /* Emulate the popcntb (Population Count Bytes) instruction. */ |
792 | if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) { | 792 | if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) { |
793 | PPC_WARN_EMULATED(popcntb); | 793 | PPC_WARN_EMULATED(popcntb, regs); |
794 | return emulate_popcntb_inst(regs, instword); | 794 | return emulate_popcntb_inst(regs, instword); |
795 | } | 795 | } |
796 | 796 | ||
797 | /* Emulate isel (Integer Select) instruction */ | 797 | /* Emulate isel (Integer Select) instruction */ |
798 | if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) { | 798 | if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) { |
799 | PPC_WARN_EMULATED(isel); | 799 | PPC_WARN_EMULATED(isel, regs); |
800 | return emulate_isel(regs, instword); | 800 | return emulate_isel(regs, instword); |
801 | } | 801 | } |
802 | 802 | ||
@@ -995,7 +995,7 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
995 | #ifdef CONFIG_MATH_EMULATION | 995 | #ifdef CONFIG_MATH_EMULATION |
996 | errcode = do_mathemu(regs); | 996 | errcode = do_mathemu(regs); |
997 | if (errcode >= 0) | 997 | if (errcode >= 0) |
998 | PPC_WARN_EMULATED(math); | 998 | PPC_WARN_EMULATED(math, regs); |
999 | 999 | ||
1000 | switch (errcode) { | 1000 | switch (errcode) { |
1001 | case 0: | 1001 | case 0: |
@@ -1018,7 +1018,7 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
1018 | #elif defined(CONFIG_8XX_MINIMAL_FPEMU) | 1018 | #elif defined(CONFIG_8XX_MINIMAL_FPEMU) |
1019 | errcode = Soft_emulate_8xx(regs); | 1019 | errcode = Soft_emulate_8xx(regs); |
1020 | if (errcode >= 0) | 1020 | if (errcode >= 0) |
1021 | PPC_WARN_EMULATED(8xx); | 1021 | PPC_WARN_EMULATED(8xx, regs); |
1022 | 1022 | ||
1023 | switch (errcode) { | 1023 | switch (errcode) { |
1024 | case 0: | 1024 | case 0: |
@@ -1129,7 +1129,7 @@ void altivec_assist_exception(struct pt_regs *regs) | |||
1129 | 1129 | ||
1130 | flush_altivec_to_thread(current); | 1130 | flush_altivec_to_thread(current); |
1131 | 1131 | ||
1132 | PPC_WARN_EMULATED(altivec); | 1132 | PPC_WARN_EMULATED(altivec, regs); |
1133 | err = emulate_altivec(regs); | 1133 | err = emulate_altivec(regs); |
1134 | if (err == 0) { | 1134 | if (err == 0) { |
1135 | regs->nip += 4; /* skip emulated instruction */ | 1135 | regs->nip += 4; /* skip emulated instruction */ |