]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
timekeeping: Remove CONFIG_DEBUG_TIMEKEEPING
authorThomas Gleixner <tglx@linutronix.de>
Thu, 31 Oct 2024 12:04:07 +0000 (13:04 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 2 Nov 2024 09:14:31 +0000 (10:14 +0100)
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
arch/riscv/configs/defconfig
include/linux/timekeeper_internal.h
kernel/time/timekeeping.c
lib/Kconfig.debug
tools/testing/selftests/wireguard/qemu/debug.config

index 2341393cfac1ae9afcd5de61c2ffb735deb53605..26c01b9e3434c4f6d548b328ff894cbc0eaa8b96 100644 (file)
@@ -301,7 +301,6 @@ CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DEBUG_PER_CPU_MAPS=y
 CONFIG_SOFTLOCKUP_DETECTOR=y
 CONFIG_WQ_WATCHDOG=y
-CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
index a3b6380a77772031d5a40948a4595e2c4687d93d..e39d4d563b1975a5902e2e160a6f34b7ceb94410 100644 (file)
@@ -76,9 +76,6 @@ struct tk_read_base {
  *                             ntp shifted nano seconds.
  * @ntp_err_mult:              Multiplication factor for scaled math conversion
  * @skip_second_overflow:      Flag used to avoid updating NTP twice with same second
- * @last_warning:              Warning ratelimiter (DEBUG_TIMEKEEPING)
- * @underflow_seen:            Underflow warning flag (DEBUG_TIMEKEEPING)
- * @overflow_seen:             Overflow warning flag (DEBUG_TIMEKEEPING)
  *
  * Note: For timespec(64) based interfaces wall_to_monotonic is what
  * we need to add to xtime (or xtime corrected for sub jiffy times)
@@ -147,19 +144,6 @@ struct timekeeper {
        u32                     ntp_error_shift;
        u32                     ntp_err_mult;
        u32                     skip_second_overflow;
-
-#ifdef CONFIG_DEBUG_TIMEKEEPING
-       long                    last_warning;
-       /*
-        * These simple flag variables are managed
-        * without locks, which is racy, but they are
-        * ok since we don't really care about being
-        * super precise about how many events were
-        * seen, just that a problem was observed.
-        */
-       int                     underflow_seen;
-       int                     overflow_seen;
-#endif
 };
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
index 17cae886ca8269c0460a94a31144b887f8ff40f7..d115adebc418c77837a6096a784e75906a080fab 100644 (file)
@@ -226,97 +226,6 @@ static inline u64 tk_clock_read(const struct tk_read_base *tkr)
        return clock->read(clock);
 }
 
-#ifdef CONFIG_DEBUG_TIMEKEEPING
-#define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */
-
-static void timekeeping_check_update(struct timekeeper *tk, u64 offset)
-{
-
-       u64 max_cycles = tk->tkr_mono.clock->max_cycles;
-       const char *name = tk->tkr_mono.clock->name;
-
-       if (offset > max_cycles) {
-               printk_deferred("WARNING: timekeeping: Cycle offset (%lld) is larger than allowed by the '%s' clock's max_cycles value (%lld): time overflow danger\n",
-                               offset, name, max_cycles);
-               printk_deferred("         timekeeping: Your kernel is sick, but tries to cope by capping time updates\n");
-       } else {
-               if (offset > (max_cycles >> 1)) {
-                       printk_deferred("INFO: timekeeping: Cycle offset (%lld) is larger than the '%s' clock's 50%% safety margin (%lld)\n",
-                                       offset, name, max_cycles >> 1);
-                       printk_deferred("      timekeeping: Your kernel is still fine, but is feeling a bit nervous\n");
-               }
-       }
-
-       if (tk->underflow_seen) {
-               if (jiffies - tk->last_warning > WARNING_FREQ) {
-                       printk_deferred("WARNING: Underflow in clocksource '%s' observed, time update ignored.\n", name);
-                       printk_deferred("         Please report this, consider using a different clocksource, if possible.\n");
-                       printk_deferred("         Your kernel is probably still fine.\n");
-                       tk->last_warning = jiffies;
-               }
-               tk->underflow_seen = 0;
-       }
-
-       if (tk->overflow_seen) {
-               if (jiffies - tk->last_warning > WARNING_FREQ) {
-                       printk_deferred("WARNING: Overflow in clocksource '%s' observed, time update capped.\n", name);
-                       printk_deferred("         Please report this, consider using a different clocksource, if possible.\n");
-                       printk_deferred("         Your kernel is probably still fine.\n");
-                       tk->last_warning = jiffies;
-               }
-               tk->overflow_seen = 0;
-       }
-}
-
-static inline u64 timekeeping_cycles_to_ns(const struct tk_read_base *tkr, u64 cycles);
-
-static inline u64 timekeeping_debug_get_ns(const struct tk_read_base *tkr)
-{
-       struct timekeeper *tk = &tk_core.timekeeper;
-       u64 now, last, mask, max, delta;
-       unsigned int seq;
-
-       /*
-        * Since we're called holding a seqcount, the data may shift
-        * under us while we're doing the calculation. This can cause
-        * false positives, since we'd note a problem but throw the
-        * results away. So nest another seqcount here to atomically
-        * grab the points we are checking with.
-        */
-       do {
-               seq = read_seqcount_begin(&tk_core.seq);
-               now = tk_clock_read(tkr);
-               last = tkr->cycle_last;
-               mask = tkr->mask;
-               max = tkr->clock->max_cycles;
-       } while (read_seqcount_retry(&tk_core.seq, seq));
-
-       delta = clocksource_delta(now, last, mask);
-
-       /*
-        * Try to catch underflows by checking if we are seeing small
-        * mask-relative negative values.
-        */
-       if (unlikely((~delta & mask) < (mask >> 3)))
-               tk->underflow_seen = 1;
-
-       /* Check for multiplication overflows */
-       if (unlikely(delta > max))
-               tk->overflow_seen = 1;
-
-       /* timekeeping_cycles_to_ns() handles both under and overflow */
-       return timekeeping_cycles_to_ns(tkr, now);
-}
-#else
-static inline void timekeeping_check_update(struct timekeeper *tk, u64 offset)
-{
-}
-static inline u64 timekeeping_debug_get_ns(const struct tk_read_base *tkr)
-{
-       BUG();
-}
-#endif
-
 /**
  * tk_setup_internals - Set up internals to use clocksource clock.
  *
@@ -421,19 +330,11 @@ static inline u64 timekeeping_cycles_to_ns(const struct tk_read_base *tkr, u64 c
        return ((delta * tkr->mult) + tkr->xtime_nsec) >> tkr->shift;
 }
 
-static __always_inline u64 __timekeeping_get_ns(const struct tk_read_base *tkr)
+static __always_inline u64 timekeeping_get_ns(const struct tk_read_base *tkr)
 {
        return timekeeping_cycles_to_ns(tkr, tk_clock_read(tkr));
 }
 
-static inline u64 timekeeping_get_ns(const struct tk_read_base *tkr)
-{
-       if (IS_ENABLED(CONFIG_DEBUG_TIMEKEEPING))
-               return timekeeping_debug_get_ns(tkr);
-
-       return __timekeeping_get_ns(tkr);
-}
-
 /**
  * update_fast_timekeeper - Update the fast and NMI safe monotonic timekeeper.
  * @tkr: Timekeeping readout base from which we take the update
@@ -477,7 +378,7 @@ static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf)
                seq = raw_read_seqcount_latch(&tkf->seq);
                tkr = tkf->base + (seq & 0x01);
                now = ktime_to_ns(tkr->base);
-               now += __timekeeping_get_ns(tkr);
+               now += timekeeping_get_ns(tkr);
        } while (raw_read_seqcount_latch_retry(&tkf->seq, seq));
 
        return now;
@@ -593,7 +494,7 @@ static __always_inline u64 __ktime_get_real_fast(struct tk_fast *tkf, u64 *mono)
                tkr = tkf->base + (seq & 0x01);
                basem = ktime_to_ns(tkr->base);
                baser = ktime_to_ns(tkr->base_real);
-               delta = __timekeeping_get_ns(tkr);
+               delta = timekeeping_get_ns(tkr);
        } while (raw_read_seqcount_latch_retry(&tkf->seq, seq));
 
        if (mono)
@@ -2333,9 +2234,6 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
        if (offset < real_tk->cycle_interval && mode == TK_ADV_TICK)
                return false;
 
-       /* Do some additional sanity checking */
-       timekeeping_check_update(tk, offset);
-
        /*
         * With NO_HZ we may have to accumulate many cycle_intervals
         * (think "ticks") worth of time at once. To do this efficiently,
index 7315f643817ae1021f1e4b3dd27b424f49e3f761..14977b9fc254efde25f5bb7872eb1c6a31cc3e21 100644 (file)
@@ -1328,19 +1328,6 @@ config SCHEDSTATS
 
 endmenu
 
-config DEBUG_TIMEKEEPING
-       bool "Enable extra timekeeping sanity checking"
-       help
-         This option will enable additional timekeeping sanity checks
-         which may be helpful when diagnosing issues where timekeeping
-         problems are suspected.
-
-         This may include checks in the timekeeping hotpaths, so this
-         option may have a (very small) performance impact to some
-         workloads.
-
-         If unsure, say N.
-
 config DEBUG_PREEMPT
        bool "Debug preemptible kernel"
        depends on DEBUG_KERNEL && PREEMPTION && TRACE_IRQFLAGS_SUPPORT
index 9d172210e2c63f2e54e05db860a2b2dbf12d3666..139fd9aa8b1218f1a017d83cf6fc7df9fd05d9b0 100644 (file)
@@ -31,7 +31,6 @@ CONFIG_SCHED_DEBUG=y
 CONFIG_SCHED_INFO=y
 CONFIG_SCHEDSTATS=y
 CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_DEBUG_PREEMPT=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK=y