diff options
author | Andre Przywara <andre.przywara@arm.com> | 2014-11-14 10:54:11 -0500 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2014-11-25 10:56:42 -0500 |
commit | 5afaa1fc1b320cec48affa7e6949f2493f875c12 (patch) | |
tree | 6d7d20ce61c2939548c6b5105bc5130c4f7191ac /arch/arm64 | |
parent | 301bcfac42897dbd1b0b3c1be49f24654a1bc49e (diff) |
arm64: add Cortex-A57 erratum 832075 workaround
The ARM erratum 832075 applies to certain revisions of Cortex-A57,
one of the workarounds is to change device loads into using
load-aquire semantics.
This is achieved using the alternatives framework.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/include/asm/cpufeature.h | 5 | ||||
-rw-r--r-- | arch/arm64/include/asm/io.h | 23 | ||||
-rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 7 |
3 files changed, 29 insertions, 6 deletions
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 92b6ee44669b..0362f8020d46 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h | |||
@@ -21,9 +21,10 @@ | |||
21 | #define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) | 21 | #define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) |
22 | #define cpu_feature(x) ilog2(HWCAP_ ## x) | 22 | #define cpu_feature(x) ilog2(HWCAP_ ## x) |
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 | 26 | ||
26 | #define NCAPS 1 | 27 | #define NCAPS 2 |
27 | 28 | ||
28 | #ifndef __ASSEMBLY__ | 29 | #ifndef __ASSEMBLY__ |
29 | 30 | ||
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 79f1d519221f..75825b63464d 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <asm/barrier.h> | 28 | #include <asm/barrier.h> |
29 | #include <asm/pgtable.h> | 29 | #include <asm/pgtable.h> |
30 | #include <asm/early_ioremap.h> | 30 | #include <asm/early_ioremap.h> |
31 | #include <asm/alternative.h> | ||
32 | #include <asm/cpufeature.h> | ||
31 | 33 | ||
32 | #include <xen/xen.h> | 34 | #include <xen/xen.h> |
33 | 35 | ||
@@ -57,28 +59,41 @@ static inline void __raw_writeq(u64 val, volatile void __iomem *addr) | |||
57 | static inline u8 __raw_readb(const volatile void __iomem *addr) | 59 | static inline u8 __raw_readb(const volatile void __iomem *addr) |
58 | { | 60 | { |
59 | u8 val; | 61 | u8 val; |
60 | asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr)); | 62 | asm volatile(ALTERNATIVE("ldrb %w0, [%1]", |
63 | "ldarb %w0, [%1]", | ||
64 | ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) | ||
65 | : "=r" (val) : "r" (addr)); | ||
61 | return val; | 66 | return val; |
62 | } | 67 | } |
63 | 68 | ||
64 | static inline u16 __raw_readw(const volatile void __iomem *addr) | 69 | static inline u16 __raw_readw(const volatile void __iomem *addr) |
65 | { | 70 | { |
66 | u16 val; | 71 | u16 val; |
67 | asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr)); | 72 | |
73 | asm volatile(ALTERNATIVE("ldrh %w0, [%1]", | ||
74 | "ldarh %w0, [%1]", | ||
75 | ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) | ||
76 | : "=r" (val) : "r" (addr)); | ||
68 | return val; | 77 | return val; |
69 | } | 78 | } |
70 | 79 | ||
71 | static inline u32 __raw_readl(const volatile void __iomem *addr) | 80 | static inline u32 __raw_readl(const volatile void __iomem *addr) |
72 | { | 81 | { |
73 | u32 val; | 82 | u32 val; |
74 | asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr)); | 83 | asm volatile(ALTERNATIVE("ldr %w0, [%1]", |
84 | "ldar %w0, [%1]", | ||
85 | ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) | ||
86 | : "=r" (val) : "r" (addr)); | ||
75 | return val; | 87 | return val; |
76 | } | 88 | } |
77 | 89 | ||
78 | static inline u64 __raw_readq(const volatile void __iomem *addr) | 90 | static inline u64 __raw_readq(const volatile void __iomem *addr) |
79 | { | 91 | { |
80 | u64 val; | 92 | u64 val; |
81 | asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr)); | 93 | asm volatile(ALTERNATIVE("ldr %0, [%1]", |
94 | "ldar %0, [%1]", | ||
95 | ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) | ||
96 | : "=r" (val) : "r" (addr)); | ||
82 | return val; | 97 | return val; |
83 | } | 98 | } |
84 | 99 | ||
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index e107ed2d66dc..30935d2da55a 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/cpufeature.h> | 24 | #include <asm/cpufeature.h> |
25 | 25 | ||
26 | #define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) | 26 | #define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) |
27 | #define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * Add a struct or another datatype to the union below if you need | 30 | * Add a struct or another datatype to the union below if you need |
@@ -71,6 +72,12 @@ struct arm64_cpu_capabilities arm64_errata[] = { | |||
71 | MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02), | 72 | MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02), |
72 | }, | 73 | }, |
73 | { | 74 | { |
75 | /* Cortex-A57 r0p0 - r1p2 */ | ||
76 | .desc = "ARM erratum 832075", | ||
77 | .capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE, | ||
78 | MIDR_RANGE(MIDR_CORTEX_A57, 0x00, 0x12), | ||
79 | }, | ||
80 | { | ||
74 | } | 81 | } |
75 | }; | 82 | }; |
76 | 83 | ||