diff options
-rw-r--r-- | arch/arm64/include/asm/vdso_datapage.h | 8 | ||||
-rw-r--r-- | arch/arm64/kernel/asm-offsets.c | 6 | ||||
-rw-r--r-- | arch/arm64/kernel/vdso.c | 8 | ||||
-rw-r--r-- | arch/arm64/kernel/vdso/gettimeofday.S | 57 |
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 | ||
23 | struct vdso_data { | 23 | struct 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) | |||
135 | 1: seqcnt_acquire | 144 | 1: 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); */ |
173 | ENTRY(__kernel_clock_gettime) | 183 | ENTRY(__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 |
183 | jumptable: | 193 | jumptable: |
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 |
249 | monotonic_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 | ||
237 | realtime_coarse: | 271 | realtime_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 |