mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
timekeeping: Remove CONFIG_DEBUG_TIMEKEEPING
Since 135225a363
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
This commit is contained in:
parent
1d4199cbbe
commit
d44d26987b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user