Skip to content

Commit 24cf262

Browse files
committed
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
2 parents 50abbe1 + 0ea4153 commit 24cf262

File tree

12 files changed

+185
-109
lines changed

12 files changed

+185
-109
lines changed

Documentation/arm64/silicon-errata.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ stable kernels.
6161
| ARM | Cortex-A76 | #1188873 | ARM64_ERRATUM_1188873 |
6262
| ARM | Cortex-A76 | #1165522 | ARM64_ERRATUM_1165522 |
6363
| ARM | Cortex-A76 | #1286807 | ARM64_ERRATUM_1286807 |
64+
| ARM | Neoverse-N1 | #1188873 | ARM64_ERRATUM_1188873 |
6465
| ARM | MMU-500 | #841119,#826419 | N/A |
6566
| | | | |
6667
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |

arch/arm/include/asm/arch_timer.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <clocksource/arm_arch_timer.h>
1212

1313
#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+
1418
int arch_timer_arch_init(void);
1519

1620
/*
@@ -79,7 +83,7 @@ static inline u32 arch_timer_get_cntfrq(void)
7983
return val;
8084
}
8185

82-
static inline u64 arch_counter_get_cntpct(void)
86+
static inline u64 __arch_counter_get_cntpct(void)
8387
{
8488
u64 cval;
8589

@@ -88,7 +92,12 @@ static inline u64 arch_counter_get_cntpct(void)
8892
return cval;
8993
}
9094

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)
92101
{
93102
u64 cval;
94103

@@ -97,6 +106,11 @@ static inline u64 arch_counter_get_cntvct(void)
97106
return cval;
98107
}
99108

109+
static inline u64 __arch_counter_get_cntvct_stable(void)
110+
{
111+
return __arch_counter_get_cntvct();
112+
}
113+
100114
static inline u32 arch_timer_get_cntkctl(void)
101115
{
102116
u32 cntkctl;

arch/arm/include/asm/cp15.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
#define BPIALL __ACCESS_CP15(c7, 0, c5, 6)
6969
#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0)
7070

71+
#define CNTVCT __ACCESS_CP15_64(1, c14)
72+
7173
extern unsigned long cr_alignment; /* defined in entry-armv.S */
7274

7375
static inline unsigned long get_cr(void)

arch/arm/vdso/vgettimeofday.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
#include <linux/compiler.h>
1919
#include <linux/hrtimer.h>
2020
#include <linux/time.h>
21-
#include <asm/arch_timer.h>
2221
#include <asm/barrier.h>
2322
#include <asm/bug.h>
23+
#include <asm/cp15.h>
2424
#include <asm/page.h>
2525
#include <asm/unistd.h>
2626
#include <asm/vdso_datapage.h>
@@ -123,7 +123,8 @@ static notrace u64 get_ns(struct vdso_data *vdata)
123123
u64 cycle_now;
124124
u64 nsec;
125125

126-
cycle_now = arch_counter_get_cntvct();
126+
isb();
127+
cycle_now = read_sysreg(CNTVCT);
127128

128129
cycle_delta = (cycle_now - vdata->cs_cycle_last) & vdata->cs_mask;
129130

arch/arm64/Kconfig

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,15 +477,17 @@ config ARM64_ERRATUM_1024718
477477
If unsure, say Y.
478478

479479
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"
481481
default y
482+
depends on COMPAT
482483
select ARM_ARCH_TIMER_OOL_WORKAROUND
483484
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.
485487

486-
Affected Cortex-A76 cores (r0p0, r1p0, r2p0) could cause
487-
register corruption when accessing the timer registers from
488-
AArch32 userspace.
488+
Affected Cortex-A76/Neoverse-N1 cores (r0p0, r1p0, r2p0) could
489+
cause register corruption when accessing the timer registers
490+
from AArch32 userspace.
489491

490492
If unsure, say Y.
491493

arch/arm64/include/asm/arch_timer.h

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,23 @@
3131
#include <clocksource/arm_arch_timer.h>
3232

