aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-11-29 17:33:29 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2012-12-05 06:20:03 -0500
commit45a7905fc48f6079932e77d64237cf7f008db5f4 (patch)
tree93b60ea0b2c3daf94b50dfa3125b2a3c59a0ff1b /arch/arm64
parentd91fb5c2677db90460611fce72e6a0af8f6c2a73 (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.c2
-rw-r--r--arch/arm64/kernel/vdso/gettimeofday.S8
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]
712: 722:
@@ -136,11 +137,13 @@ ENTRY(__kernel_clock_gettime)
1364: 1374:
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
1546: /* Store to the user timespec. */ 1576: /* 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 */
210ENTRY(__do_get_tspec) 214ENTRY(__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