diff options
author | Will Deacon <will.deacon@arm.com> | 2012-04-20 12:20:08 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-04-23 09:21:52 -0400 |
commit | f0c4b8d653f5ee091fb8d4d02ed7eaad397491bb (patch) | |
tree | cc7f1d1be2354dee506453f63f92a878384f30a8 /arch | |
parent | e895bd7992df1ebd1e0c28f7965520482bc83b74 (diff) |
ARM: 7396/1: errata: only handle ARM erratum #326103 on affected cores
Erratum #326103 ("FSR write bit incorrect on a SWP to read-only memory")
only affects the ARM 1136 core prior to r1p0. The workaround
disassembles the faulting instruction to determine whether it was a read
or write access on all v6 cores.
An issue has been reported on the ARM 11MPCore whereby loading the
faulting instruction may happen in parallel with that page being
unmapped, resulting in a deadlock due to the lack of TLB broadcasting
in hardware:
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-March/091561.html
This patch limits the workaround so that it is only used on affected
cores, which are known to be UP only. Other v6 cores can rely on the
FSR to indicate the access type correctly.
Cc: stable@vger.kernel.org
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/Kconfig | 9 | ||||
-rw-r--r-- | arch/arm/mm/abort-ev6.S | 17 |
2 files changed, 20 insertions, 6 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index cf006d40342c..36586dba6fa6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1186,6 +1186,15 @@ if !MMU | |||
1186 | source "arch/arm/Kconfig-nommu" | 1186 | source "arch/arm/Kconfig-nommu" |
1187 | endif | 1187 | endif |
1188 | 1188 | ||
1189 | config ARM_ERRATA_326103 | ||
1190 | bool "ARM errata: FSR write bit incorrect on a SWP to read-only memory" | ||
1191 | depends on CPU_V6 | ||
1192 | help | ||
1193 | Executing a SWP instruction to read-only memory does not set bit 11 | ||
1194 | of the FSR on the ARM 1136 prior to r1p0. This causes the kernel to | ||
1195 | treat the access as a read, preventing a COW from occurring and | ||
1196 | causing the faulting task to livelock. | ||
1197 | |||
1189 | config ARM_ERRATA_411920 | 1198 | config ARM_ERRATA_411920 |
1190 | bool "ARM errata: Invalidation of the Instruction Cache operation can fail" | 1199 | bool "ARM errata: Invalidation of the Instruction Cache operation can fail" |
1191 | depends on CPU_V6 || CPU_V6K | 1200 | depends on CPU_V6 || CPU_V6K |
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index ff1f7cc11f87..80741992a9fc 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S | |||
@@ -26,18 +26,23 @@ ENTRY(v6_early_abort) | |||
26 | mrc p15, 0, r1, c5, c0, 0 @ get FSR | 26 | mrc p15, 0, r1, c5, c0, 0 @ get FSR |
27 | mrc p15, 0, r0, c6, c0, 0 @ get FAR | 27 | mrc p15, 0, r0, c6, c0, 0 @ get FAR |
28 | /* | 28 | /* |
29 | * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR (erratum 326103). | 29 | * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR. |
30 | * The test below covers all the write situations, including Java bytecodes | ||
31 | */ | 30 | */ |
32 | bic r1, r1, #1 << 11 @ clear bit 11 of FSR | 31 | #ifdef CONFIG_ARM_ERRATA_326103 |
32 | ldr ip, =0x4107b36 | ||
33 | mrc p15, 0, r3, c0, c0, 0 @ get processor id | ||
34 | teq ip, r3, lsr #4 @ r0 ARM1136? | ||
35 | bne do_DataAbort | ||
33 | tst r5, #PSR_J_BIT @ Java? | 36 | tst r5, #PSR_J_BIT @ Java? |
37 | tsteq r5, #PSR_T_BIT @ Thumb? | ||
34 | bne do_DataAbort | 38 | bne do_DataAbort |
35 | do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 | 39 | bic r1, r1, #1 << 11 @ clear bit 11 of FSR |
36 | ldreq r3, [r4] @ read aborted ARM instruction | 40 | ldr r3, [r4] @ read aborted ARM instruction |
37 | #ifdef CONFIG_CPU_ENDIAN_BE8 | 41 | #ifdef CONFIG_CPU_ENDIAN_BE8 |
38 | reveq r3, r3 | 42 | rev r3, r3 |
39 | #endif | 43 | #endif |
40 | do_ldrd_abort tmp=ip, insn=r3 | 44 | do_ldrd_abort tmp=ip, insn=r3 |
41 | tst r3, #1 << 20 @ L = 0 -> write | 45 | tst r3, #1 << 20 @ L = 0 -> write |
42 | orreq r1, r1, #1 << 11 @ yes. | 46 | orreq r1, r1, #1 << 11 @ yes. |
47 | #endif | ||
43 | b do_DataAbort | 48 | b do_DataAbort |