diff options
author | Mark Rutland <mark.rutland@arm.com> | 2014-08-15 07:11:50 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-08-27 10:40:13 -0400 |
commit | 2c32c65e3726c773760038910be30cce1b4d4149 (patch) | |
tree | 5882204a965a7b819f20bc8cc7ae33088d3bde88 /arch/arm | |
parent | 85868313177700d20644263a782351262d2aff84 (diff) |
ARM: 8129/1: errata: work around Cortex-A15 erratum 830321 using dummy strex
On revisions of Cortex-A15 prior to r3p3, a CLREX instruction at PL1 may
falsely trigger a watchpoint exception, leading to potential data aborts
during exception return and/or livelock.
This patch resolves the issue in the following ways:
- Replacing our uses of CLREX with a dummy STREX sequence instead (as
we did for v6 CPUs).
- Removing the clrex code from v7_exit_coherency_flush and derivatives,
since this only exists as a minor performance improvement when
non-cached exclusives are in use (Linux doesn't use these).
Benchmarking on a variety of ARM cores revealed no measurable
performance difference with this change applied, so the change is
performed unconditionally and no new Kconfig entry is added.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Cc: stable@vger.kernel.org
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/cacheflush.h | 1 | ||||
-rw-r--r-- | arch/arm/kernel/entry-header.S | 29 | ||||
-rw-r--r-- | arch/arm/mach-exynos/mcpm-exynos.c | 1 |
3 files changed, 15 insertions, 16 deletions
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index fd43f7f55b70..79ecb4f34ffb 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -472,7 +472,6 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size) | |||
472 | "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \ | 472 | "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \ |
473 | "isb \n\t" \ | 473 | "isb \n\t" \ |
474 | "bl v7_flush_dcache_"__stringify(level)" \n\t" \ | 474 | "bl v7_flush_dcache_"__stringify(level)" \n\t" \ |
475 | "clrex \n\t" \ | ||
476 | "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \ | 475 | "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \ |
477 | "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ | 476 | "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ |
478 | "mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \ | 477 | "mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \ |
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 8db307d0954b..2fdf8679b46e 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S | |||
@@ -208,26 +208,21 @@ | |||
208 | #endif | 208 | #endif |
209 | .endif | 209 | .endif |
210 | msr spsr_cxsf, \rpsr | 210 | msr spsr_cxsf, \rpsr |
211 | #if defined(CONFIG_CPU_V6) | 211 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) |
212 | ldr r0, [sp] | 212 | @ We must avoid clrex due to Cortex-A15 erratum #830321 |
213 | strex r1, r2, [sp] @ clear the exclusive monitor | 213 | sub r0, sp, #4 @ uninhabited address |
214 | ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr | 214 | strex r1, r2, [r0] @ clear the exclusive monitor |
215 | #elif defined(CONFIG_CPU_32v6K) | ||
216 | clrex @ clear the exclusive monitor | ||
217 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr | ||
218 | #else | ||
219 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr | ||
220 | #endif | 215 | #endif |
216 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr | ||
221 | .endm | 217 | .endm |
222 | 218 | ||
223 | .macro restore_user_regs, fast = 0, offset = 0 | 219 | .macro restore_user_regs, fast = 0, offset = 0 |
224 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr | 220 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr |
225 | ldr lr, [sp, #\offset + S_PC]! @ get pc | 221 | ldr lr, [sp, #\offset + S_PC]! @ get pc |
226 | msr spsr_cxsf, r1 @ save in spsr_svc | 222 | msr spsr_cxsf, r1 @ save in spsr_svc |
227 | #if defined(CONFIG_CPU_V6) | 223 | #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) |
224 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | ||
228 | strex r1, r2, [sp] @ clear the exclusive monitor | 225 | strex r1, r2, [sp] @ clear the exclusive monitor |
229 | #elif defined(CONFIG_CPU_32v6K) | ||
230 | clrex @ clear the exclusive monitor | ||
231 | #endif | 226 | #endif |
232 | .if \fast | 227 | .if \fast |
233 | ldmdb sp, {r1 - lr}^ @ get calling r1 - lr | 228 | ldmdb sp, {r1 - lr}^ @ get calling r1 - lr |
@@ -261,7 +256,10 @@ | |||
261 | .endif | 256 | .endif |
262 | ldr lr, [sp, #S_SP] @ top of the stack | 257 | ldr lr, [sp, #S_SP] @ top of the stack |
263 | ldrd r0, r1, [sp, #S_LR] @ calling lr and pc | 258 | ldrd r0, r1, [sp, #S_LR] @ calling lr and pc |
264 | clrex @ clear the exclusive monitor | 259 | |
260 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | ||
261 | strex r2, r1, [sp, #S_LR] @ clear the exclusive monitor | ||
262 | |||
265 | stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context | 263 | stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context |
266 | ldmia sp, {r0 - r12} | 264 | ldmia sp, {r0 - r12} |
267 | mov sp, lr | 265 | mov sp, lr |
@@ -282,13 +280,16 @@ | |||
282 | .endm | 280 | .endm |
283 | #else /* ifdef CONFIG_CPU_V7M */ | 281 | #else /* ifdef CONFIG_CPU_V7M */ |
284 | .macro restore_user_regs, fast = 0, offset = 0 | 282 | .macro restore_user_regs, fast = 0, offset = 0 |
285 | clrex @ clear the exclusive monitor | ||
286 | mov r2, sp | 283 | mov r2, sp |
287 | load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr | 284 | load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr |
288 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr | 285 | ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr |
289 | ldr lr, [sp, #\offset + S_PC] @ get pc | 286 | ldr lr, [sp, #\offset + S_PC] @ get pc |
290 | add sp, sp, #\offset + S_SP | 287 | add sp, sp, #\offset + S_SP |
291 | msr spsr_cxsf, r1 @ save in spsr_svc | 288 | msr spsr_cxsf, r1 @ save in spsr_svc |
289 | |||
290 | @ We must avoid clrex due to Cortex-A15 erratum #830321 | ||
291 | strex r1, r2, [sp] @ clear the exclusive monitor | ||
292 | |||
292 | .if \fast | 293 | .if \fast |
293 | ldmdb sp, {r1 - r12} @ get calling r1 - r12 | 294 | ldmdb sp, {r1 - r12} @ get calling r1 - r12 |
294 | .else | 295 | .else |
diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c index b2f8b60cf0e9..dc9a764a7c37 100644 --- a/arch/arm/mach-exynos/mcpm-exynos.c +++ b/arch/arm/mach-exynos/mcpm-exynos.c | |||
@@ -43,7 +43,6 @@ | |||
43 | "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \ | 43 | "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \ |
44 | "isb\n\t"\ | 44 | "isb\n\t"\ |
45 | "bl v7_flush_dcache_"__stringify(level)"\n\t" \ | 45 | "bl v7_flush_dcache_"__stringify(level)"\n\t" \ |
46 | "clrex\n\t"\ | ||
47 | "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \ | 46 | "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \ |
48 | "bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \ | 47 | "bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \ |
49 | /* Dummy Load of a device register to avoid Erratum 799270 */ \ | 48 | /* Dummy Load of a device register to avoid Erratum 799270 */ \ |