diff options
author | Will Deacon <will.deacon@arm.com> | 2012-11-29 17:33:29 -0500 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2012-12-05 06:20:03 -0500 |
commit | 45a7905fc48f6079932e77d64237cf7f008db5f4 (patch) | |
tree | 93b60ea0b2c3daf94b50dfa3125b2a3c59a0ff1b /arch/arm64 | |
parent | d91fb5c2677db90460611fce72e6a0af8f6c2a73 (diff) |
arm64: vdso: defer shifting of nanosecond component of timespec
Shifting the nanosecond component of the computed timespec early can
lead to sub-ns inaccuracies when using the truncated value as input to
further arithmetic for things like conversions to monotonic time.
This patch defers the timespec shifting until after the final value has
been computed.
Reported-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/kernel/vdso.c | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/vdso/gettimeofday.S | 8 |
2 files changed, 7 insertions, 3 deletions
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index ba457943a16b..c958cb84d75f 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c | |||
@@ -239,7 +239,7 @@ void update_vsyscall(struct timekeeper *tk) | |||
239 | if (!use_syscall) { | 239 | if (!use_syscall) { |
240 | vdso_data->cs_cycle_last = tk->clock->cycle_last; | 240 | vdso_data->cs_cycle_last = tk->clock->cycle_last; |
241 | vdso_data->xtime_clock_sec = tk->xtime_sec; | 241 | vdso_data->xtime_clock_sec = tk->xtime_sec; |
242 | vdso_data->xtime_clock_nsec = tk->xtime_nsec >> tk->shift; | 242 | vdso_data->xtime_clock_nsec = tk->xtime_nsec; |
243 | vdso_data->cs_mult = tk->mult; | 243 | vdso_data->cs_mult = tk->mult; |
244 | vdso_data->cs_shift = tk->shift; | 244 | vdso_data->cs_shift = tk->shift; |
245 | vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec; | 245 | vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec; |
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S index 99b7d405767c..6681f4032260 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.S +++ b/arch/arm64/kernel/vdso/gettimeofday.S | |||
@@ -66,6 +66,7 @@ ENTRY(__kernel_gettimeofday) | |||
66 | 66 | ||
67 | /* Convert ns to us. */ | 67 | /* Convert ns to us. */ |
68 | mov x13, #1000 | 68 | mov x13, #1000 |
69 | lsl x13, x13, x12 | ||
69 | udiv x11, x11, x13 | 70 | udiv x11, x11, x13 |
70 | stp x10, x11, [x0, #TVAL_TV_SEC] | 71 | stp x10, x11, [x0, #TVAL_TV_SEC] |
71 | 2: | 72 | 2: |
@@ -136,11 +137,13 @@ ENTRY(__kernel_clock_gettime) | |||
136 | 4: | 137 | 4: |
137 | /* Add on wtm timespec. */ | 138 | /* Add on wtm timespec. */ |
138 | add x10, x10, x13 | 139 | add x10, x10, x13 |
140 | lsl x14, x14, x12 | ||
139 | add x11, x11, x14 | 141 | add x11, x11, x14 |
140 | 142 | ||
141 | /* Normalise the new timespec. */ | 143 | /* Normalise the new timespec. */ |
142 | mov x15, #NSEC_PER_SEC_LO16 | 144 | mov x15, #NSEC_PER_SEC_LO16 |
143 | movk x15, #NSEC_PER_SEC_HI16, lsl #16 | 145 | movk x15, #NSEC_PER_SEC_HI16, lsl #16 |
146 | lsl x15, x15, x12 | ||
144 | cmp x11, x15 | 147 | cmp x11, x15 |
145 | b.lt 5f | 148 | b.lt 5f |
146 | sub x11, x11, x15 | 149 | sub x11, x11, x15 |
@@ -152,6 +155,7 @@ ENTRY(__kernel_clock_gettime) | |||
152 | sub x10, x10, #1 | 155 | sub x10, x10, #1 |
153 | 156 | ||
154 | 6: /* Store to the user timespec. */ | 157 | 6: /* Store to the user timespec. */ |
158 | lsr x11, x11, x12 | ||
155 | stp x10, x11, [x1, #TSPEC_TV_SEC] | 159 | stp x10, x11, [x1, #TSPEC_TV_SEC] |
156 | mov x0, xzr | 160 | mov x0, xzr |
157 | ret x2 | 161 | ret x2 |
@@ -204,7 +208,7 @@ ENDPROC(__kernel_clock_getres) | |||
204 | * Clobbers the temporary registers (x9 - x15). | 208 | * Clobbers the temporary registers (x9 - x15). |
205 | * Returns: | 209 | * Returns: |
206 | * - w9 = vDSO sequence counter | 210 | * - w9 = vDSO sequence counter |
207 | * - (x10, x11) = (ts->tv_sec, ts->tv_nsec) | 211 | * - (x10, x11) = (ts->tv_sec, shifted ts->tv_nsec) |
208 | * - w12 = cs_shift | 212 | * - w12 = cs_shift |
209 | */ | 213 | */ |
210 | ENTRY(__do_get_tspec) | 214 | ENTRY(__do_get_tspec) |
@@ -226,11 +230,11 @@ ENTRY(__do_get_tspec) | |||
226 | movn x15, #0xff00, lsl #48 | 230 | movn x15, #0xff00, lsl #48 |
227 | and x10, x15, x10 | 231 | and x10, x15, x10 |
228 | mul x10, x10, x11 | 232 | mul x10, x10, x11 |
229 | lsr x10, x10, x12 | ||
230 | 233 | ||
231 | /* Use the kernel time to calculate the new timespec. */ | 234 | /* Use the kernel time to calculate the new timespec. */ |
232 | mov x11, #NSEC_PER_SEC_LO16 | 235 | mov x11, #NSEC_PER_SEC_LO16 |
233 | movk x11, #NSEC_PER_SEC_HI16, lsl #16 | 236 | movk x11, #NSEC_PER_SEC_HI16, lsl #16 |
237 | lsl x11, x11, x12 | ||
234 | add x15, x10, x14 | 238 | add x15, x10, x14 |
235 | udiv x14, x15, x11 | 239 | udiv x14, x15, x11 |
236 | add x10, x13, x14 | 240 | add x10, x13, x14 |