Skip to content

Commit 32cf6d0

Browse files
committed
Merge branch 'timers/drivers/armv8.6_arch_timer' into timers/drivers/next
The branch is a stable branch shared with ARM maintainers for the first 13th patches of the series: It is based on v5.14-rc3. As stated by the changelog: " [... ] enabling ARMv8.6 support for timer subsystem, and was prompted by a discussion with Oliver around the fact that an ARMv8.6 implementation must have a 1GHz counter, which leads to a number of things to break in the timer code: - the counter rollover can come pretty quickly as we only advertise a 56bit counter, - the maximum timer delta can be remarkably small, as we use the countdown interface which is limited to 32bit... Thankfully, there is a way out: we can compute the minimal width of the counter based on the guarantees that the architecture gives us, and we can use the 64bit comparator interface instead of the countdown to program the timer. Finally, we start making use of the ARMv8.6 ECV features by switching accesses to the counters to a self-synchronising register, removing the need for an ISB. Hopefully, implementations will *not* just stick an invisible ISB there... A side effect of the switch to CVAL is that XGene-1 breaks. I have added a workaround to keep it alive. I have added Oliver's original patch[0] to the series and tweaked a couple of things. Blame me if I broke anything. The whole things has been tested on Juno (sysreg + MMIO timers), XGene-1 (broken sysreg timers), FVP (FEAT_ECV, CNT*CTSS_EL0). " Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Daniel Lezcano <[email protected]>
2 parents 58100c3 + db26f8f commit 32cf6d0

File tree

4 files changed

+193
-141
lines changed

4 files changed

+193
-141
lines changed

arch/arm/include/asm/arch_timer.h

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <asm/hwcap.h>
88
#include <linux/clocksource.h>
99
#include <linux/init.h>
10+
#include <linux/io-64-nonatomic-lo-hi.h>
1011
#include <linux/types.h>
1112

1213
#include <clocksource/arm_arch_timer.h>
@@ -24,29 +25,35 @@ int arch_timer_arch_init(void);
2425
* the code. At least it does so with a recent GCC (4.6.3).
2526
*/
2627
static __always_inline
27-
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
28+
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val)
2829
{
2930
if (access == ARCH_TIMER_PHYS_ACCESS) {
3031
switch (reg) {
3132
case ARCH_TIMER_REG_CTRL:
32-
asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
33+
asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" ((u32)val));
34+
isb();
3335
break;
34-
case ARCH_TIMER_REG_TVAL:
35-
asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
36+
case ARCH_TIMER_REG_CVAL:
37+
asm volatile("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val));
3638
break;
39+
default:
40+
BUILD_BUG();
3741
}
3842
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
3943
switch (reg) {
4044
case ARCH_TIMER_REG_CTRL:
41-
asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
45+
asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" ((u32)val));
46+
isb();
4247
break;
43-
case ARCH_TIMER_REG_TVAL:
44-
asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
48+
case ARCH_TIMER_REG_CVAL:
49+
asm volatile("mcrr p15, 3, %Q0, %R0, c14" : : "r" (val));
4550
break;
51+
default:
52+
BUILD_BUG();
4653
}
54+
} else {
55+
BUILD_BUG();
4756
}
48-
49-
isb();
5057
}
5158

5259
static __always_inline
@@ -59,19 +66,19 @@ u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
5966
case ARCH_TIMER_REG_CTRL:
6067
asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
6168
break;
62-
case ARCH_TIMER_REG_TVAL:
63-
asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
64-
break;
69+
default:
70+
BUILD_BUG();
6571
}
6672
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
6773
switch (reg) {
6874
case ARCH_TIMER_REG_CTRL:
6975
asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
7076
break;
71-
case ARCH_TIMER_REG_TVAL:
72-
asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
73-
break;
77+
default:
78+
BUILD_BUG();
7479
}
80+
} else {
81+
BUILD_BUG();
7582
}
7683

7784
return val;

arch/arm64/include/asm/arch_timer.h

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
({ \
3333
const struct arch_timer_erratum_workaround *__wa; \
3434
__wa = __this_cpu_read(timer_unstable_counter_workaround); \
35-
(__wa && __wa->h) ? __wa->h : arch_timer_##h; \
35+
(__wa && __wa->h) ? ({ isb(); __wa->h;}) : arch_timer_##h; \
3636
})
3737

