aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/vdso_datapage.h8
-rw-r--r--arch/arm64/kernel/asm-offsets.c6
-rw-r--r--arch/arm64/kernel/vdso.c8
-rw-r--r--arch/arm64/kernel/vdso/gettimeofday.S57
4 files changed, 64 insertions, 15 deletions
diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h
index de66199673d7..2b9a63771eda 100644
--- a/arch/arm64/include/asm/vdso_datapage.h
+++ b/arch/arm64/include/asm/vdso_datapage.h
@@ -22,6 +22,8 @@
22 22
23struct vdso_data { 23struct vdso_data {
24 __u64 cs_cycle_last; /* Timebase at clocksource init */ 24 __u64 cs_cycle_last; /* Timebase at clocksource init */
25 __u64 raw_time_sec; /* Raw time */
26 __u64 raw_time_nsec;
25 __u64 xtime_clock_sec; /* Kernel time */ 27 __u64 xtime_clock_sec; /* Kernel time */
26 __u64 xtime_clock_nsec; 28 __u64 xtime_clock_nsec;
27 __u64 xtime_coarse_sec; /* Coarse time */ 29 __u64 xtime_coarse_sec; /* Coarse time */
@@ -29,8 +31,10 @@ struct vdso_data {
29 __u64 wtm_clock_sec; /* Wall to monotonic time */ 31 __u64 wtm_clock_sec; /* Wall to monotonic time */
30 __u64 wtm_clock_nsec; 32 __u64 wtm_clock_nsec;
31 __u32 tb_seq_count; /* Timebase sequence counter */ 33 __u32 tb_seq_count; /* Timebase sequence counter */
32 __u32 cs_mult; /* Clocksource multiplier */ 34 /* cs_* members must be adjacent and in this order (ldp accesses) */
33 __u32 cs_shift; /* Clocksource shift */ 35 __u32 cs_mono_mult; /* NTP-adjusted clocksource multiplier */
36 __u32 cs_shift; /* Clocksource shift (mono = raw) */
37 __u32 cs_raw_mult; /* Raw clocksource multiplier */
34 __u32 tz_minuteswest; /* Whacky timezone stuff */ 38 __u32 tz_minuteswest; /* Whacky timezone stuff */
35 __u32 tz_dsttime; 39 __u32 tz_dsttime;
36 __u32 use_syscall; 40 __u32 use_syscall;
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index f8e5d47f0880..334a1cd7a942 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -77,6 +77,7 @@ int main(void)
77 BLANK(); 77 BLANK();
78 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); 78 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
79 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); 79 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
80 DEFINE(CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_RAW);
80 DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); 81 DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
81 DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE); 82 DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
82 DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE); 83 DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE);
@@ -84,6 +85,8 @@ int main(void)
84 DEFINE(NSEC_PER_SEC, NSEC_PER_SEC); 85 DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
85 BLANK(); 86 BLANK();
86 DEFINE(VDSO_CS_CYCLE_LAST, offsetof(struct vdso_data, cs_cycle_last)); 87 DEFINE(VDSO_CS_CYCLE_LAST, offsetof(struct vdso_data, cs_cycle_last));
88 DEFINE(VDSO_RAW_TIME_SEC, offsetof(struct vdso_data, raw_time_sec));
89 DEFINE(VDSO_RAW_TIME_NSEC, offsetof(struct vdso_data, raw_time_nsec));
87 DEFINE(VDSO_XTIME_CLK_SEC, offsetof(struct vdso_data, xtime_clock_sec)); 90 DEFINE(VDSO_XTIME_CLK_SEC, offsetof(struct vdso_data, xtime_clock_sec));
88 DEFINE(VDSO_XTIME_CLK_NSEC, offsetof(struct vdso_data, xtime_clock_nsec)); 91 DEFINE(VDSO_XTIME_CLK_NSEC, offsetof(struct vdso_data, xtime_clock_nsec));
89 DEFINE(VDSO_XTIME_CRS_SEC, offsetof(struct vdso_data, xtime_coarse_sec)); 92 DEFINE(VDSO_XTIME_CRS_SEC, offsetof(struct vdso_data, xtime_coarse_sec));
@@ -91,7 +94,8 @@ int main(void)
91 DEFINE(VDSO_WTM_CLK_SEC, offsetof(struct vdso_data, wtm_clock_sec)); 94 DEFINE(VDSO_WTM_CLK_SEC, offsetof(struct vdso_data, wtm_clock_sec));
92 DEFINE(VDSO_WTM_CLK_NSEC, offsetof(struct vdso_data, wtm_clock_nsec)); 95 DEFINE(VDSO_WTM_CLK_NSEC, offsetof(struct vdso_data, wtm_clock_nsec));
93 DEFINE(VDSO_TB_SEQ_COUNT, offsetof(struct vdso_data, tb_seq_count)); 96 DEFINE(VDSO_TB_SEQ_COUNT, offsetof(struct vdso_data, tb_seq_count));
94 DEFINE(VDSO_CS_MULT, offsetof(struct vdso_data, cs_mult)); 97 DEFINE(VDSO_CS_MONO_MULT, offsetof(struct vdso_data, cs_mono_mult));
98 DEFINE(VDSO_CS_RAW_MULT, offsetof(struct vdso_data, cs_raw_mult));
95 DEFINE(VDSO_CS_SHIFT, offsetof(struct vdso_data, cs_shift)); 99 DEFINE(VDSO_CS_SHIFT, offsetof(struct vdso_data, cs_shift));
96 DEFINE(VDSO_TZ_MINWEST, offsetof(struct vdso_data, tz_minuteswest)); 100 DEFINE(VDSO_TZ_MINWEST, offsetof(struct vdso_data, tz_minuteswest));
97 DEFINE(VDSO_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime)); 101 DEFINE(VDSO_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime));
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 9fefb005812a..076312b17d4f 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -214,10 +214,16 @@ void update_vsyscall(struct timekeeper *tk)
214 vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec; 214 vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
215 215
216 if (!use_syscall) { 216 if (!use_syscall) {
217 /* tkr_mono.cycle_last == tkr_raw.cycle_last */
217 vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last; 218 vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last;
219 vdso_data->raw_time_sec = tk->raw_time.tv_sec;
220 vdso_data->raw_time_nsec = tk->raw_time.tv_nsec;
218 vdso_data->xtime_clock_sec = tk->xtime_sec; 221 vdso_data->xtime_clock_sec = tk->xtime_sec;
219 vdso_data->xtime_clock_nsec = tk->tkr_mono.xtime_nsec; 222 vdso_data->xtime_clock_nsec = tk->tkr_mono.xtime_nsec;
220 vdso_data->cs_mult = tk->tkr_mono.mult; 223 /* tkr_raw.xtime_nsec == 0 */
224 vdso_data->cs_mono_mult = tk->tkr_mono.mult;
225 vdso_data->cs_raw_mult = tk->tkr_raw.mult;
226 /* tkr_mono.shift == tkr_raw.shift */
221 vdso_data->cs_shift = tk->tkr_mono.shift; 227 vdso_data->cs_shift = tk->tkr_mono.shift;
222 } 228 }
223 229
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index c06919ee29e1..e00b4671bd7c 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -87,6 +87,15 @@ x_tmp .req x8
87 msub \res_nsec, x_tmp, \nsec_to_sec, \res_nsec 87 msub \res_nsec, x_tmp, \nsec_to_sec, \res_nsec
88 .endm 88 .endm
89 89
90 /*
91 * Returns in res_{sec,nsec} the timespec based on the clock_raw delta,
92 * used for CLOCK_MONOTONIC_RAW.
93 */
94 .macro get_ts_clock_raw res_sec, res_nsec, clock_nsec, nsec_to_sec
95 udiv \res_sec, \clock_nsec, \nsec_to_sec
96 msub \res_nsec, \res_sec, \nsec_to_sec, \clock_nsec
97 .endm
98
90 /* sec and nsec are modified in place. */ 99 /* sec and nsec are modified in place. */
91 .macro add_ts sec, nsec, ts_sec, ts_nsec, nsec_to_sec 100 .macro add_ts sec, nsec, ts_sec, ts_nsec, nsec_to_sec
92 /* Add timespec. */ 101 /* Add timespec. */
@@ -135,7 +144,8 @@ ENTRY(__kernel_gettimeofday)
1351: seqcnt_acquire 1441: seqcnt_acquire
136 syscall_check fail=4f 145 syscall_check fail=4f
137 ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST] 146 ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
138 ldp w11, w12, [vdso_data, #VDSO_CS_MULT] 147 /* w11 = cs_mono_mult, w12 = cs_shift */
148 ldp w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
139 ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC] 149 ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
140 seqcnt_check fail=1b 150 seqcnt_check fail=1b
141 151
@@ -172,20 +182,20 @@ ENDPROC(__kernel_gettimeofday)
172/* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */ 182/* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
173ENTRY(__kernel_clock_gettime) 183ENTRY(__kernel_clock_gettime)
174 .cfi_startproc 184 .cfi_startproc
175 cmp w0, #JUMPSLOT_MAX 185 cmp w0, #JUMPSLOT_MAX
176 b.hi syscall 186 b.hi syscall
177 adr vdso_data, _vdso_data 187 adr vdso_data, _vdso_data
178 adr x_tmp, jumptable 188 adr x_tmp, jumptable
179 add x_tmp, x_tmp, w0, uxtw #2 189 add x_tmp, x_tmp, w0, uxtw #2
180 br x_tmp 190 br x_tmp
181 191
182 ALIGN 192 ALIGN
183jumptable: 193jumptable:
184 jump_slot jumptable, CLOCK_REALTIME, realtime 194 jump_slot jumptable, CLOCK_REALTIME, realtime
185 jump_slot jumptable, CLOCK_MONOTONIC, monotonic 195 jump_slot jumptable, CLOCK_MONOTONIC, monotonic
186 b syscall 196 b syscall
187 b syscall 197 b syscall
188 b syscall 198 jump_slot jumptable, CLOCK_MONOTONIC_RAW, monotonic_raw
189 jump_slot jumptable, CLOCK_REALTIME_COARSE, realtime_coarse 199 jump_slot jumptable, CLOCK_REALTIME_COARSE, realtime_coarse
190 jump_slot jumptable, CLOCK_MONOTONIC_COARSE, monotonic_coarse 200 jump_slot jumptable, CLOCK_MONOTONIC_COARSE, monotonic_coarse
191 201
@@ -198,7 +208,8 @@ realtime:
198 seqcnt_acquire 208 seqcnt_acquire
199 syscall_check fail=syscall 209 syscall_check fail=syscall
200 ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST] 210 ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
201 ldp w11, w12, [vdso_data, #VDSO_CS_MULT] 211 /* w11 = cs_mono_mult, w12 = cs_shift */
212 ldp w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
202 ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC] 213 ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
203 seqcnt_check fail=realtime 214 seqcnt_check fail=realtime
204 215
@@ -216,7 +227,8 @@ monotonic:
216 seqcnt_acquire 227 seqcnt_acquire
217 syscall_check fail=syscall 228 syscall_check fail=syscall
218 ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST] 229 ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
219 ldp w11, w12, [vdso_data, #VDSO_CS_MULT] 230 /* w11 = cs_mono_mult, w12 = cs_shift */
231 ldp w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
220 ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC] 232 ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
221 ldp x3, x4, [vdso_data, #VDSO_WTM_CLK_SEC] 233 ldp x3, x4, [vdso_data, #VDSO_WTM_CLK_SEC]
222 seqcnt_check fail=monotonic 234 seqcnt_check fail=monotonic
@@ -234,6 +246,28 @@ monotonic:
234 clock_gettime_return, shift=1 246 clock_gettime_return, shift=1
235 247
236 ALIGN 248 ALIGN
249monotonic_raw:
250 seqcnt_acquire
251 syscall_check fail=syscall
252 ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
253 /* w11 = cs_raw_mult, w12 = cs_shift */
254 ldp w12, w11, [vdso_data, #VDSO_CS_SHIFT]
255 ldp x13, x14, [vdso_data, #VDSO_RAW_TIME_SEC]
256 seqcnt_check fail=monotonic_raw
257
258 /* All computations are done with left-shifted nsecs. */
259 lsl x14, x14, x12
260 get_nsec_per_sec res=x9
261 lsl x9, x9, x12
262
263 get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
264 get_ts_clock_raw res_sec=x10, res_nsec=x11, \
265 clock_nsec=x15, nsec_to_sec=x9
266
267 add_ts sec=x10, nsec=x11, ts_sec=x13, ts_nsec=x14, nsec_to_sec=x9
268 clock_gettime_return, shift=1
269
270 ALIGN
237realtime_coarse: 271realtime_coarse:
238 seqcnt_acquire 272 seqcnt_acquire
239 ldp x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC] 273 ldp x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
@@ -265,6 +299,7 @@ ENTRY(__kernel_clock_getres)
265 .cfi_startproc 299 .cfi_startproc
266 cmp w0, #CLOCK_REALTIME 300 cmp w0, #CLOCK_REALTIME
267 ccmp w0, #CLOCK_MONOTONIC, #0x4, ne 301 ccmp w0, #CLOCK_MONOTONIC, #0x4, ne
302 ccmp w0, #CLOCK_MONOTONIC_RAW, #0x4, ne
268 b.ne 1f 303 b.ne 1f
269 304
270 ldr x2, 5f 305 ldr x2, 5f