@@ -296,6 +296,11 @@ static struct {
296296 spinlock_t lock ;
297297} host_ts ;
298298
299+ static bool timesync_implicit ;
300+
301+ module_param (timesync_implicit , bool , 0644 );
302+ MODULE_PARM_DESC (timesync_implicit , "If set treat SAMPLE as SYNC when clock is behind" );
303+
299304static inline u64 reftime_to_ns (u64 reftime )
300305{
301306 return (reftime - WLTIMEDELTA ) * 100 ;
@@ -344,6 +349,29 @@ static void hv_set_host_time(struct work_struct *work)
344349 do_settimeofday64 (& ts );
345350}
346351
352+ /*
353+ * Due to a bug on Hyper-V hosts, the sync flag may not always be sent on resume.
354+ * Force a sync if the guest is behind.
355+ */
356+ static inline bool hv_implicit_sync (u64 host_time )
357+ {
358+ struct timespec64 new_ts ;
359+ struct timespec64 threshold_ts ;
360+
361+ new_ts = ns_to_timespec64 (reftime_to_ns (host_time ));
362+ ktime_get_real_ts64 (& threshold_ts );
363+
364+ threshold_ts .tv_sec += 5 ;
365+
366+ /*
367+ * If guest behind the host by 5 or more seconds.
368+ */
369+ if (timespec64_compare (& new_ts , & threshold_ts ) >= 0 )
370+ return true;
371+
372+ return false;
373+ }
374+
347375/*
348376 * Synchronize time with host after reboot, restore, etc.
349377 *
@@ -384,7 +412,8 @@ static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags)
384412 spin_unlock_irqrestore (& host_ts .lock , flags );
385413
386414 /* Schedule work to do do_settimeofday64() */
387- if (adj_flags & ICTIMESYNCFLAG_SYNC )
415+ if ((adj_flags & ICTIMESYNCFLAG_SYNC ) ||
416+ (timesync_implicit && hv_implicit_sync (host_ts .host_time )))
388417 schedule_work (& adj_time_work );
389418}
390419
0 commit comments