diff options
author | Will Deacon <will.deacon@arm.com> | 2019-05-01 10:45:36 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2019-05-01 10:45:36 -0400 |
commit | 24cf262da1ad303fc940c798aab0bd1bd50e3fc2 (patch) | |
tree | da38a3ae51128dfb959fb53d633201ab4ffb4209 | |
parent | 50abbe19623e08e2aa34e0e526bd6115569f3dc3 (diff) | |
parent | 0ea415390cd345b7d09e8c9ebd4b68adfe873043 (diff) |
Merge branch 'for-next/timers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux into for-next/core
Conflicts:
arch/arm64/Kconfig
arch/arm64/include/asm/arch_timer.h
-rw-r--r-- | Documentation/arm64/silicon-errata.txt | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/arch_timer.h | 18 | ||||
-rw-r--r-- | arch/arm/include/asm/cp15.h | 2 | ||||
-rw-r--r-- | arch/arm/vdso/vgettimeofday.c | 5 | ||||
-rw-r--r-- | arch/arm64/Kconfig | 12 | ||||
-rw-r--r-- | arch/arm64/include/asm/arch_timer.h | 86 | ||||
-rw-r--r-- | arch/arm64/include/asm/cputype.h | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 13 | ||||
-rw-r--r-- | arch/arm64/kernel/entry.S | 19 | ||||
-rw-r--r-- | arch/arm64/kernel/traps.c | 4 | ||||
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 130 | ||||
-rw-r--r-- | drivers/watchdog/sbsa_gwdt.c | 2 |
12 files changed, 185 insertions, 109 deletions
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt index d1e2bb801e1b..d5a124d7e242 100644 --- a/Documentation/arm64/silicon-errata.txt +++ b/Documentation/arm64/silicon-errata.txt | |||
@@ -61,6 +61,7 @@ stable kernels. | |||
61 | | ARM | Cortex-A76 | #1188873 | ARM64_ERRATUM_1188873 | | 61 | | ARM | Cortex-A76 | #1188873 | ARM64_ERRATUM_1188873 | |
62 | | ARM | Cortex-A76 | #1165522 | ARM64_ERRATUM_1165522 | | 62 | | ARM | Cortex-A76 | #1165522 | ARM64_ERRATUM_1165522 | |
63 | | ARM | Cortex-A76 | #1286807 | ARM64_ERRATUM_1286807 | | 63 | | ARM | Cortex-A76 | #1286807 | ARM64_ERRATUM_1286807 | |
64 | | ARM | Neoverse-N1 | #1188873 | ARM64_ERRATUM_1188873 | | ||
64 | | ARM | MMU-500 | #841119,#826419 | N/A | | 65 | | ARM | MMU-500 | #841119,#826419 | N/A | |
65 | | | | | | | 66 | | | | | | |
66 | | Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 | | 67 | | Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 | |
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 0a8d7bba2cb0..4b66ecd6be99 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h | |||
@@ -11,6 +11,10 @@ | |||
11 | #include <clocksource/arm_arch_timer.h> | 11 | #include <clocksource/arm_arch_timer.h> |
12 | 12 | ||
13 | #ifdef CONFIG_ARM_ARCH_TIMER | 13 | #ifdef CONFIG_ARM_ARCH_TIMER |
14 | /* 32bit ARM doesn't know anything about timer errata... */ | ||
15 | #define has_erratum_handler(h) (false) | ||
16 | #define erratum_handler(h) (arch_timer_##h) | ||
17 | |||
14 | int arch_timer_arch_init(void); | 18 | int arch_timer_arch_init(void); |
15 | 19 | ||
16 | /* | 20 | /* |
@@ -79,7 +83,7 @@ static inline u32 arch_timer_get_cntfrq(void) | |||
79 | return val; | 83 | return val; |
80 | } | 84 | } |
81 | 85 | ||
82 | static inline u64 arch_counter_get_cntpct(void) | 86 | static inline u64 __arch_counter_get_cntpct(void) |
83 | { | 87 | { |
84 | u64 cval; | 88 | u64 cval; |
85 | 89 | ||
@@ -88,7 +92,12 @@ static inline u64 arch_counter_get_cntpct(void) | |||
88 | return cval; | 92 | return cval; |
89 | } | 93 | } |
90 | 94 | ||
91 | static inline u64 arch_counter_get_cntvct(void) | 95 | static inline u64 __arch_counter_get_cntpct_stable(void) |
96 | { | ||
97 | return __arch_counter_get_cntpct(); | ||
98 | } | ||
99 | |||
100 | static inline u64 __arch_counter_get_cntvct(void) | ||
92 | { | 101 | { |
93 | u64 cval; | 102 | u64 cval; |
94 | 103 | ||
@@ -97,6 +106,11 @@ static inline u64 arch_counter_get_cntvct(void) | |||
97 | return cval; | 106 | return cval; |
98 | } | 107 | } |
99 | 108 | ||
109 | static inline u64 __arch_counter_get_cntvct_stable(void) | ||
110 | { | ||
111 | return __arch_counter_get_cntvct(); | ||
112 | } | ||
113 | |||
100 | static inline u32 arch_timer_get_cntkctl(void) | 114 | static inline u32 arch_timer_get_cntkctl(void) |
101 | { | 115 | { |
102 | u32 cntkctl; | 116 | u32 cntkctl; |
diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h index 07e27f212dc7..d2453e2d3f1f 100644 --- a/arch/arm/include/asm/cp15.h +++ b/arch/arm/include/asm/cp15.h | |||
@@ -68,6 +68,8 @@ | |||
68 | #define BPIALL __ACCESS_CP15(c7, 0, c5, 6) | 68 | #define BPIALL __ACCESS_CP15(c7, 0, c5, 6) |
69 | #define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) | 69 | #define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) |
70 | 70 | ||
71 | #define CNTVCT __ACCESS_CP15_64(1, c14) | ||
72 | |||
71 | extern unsigned long cr_alignment; /* defined in entry-armv.S */ | 73 | extern unsigned long cr_alignment; /* defined in entry-armv.S */ |
72 | 74 | ||
73 | static inline unsigned long get_cr(void) | 75 | static inline unsigned long get_cr(void) |
diff --git a/arch/arm/vdso/vgettimeofday.c b/arch/arm/vdso/vgettimeofday.c index a9dd619c6c29..7bdbf5d5c47d 100644 --- a/arch/arm/vdso/vgettimeofday.c +++ b/arch/arm/vdso/vgettimeofday.c | |||
@@ -18,9 +18,9 @@ | |||
18 | #include <linux/compiler.h> | 18 | #include <linux/compiler.h> |
19 | #include <linux/hrtimer.h> | 19 | #include <linux/hrtimer.h> |
20 | #include <linux/time.h> | 20 | #include <linux/time.h> |
21 | #include <asm/arch_timer.h> | ||
22 | #include <asm/barrier.h> | 21 | #include <asm/barrier.h> |
23 | #include <asm/bug.h> | 22 | #include <asm/bug.h> |
23 | #include <asm/cp15.h> | ||
24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
25 | #include <asm/unistd.h> | 25 | #include <asm/unistd.h> |
26 | #include <asm/vdso_datapage.h> | 26 | #include <asm/vdso_datapage.h> |
@@ -123,7 +123,8 @@ static notrace u64 get_ns(struct vdso_data *vdata) | |||
123 | u64 cycle_now; | 123 | u64 cycle_now; |
124 | u64 nsec; | 124 | u64 nsec; |
125 | 125 | ||
126 | cycle_now = arch_counter_get_cntvct(); | 126 | isb(); |
127 | cycle_now = read_sysreg(CNTVCT); | ||
127 | 128 | ||
128 | cycle_delta = (cycle_now - vdata->cs_cycle_last) & vdata->cs_mask; | 129 | cycle_delta = (cycle_now - vdata->cs_cycle_last) & vdata->cs_mask; |
129 | 130 | ||
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b5c6943225ce..1c0cb5131c2a 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -477,15 +477,17 @@ config ARM64_ERRATUM_1024718 | |||
477 | If unsure, say Y. | 477 | If unsure, say Y. |
478 | 478 | ||
479 | config ARM64_ERRATUM_1188873 | 479 | config ARM64_ERRATUM_1188873 |
480 | bool "Cortex-A76: MRC read following MRRC read of specific Generic Timer in AArch32 might give incorrect result" | 480 | bool "Cortex-A76/Neoverse-N1: MRC read following MRRC read of specific Generic Timer in AArch32 might give incorrect result" |
481 | default y | 481 | default y |
482 | depends on COMPAT | ||
482 | select ARM_ARCH_TIMER_OOL_WORKAROUND | 483 | select ARM_ARCH_TIMER_OOL_WORKAROUND |
483 | help | 484 | help |
484 | This option adds a workaround for ARM Cortex-A76 erratum 1188873. | 485 | This option adds a workaround for ARM Cortex-A76/Neoverse-N1 |
486 | erratum 1188873. | ||
485 | 487 | ||
486 | Affected Cortex-A76 cores (r0p0, r1p0, r2p0) could cause | 488 | Affected Cortex-A76/Neoverse-N1 cores (r0p0, r1p0, r2p0) could |
487 | register corruption when accessing the timer registers from | 489 | cause register corruption when accessing the timer registers |
488 | AArch32 userspace. | 490 | from AArch32 userspace. |
489 | 491 | ||
490 | If unsure, say Y. | 492 | If unsure, say Y. |
491 | 493 | ||
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 93e07512b4b6..b7bca1ae09e6 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h | |||
@@ -31,11 +31,23 @@ | |||
31 | #include <clocksource/arm_arch_timer.h> | 31 | #include <clocksource/arm_arch_timer.h> |
32 | 32 | ||
33 | #if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND) | 33 | #if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND) |
34 | extern struct static_key_false arch_timer_read_ool_enabled; | 34 | #define has_erratum_handler(h) \ |
35 | #define needs_unstable_timer_counter_workaround() \ | 35 | ({ \ |
36 | static_branch_unlikely(&arch_timer_read_ool_enabled) | 36 | const struct arch_timer_erratum_workaround *__wa; \ |
37 | __wa = __this_cpu_read(timer_unstable_counter_workaround); \ | ||
38 | (__wa && __wa->h); \ | ||
39 | }) | ||
40 | |||
41 | #define erratum_handler(h) \ | ||
42 | ({ \ | ||
43 | const struct arch_timer_erratum_workaround *__wa; \ | ||
44 | __wa = __this_cpu_read(timer_unstable_counter_workaround); \ | ||
45 | (__wa && __wa->h) ? __wa->h : arch_timer_##h; \ | ||
46 | }) | ||
47 | |||
37 | #else | 48 | #else |
38 | #define needs_unstable_timer_counter_workaround() false | 49 | #define has_erratum_handler(h) false |
50 | #define erratum_handler(h) (arch_timer_##h) | ||
39 | #endif | 51 | #endif |
40 | 52 | ||
41 | enum arch_timer_erratum_match_type { | 53 | enum arch_timer_erratum_match_type { |
@@ -61,23 +73,37 @@ struct arch_timer_erratum_workaround { | |||
61 | DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *, | 73 | DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *, |
62 | timer_unstable_counter_workaround); | 74 | timer_unstable_counter_workaround); |
63 | 75 | ||
76 | /* inline sysreg accessors that make erratum_handler() work */ | ||
77 | static inline notrace u32 arch_timer_read_cntp_tval_el0(void) | ||
78 | { | ||
79 | return read_sysreg(cntp_tval_el0); | ||
80 | } | ||
81 | |||
82 | static inline notrace u32 arch_timer_read_cntv_tval_el0(void) | ||
83 | { | ||
84 | return read_sysreg(cntv_tval_el0); | ||
85 | } | ||
86 | |||
87 | static inline notrace u64 arch_timer_read_cntpct_el0(void) | ||
88 | { | ||
89 | return read_sysreg(cntpct_el0); | ||
90 | } | ||
91 | |||
92 | static inline notrace u64 arch_timer_read_cntvct_el0(void) | ||
93 | { | ||
94 | return read_sysreg(cntvct_el0); | ||
95 | } | ||
96 | |||
64 | #define arch_timer_reg_read_stable(reg) \ | 97 | #define arch_timer_reg_read_stable(reg) \ |
65 | ({ \ | 98 | ({ \ |
66 | u64 _val; \ | 99 | u64 _val; \ |
67 | if (needs_unstable_timer_counter_workaround()) { \ | 100 | \ |
68 | const struct arch_timer_erratum_workaround *wa; \ | ||
69 | preempt_disable_notrace(); \ | 101 | preempt_disable_notrace(); \ |
70 | wa = __this_cpu_read(timer_unstable_counter_workaround); \ | 102 | _val = erratum_handler(read_ ## reg)(); \ |
71 | if (wa && wa->read_##reg) \ | ||
72 | _val = wa->read_##reg(); \ | ||
73 | else \ | ||
74 | _val = read_sysreg(reg); \ | ||
75 | preempt_enable_notrace(); \ | 103 | preempt_enable_notrace(); \ |
76 | } else { \ | 104 | \ |
77 | _val = read_sysreg(reg); \ | 105 | _val; \ |
78 | } \ | 106 | }) |
79 | _val; \ | ||
80 | }) | ||
81 | 107 | ||
82 | /* | 108 | /* |
83 | * These register accessors are marked inline so the compiler can | 109 | * These register accessors are marked inline so the compiler can |
@@ -167,7 +193,7 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl) | |||
167 | : "=r" (tmp) : "r" (_val)); \ | 193 | : "=r" (tmp) : "r" (_val)); \ |
168 | } while (0) | 194 | } while (0) |
169 | 195 | ||
170 | static inline u64 arch_counter_get_cntpct(void) | 196 | static inline u64 __arch_counter_get_cntpct_stable(void) |
171 | { | 197 | { |
172 | u64 cnt; | 198 | u64 cnt; |
173 | 199 | ||
@@ -177,7 +203,17 @@ static inline u64 arch_counter_get_cntpct(void) | |||
177 | return cnt; | 203 | return cnt; |
178 | } | 204 | } |
179 | 205 | ||
180 | static inline u64 arch_counter_get_cntvct(void) | 206 | static inline u64 __arch_counter_get_cntpct(void) |
207 | { | ||
208 | u64 cnt; | ||
209 | |||
210 | isb(); | ||
211 | cnt = read_sysreg(cntpct_el0); | ||
212 | arch_counter_enforce_ordering(cnt); | ||
213 | return cnt; | ||
214 | } | ||
215 | |||
216 | static inline u64 __arch_counter_get_cntvct_stable(void) | ||
181 | { | 217 | { |
182 | u64 cnt; | 218 | u64 cnt; |
183 | 219 | ||
@@ -187,6 +223,16 @@ static inline u64 arch_counter_get_cntvct(void) | |||
187 | return cnt; | 223 | return cnt; |
188 | } | 224 | } |
189 | 225 | ||
226 | static inline u64 __arch_counter_get_cntvct(void) | ||
227 | { | ||
228 | u64 cnt; | ||
229 | |||
230 | isb(); | ||
231 | cnt = read_sysreg(cntvct_el0); | ||
232 | arch_counter_enforce_ordering(cnt); | ||
233 | return cnt; | ||
234 | } | ||
235 | |||
190 | #undef arch_counter_enforce_ordering | 236 | #undef arch_counter_enforce_ordering |
191 | 237 | ||
192 | static inline int arch_timer_arch_init(void) | 238 | static inline int arch_timer_arch_init(void) |
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 5f1437099b99..2602bae334fb 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h | |||
@@ -89,6 +89,7 @@ | |||
89 | #define ARM_CPU_PART_CORTEX_A35 0xD04 | 89 | #define ARM_CPU_PART_CORTEX_A35 0xD04 |
90 | #define ARM_CPU_PART_CORTEX_A55 0xD05 | 90 | #define ARM_CPU_PART_CORTEX_A55 0xD05 |
91 | #define ARM_CPU_PART_CORTEX_A76 0xD0B | 91 | #define ARM_CPU_PART_CORTEX_A76 0xD0B |
92 | #define ARM_CPU_PART_NEOVERSE_N1 0xD0C | ||
92 | 93 | ||
93 | #define APM_CPU_PART_POTENZA 0x000 | 94 | #define APM_CPU_PART_POTENZA 0x000 |
94 | 95 | ||
@@ -118,6 +119,7 @@ | |||
118 | #define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35) | 119 | #define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35) |
119 | #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55) | 120 | #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55) |
120 | #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) | 121 | #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) |
122 | #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1) | ||
121 | #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) | 123 | #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) |
122 | #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) | 124 | #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) |
123 | #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) | 125 | #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) |
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 1b9ce0fdd81d..e88d4e7bdfc7 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c | |||
@@ -682,6 +682,16 @@ static const struct midr_range workaround_clean_cache[] = { | |||
682 | }; | 682 | }; |
683 | #endif | 683 | #endif |
684 | 684 | ||
685 | #ifdef CONFIG_ARM64_ERRATUM_1188873 | ||
686 | static const struct midr_range erratum_1188873_list[] = { | ||
687 | /* Cortex-A76 r0p0 to r2p0 */ | ||
688 | MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 2, 0), | ||
689 | /* Neoverse-N1 r0p0 to r2p0 */ | ||
690 | MIDR_RANGE(MIDR_NEOVERSE_N1, 0, 0, 2, 0), | ||
691 | {}, | ||
692 | }; | ||
693 | #endif | ||
694 | |||
685 | const struct arm64_cpu_capabilities arm64_errata[] = { | 695 | const struct arm64_cpu_capabilities arm64_errata[] = { |
686 | #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE | 696 | #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE |
687 | { | 697 | { |
@@ -801,10 +811,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = { | |||
801 | }, | 811 | }, |
802 | #ifdef CONFIG_ARM64_ERRATUM_1188873 | 812 | #ifdef CONFIG_ARM64_ERRATUM_1188873 |
803 | { | 813 | { |
804 | /* Cortex-A76 r0p0 to r2p0 */ | ||
805 | .desc = "ARM erratum 1188873", | 814 | .desc = "ARM erratum 1188873", |
806 | .capability = ARM64_WORKAROUND_1188873, | 815 | .capability = ARM64_WORKAROUND_1188873, |
807 | ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 2, 0), | 816 | ERRATA_MIDR_RANGE_LIST(erratum_1188873_list), |
808 | }, | 817 | }, |
809 | #endif | 818 | #endif |
810 | #ifdef CONFIG_ARM64_ERRATUM_1165522 | 819 | #ifdef CONFIG_ARM64_ERRATUM_1165522 |
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index c50a7a75f2e0..1a7811b7e3c4 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S | |||
@@ -336,6 +336,21 @@ alternative_if ARM64_WORKAROUND_845719 | |||
336 | alternative_else_nop_endif | 336 | alternative_else_nop_endif |
337 | #endif | 337 | #endif |
338 | 3: | 338 | 3: |
339 | #ifdef CONFIG_ARM64_ERRATUM_1188873 | ||
340 | alternative_if_not ARM64_WORKAROUND_1188873 | ||
341 | b 4f | ||
342 | alternative_else_nop_endif | ||
343 | /* | ||
344 | * if (x22.mode32 == cntkctl_el1.el0vcten) | ||
345 | * cntkctl_el1.el0vcten = ~cntkctl_el1.el0vcten | ||
346 | */ | ||
347 | mrs x1, cntkctl_el1 | ||
348 | eon x0, x1, x22, lsr #3 | ||
349 | tbz x0, #1, 4f | ||
350 | eor x1, x1, #2 // ARCH_TIMER_USR_VCT_ACCESS_EN | ||
351 | msr cntkctl_el1, x1 | ||
352 | 4: | ||
353 | #endif | ||
339 | apply_ssbd 0, x0, x1 | 354 | apply_ssbd 0, x0, x1 |
340 | .endif | 355 | .endif |
341 | 356 | ||
@@ -362,11 +377,11 @@ alternative_else_nop_endif | |||
362 | .if \el == 0 | 377 | .if \el == 0 |
363 | alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 | 378 | alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 |
364 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 | 379 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
365 | bne 4f | 380 | bne 5f |
366 | msr far_el1, x30 | 381 | msr far_el1, x30 |
367 | tramp_alias x30, tramp_exit_native | 382 | tramp_alias x30, tramp_exit_native |
368 | br x30 | 383 | br x30 |
369 | 4: | 384 | 5: |
370 | tramp_alias x30, tramp_exit_compat | 385 | tramp_alias x30, tramp_exit_compat |
371 | br x30 | 386 | br x30 |
372 | #endif | 387 | #endif |
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 21e73954762c..48432027969c 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c | |||
@@ -496,7 +496,7 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) | |||
496 | { | 496 | { |
497 | int rt = ESR_ELx_SYS64_ISS_RT(esr); | 497 | int rt = ESR_ELx_SYS64_ISS_RT(esr); |
498 | 498 | ||
499 | pt_regs_write_reg(regs, rt, arch_counter_get_cntvct()); | 499 | pt_regs_write_reg(regs, rt, arch_timer_read_counter()); |
500 | arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); | 500 | arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); |
501 | } | 501 | } |
502 | 502 | ||
@@ -668,7 +668,7 @@ static void compat_cntvct_read_handler(unsigned int esr, struct pt_regs *regs) | |||
668 | { | 668 | { |
669 | int rt = (esr & ESR_ELx_CP15_64_ISS_RT_MASK) >> ESR_ELx_CP15_64_ISS_RT_SHIFT; | 669 | int rt = (esr & ESR_ELx_CP15_64_ISS_RT_MASK) >> ESR_ELx_CP15_64_ISS_RT_SHIFT; |
670 | int rt2 = (esr & ESR_ELx_CP15_64_ISS_RT2_MASK) >> ESR_ELx_CP15_64_ISS_RT2_SHIFT; | 670 | int rt2 = (esr & ESR_ELx_CP15_64_ISS_RT2_MASK) >> ESR_ELx_CP15_64_ISS_RT2_SHIFT; |
671 | u64 val = arch_counter_get_cntvct(); | 671 | u64 val = arch_timer_read_counter(); |
672 | 672 | ||
673 | pt_regs_write_reg(regs, rt, lower_32_bits(val)); | 673 | pt_regs_write_reg(regs, rt, lower_32_bits(val)); |
674 | pt_regs_write_reg(regs, rt2, upper_32_bits(val)); | 674 | pt_regs_write_reg(regs, rt2, upper_32_bits(val)); |
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 6cc8aff83805..9a2f23df7610 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -152,6 +152,26 @@ u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, | |||
152 | return val; | 152 | return val; |
153 | } | 153 | } |
154 | 154 | ||
155 | static u64 arch_counter_get_cntpct_stable(void) | ||
156 | { | ||
157 | return __arch_counter_get_cntpct_stable(); | ||
158 | } | ||
159 | |||
160 | static u64 arch_counter_get_cntpct(void) | ||
161 | { | ||
162 | return __arch_counter_get_cntpct(); | ||
163 | } | ||
164 | |||
165 | static u64 arch_counter_get_cntvct_stable(void) | ||
166 | { | ||
167 | return __arch_counter_get_cntvct_stable(); | ||
168 | } | ||
169 | |||
170 | static u64 arch_counter_get_cntvct(void) | ||
171 | { | ||
172 | return __arch_counter_get_cntvct(); | ||
173 | } | ||
174 | |||
155 | /* | 175 | /* |
156 | * Default to cp15 based access because arm64 uses this function for | 176 | * Default to cp15 based access because arm64 uses this function for |
157 | * sched_clock() before DT is probed and the cp15 method is guaranteed | 177 | * sched_clock() before DT is probed and the cp15 method is guaranteed |
@@ -319,13 +339,6 @@ static u64 notrace arm64_858921_read_cntvct_el0(void) | |||
319 | } | 339 | } |
320 | #endif | 340 | #endif |
321 | 341 | ||
322 | #ifdef CONFIG_ARM64_ERRATUM_1188873 | ||
323 | static u64 notrace arm64_1188873_read_cntvct_el0(void) | ||
324 | { | ||
325 | return read_sysreg(cntvct_el0); | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1 | 342 | #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1 |
330 | /* | 343 | /* |
331 | * The low bits of the counter registers are indeterminate while bit 10 or | 344 | * The low bits of the counter registers are indeterminate while bit 10 or |
@@ -372,8 +385,7 @@ static u32 notrace sun50i_a64_read_cntv_tval_el0(void) | |||
372 | DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); | 385 | DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); |
373 | EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); | 386 | EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); |
374 | 387 | ||
375 | DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); | 388 | static atomic_t timer_unstable_counter_workaround_in_use = ATOMIC_INIT(0); |
376 | EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled); | ||
377 | 389 | ||
378 | static void erratum_set_next_event_tval_generic(const int access, unsigned long evt, | 390 | static void erratum_set_next_event_tval_generic(const int access, unsigned long evt, |
379 | struct clock_event_device *clk) | 391 | struct clock_event_device *clk) |
@@ -457,14 +469,6 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { | |||
457 | .read_cntvct_el0 = arm64_858921_read_cntvct_el0, | 469 | .read_cntvct_el0 = arm64_858921_read_cntvct_el0, |
458 | }, | 470 | }, |
459 | #endif | 471 | #endif |
460 | #ifdef CONFIG_ARM64_ERRATUM_1188873 | ||
461 | { | ||
462 | .match_type = ate_match_local_cap_id, | ||
463 | .id = (void *)ARM64_WORKAROUND_1188873, | ||
464 | .desc = "ARM erratum 1188873", | ||
465 | .read_cntvct_el0 = arm64_1188873_read_cntvct_el0, | ||
466 | }, | ||
467 | #endif | ||
468 | #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1 | 472 | #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1 |
469 | { | 473 | { |
470 | .match_type = ate_match_dt, | 474 | .match_type = ate_match_dt, |
@@ -552,11 +556,8 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa | |||
552 | per_cpu(timer_unstable_counter_workaround, i) = wa; | 556 | per_cpu(timer_unstable_counter_workaround, i) = wa; |
553 | } | 557 | } |
554 | 558 | ||
555 | /* | 559 | if (wa->read_cntvct_el0 || wa->read_cntpct_el0) |
556 | * Use the locked version, as we're called from the CPU | 560 | atomic_set(&timer_unstable_counter_workaround_in_use, 1); |
557 | * hotplug framework. Otherwise, we end-up in deadlock-land. | ||
558 | */ | ||
559 | static_branch_enable_cpuslocked(&arch_timer_read_ool_enabled); | ||
560 | 561 | ||
561 | /* | 562 | /* |
562 | * Don't use the vdso fastpath if errata require using the | 563 | * Don't use the vdso fastpath if errata require using the |
@@ -573,7 +574,7 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa | |||
573 | static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, | 574 | static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, |
574 | void *arg) | 575 | void *arg) |
575 | { | 576 | { |
576 | const struct arch_timer_erratum_workaround *wa; | 577 | const struct arch_timer_erratum_workaround *wa, *__wa; |
577 | ate_match_fn_t match_fn = NULL; | 578 | ate_match_fn_t match_fn = NULL; |
578 | bool local = false; | 579 | bool local = false; |
579 | 580 | ||
@@ -597,53 +598,32 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t | |||
597 | if (!wa) | 598 | if (!wa) |
598 | return; | 599 | return; |
599 | 600 | ||
600 | if (needs_unstable_timer_counter_workaround()) { | 601 | __wa = __this_cpu_read(timer_unstable_counter_workaround); |
601 | const struct arch_timer_erratum_workaround *__wa; | 602 | if (__wa && wa != __wa) |
602 | __wa = __this_cpu_read(timer_unstable_counter_workaround); | 603 | pr_warn("Can't enable workaround for %s (clashes with %s\n)", |
603 | if (__wa && wa != __wa) | 604 | wa->desc, __wa->desc); |
604 | pr_warn("Can't enable workaround for %s (clashes with %s\n)", | ||
605 | wa->desc, __wa->desc); | ||
606 | 605 | ||
607 | if (__wa) | 606 | if (__wa) |
608 | return; | 607 | return; |
609 | } | ||
610 | 608 | ||
611 | arch_timer_enable_workaround(wa, local); | 609 | arch_timer_enable_workaround(wa, local); |
612 | pr_info("Enabling %s workaround for %s\n", | 610 | pr_info("Enabling %s workaround for %s\n", |
613 | local ? "local" : "global", wa->desc); | 611 | local ? "local" : "global", wa->desc); |
614 | } | 612 | } |
615 | 613 | ||
616 | #define erratum_handler(fn, r, ...) \ | ||
617 | ({ \ | ||
618 | bool __val; \ | ||
619 | if (needs_unstable_timer_counter_workaround()) { \ | ||
620 | const struct arch_timer_erratum_workaround *__wa; \ | ||
621 | __wa = __this_cpu_read(timer_unstable_counter_workaround); \ | ||
622 | if (__wa && __wa->fn) { \ | ||
623 | r = __wa->fn(__VA_ARGS__); \ | ||
624 | __val = true; \ | ||
625 | } else { \ | ||
626 | __val = false; \ | ||
627 | } \ | ||
628 | } else { \ | ||
629 | __val = false; \ | ||
630 | } \ | ||
631 | __val; \ | ||
632 | }) | ||
633 | |||
634 | static bool arch_timer_this_cpu_has_cntvct_wa(void) | 614 | static bool arch_timer_this_cpu_has_cntvct_wa(void) |
635 | { | 615 | { |
636 | const struct arch_timer_erratum_workaround *wa; | 616 | return has_erratum_handler(read_cntvct_el0); |
617 | } | ||
637 | 618 | ||
638 | wa = __this_cpu_read(timer_unstable_counter_workaround); | 619 | static bool arch_timer_counter_has_wa(void) |
639 | return wa && wa->read_cntvct_el0; | 620 | { |
621 | return atomic_read(&timer_unstable_counter_workaround_in_use); | ||
640 | } | 622 | } |
641 | #else | 623 | #else |
642 | #define arch_timer_check_ool_workaround(t,a) do { } while(0) | 624 | #define arch_timer_check_ool_workaround(t,a) do { } while(0) |
643 | #define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) | ||
644 | #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) | ||
645 | #define erratum_handler(fn, r, ...) ({false;}) | ||
646 | #define arch_timer_this_cpu_has_cntvct_wa() ({false;}) | 625 | #define arch_timer_this_cpu_has_cntvct_wa() ({false;}) |
626 | #define arch_timer_counter_has_wa() ({false;}) | ||
647 | #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ | 627 | #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ |
648 | 628 | ||
649 | static __always_inline irqreturn_t timer_handler(const int access, | 629 | static __always_inline irqreturn_t timer_handler(const int access, |
@@ -736,11 +716,6 @@ static __always_inline void set_next_event(const int access, unsigned long evt, | |||
736 | static int arch_timer_set_next_event_virt(unsigned long evt, | 716 | static int arch_timer_set_next_event_virt(unsigned long evt, |
737 | struct clock_event_device *clk) | 717 | struct clock_event_device *clk) |
738 | { | 718 | { |
739 | int ret; | ||
740 | |||
741 | if (erratum_handler(set_next_event_virt, ret, evt, clk)) | ||
742 | return ret; | ||
743 | |||
744 | set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); | 719 | set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); |
745 | return 0; | 720 | return 0; |
746 | } | 721 | } |
@@ -748,11 +723,6 @@ static int arch_timer_set_next_event_virt(unsigned long evt, | |||
748 | static int arch_timer_set_next_event_phys(unsigned long evt, | 723 | static int arch_timer_set_next_event_phys(unsigned long evt, |
749 | struct clock_event_device *clk) | 724 | struct clock_event_device *clk) |
750 | { | 725 | { |
751 | int ret; | ||
752 | |||
753 | if (erratum_handler(set_next_event_phys, ret, evt, clk)) | ||
754 | return ret; | ||
755 | |||
756 | set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); | 726 | set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); |
757 | return 0; | 727 | return 0; |
758 | } | 728 | } |
@@ -777,6 +747,10 @@ static void __arch_timer_setup(unsigned type, | |||
777 | clk->features = CLOCK_EVT_FEAT_ONESHOT; | 747 | clk->features = CLOCK_EVT_FEAT_ONESHOT; |
778 | 748 | ||
779 | if (type == ARCH_TIMER_TYPE_CP15) { | 749 | if (type == ARCH_TIMER_TYPE_CP15) { |
750 | typeof(clk->set_next_event) sne; | ||
751 | |||
752 | arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); | ||
753 | |||
780 | if (arch_timer_c3stop) | 754 | if (arch_timer_c3stop) |
781 | clk->features |= CLOCK_EVT_FEAT_C3STOP; | 755 | clk->features |= CLOCK_EVT_FEAT_C3STOP; |
782 | clk->name = "arch_sys_timer"; | 756 | clk->name = "arch_sys_timer"; |
@@ -787,20 +761,20 @@ static void __arch_timer_setup(unsigned type, | |||
787 | case ARCH_TIMER_VIRT_PPI: | 761 | case ARCH_TIMER_VIRT_PPI: |
788 | clk->set_state_shutdown = arch_timer_shutdown_virt; | 762 | clk->set_state_shutdown = arch_timer_shutdown_virt; |
789 | clk->set_state_oneshot_stopped = arch_timer_shutdown_virt; | 763 | clk->set_state_oneshot_stopped = arch_timer_shutdown_virt; |
790 | clk->set_next_event = arch_timer_set_next_event_virt; | 764 | sne = erratum_handler(set_next_event_virt); |
791 | break; | 765 | break; |
792 | case ARCH_TIMER_PHYS_SECURE_PPI: | 766 | case ARCH_TIMER_PHYS_SECURE_PPI: |
793 | case ARCH_TIMER_PHYS_NONSECURE_PPI: | 767 | case ARCH_TIMER_PHYS_NONSECURE_PPI: |
794 | case ARCH_TIMER_HYP_PPI: | 768 | case ARCH_TIMER_HYP_PPI: |
795 | clk->set_state_shutdown = arch_timer_shutdown_phys; | 769 | clk->set_state_shutdown = arch_timer_shutdown_phys; |
796 | clk->set_state_oneshot_stopped = arch_timer_shutdown_phys; | 770 | clk->set_state_oneshot_stopped = arch_timer_shutdown_phys; |
797 | clk->set_next_event = arch_timer_set_next_event_phys; | 771 | sne = erratum_handler(set_next_event_phys); |
798 | break; | 772 | break; |
799 | default: | 773 | default: |
800 | BUG(); | 774 | BUG(); |
801 | } | 775 | } |
802 | 776 | ||
803 | arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); | 777 | clk->set_next_event = sne; |
804 | } else { | 778 | } else { |
805 | clk->features |= CLOCK_EVT_FEAT_DYNIRQ; | 779 | clk->features |= CLOCK_EVT_FEAT_DYNIRQ; |
806 | clk->name = "arch_mem_timer"; | 780 | clk->name = "arch_mem_timer"; |
@@ -1002,12 +976,22 @@ static void __init arch_counter_register(unsigned type) | |||
1002 | 976 | ||
1003 | /* Register the CP15 based counter if we have one */ | 977 | /* Register the CP15 based counter if we have one */ |
1004 | if (type & ARCH_TIMER_TYPE_CP15) { | 978 | if (type & ARCH_TIMER_TYPE_CP15) { |
979 | u64 (*rd)(void); | ||
980 | |||
1005 | if ((IS_ENABLED(CONFIG_ARM64) && !is_hyp_mode_available()) || | 981 | if ((IS_ENABLED(CONFIG_ARM64) && !is_hyp_mode_available()) || |
1006 | arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) | 982 | arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) { |
1007 | arch_timer_read_counter = arch_counter_get_cntvct; | 983 | if (arch_timer_counter_has_wa()) |
1008 | else | 984 | rd = arch_counter_get_cntvct_stable; |
1009 | arch_timer_read_counter = arch_counter_get_cntpct; | 985 | else |
986 | rd = arch_counter_get_cntvct; | ||
987 | } else { | ||
988 | if (arch_timer_counter_has_wa()) | ||
989 | rd = arch_counter_get_cntpct_stable; | ||
990 | else | ||
991 | rd = arch_counter_get_cntpct; | ||
992 | } | ||
1010 | 993 | ||
994 | arch_timer_read_counter = rd; | ||
1011 | clocksource_counter.archdata.vdso_direct = vdso_default; | 995 | clocksource_counter.archdata.vdso_direct = vdso_default; |
1012 | } else { | 996 | } else { |
1013 | arch_timer_read_counter = arch_counter_get_cntvct_mem; | 997 | arch_timer_read_counter = arch_counter_get_cntvct_mem; |
diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c index e8bd9887c566..e221e47396ab 100644 --- a/drivers/watchdog/sbsa_gwdt.c +++ b/drivers/watchdog/sbsa_gwdt.c | |||
@@ -161,7 +161,7 @@ static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd) | |||
161 | timeleft += readl(gwdt->control_base + SBSA_GWDT_WOR); | 161 | timeleft += readl(gwdt->control_base + SBSA_GWDT_WOR); |
162 | 162 | ||
163 | timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) - | 163 | timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) - |
164 | arch_counter_get_cntvct(); | 164 | arch_timer_read_counter(); |
165 | 165 | ||
166 | do_div(timeleft, gwdt->clk); | 166 | do_div(timeleft, gwdt->clk); |
167 | 167 | ||