diff options
author | Will Deacon <will.deacon@arm.com> | 2015-03-23 15:07:02 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2015-04-01 05:24:31 -0400 |
commit | 905e8c5dcaa147163672b06fe9dcb5abaacbc711 (patch) | |
tree | 4284f6e2ecac493b6e4938e4b60e57fb521c3790 /arch/arm64 | |
parent | cc3979b54d5f1d5b5059b404892888c304d28080 (diff) |
arm64: errata: add workaround for cortex-a53 erratum #845719
When running a compat (AArch32) userspace on Cortex-A53, a load at EL0
from a virtual address that matches the bottom 32 bits of the virtual
address used by a recent load at (AArch64) EL1 might return incorrect
data.
This patch works around the issue by writing to the contextidr_el1
register on the exception return path when returning to a 32-bit task.
This workaround is patched in at runtime based on the MIDR value of the
processor.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/Kconfig | 21 | ||||
-rw-r--r-- | arch/arm64/include/asm/cpufeature.h | 3 | ||||
-rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 8 | ||||
-rw-r--r-- | arch/arm64/kernel/entry.S | 20 |
4 files changed, 51 insertions, 1 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 02f67a9d7426..23d51be7d60a 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -361,6 +361,27 @@ config ARM64_ERRATUM_832075 | |||
361 | 361 | ||
362 | If unsure, say Y. | 362 | If unsure, say Y. |
363 | 363 | ||
364 | config ARM64_ERRATUM_845719 | ||
365 | bool "Cortex-A53: 845719: a load might read incorrect data" | ||
366 | depends on COMPAT | ||
367 | default y | ||
368 | help | ||
369 | This option adds an alternative code sequence to work around ARM | ||
370 | erratum 845719 on Cortex-A53 parts up to r0p4. | ||
371 | |||
372 | When running a compat (AArch32) userspace on an affected Cortex-A53 | ||
373 | part, a load at EL0 from a virtual address that matches the bottom 32 | ||
374 | bits of the virtual address used by a recent load at (AArch64) EL1 | ||
375 | might return incorrect data. | ||
376 | |||
377 | The workaround is to write the contextidr_el1 register on exception | ||
378 | return to a 32-bit task. | ||
379 | Please note that this does not necessarily enable the workaround, | ||
380 | as it depends on the alternative framework, which will only patch | ||
381 | the kernel if an affected CPU is detected. | ||
382 | |||
383 | If unsure, say Y. | ||
384 | |||
364 | endmenu | 385 | endmenu |
365 | 386 | ||
366 | 387 | ||
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 6ae35d160464..82cb9f98ba1a 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h | |||
@@ -23,8 +23,9 @@ | |||
23 | 23 | ||
24 | #define ARM64_WORKAROUND_CLEAN_CACHE 0 | 24 | #define ARM64_WORKAROUND_CLEAN_CACHE 0 |
25 | #define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1 | 25 | #define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1 |
26 | #define ARM64_WORKAROUND_845719 2 | ||
26 | 27 | ||
27 | #define ARM64_NCAPS 2 | 28 | #define ARM64_NCAPS 3 |
28 | 29 | ||
29 | #ifndef __ASSEMBLY__ | 30 | #ifndef __ASSEMBLY__ |
30 | 31 | ||
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index a66f4fa4d541..4672860def1f 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c | |||
@@ -73,6 +73,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { | |||
73 | MIDR_RANGE(MIDR_CORTEX_A57, 0x00, 0x12), | 73 | MIDR_RANGE(MIDR_CORTEX_A57, 0x00, 0x12), |
74 | }, | 74 | }, |
75 | #endif | 75 | #endif |
76 | #ifdef CONFIG_ARM64_ERRATUM_845719 | ||
77 | { | ||
78 | /* Cortex-A53 r0p[01234] */ | ||
79 | .desc = "ARM erratum 845719", | ||
80 | .capability = ARM64_WORKAROUND_845719, | ||
81 | MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04), | ||
82 | }, | ||
83 | #endif | ||
76 | { | 84 | { |
77 | } | 85 | } |
78 | }; | 86 | }; |
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index cf21bb3bf752..959fe8733560 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S | |||
@@ -21,8 +21,10 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/linkage.h> | 22 | #include <linux/linkage.h> |
23 | 23 | ||
24 | #include <asm/alternative-asm.h> | ||
24 | #include <asm/assembler.h> | 25 | #include <asm/assembler.h> |
25 | #include <asm/asm-offsets.h> | 26 | #include <asm/asm-offsets.h> |
27 | #include <asm/cpufeature.h> | ||
26 | #include <asm/errno.h> | 28 | #include <asm/errno.h> |
27 | #include <asm/esr.h> | 29 | #include <asm/esr.h> |
28 | #include <asm/thread_info.h> | 30 | #include <asm/thread_info.h> |
@@ -120,6 +122,24 @@ | |||
120 | ct_user_enter | 122 | ct_user_enter |
121 | ldr x23, [sp, #S_SP] // load return stack pointer | 123 | ldr x23, [sp, #S_SP] // load return stack pointer |
122 | msr sp_el0, x23 | 124 | msr sp_el0, x23 |
125 | |||
126 | #ifdef CONFIG_ARM64_ERRATUM_845719 | ||
127 | alternative_insn \ | ||
128 | "nop", \ | ||
129 | "tbz x22, #4, 1f", \ | ||
130 | ARM64_WORKAROUND_845719 | ||
131 | #ifdef CONFIG_PID_IN_CONTEXTIDR | ||
132 | alternative_insn \ | ||
133 | "nop; nop", \ | ||
134 | "mrs x29, contextidr_el1; msr contextidr_el1, x29; 1:", \ | ||
135 | ARM64_WORKAROUND_845719 | ||
136 | #else | ||
137 | alternative_insn \ | ||
138 | "nop", \ | ||
139 | "msr contextidr_el1, xzr; 1:", \ | ||
140 | ARM64_WORKAROUND_845719 | ||
141 | #endif | ||
142 | #endif | ||
123 | .endif | 143 | .endif |
124 | msr elr_el1, x21 // set up the return data | 144 | msr elr_el1, x21 // set up the return data |
125 | msr spsr_el1, x22 | 145 | msr spsr_el1, x22 |