[ARM] 5488/1: ARM errata: Invalidation of the Instruction Cache operation can fail
This patch implements the recommended workaround for erratum 411920 (ARM1136, ARM1156, ARM1176). Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
10993374f8
commit
9cba3ccc8f
@ -740,6 +740,15 @@ if !MMU
|
|||||||
source "arch/arm/Kconfig-nommu"
|
source "arch/arm/Kconfig-nommu"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
config ARM_ERRATA_411920
|
||||||
|
bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
|
||||||
|
depends on CPU_V6 && !SMP
|
||||||
|
help
|
||||||
|
Invalidation of the Instruction Cache operation can
|
||||||
|
fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
|
||||||
|
It does not affect the MPCore. This option enables the ARM Ltd.
|
||||||
|
recommended workaround.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
source "arch/arm/common/Kconfig"
|
source "arch/arm/common/Kconfig"
|
||||||
|
@ -20,6 +20,31 @@
|
|||||||
#define D_CACHE_LINE_SIZE 32
|
#define D_CACHE_LINE_SIZE 32
|
||||||
#define BTB_FLUSH_SIZE 8
|
#define BTB_FLUSH_SIZE 8
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_411920
|
||||||
|
/*
|
||||||
|
* Invalidate the entire I cache (this code is a workaround for the ARM1136
|
||||||
|
* erratum 411920 - Invalidate Instruction Cache operation can fail. This
|
||||||
|
* erratum 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
|
||||||
|
.rept 11 @ ARM Ltd recommends at least
|
||||||
|
nop @ 11 NOPs
|
||||||
|
.endr
|
||||||
|
mov pc, lr
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* v6_flush_cache_all()
|
* v6_flush_cache_all()
|
||||||
*
|
*
|
||||||
@ -31,7 +56,11 @@ ENTRY(v6_flush_kern_cache_all)
|
|||||||
mov r0, #0
|
mov r0, #0
|
||||||
#ifdef HARVARD_CACHE
|
#ifdef HARVARD_CACHE
|
||||||
mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate
|
mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate
|
||||||
|
#ifndef CONFIG_ARM_ERRATA_411920
|
||||||
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
||||||
|
#else
|
||||||
|
b v6_icache_inval_all
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
|
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
|
||||||
#endif
|
#endif
|
||||||
@ -103,7 +132,11 @@ ENTRY(v6_coherent_user_range)
|
|||||||
mov r0, #0
|
mov r0, #0
|
||||||
#ifdef HARVARD_CACHE
|
#ifdef HARVARD_CACHE
|
||||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||||
|
#ifndef CONFIG_ARM_ERRATA_411920
|
||||||
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
||||||
|
#else
|
||||||
|
b v6_icache_inval_all
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
|
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
|
|
||||||
#include "mm.h"
|
#include "mm.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_411920
|
||||||
|
extern void v6_icache_inval_all(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_CACHE_VIPT
|
#ifdef CONFIG_CPU_CACHE_VIPT
|
||||||
|
|
||||||
#define ALIAS_FLUSH_START 0xffff4000
|
#define ALIAS_FLUSH_START 0xffff4000
|
||||||
@ -32,10 +36,15 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
|
|||||||
|
|
||||||
asm( "mcrr p15, 0, %1, %0, c14\n"
|
asm( "mcrr p15, 0, %1, %0, c14\n"
|
||||||
" mcr p15, 0, %2, c7, c10, 4\n"
|
" mcr p15, 0, %2, c7, c10, 4\n"
|
||||||
|
#ifndef CONFIG_ARM_ERRATA_411920
|
||||||
" mcr p15, 0, %2, c7, c5, 0\n"
|
" mcr p15, 0, %2, c7, c5, 0\n"
|
||||||
|
#endif
|
||||||
:
|
:
|
||||||
: "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
|
: "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
|
||||||
: "cc");
|
: "cc");
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_411920
|
||||||
|
v6_icache_inval_all();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush_cache_mm(struct mm_struct *mm)
|
void flush_cache_mm(struct mm_struct *mm)
|
||||||
@ -48,11 +57,16 @@ void flush_cache_mm(struct mm_struct *mm)
|
|||||||
|
|
||||||
if (cache_is_vipt_aliasing()) {
|
if (cache_is_vipt_aliasing()) {
|
||||||
asm( "mcr p15, 0, %0, c7, c14, 0\n"
|
asm( "mcr p15, 0, %0, c7, c14, 0\n"
|
||||||
|
" mcr p15, 0, %0, c7, c10, 4\n"
|
||||||
|
#ifndef CONFIG_ARM_ERRATA_411920
|
||||||
" mcr p15, 0, %0, c7, c5, 0\n"
|
" mcr p15, 0, %0, c7, c5, 0\n"
|
||||||
" mcr p15, 0, %0, c7, c10, 4"
|
#endif
|
||||||
:
|
:
|
||||||
: "r" (0)
|
: "r" (0)
|
||||||
: "cc");
|
: "cc");
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_411920
|
||||||
|
v6_icache_inval_all();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +81,16 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned
|
|||||||
|
|
||||||
if (cache_is_vipt_aliasing()) {
|
if (cache_is_vipt_aliasing()) {
|
||||||
asm( "mcr p15, 0, %0, c7, c14, 0\n"
|
asm( "mcr p15, 0, %0, c7, c14, 0\n"
|
||||||
|
" mcr p15, 0, %0, c7, c10, 4\n"
|
||||||
|
#ifndef CONFIG_ARM_ERRATA_411920
|
||||||
" mcr p15, 0, %0, c7, c5, 0\n"
|
" mcr p15, 0, %0, c7, c5, 0\n"
|
||||||
" mcr p15, 0, %0, c7, c10, 4"
|
#endif
|
||||||
:
|
:
|
||||||
: "r" (0)
|
: "r" (0)
|
||||||
: "cc");
|
: "cc");
|
||||||
|
#ifdef CONFIG_ARM_ERRATA_411920
|
||||||
|
v6_icache_inval_all();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user