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 | ||
