@@ -164,17 +164,42 @@ static inline struct timespec64 tk_xtime(const struct timekeeper *tk)
164164 return ts ;
165165}
166166
167+ static inline struct timespec64 tk_xtime_coarse (const struct timekeeper * tk )
168+ {
169+ struct timespec64 ts ;
170+
171+ ts .tv_sec = tk -> xtime_sec ;
172+ ts .tv_nsec = tk -> coarse_nsec ;
173+ return ts ;
174+ }
175+
176+ /*
177+ * Update the nanoseconds part for the coarse time keepers. They can't rely
178+ * on xtime_nsec because xtime_nsec could be adjusted by a small negative
179+ * amount when the multiplication factor of the clock is adjusted, which
180+ * could cause the coarse clocks to go slightly backwards. See
181+ * timekeeping_apply_adjustment(). Thus we keep a separate copy for the coarse
182+ * clockids which only is updated when the clock has been set or we have
183+ * accumulated time.
184+ */
185+ static inline void tk_update_coarse_nsecs (struct timekeeper * tk )
186+ {
187+ tk -> coarse_nsec = tk -> tkr_mono .xtime_nsec >> tk -> tkr_mono .shift ;
188+ }
189+
167190static void tk_set_xtime (struct timekeeper * tk , const struct timespec64 * ts )
168191{
169192 tk -> xtime_sec = ts -> tv_sec ;
170193 tk -> tkr_mono .xtime_nsec = (u64 )ts -> tv_nsec << tk -> tkr_mono .shift ;
194+ tk_update_coarse_nsecs (tk );
171195}
172196
173197static void tk_xtime_add (struct timekeeper * tk , const struct timespec64 * ts )
174198{
175199 tk -> xtime_sec += ts -> tv_sec ;
176200 tk -> tkr_mono .xtime_nsec += (u64 )ts -> tv_nsec << tk -> tkr_mono .shift ;
177201 tk_normalize_xtime (tk );
202+ tk_update_coarse_nsecs (tk );
178203}
179204
180205static void tk_set_wall_to_mono (struct timekeeper * tk , struct timespec64 wtm )
@@ -708,6 +733,7 @@ static void timekeeping_forward_now(struct timekeeper *tk)
708733 tk_normalize_xtime (tk );
709734 delta -= incr ;
710735 }
736+ tk_update_coarse_nsecs (tk );
711737}
712738
713739/**
@@ -804,16 +830,16 @@ EXPORT_SYMBOL_GPL(ktime_get_with_offset);
804830ktime_t ktime_get_coarse_with_offset (enum tk_offsets offs )
805831{
806832 struct timekeeper * tk = & tk_core .timekeeper ;
807- unsigned int seq ;
808833 ktime_t base , * offset = offsets [offs ];
834+ unsigned int seq ;
809835 u64 nsecs ;
810836
811837 WARN_ON (timekeeping_suspended );
812838
813839 do {
814840 seq = read_seqcount_begin (& tk_core .seq );
815841 base = ktime_add (tk -> tkr_mono .base , * offset );
816- nsecs = tk -> tkr_mono . xtime_nsec >> tk -> tkr_mono . shift ;
842+ nsecs = tk -> coarse_nsec ;
817843
818844 } while (read_seqcount_retry (& tk_core .seq , seq ));
819845
@@ -2161,7 +2187,7 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
21612187 struct timekeeper * real_tk = & tk_core .timekeeper ;
21622188 unsigned int clock_set = 0 ;
21632189 int shift = 0 , maxshift ;
2164- u64 offset ;
2190+ u64 offset , orig_offset ;
21652191
21662192 guard (raw_spinlock_irqsave )(& tk_core .lock );
21672193
@@ -2172,7 +2198,7 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
21722198 offset = clocksource_delta (tk_clock_read (& tk -> tkr_mono ),
21732199 tk -> tkr_mono .cycle_last , tk -> tkr_mono .mask ,
21742200 tk -> tkr_mono .clock -> max_raw_delta );
2175-
2201+ orig_offset = offset ;
21762202 /* Check if there's really nothing to do */
21772203 if (offset < real_tk -> cycle_interval && mode == TK_ADV_TICK )
21782204 return false;
@@ -2205,6 +2231,14 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
22052231 */
22062232 clock_set |= accumulate_nsecs_to_secs (tk );
22072233
2234+ /*
2235+ * To avoid inconsistencies caused adjtimex TK_ADV_FREQ calls
2236+ * making small negative adjustments to the base xtime_nsec
2237+ * value, only update the coarse clocks if we accumulated time
2238+ */
2239+ if (orig_offset != offset )
2240+ tk_update_coarse_nsecs (tk );
2241+
22082242 timekeeping_update_from_shadow (& tk_core , clock_set );
22092243
22102244 return !!clock_set ;
@@ -2248,7 +2282,7 @@ void ktime_get_coarse_real_ts64(struct timespec64 *ts)
22482282 do {
22492283 seq = read_seqcount_begin (& tk_core .seq );
22502284
2251- * ts = tk_xtime (tk );
2285+ * ts = tk_xtime_coarse (tk );
22522286 } while (read_seqcount_retry (& tk_core .seq , seq ));
22532287}
22542288EXPORT_SYMBOL (ktime_get_coarse_real_ts64 );
@@ -2271,7 +2305,7 @@ void ktime_get_coarse_real_ts64_mg(struct timespec64 *ts)
22712305
22722306 do {
22732307 seq = read_seqcount_begin (& tk_core .seq );
2274- * ts = tk_xtime (tk );
2308+ * ts = tk_xtime_coarse (tk );
22752309 offset = tk_core .timekeeper .offs_real ;
22762310 } while (read_seqcount_retry (& tk_core .seq , seq ));
22772311
@@ -2350,12 +2384,12 @@ void ktime_get_coarse_ts64(struct timespec64 *ts)
23502384 do {
23512385 seq = read_seqcount_begin (& tk_core .seq );
23522386
2353- now = tk_xtime (tk );
2387+ now = tk_xtime_coarse (tk );
23542388 mono = tk -> wall_to_monotonic ;
23552389 } while (read_seqcount_retry (& tk_core .seq , seq ));
23562390
23572391 set_normalized_timespec64 (ts , now .tv_sec + mono .tv_sec ,
2358- now .tv_nsec + mono .tv_nsec );
2392+ now .tv_nsec + mono .tv_nsec );
23592393}
23602394EXPORT_SYMBOL (ktime_get_coarse_ts64 );
23612395
0 commit comments