3838
#else
@@ -52,8 +52,6 @@ struct arch_timer_erratum_workaround {
5252
enum arch_timer_erratum_match_type match_type;
5353
const void *id;
5454
const char *desc;
55-
u32 (*read_cntp_tval_el0)(void);
56-
u32 (*read_cntv_tval_el0)(void);
5755
u64 (*read_cntpct_el0)(void);
5856
u64 (*read_cntvct_el0)(void);
5957
int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
@@ -64,24 +62,15 @@ struct arch_timer_erratum_workaround {
6462
DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
6563
timer_unstable_counter_workaround);
6664

67-
/* inline sysreg accessors that make erratum_handler() work */
68-
static inline notrace u32 arch_timer_read_cntp_tval_el0(void)
69-
{
70-
return read_sysreg(cntp_tval_el0);
71-
}
72-
73-
static inline notrace u32 arch_timer_read_cntv_tval_el0(void)
74-
{
75-
return read_sysreg(cntv_tval_el0);
76-
}
77-
7865
static inline notrace u64 arch_timer_read_cntpct_el0(void)
7966
{
67+
isb();
8068
return read_sysreg(cntpct_el0);
8169
}
8270

8371
static inline notrace u64 arch_timer_read_cntvct_el0(void)
8472
{
73+
isb();
8574
return read_sysreg(cntvct_el0);
8675
}
8776

@@ -102,51 +91,58 @@ static inline notrace u64 arch_timer_read_cntvct_el0(void)
10291
* the code.
10392
*/
10493
static __always_inline
105-
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
94+
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val)
10695
{
10796
if (access == ARCH_TIMER_PHYS_ACCESS) {
10897
switch (reg) {
10998
case ARCH_TIMER_REG_CTRL:
11099
write_sysreg(val, cntp_ctl_el0);
100+
isb();
111101
break;
112-
case ARCH_TIMER_REG_TVAL:
113-
write_sysreg(val, cntp_tval_el0);
102+
case ARCH_TIMER_REG_CVAL:
103+
write_sysreg(val, cntp_cval_el0);
114104
break;
105+
default:
106+
BUILD_BUG();
115107
}
116108
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
117109
switch (reg) {
118110
case ARCH_TIMER_REG_CTRL:
119111
write_sysreg(val, cntv_ctl_el0);
112+
isb();
120113
break;
121-
case ARCH_TIMER_REG_TVAL:
122-
write_sysreg(val, cntv_tval_el0);
114+
case ARCH_TIMER_REG_CVAL:
115+
write_sysreg(val, cntv_cval_el0);
123116
break;
117+
default:
118+
BUILD_BUG();
124119
}
120+
} else {
121+
BUILD_BUG();
125122
}
126-
127-
isb();
128123
}
129124

130125
static __always_inline
131-
u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
126+
u64 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
132127
{
133128
if (access == ARCH_TIMER_PHYS_ACCESS) {
134129
switch (reg) {
135130
case ARCH_TIMER_REG_CTRL:
136131
return read_sysreg(cntp_ctl_el0);
137-
case ARCH_TIMER_REG_TVAL:
138-
return arch_timer_reg_read_stable(cntp_tval_el0);
132+
default:
133+
BUILD_BUG();
139134
}
140135
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
141136
switch (reg) {
142137
case ARCH_TIMER_REG_CTRL:
143138
return read_sysreg(cntv_ctl_el0);
144-
case ARCH_TIMER_REG_TVAL:
145-
return arch_timer_reg_read_stable(cntv_tval_el0);
139+
default:
140+
BUILD_BUG();
146141
}
147142
}
148143

149-
BUG();
144+
BUILD_BUG();
145+
unreachable();
150146
}
151147

152148
static inline u32 arch_timer_get_cntfrq(void)
@@ -169,7 +165,6 @@ static __always_inline u64 __arch_counter_get_cntpct_stable(void)
169165
{
170166
u64 cnt;
171167

172-
isb();
173168
cnt = arch_timer_reg_read_stable(cntpct_el0);
174169
arch_counter_enforce_ordering(cnt);
175170
return cnt;
@@ -189,7 +184,6 @@ static __always_inline u64 __arch_counter_get_cntvct_stable(void)
189184
{
190185
u64 cnt;
191186

192-
isb();
193187
cnt = arch_timer_reg_read_stable(cntvct_el0);
194188
arch_counter_enforce_ordering(cnt);
195189
return cnt;

0 commit comments

Comments
 (0)