3333
#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
34-
extern struct static_key_false arch_timer_read_ool_enabled;
35-
#define needs_unstable_timer_counter_workaround() \
36-
static_branch_unlikely(&arch_timer_read_ool_enabled)
34+
#define has_erratum_handler(h) \
35+
({ \
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+
3748
#else
38-
#define needs_unstable_timer_counter_workaround() false
49+
#define has_erratum_handler(h) false
50+
#define erratum_handler(h) (arch_timer_##h)
3951
#endif
4052

4153
enum arch_timer_erratum_match_type {
@@ -61,23 +73,37 @@ struct arch_timer_erratum_workaround {
6173
DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
6274
timer_unstable_counter_workaround);
6375

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+
6497
#define arch_timer_reg_read_stable(reg) \
65-
({ \
66-
u64 _val; \
67-
if (needs_unstable_timer_counter_workaround()) { \
68-
const struct arch_timer_erratum_workaround *wa; \
98+
({ \
99+
u64 _val; \
100+
\
69101
preempt_disable_notrace(); \
70-
wa = __this_cpu_read(timer_unstable_counter_workaround); \
71-
if (wa && wa->read_##reg) \
72-
_val = wa->read_##reg(); \
73-
else \
74-
_val = read_sysreg(reg); \
102+
_val = erratum_handler(read_ ## reg)(); \
75103
preempt_enable_notrace(); \
76-
} else { \
77-
_val = read_sysreg(reg); \
78-
} \
79-
_val; \
80-
})
104+
\
105+
_val; \
106+
})
81107

82108
/*
83109
* These register accessors are marked inline so the compiler can
@@ -167,7 +193,7 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
167193
: "=r" (tmp) : "r" (_val)); \
168194
} while (0)
169195

170-
static inline u64 arch_counter_get_cntpct(void)
196+
static inline u64 __arch_counter_get_cntpct_stable(void)
171197
{
172198
u64 cnt;
173199

@@ -177,7 +203,17 @@ static inline u64 arch_counter_get_cntpct(void)
177203
return cnt;
178204
}
179205

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)
181217
{
182218
u64 cnt;
183219

@@ -187,6 +223,16 @@ static inline u64 arch_counter_get_cntvct(void)
187223
return cnt;
188224
}
189225

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+
190236
#undef arch_counter_enforce_ordering
191237

192238
static inline int arch_timer_arch_init(void)

arch/arm64/include/asm/cputype.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
#define ARM_CPU_PART_CORTEX_A35 0xD04
9090
#define ARM_CPU_PART_CORTEX_A55 0xD05
9191
#define ARM_CPU_PART_CORTEX_A76 0xD0B
92+
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
9293

9394
#define APM_CPU_PART_POTENZA 0x000
9495

@@ -118,6 +119,7 @@
118119
#define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35)
119120
#define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
120121
#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)
121123
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
122124
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
123125
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)

arch/arm64/kernel/cpu_errata.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,16 @@ static const struct midr_range workaround_clean_cache[] = {
682682
};
683683
#endif
684684

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+
685695
const struct arm64_cpu_capabilities arm64_errata[] = {
686696
#ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
687697
{
@@ -801,10 +811,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
801811
},
802812
#ifdef CONFIG_ARM64_ERRATUM_1188873
803813
{
804-
/* Cortex-A76 r0p0 to r2p0 */
805814
.desc = "ARM erratum 1188873",
806815
.capability = ARM64_WORKAROUND_1188873,
807-
ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 2, 0),
816+
ERRATA_MIDR_RANGE_LIST(erratum_1188873_list),
808817
},
809818
#endif
810819
#ifdef CONFIG_ARM64_ERRATUM_1165522

arch/arm64/kernel/entry.S

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,21 @@ alternative_if ARM64_WORKAROUND_845719
336336
alternative_else_nop_endif
337337
#endif
338338
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
339354
apply_ssbd 0, x0, x1
340355
.endif
341356

@@ -362,11 +377,11 @@ alternative_else_nop_endif
362377
.if \el == 0
363378
alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
364379
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
365-
bne 4f
380+
bne 5f
366381
msr far_el1, x30
367382
tramp_alias x30, tramp_exit_native
368383
br x30
369-
4:
384+
5:
370385
tramp_alias x30, tramp_exit_compat
371386
br x30
372387
#endif

arch/arm64/kernel/traps.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
496496
{
497497
int rt = ESR_ELx_SYS64_ISS_RT(esr);
498498

499-
pt_regs_write_reg(regs, rt, arch_counter_get_cntvct());
499+
pt_regs_write_reg(regs, rt, arch_timer_read_counter());
500500
arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
501501
}
502502

@@ -668,7 +668,7 @@ static void compat_cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
668668
{
669669
int rt = (esr & ESR_ELx_CP15_64_ISS_RT_MASK) >> ESR_ELx_CP15_64_ISS_RT_SHIFT;
670670
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();
672672

673673
pt_regs_write_reg(regs, rt, lower_32_bits(val));
674674
pt_regs_write_reg(regs, rt2, upper_32_bits(val));

0 commit comments

Comments
 (0)