aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
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
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')
-rw-r--r--arch/powerpc/include/asm/reg.h2
-rw-r--r--arch/powerpc/math-emu/math_efp.c53
2 files changed, 54 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index bd0d36e1c945..1bc6a12f3725 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -862,6 +862,8 @@
862#define PVR_7450 0x80000000 862#define PVR_7450 0x80000000
863#define PVR_8540 0x80200000 863#define PVR_8540 0x80200000
864#define PVR_8560 0x80200000 864#define PVR_8560 0x80200000
865#define PVR_VER_E500V1 0x8020
866#define PVR_VER_E500V2 0x8021
865/* 867/*
866 * For the 8xx processors, all of them report the same PVR family for 868 * For the 8xx processors, all of them report the same PVR family for
867 * the PowerPC core. The various versions of these processors must be 869 * the PowerPC core. The various versions of these processors must be
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);