From 0741f1a58a1255531b0dcb1bea598b08112616e3 Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Tue, 13 Feb 2007 13:17:29 +0000 Subject: [PATCH] Workaround for the global I cache invalidation ARM1136 Errata Errata 411920 - Invalidation of the Instruction Cache operation can fail. This Errata is present in 1136, 1156 and 1176. It does not affect the MPCore. This patch implements the ARM Ltd recommended workaround. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- arch/arm/mm/cache-v6.S | 41 +++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/flush.c | 22 +++++++++++++++++----- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 2c6c2a7c05a..c9c4d7baad0 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -20,6 +20,39 @@ #define D_CACHE_LINE_SIZE 32 #define BTB_FLUSH_SIZE 8 +#ifndef CONFIG_SMP +/* + * Invalidate the entire I cache (this code is a workaround for the ARM1136 + * Errata 411920 - Invalidate Instruction Cache operation can fail. This + * Errata is present in 1136, 1156 and 1176. It does not affect the MPCore + * + * Registers: + * r0 - set to 0 + * r1 - corrupted + */ +ENTRY(v6_icache_inval_all) + mov r0, #0 + mrs r1, cpsr + cpsid ifa @ disable interrupts + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + msr cpsr_cx, r1 @ restore interrupts + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + mov pc, lr +#endif + /* * v6_flush_cache_all() * @@ -31,7 +64,11 @@ ENTRY(v6_flush_kern_cache_all) mov r0, #0 #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate +#ifdef CONFIG_SMP mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate +#else + b v6_icache_inval_all +#endif #else mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate #endif @@ -103,7 +140,11 @@ ENTRY(v6_coherent_user_range) mov r0, #0 #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c10, 4 @ drain write buffer +#ifdef CONFIG_SMP mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate +#else + b v6_icache_inval_all +#endif #else mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB #endif diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 454205b789d..1b33376e04b 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -31,10 +31,14 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) asm( "mcrr p15, 0, %1, %0, c14\n" " mcr p15, 0, %2, c7, c10, 4\n" +#if __LINUX_ARM_ARCH__ != 6 || defined(CONFIG_SMP) " mcr p15, 0, %2, c7, c5, 0\n" +#else + " bl v6_icache_inval_all\n" +#endif : : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero) - : "cc"); + : "r0", "r1", "lr"); } void flush_cache_mm(struct mm_struct *mm) @@ -47,11 +51,15 @@ void flush_cache_mm(struct mm_struct *mm) if (cache_is_vipt_aliasing()) { asm( "mcr p15, 0, %0, c7, c14, 0\n" + " mcr p15, 0, %0, c7, c10, 4\n" +#if __LINUX_ARM_ARCH__ != 6 || defined(CONFIG_SMP) " mcr p15, 0, %0, c7, c5, 0\n" - " mcr p15, 0, %0, c7, c10, 4" +#else + " bl v6_icache_inval_all\n" +#endif : : "r" (0) - : "cc"); + : "r0", "r1", "lr", "cc"); } } @@ -66,11 +74,15 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned if (cache_is_vipt_aliasing()) { asm( "mcr p15, 0, %0, c7, c14, 0\n" + " mcr p15, 0, %0, c7, c10, 4\n" +#if __LINUX_ARM_ARCH__ != 6 || defined(CONFIG_SMP) " mcr p15, 0, %0, c7, c5, 0\n" - " mcr p15, 0, %0, c7, c10, 4" +#else + " bl v6_icache_inval_all\n" +#endif : : "r" (0) - : "cc"); + : "r0", "r1", "lr", "cc"); } } -- 2.25.4