Commit 5f6b5b97 authored by Paul Mackerras's avatar Paul Mackerras

powerpc: Fix time setting bug on 32-bit

This fixes a bug where settimeofday would set the wrong parameters
in do_gtod, resulting in gettimeofday returning a value about 4
hours after the correct time.  The bug was that we divided a
negative 64-bit value with do_div, which treated it as unsigned
and gave us a result that was approximately 1.8e10 too large
(since the divisor was 1e9).
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent eb66ce63
...@@ -518,7 +518,7 @@ int do_settimeofday(struct timespec *tv) ...@@ -518,7 +518,7 @@ int do_settimeofday(struct timespec *tv)
long wtm_nsec, new_nsec = tv->tv_nsec; long wtm_nsec, new_nsec = tv->tv_nsec;
unsigned long flags; unsigned long flags;
long int tb_delta; long int tb_delta;
u64 new_xsec; u64 new_xsec, tb_delta_xs;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -541,8 +541,7 @@ int do_settimeofday(struct timespec *tv) ...@@ -541,8 +541,7 @@ int do_settimeofday(struct timespec *tv)
#endif #endif
tb_delta = tb_ticks_since(tb_last_stamp); tb_delta = tb_ticks_since(tb_last_stamp);
tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy; tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
tb_delta_xs = mulhdu(tb_delta, do_gtod.varp->tb_to_xs);
new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec); wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
...@@ -557,9 +556,12 @@ int do_settimeofday(struct timespec *tv) ...@@ -557,9 +556,12 @@ int do_settimeofday(struct timespec *tv)
ntp_clear(); ntp_clear();
new_xsec = (u64)new_nsec * XSEC_PER_SEC; new_xsec = 0;
do_div(new_xsec, NSEC_PER_SEC); if (new_nsec != 0) {
new_xsec += (u64)new_sec * XSEC_PER_SEC; new_xsec = (u64)new_nsec * XSEC_PER_SEC;
do_div(new_xsec, NSEC_PER_SEC);
}
new_xsec += (u64)new_sec * XSEC_PER_SEC - tb_delta_xs;
update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment