diff mbox

e500: Erratum cpu a005 workaround

Message ID 1295935333-13045-1-git-send-email-yu.liu@freescale.com (mailing list archive)
State Accepted, archived
Delegated to: Kumar Gala
Headers show

Commit Message

Liu Yu-B13201 Jan. 25, 2011, 6:02 a.m. UTC
This errata 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>
---
This is an erratum workaround patch.
It would be better if the patch can go into 2.6.38.

 arch/powerpc/include/asm/reg.h   |    2 +
 arch/powerpc/math-emu/math_efp.c |   53 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletions(-)

Comments

Kumar Gala Jan. 25, 2011, 7:01 a.m. UTC | #1
On Jan 25, 2011, at 12:02 AM, Liu Yu wrote:

> This errata 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>
> ---
> This is an erratum workaround patch.
> It would be better if the patch can go into 2.6.38.
> 
> arch/powerpc/include/asm/reg.h   |    2 +
> arch/powerpc/math-emu/math_efp.c |   53 +++++++++++++++++++++++++++++++++++++-
> 2 files changed, 54 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index 6315edc..0abfd91 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -833,6 +833,8 @@
> #define PVR_7450	0x80000000
> #define PVR_8540	0x80200000
> #define PVR_8560	0x80200000
> +#define PVR_VER_E500V1	0x8020
> +#define PVR_VER_E500V2	0x8021
> /*
>  * For the 8xx processors, all of them report the same PVR family for
>  * 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 41f4ef3..634830b 100644
> --- a/arch/powerpc/math-emu/math_efp.c
> +++ b/arch/powerpc/math-emu/math_efp.c
> @@ -1,7 +1,7 @@
> /*
>  * arch/powerpc/math-emu/math_efp.c
>  *
> - * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
> + * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
>  *
>  * Author: Ebony Zhu,	<ebony.zhu@freescale.com>
>  *         Yu Liu,	<yu.liu@freescale.com>
> @@ -104,6 +104,8 @@
> #define FP_EX_MASK	(FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
> 			FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
> 
> +static int have_e500_cpu_a005_erratum;
> +
> union dw_union {
> 	u64 dp[1];
> 	u32 wp[2];
> @@ -652,6 +654,15 @@ update_regs:
> 	return 0;
> 
> illegal:
> +	if (have_e500_cpu_a005_erratum) {
> +		/* according to e500 cpu a005 erratum, reissue efp inst */
> +		regs->nip -= 4;
> +#ifdef DEBUG
> +		printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
> +#endif
> +		return 0;
> +	}
> +
> 	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
> 	return -ENOSYS;
> }
> @@ -718,3 +729,43 @@ int speround_handler(struct pt_regs *regs)
> 
> 	return 0;
> }
> +
> +int __init spe_mathemu_init(void)
> +{
> +	u32 pvr, maj, min;
> +
> +	pvr = mfspr(SPRN_PVR);
> +
> +	if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
> +	    (PVR_VER(pvr) == PVR_VER_E500V2)) {
> +		maj = PVR_MAJ(pvr);
> +		min = PVR_MIN(pvr);
> +
> +		/*
> +		 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
> +		 * need cpu a005 errata workaround
> +		 */

This isn't the way to do this.  We normally add entries in cputable.c an add a new cpu_feature_bit for the errata.

Than above we'd do:

if (cur_cpu_spec->cpu_features & CPU_FTR_E500_A005_ERRATUM)


> +		switch (maj) {
> +		case 1:
> +			if (min < 1)
> +				have_e500_cpu_a005_erratum = 1;
> +			break;
> +		case 2:
> +			if (min < 3)
> +				have_e500_cpu_a005_erratum = 1;
> +			break;
> +		case 3:
> +		case 4:
> +		case 5:
> +			if (min < 1)
> +				have_e500_cpu_a005_erratum = 1;
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +module_init(spe_mathemu_init);
> -- 
> 1.6.4
Liu Yu-B13201 Jan. 25, 2011, 8:57 a.m. UTC | #2
> -----Original Message-----
> From: Gala Kumar-B11780 
> Sent: Tuesday, January 25, 2011 3:01 PM
> To: Liu Yu-B13201
> Cc: linuxppc-dev@lists.ozlabs.org; Gala Kumar-B11780
> Subject: Re: [PATCH] e500: Erratum cpu a005 workaround
> 
> 
> On Jan 25, 2011, at 12:02 AM, Liu Yu wrote:
> 
> > This errata 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>
> > ---
> > This is an erratum workaround patch.
> > It would be better if the patch can go into 2.6.38.
> > 
> > arch/powerpc/include/asm/reg.h   |    2 +
> > arch/powerpc/math-emu/math_efp.c |   53 
> +++++++++++++++++++++++++++++++++++++-
> > 2 files changed, 54 insertions(+), 1 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/reg.h 
> b/arch/powerpc/include/asm/reg.h
> > index 6315edc..0abfd91 100644
> > --- a/arch/powerpc/include/asm/reg.h
> > +++ b/arch/powerpc/include/asm/reg.h
> > @@ -833,6 +833,8 @@
> > #define PVR_7450	0x80000000
> > #define PVR_8540	0x80200000
> > #define PVR_8560	0x80200000
> > +#define PVR_VER_E500V1	0x8020
> > +#define PVR_VER_E500V2	0x8021
> > /*
> >  * For the 8xx processors, all of them report the same PVR 
> family for
> >  * 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 41f4ef3..634830b 100644
> > --- a/arch/powerpc/math-emu/math_efp.c
> > +++ b/arch/powerpc/math-emu/math_efp.c
> > @@ -1,7 +1,7 @@
> > /*
> >  * arch/powerpc/math-emu/math_efp.c
> >  *
> > - * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. 
> All rights reserved.
> > + * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
> >  *
> >  * Author: Ebony Zhu,	<ebony.zhu@freescale.com>
> >  *         Yu Liu,	<yu.liu@freescale.com>
> > @@ -104,6 +104,8 @@
> > #define FP_EX_MASK	(FP_EX_INEXACT | FP_EX_INVALID | 
> FP_EX_DIVZERO | \
> > 			FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
> > 
> > +static int have_e500_cpu_a005_erratum;
> > +
> > union dw_union {
> > 	u64 dp[1];
> > 	u32 wp[2];
> > @@ -652,6 +654,15 @@ update_regs:
> > 	return 0;
> > 
> > illegal:
> > +	if (have_e500_cpu_a005_erratum) {
> > +		/* according to e500 cpu a005 erratum, reissue 
> efp inst */
> > +		regs->nip -= 4;
> > +#ifdef DEBUG
> > +		printk(KERN_DEBUG "re-issue efp inst: %08lx\n", 
> speinsn);
> > +#endif
> > +		return 0;
> > +	}
> > +
> > 	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler 
> encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
> > 	return -ENOSYS;
> > }
> > @@ -718,3 +729,43 @@ int speround_handler(struct pt_regs *regs)
> > 
> > 	return 0;
> > }
> > +
> > +int __init spe_mathemu_init(void)
> > +{
> > +	u32 pvr, maj, min;
> > +
> > +	pvr = mfspr(SPRN_PVR);
> > +
> > +	if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
> > +	    (PVR_VER(pvr) == PVR_VER_E500V2)) {
> > +		maj = PVR_MAJ(pvr);
> > +		min = PVR_MIN(pvr);
> > +
> > +		/*
> > +		 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
> > +		 * need cpu a005 errata workaround
> > +		 */
> 
> This isn't the way to do this.  We normally add entries in 
> cputable.c an add a new cpu_feature_bit for the errata.
> 
> Than above we'd do:
> 
> if (cur_cpu_spec->cpu_features & CPU_FTR_E500_A005_ERRATUM)
> 
> 

IMHO, a cpu erratum is not a cpu feature.
See there're only 32 bits can be used for all PowerPC platform to represent cpu feature, 
then is it worth consuming one of them to represent one e500 erratum?


Thanks,
Yu
Benjamin Herrenschmidt Feb. 6, 2011, 11:49 p.m. UTC | #3
> > 
> > This isn't the way to do this.  We normally add entries in 
> > cputable.c an add a new cpu_feature_bit for the errata.
> > 
> > Than above we'd do:
> > 
> > if (cur_cpu_spec->cpu_features & CPU_FTR_E500_A005_ERRATUM)
> > 
> > 
> 
> IMHO, a cpu erratum is not a cpu feature.
> See there're only 32 bits can be used for all PowerPC platform to represent cpu feature, 
> then is it worth consuming one of them to represent one e500 erratum?

This is an interesting debate :-)

