aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/math-emu
diff options
context:
space:
mode:
authorLiu Yu <yu.liu@freescale.com>2011-01-25 01:02:13 -0500
committerKumar Gala <galak@kernel.crashing.org>2011-03-15 11:05:06 -0400
commitac6f120369ffe66058518fabf90cdd53b2503a82 (patch)
tree00bda32e2c6da757ada25afcb8abd81996d6e6d3 /arch/powerpc/math-emu
parentf4154e160aa2a40dccc963110768b63ce004fed9 (diff)
powerpc/85xx: Workaroudn e500 CPU erratum A005
This erratum can occur if a single-precision floating-point, double-precision floating-point or vector floating-point instruction on a mispredicted branch path signals one of the floating-point data interrupts which are enabled by the SPEFSCR (FINVE, FDBZE, FUNFE or FOVFE bits). This interrupt must be recorded in a one-cycle window when the misprediction is resolved. If this extremely rare event should occur, the result could be: The SPE Data Exception from the mispredicted path may be reported erroneously if a single-precision floating-point, double-precision floating-point or vector floating-point instruction is the second instruction on the correct branch path. According to errata description, some efp instructions which are not supposed to trigger SPE exceptions can trigger the exceptions in this case. However, as we haven't emulated these instructions here, a signal will send to userspace, and userspace application would exit. This patch re-issue the efp instruction that we haven't emulated, so that hardware can properly execute it again if this case happen. Signed-off-by: Liu Yu <yu.liu@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/math-emu')
-rw-r--r--arch/powerpc/math-emu/math_efp.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c
index 41f4ef30e480..634830bdc0be 100644
--- a/arch/powerpc/math-emu/math_efp.c
+++ b/arch/powerpc/math-emu/math_efp.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/powerpc/math-emu/math_efp.c 2 * arch/powerpc/math-emu/math_efp.c
3 * 3 *
4 * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved. 4 * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
5 * 5 *
6 * Author: Ebony Zhu, <ebony.zhu@freescale.com> 6 * Author: Ebony Zhu, <ebony.zhu@freescale.com>
7 * Yu Liu, <yu.liu@freescale.com> 7 * Yu Liu, <yu.liu@freescale.com>
@@ -104,6 +104,8 @@
104#define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \ 104#define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
105 FP_EX_UNDERFLOW | FP_EX_OVERFLOW) 105 FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
106 106
107static int have_e500_cpu_a005_erratum;
108
107union dw_union { 109union dw_union {
108 u64 dp[1]; 110 u64 dp[1];
109 u32 wp[2]; 111 u32 wp[2];
@@ -652,6 +654,15 @@ update_regs:
652 return 0; 654 return 0;
653 655
654illegal: 656illegal:
657 if (have_e500_cpu_a005_erratum) {
658 /* according to e500 cpu a005 erratum, reissue efp inst */
659 regs->nip -= 4;
660#ifdef DEBUG
661 printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
662#endif
663 return 0;
664 }
665
655 printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn); 666 printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
656 return -ENOSYS; 667 return -ENOSYS;
657} 668}
@@ -718,3 +729,43 @@ int speround_handler(struct pt_regs *regs)
718 729
719 return 0; 730 return 0;
720} 731}
732
733int __init spe_mathemu_init(void)
734{
735 u32 pvr, maj, min;
736
737 pvr = mfspr(SPRN_PVR);
738
739 if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
740 (PVR_VER(pvr) == PVR_VER_E500V2)) {
741 maj = PVR_MAJ(pvr);
742 min = PVR_MIN(pvr);
743
744 /*
745 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
746 * need cpu a005 errata workaround
747 */
748 switch (maj) {
749 case 1:
750 if (min < 1)
751 have_e500_cpu_a005_erratum = 1;
752 break;
753 case 2:
754 if (min < 3)
755 have_e500_cpu_a005_erratum = 1;
756 break;
757 case 3:
758 case 4:
759 case 5:
760 if (min < 1)
761 have_e500_cpu_a005_erratum = 1;
762 break;
763 default:
764 break;
765 }
766 }
767
768 return 0;
769}
770
771module_init(spe_mathemu_init);