[PATCH 2/5] ARM: 7855/1: Add check for Cortex-A15 errata 798181 ECO

Andy Whitcroft apw at canonical.com
Thu Nov 7 14:26:19 UTC 2013


On Wed, Nov 06, 2013 at 03:34:44PM +0100, Paolo Pisati wrote:
> From: Rob Herring <rob.herring at calxeda.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1239800
> 
> The work-around for A15 errata 798181 is not needed if appropriate ECO
> fixes have been applied to r3p2 and earlier core revisions. This can be
> checked by reading REVIDR register bits 4 and 9. If only bit 4 is set,
> then the IPI broadcast can be skipped.
> 
> Signed-off-by: Rob Herring <rob.herring at calxeda.com>
> Reviewed-by: Will Deacon <will.deacon at arm.com>
> Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> (cherry picked from commit 92871b94a5f9892e324c31960678387922c75049 via rmk's
> tree http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm.git
> for-next)
> Signed-off-by: Paolo Pisati <paolo.pisati at canonical.com>
> ---
>  arch/arm/include/asm/cputype.h  |  1 +
>  arch/arm/include/asm/tlbflush.h | 48 +++++++++++++++--------------------------
>  arch/arm/kernel/setup.c         |  2 ++
>  arch/arm/kernel/smp_tlb.c       | 36 +++++++++++++++++++++++++++++--
>  4 files changed, 54 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
> index 9672e97..acdde76 100644
> --- a/arch/arm/include/asm/cputype.h
> +++ b/arch/arm/include/asm/cputype.h
> @@ -10,6 +10,7 @@
>  #define CPUID_TLBTYPE	3
>  #define CPUID_MPUIR	4
>  #define CPUID_MPIDR	5
> +#define CPUID_REVIDR	6
>  
>  #ifdef CONFIG_CPU_V7M
>  #define CPUID_EXT_PFR0	0x40
> diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
> index 3316264..deba3a0 100644
> --- a/arch/arm/include/asm/tlbflush.h
> +++ b/arch/arm/include/asm/tlbflush.h
> @@ -541,37 +541,6 @@ static inline void local_flush_bp_all(void)
>  		isb();
>  }
>  
> -#include <asm/cputype.h>
> -#ifdef CONFIG_ARM_ERRATA_798181
> -static inline int erratum_a15_798181(void)
> -{
> -	unsigned int midr = read_cpuid_id();
> -
> -	/* Cortex-A15 r0p0..r3p2 affected */
> -	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
> -		return 0;
> -	return 1;
> -}
> -
> -static inline void dummy_flush_tlb_a15_erratum(void)
> -{
> -	/*
> -	 * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
> -	 */
> -	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
> -	dsb();
> -}
> -#else
> -static inline int erratum_a15_798181(void)
> -{
> -	return 0;
> -}
> -
> -static inline void dummy_flush_tlb_a15_erratum(void)
> -{
> -}
> -#endif
> -
>  /*
>   *	flush_pmd_entry
>   *
> @@ -678,4 +647,21 @@ extern void flush_bp_all(void);
>  
>  #endif
>  
> +#ifndef __ASSEMBLY__
> +#ifdef CONFIG_ARM_ERRATA_798181
> +extern void erratum_a15_798181_init(void);
> +#else
> +static inline void erratum_a15_798181_init(void) {}
> +#endif
> +extern bool (*erratum_a15_798181_handler)(void);
> +
> +static inline bool erratum_a15_798181(void)
> +{
> +	if (unlikely(IS_ENABLED(CONFIG_ARM_ERRATA_798181) &&
> +		erratum_a15_798181_handler))
> +		return erratum_a15_798181_handler();
> +	return false;
> +}
> +#endif
> +
>  #endif
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index afc2489..f3030e3 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -599,6 +599,8 @@ static void __init setup_processor(void)
>  	elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
>  #endif
>  
> +	erratum_a15_798181_init();
> +
>  	feat_v6_fixup();
>  
>  	cacheid_init();
> diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
> index 5883b8a..a1c2dc9 100644
> --- a/arch/arm/kernel/smp_tlb.c
> +++ b/arch/arm/kernel/smp_tlb.c
> @@ -70,6 +70,40 @@ static inline void ipi_flush_bp_all(void *ignored)
>  	local_flush_bp_all();
>  }
>  
> +#ifdef CONFIG_ARM_ERRATA_798181
> +bool (*erratum_a15_798181_handler)(void);
> +
> +static bool erratum_a15_798181_partial(void)
> +{
> +	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
> +	dsb();
> +	return false;
> +}
> +
> +static bool erratum_a15_798181_broadcast(void)
> +{
> +	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
> +	dsb();
> +	return true;
> +}
> +
> +void erratum_a15_798181_init(void)
> +{
> +	unsigned int midr = read_cpuid_id();
> +	unsigned int revidr = read_cpuid(CPUID_REVIDR);
> +
> +	/* Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
> +	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2 ||
> +	    (revidr & 0x210) == 0x210) {
> +		return;
> +	}
> +	if (revidr & 0x10)
> +		erratum_a15_798181_handler = erratum_a15_798181_partial;
> +	else
> +		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
> +}
> +#endif
> +
>  static void ipi_flush_tlb_a15_erratum(void *arg)
>  {
>  	dmb();
> @@ -80,7 +114,6 @@ static void broadcast_tlb_a15_erratum(void)
>  	if (!erratum_a15_798181())
>  		return;
>  
> -	dummy_flush_tlb_a15_erratum();
>  	smp_call_function(ipi_flush_tlb_a15_erratum, NULL, 1);
>  }
>  
> @@ -92,7 +125,6 @@ static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
>  	if (!erratum_a15_798181())
>  		return;
>  
> -	dummy_flush_tlb_a15_erratum();
>  	this_cpu = get_cpu();
>  	a15_erratum_get_cpumask(this_cpu, mm, &mask);
>  	smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);

Looks reasonable.

-apw




More information about the kernel-team mailing list