Commit 2c32c65e authored by Mark Rutland's avatar Mark Rutland Committed by Russell King

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: default avatarMark Rutland <mark.rutland@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 85868313
...@@ -472,7 +472,6 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size) ...@@ -472,7 +472,6 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)
"mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \ "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \
"isb \n\t" \ "isb \n\t" \
"bl v7_flush_dcache_"__stringify(level)" \n\t" \ "bl v7_flush_dcache_"__stringify(level)" \n\t" \
"clrex \n\t" \
"mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \ "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \
"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \ "bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \
"mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \ "mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \
......
...@@ -208,26 +208,21 @@ ...@@ -208,26 +208,21 @@
#endif #endif
.endif .endif
msr spsr_cxsf, \rpsr msr spsr_cxsf, \rpsr
#if defined(CONFIG_CPU_V6) #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
ldr r0, [sp] @ We must avoid clrex due to Cortex-A15 erratum #830321
strex r1, r2, [sp] @ clear the exclusive monitor sub r0, sp, #4 @ uninhabited address
ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr strex r1, r2, [r0] @ clear the exclusive monitor
#elif defined(CONFIG_CPU_32v6K)
clrex @ clear the exclusive monitor
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
#else
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
#endif #endif
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
.endm .endm
.macro restore_user_regs, fast = 0, offset = 0 .macro restore_user_regs, fast = 0, offset = 0
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
ldr lr, [sp, #\offset + S_PC]! @ get pc ldr lr, [sp, #\offset + S_PC]! @ get pc
msr spsr_cxsf, r1 @ save in spsr_svc msr spsr_cxsf, r1 @ save in spsr_svc
#if defined(CONFIG_CPU_V6) #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
@ We must avoid clrex due to Cortex-A15 erratum #830321
strex r1, r2, [sp] @ clear the exclusive monitor strex r1, r2, [sp] @ clear the exclusive monitor
#elif defined(CONFIG_CPU_32v6K)
clrex @ clear the exclusive monitor
#endif #endif
.if \fast .if \fast
ldmdb sp, {r1 - lr}^ @ get calling r1 - lr ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
...@@ -261,7 +256,10 @@ ...@@ -261,7 +256,10 @@
.endif .endif
ldr lr, [sp, #S_SP] @ top of the stack ldr lr, [sp, #S_SP] @ top of the stack
ldrd r0, r1, [sp, #S_LR] @ calling lr and pc ldrd r0, r1, [sp, #S_LR] @ calling lr and pc
clrex @ clear the exclusive monitor
@ We must avoid clrex due to Cortex-A15 erratum #830321
strex r2, r1, [sp, #S_LR] @ clear the exclusive monitor
stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context
ldmia sp, {r0 - r12} ldmia sp, {r0 - r12}
mov sp, lr mov sp, lr
...@@ -282,13 +280,16 @@ ...@@ -282,13 +280,16 @@
.endm .endm
#else /* ifdef CONFIG_CPU_V7M */ #else /* ifdef CONFIG_CPU_V7M */
.macro restore_user_regs, fast = 0, offset = 0 .macro restore_user_regs, fast = 0, offset = 0
clrex @ clear the exclusive monitor
mov r2, sp mov r2, sp
load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
ldr lr, [sp, #\offset + S_PC] @ get pc ldr lr, [sp, #\offset + S_PC] @ get pc
add sp, sp, #\offset + S_SP add sp, sp, #\offset + S_SP
msr spsr_cxsf, r1 @ save in spsr_svc msr spsr_cxsf, r1 @ save in spsr_svc
@ We must avoid clrex due to Cortex-A15 erratum #830321
strex r1, r2, [sp] @ clear the exclusive monitor
.if \fast .if \fast
ldmdb sp, {r1 - r12} @ get calling r1 - r12 ldmdb sp, {r1 - r12} @ get calling r1 - r12
.else .else
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
"mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \ "mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \
"isb\n\t"\ "isb\n\t"\
"bl v7_flush_dcache_"__stringify(level)"\n\t" \ "bl v7_flush_dcache_"__stringify(level)"\n\t" \
"clrex\n\t"\
"mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \ "mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \
"bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \ "bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \
/* Dummy Load of a device register to avoid Erratum 799270 */ \ /* Dummy Load of a device register to avoid Erratum 799270 */ \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment