[PATCH] e500: Erratum cpu a005 workaround

Kumar Gala kumar.gala at freescale.com
Tue Jan 25 18:01:23 EST 2011


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 at 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 at freescale.com>
>  *         Yu Liu,	<yu.liu at 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




More information about the Linuxppc-dev mailing list