Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −6
Original line number Original line Diff line number Diff line
@@ -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)
#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)


	ntp_clear();
	ntp_clear();


	new_xsec = 0;
	if (new_nsec != 0) {
		new_xsec = (u64)new_nsec * XSEC_PER_SEC;
		new_xsec = (u64)new_nsec * XSEC_PER_SEC;
		do_div(new_xsec, NSEC_PER_SEC);
		do_div(new_xsec, NSEC_PER_SEC);
	new_xsec += (u64)new_sec * XSEC_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