Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

timekeeping: Remove CONFIG_DEBUG_TIMEKEEPING

Since 135225a363ae timekeeping_cycles_to_ns() handles large offsets which
would lead to 64bit multiplication overflows correctly. It's also protected
against negative motion of the clocksource unconditionally, which was
exclusive to x86 before.

timekeeping_advance() handles large offsets already correctly.

That means the value of CONFIG_DEBUG_TIMEKEEPING which analyzed these cases
is very close to zero. Remove all of it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20241031120328.536010148@linutronix.de

+3 -136
-1
arch/riscv/configs/defconfig
··· 301 301 CONFIG_DEBUG_PER_CPU_MAPS=y 302 302 CONFIG_SOFTLOCKUP_DETECTOR=y 303 303 CONFIG_WQ_WATCHDOG=y 304 - CONFIG_DEBUG_TIMEKEEPING=y 305 304 CONFIG_DEBUG_RT_MUTEXES=y 306 305 CONFIG_DEBUG_SPINLOCK=y 307 306 CONFIG_DEBUG_MUTEXES=y
-16
include/linux/timekeeper_internal.h
··· 76 76 * ntp shifted nano seconds. 77 77 * @ntp_err_mult: Multiplication factor for scaled math conversion 78 78 * @skip_second_overflow: Flag used to avoid updating NTP twice with same second 79 - * @last_warning: Warning ratelimiter (DEBUG_TIMEKEEPING) 80 - * @underflow_seen: Underflow warning flag (DEBUG_TIMEKEEPING) 81 - * @overflow_seen: Overflow warning flag (DEBUG_TIMEKEEPING) 82 79 * 83 80 * Note: For timespec(64) based interfaces wall_to_monotonic is what 84 81 * we need to add to xtime (or xtime corrected for sub jiffy times) ··· 144 147 u32 ntp_error_shift; 145 148 u32 ntp_err_mult; 146 149 u32 skip_second_overflow; 147 - 148 - #ifdef CONFIG_DEBUG_TIMEKEEPING 149 - long last_warning; 150 - /* 151 - * These simple flag variables are managed 152 - * without locks, which is racy, but they are 153 - * ok since we don't really care about being 154 - * super precise about how many events were 155 - * seen, just that a problem was observed. 156 - */ 157 - int underflow_seen; 158 - int overflow_seen; 159 - #endif 160 150 }; 161 151 162 152 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
+3 -105
kernel/time/timekeeping.c
··· 226 226 return clock->read(clock); 227 227 } 228 228 229 - #ifdef CONFIG_DEBUG_TIMEKEEPING 230 - #define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */ 231 - 232 - static void timekeeping_check_update(struct timekeeper *tk, u64 offset) 233 - { 234 - 235 - u64 max_cycles = tk->tkr_mono.clock->max_cycles; 236 - const char *name = tk->tkr_mono.clock->name; 237 - 238 - if (offset > max_cycles) { 239 - printk_deferred("WARNING: timekeeping: Cycle offset (%lld) is larger than allowed by the '%s' clock's max_cycles value (%lld): time overflow danger\n", 240 - offset, name, max_cycles); 241 - printk_deferred(" timekeeping: Your kernel is sick, but tries to cope by capping time updates\n"); 242 - } else { 243 - if (offset > (max_cycles >> 1)) { 244 - printk_deferred("INFO: timekeeping: Cycle offset (%lld) is larger than the '%s' clock's 50%% safety margin (%lld)\n", 245 - offset, name, max_cycles >> 1); 246 - printk_deferred(" timekeeping: Your kernel is still fine, but is feeling a bit nervous\n"); 247 - } 248 - } 249 - 250 - if (tk->underflow_seen) { 251 - if (jiffies - tk->last_warning > WARNING_FREQ) { 252 - printk_deferred("WARNING: Underflow in clocksource '%s' observed, time update ignored.\n", name); 253 - printk_deferred(" Please report this, consider using a different clocksource, if possible.\n"); 254 - printk_deferred(" Your kernel is probably still fine.\n"); 255 - tk->last_warning = jiffies; 256 - } 257 - tk->underflow_seen = 0; 258 - } 259 - 260 - if (tk->overflow_seen) { 261 - if (jiffies - tk->last_warning > WARNING_FREQ) { 262 - printk_deferred("WARNING: Overflow in clocksource '%s' observed, time update capped.\n", name); 263 - printk_deferred(" Please report this, consider using a different clocksource, if possible.\n"); 264 - printk_deferred(" Your kernel is probably still fine.\n"); 265 - tk->last_warning = jiffies; 266 - } 267 - tk->overflow_seen = 0; 268 - } 269 - } 270 - 271 - static inline u64 timekeeping_cycles_to_ns(const struct tk_read_base *tkr, u64 cycles); 272 - 273 - static inline u64 timekeeping_debug_get_ns(const struct tk_read_base *tkr) 274 - { 275 - struct timekeeper *tk = &tk_core.timekeeper; 276 - u64 now, last, mask, max, delta; 277 - unsigned int seq; 278 - 279 - /* 280 - * Since we're called holding a seqcount, the data may shift 281 - * under us while we're doing the calculation. This can cause 282 - * false positives, since we'd note a problem but throw the 283 - * results away. So nest another seqcount here to atomically 284 - * grab the points we are checking with. 285 - */ 286 - do { 287 - seq = read_seqcount_begin(&tk_core.seq); 288 - now = tk_clock_read(tkr); 289 - last = tkr->cycle_last; 290 - mask = tkr->mask; 291 - max = tkr->clock->max_cycles; 292 - } while (read_seqcount_retry(&tk_core.seq, seq)); 293 - 294 - delta = clocksource_delta(now, last, mask); 295 - 296 - /* 297 - * Try to catch underflows by checking if we are seeing small 298 - * mask-relative negative values. 299 - */ 300 - if (unlikely((~delta & mask) < (mask >> 3))) 301 - tk->underflow_seen = 1; 302 - 303 - /* Check for multiplication overflows */ 304 - if (unlikely(delta > max)) 305 - tk->overflow_seen = 1; 306 - 307 - /* timekeeping_cycles_to_ns() handles both under and overflow */ 308 - return timekeeping_cycles_to_ns(tkr, now); 309 - } 310 - #else 311 - static inline void timekeeping_check_update(struct timekeeper *tk, u64 offset) 312 - { 313 - } 314 - static inline u64 timekeeping_debug_get_ns(const struct tk_read_base *tkr) 315 - { 316 - BUG(); 317 - } 318 - #endif 319 - 320 229 /** 321 230 * tk_setup_internals - Set up internals to use clocksource clock. 322 231 * ··· 330 421 return ((delta * tkr->mult) + tkr->xtime_nsec) >> tkr->shift; 331 422 } 332 423 333 - static __always_inline u64 __timekeeping_get_ns(const struct tk_read_base *tkr) 424 + static __always_inline u64 timekeeping_get_ns(const struct tk_read_base *tkr) 334 425 { 335 426 return timekeeping_cycles_to_ns(tkr, tk_clock_read(tkr)); 336 - } 337 - 338 - static inline u64 timekeeping_get_ns(const struct tk_read_base *tkr) 339 - { 340 - if (IS_ENABLED(CONFIG_DEBUG_TIMEKEEPING)) 341 - return timekeeping_debug_get_ns(tkr); 342 - 343 - return __timekeeping_get_ns(tkr); 344 427 } 345 428 346 429 /** ··· 378 477 seq = raw_read_seqcount_latch(&tkf->seq); 379 478 tkr = tkf->base + (seq & 0x01); 380 479 now = ktime_to_ns(tkr->base); 381 - now += __timekeeping_get_ns(tkr); 480 + now += timekeeping_get_ns(tkr); 382 481 } while (raw_read_seqcount_latch_retry(&tkf->seq, seq)); 383 482 384 483 return now; ··· 494 593 tkr = tkf->base + (seq & 0x01); 495 594 basem = ktime_to_ns(tkr->base); 496 595 baser = ktime_to_ns(tkr->base_real); 497 - delta = __timekeeping_get_ns(tkr); 596 + delta = timekeeping_get_ns(tkr); 498 597 } while (raw_read_seqcount_latch_retry(&tkf->seq, seq)); 499 598 500 599 if (mono) ··· 2233 2332 /* Check if there's really nothing to do */ 2234 2333 if (offset < real_tk->cycle_interval && mode == TK_ADV_TICK) 2235 2334 return false; 2236 - 2237 - /* Do some additional sanity checking */ 2238 - timekeeping_check_update(tk, offset); 2239 2335 2240 2336 /* 2241 2337 * With NO_HZ we may have to accumulate many cycle_intervals
-13
lib/Kconfig.debug
··· 1328 1328 1329 1329 endmenu 1330 1330 1331 - config DEBUG_TIMEKEEPING 1332 - bool "Enable extra timekeeping sanity checking" 1333 - help 1334 - This option will enable additional timekeeping sanity checks 1335 - which may be helpful when diagnosing issues where timekeeping 1336 - problems are suspected. 1337 - 1338 - This may include checks in the timekeeping hotpaths, so this 1339 - option may have a (very small) performance impact to some 1340 - workloads. 1341 - 1342 - If unsure, say N. 1343 - 1344 1331 config DEBUG_PREEMPT 1345 1332 bool "Debug preemptible kernel" 1346 1333 depends on DEBUG_KERNEL && PREEMPTION && TRACE_IRQFLAGS_SUPPORT
-1
tools/testing/selftests/wireguard/qemu/debug.config
··· 31 31 CONFIG_SCHED_INFO=y 32 32 CONFIG_SCHEDSTATS=y 33 33 CONFIG_SCHED_STACK_END_CHECK=y 34 - CONFIG_DEBUG_TIMEKEEPING=y 35 34 CONFIG_DEBUG_PREEMPT=y 36 35 CONFIG_DEBUG_RT_MUTEXES=y 37 36 CONFIG_DEBUG_SPINLOCK=y