We have used cpu_features for errata in the past. However, we are
getting a bit short and I'd rather keep CPU features for things
that are spread out in multiple places and/or hitting hot code path.

If the workaround is very limited to a single non-critical code path,
testing the PVR might actually be a nicer way to do it.

Now, this specific patch is ... hrm ... hard to decide. I don't like
that much the global variable. On the other hand, it's static and allows
the whole business of this errata to be completely local to the
math_efp.c file which is a good thing.

So I'm tempted to say go with the patch as it-is, but I'll let Kumar
ultimately decide.

Cheers,
Ben.
Kumar Gala March 15, 2011, 3:07 p.m. UTC | #4
On Jan 25, 2011, at 12:02 AM, Liu Yu wrote:

> This errata 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>
> ---
> This is an erratum workaround patch.
> It would be better if the patch can go into 2.6.38.
> 
> arch/powerpc/include/asm/reg.h   |    2 +
> arch/powerpc/math-emu/math_efp.c |   53 +++++++++++++++++++++++++++++++++++++-
> 2 files changed, 54 insertions(+), 1 deletions(-)

applied

- k
diff mbox

Patch

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 6315edc..0abfd91 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -833,6 +833,8 @@ 
 #define PVR_7450	0x80000000
 #define PVR_8540	0x80200000
 #define PVR_8560	0x80200000
