diff options
| -rw-r--r-- | kernel/time/timekeeping.c | 12 | 
1 files changed, 11 insertions, 1 deletions
| diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 749387f22f0f..d17484082e2c 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -367,7 +367,17 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)  static inline u64 timekeeping_cycles_to_ns(const struct tk_read_base *tkr, u64 cycles)  {  	/* Calculate the delta since the last update_wall_time() */ -	u64 delta = clocksource_delta(cycles, tkr->cycle_last, tkr->mask); +	u64 mask = tkr->mask, delta = (cycles - tkr->cycle_last) & mask; + +	if (IS_ENABLED(CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE)) { +		/* +		 * Handle clocksource inconsistency between CPUs to prevent +		 * time from going backwards by checking for the MSB of the +		 * mask being set in the delta. +		 */ +		if (unlikely(delta & ~(mask >> 1))) +			return tkr->xtime_nsec >> tkr->shift; +	}  	return ((delta * tkr->mult) + tkr->xtime_nsec) >> tkr->shift;  } | 
