[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