+#define PVR_VER_E500V1	0x8020
+#define PVR_VER_E500V2	0x8021
 /*
  * For the 8xx processors, all of them report the same PVR family for
  * 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 41f4ef3..634830b 100644
--- a/arch/powerpc/math-emu/math_efp.c
+++ b/arch/powerpc/math-emu/math_efp.c
@@ -1,7 +1,7 @@ 
 /*
  * arch/powerpc/math-emu/math_efp.c
  *
- * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
  *
  * Author: Ebony Zhu,	<ebony.zhu@freescale.com>
  *         Yu Liu,	<yu.liu@freescale.com>
@@ -104,6 +104,8 @@ 
 #define FP_EX_MASK	(FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
 			FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
 
+static int have_e500_cpu_a005_erratum;
+
 union dw_union {
 	u64 dp[1];
 	u32 wp[2];
@@ -652,6 +654,15 @@  update_regs:
 	return 0;
 
 illegal:
+	if (have_e500_cpu_a005_erratum) {
+		/* according to e500 cpu a005 erratum, reissue efp inst */
+		regs->nip -= 4;
+#ifdef DEBUG
+		printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
+#endif
+		return 0;
+	}
+
 	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
 	return -ENOSYS;
 }
@@ -718,3 +729,43 @@  int speround_handler(struct pt_regs *regs)
 
 	return 0;
 }
+
+int __init spe_mathemu_init(void)
+{
+	u32 pvr, maj, min;
+
+	pvr = mfspr(SPRN_PVR);
+
+	if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
+	    (PVR_VER(pvr) == PVR_VER_E500V2)) {
+		maj = PVR_MAJ(pvr);
+		min = PVR_MIN(pvr);
+
+		/*
+		 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
+		 * need cpu a005 errata workaround
+		 */
+		switch (maj) {
+		case 1:
+			if (min < 1)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		case 2:
+			if (min < 3)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		case 3:
+		case 4:
+		case 5:
+			if (min < 1)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+module_init(spe_mathemu_init);