1526 lines · 43.1 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0+/* * This file contains the functions which manage clocksource drivers. * * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/device.h>#include <linux/clocksource.h>#include <linux/init.h>#include <linux/module.h>#include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */#include <linux/tick.h>#include <linux/kthread.h>#include <linux/prandom.h>#include <linux/cpu.h> #include "tick-internal.h"#include "timekeeping_internal.h" static noinline u64 cycles_to_nsec_safe(struct clocksource *cs, u64 start, u64 end){	u64 delta = clocksource_delta(end, start, cs->mask); 	if (likely(delta < cs->max_cycles))		return clocksource_cyc2ns(delta, cs->mult, cs->shift); 	return mul_u64_u32_shr(delta, cs->mult, cs->shift);} /** * clocks_calc_mult_shift - calculate mult/shift factors for scaled math of clocks * @mult:	pointer to mult variable * @shift:	pointer to shift variable * @from:	frequency to convert from * @to:		frequency to convert to * @maxsec:	guaranteed runtime conversion range in seconds * * The function evaluates the shift/mult pair for the scaled math * operations of clocksources and clockevents. * * @to and @from are frequency values in HZ. For clock sources @to is * NSEC_PER_SEC == 1GHz and @from is the counter frequency. For clock * event @to is the counter frequency and @from is NSEC_PER_SEC. * * The @maxsec conversion range argument controls the time frame in * seconds which must be covered by the runtime conversion with the * calculated mult and shift factors. This guarantees that no 64bit * overflow happens when the input value of the conversion is * multiplied with the calculated mult factor. Larger ranges may * reduce the conversion accuracy by choosing smaller mult and shift * factors. */voidclocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec){	u64 tmp;	u32 sft, sftacc= 32; 	/*	 * Calculate the shift factor which is limiting the conversion	 * range:	 */	tmp = ((u64)maxsec * from) >> 32;	while (tmp) {		tmp >>=1;		sftacc--;	} 	/*	 * Find the conversion shift/mult pair which has the best	 * accuracy and fits the maxsec conversion range:	 */	for (sft = 32; sft > 0; sft--) {		tmp = (u64) to << sft;		tmp += from / 2;		do_div(tmp, from);		if ((tmp >> sftacc) == 0)			break;	}	*mult = tmp;	*shift = sft;}EXPORT_SYMBOL_GPL(clocks_calc_mult_shift); /*[Clocksource internal variables]--------- * curr_clocksource: *	currently selected clocksource. * suspend_clocksource: *	used to calculate the suspend time. * clocksource_list: *	linked list with the registered clocksources * clocksource_mutex: *	protects manipulations to curr_clocksource and the clocksource_list * override_name: *	Name of the user-specified clocksource. */static struct clocksource *curr_clocksource;static struct clocksource *suspend_clocksource;static LIST_HEAD(clocksource_list);static DEFINE_MUTEX(clocksource_mutex);static char override_name[CS_NAME_LEN];static int finished_booting;static u64 suspend_start; /* * Interval: 0.5sec. */#define WATCHDOG_INTERVAL (HZ >> 1)#define WATCHDOG_INTERVAL_MAX_NS ((2 * WATCHDOG_INTERVAL) * (NSEC_PER_SEC / HZ)) /* * Threshold: 0.0312s, when doubled: 0.0625s. * Also a default for cs->uncertainty_margin when registering clocks. */#define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 5) /* * Maximum permissible delay between two readouts of the watchdog * clocksource surrounding a read of the clocksource being validated. * This delay could be due to SMIs, NMIs, or to VCPU preemptions.  Used as * a lower bound for cs->uncertainty_margin values when registering clocks. * * The default of 500 parts per million is based on NTP's limits. * If a clocksource is good enough for NTP, it is good enough for us! */#ifdef CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US#define MAX_SKEW_USEC	CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US#else#define MAX_SKEW_USEC	(125 * WATCHDOG_INTERVAL / HZ)#endif #define WATCHDOG_MAX_SKEW (MAX_SKEW_USEC * NSEC_PER_USEC) #ifdef CONFIG_CLOCKSOURCE_WATCHDOGstatic void clocksource_watchdog_work(struct work_struct *work);static void clocksource_select(void); static LIST_HEAD(watchdog_list);static struct clocksource *watchdog;static struct timer_list watchdog_timer;static DECLARE_WORK(watchdog_work, clocksource_watchdog_work);static DEFINE_SPINLOCK(watchdog_lock);static int watchdog_running;static atomic_t watchdog_reset_pending;static int64_t watchdog_max_interval; static inline void clocksource_watchdog_lock(unsigned long *flags){	spin_lock_irqsave(&watchdog_lock, *flags);} static inline void clocksource_watchdog_unlock(unsigned long *flags){	spin_unlock_irqrestore(&watchdog_lock, *flags);} static int clocksource_watchdog_kthread(void *data);static void __clocksource_change_rating(struct clocksource *cs, int rating); static void clocksource_watchdog_work(struct work_struct *work){	/*	 * We cannot directly run clocksource_watchdog_kthread() here, because	 * clocksource_select() calls timekeeping_notify() which uses	 * stop_machine(). One cannot use stop_machine() from a workqueue() due	 * lock inversions wrt CPU hotplug.	 *	 * Also, we only ever run this work once or twice during the lifetime	 * of the kernel, so there is no point in creating a more permanent	 * kthread for this.	 *	 * If kthread_run fails the next watchdog scan over the	 * watchdog_list will find the unstable clock again.	 */	kthread_run(clocksource_watchdog_kthread, NULL, "kwatchdog");} static void __clocksource_unstable(struct clocksource *cs){	cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);	cs->flags |= CLOCK_SOURCE_UNSTABLE; 	/*	 * If the clocksource is registered clocksource_watchdog_kthread() will	 * re-rate and re-select.	 */	if (list_empty(&cs->list)) {		cs->rating = 0;		return;	} 	if (cs->mark_unstable)		cs->mark_unstable(cs); 	/* kick clocksource_watchdog_kthread() */	if (finished_booting)		schedule_work(&watchdog_work);} /** * clocksource_mark_unstable - mark clocksource unstable via watchdog * @cs:		clocksource to be marked unstable * * This function is called by the x86 TSC code to mark clocksources as unstable; * it defers demotion and re-selection to a kthread. */void clocksource_mark_unstable(struct clocksource *cs){	unsigned long flags; 	spin_lock_irqsave(&watchdog_lock, flags);	if (!(cs->flags & CLOCK_SOURCE_UNSTABLE)) {		if (!list_empty(&cs->list) && list_empty(&cs->wd_list))			list_add(&cs->wd_list, &watchdog_list);		__clocksource_unstable(cs);	}	spin_unlock_irqrestore(&watchdog_lock, flags);} static int verify_n_cpus = 8;module_param(verify_n_cpus, int, 0644); enum wd_read_status {	WD_READ_SUCCESS,	WD_READ_UNSTABLE,	WD_READ_SKIP}; static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow){	unsigned int nretries, max_retries;	int64_t wd_delay, wd_seq_delay;	u64 wd_end, wd_end2; 	max_retries = clocksource_get_max_watchdog_retry();	for (nretries = 0; nretries <= max_retries; nretries++) {		local_irq_disable();		*wdnow = watchdog->read(watchdog);		*csnow = cs->read(cs);		wd_end = watchdog->read(watchdog);		wd_end2 = watchdog->read(watchdog);		local_irq_enable(); 		wd_delay = cycles_to_nsec_safe(watchdog, *wdnow, wd_end);		if (wd_delay <= WATCHDOG_MAX_SKEW) {			if (nretries > 1 && nretries >= max_retries) {				pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n",					smp_processor_id(), watchdog->name, nretries);			}			return WD_READ_SUCCESS;		} 		/*		 * Now compute delay in consecutive watchdog read to see if		 * there is too much external interferences that cause		 * significant delay in reading both clocksource and watchdog.		 *		 * If consecutive WD read-back delay > WATCHDOG_MAX_SKEW/2,		 * report system busy, reinit the watchdog and skip the current		 * watchdog test.		 */		wd_seq_delay = cycles_to_nsec_safe(watchdog, wd_end, wd_end2);		if (wd_seq_delay > WATCHDOG_MAX_SKEW/2)			goto skip_test;	} 	pr_warn("timekeeping watchdog on CPU%d: wd-%s-wd excessive read-back delay of %lldns vs. limit of %ldns, wd-wd read-back delay only %lldns, attempt %d, marking %s unstable\n",		smp_processor_id(), cs->name, wd_delay, WATCHDOG_MAX_SKEW, wd_seq_delay, nretries, cs->name);	return WD_READ_UNSTABLE; skip_test:	pr_info("timekeeping watchdog on CPU%d: %s wd-wd read-back delay of %lldns\n",		smp_processor_id(), watchdog->name, wd_seq_delay);	pr_info("wd-%s-wd read-back delay of %lldns, clock-skew test skipped!\n",		cs->name, wd_delay);	return WD_READ_SKIP;} static u64 csnow_mid;static cpumask_t cpus_ahead;static cpumask_t cpus_behind;static cpumask_t cpus_chosen; static void clocksource_verify_choose_cpus(void){	int cpu, i, n = verify_n_cpus; 	if (n < 0) {		/* Check all of the CPUs. */		cpumask_copy(&cpus_chosen, cpu_online_mask);		cpumask_clear_cpu(smp_processor_id(), &cpus_chosen);		return;	} 	/* If no checking desired, or no other CPU to check, leave. */	cpumask_clear(&cpus_chosen);	if (n == 0 || num_online_cpus() <= 1)		return; 	/* Make sure to select at least one CPU other than the current CPU. */	cpu = cpumask_first(cpu_online_mask);	if (cpu == smp_processor_id())		cpu = cpumask_next(cpu, cpu_online_mask);	if (WARN_ON_ONCE(cpu >= nr_cpu_ids))		return;	cpumask_set_cpu(cpu, &cpus_chosen); 	/* Force a sane value for the boot parameter. */	if (n > nr_cpu_ids)		n = nr_cpu_ids; 	/*	 * Randomly select the specified number of CPUs.  If the same	 * CPU is selected multiple times, that CPU is checked only once,	 * and no replacement CPU is selected.  This gracefully handles	 * situations where verify_n_cpus is greater than the number of	 * CPUs that are currently online.	 */	for (i = 1; i < n; i++) {		cpu = get_random_u32_below(nr_cpu_ids);		cpu = cpumask_next(cpu - 1, cpu_online_mask);		if (cpu >= nr_cpu_ids)			cpu = cpumask_first(cpu_online_mask);		if (!WARN_ON_ONCE(cpu >= nr_cpu_ids))			cpumask_set_cpu(cpu, &cpus_chosen);	} 	/* Don't verify ourselves. */	cpumask_clear_cpu(smp_processor_id(), &cpus_chosen);} static void clocksource_verify_one_cpu(void *csin){	struct clocksource *cs = (struct clocksource *)csin; 	csnow_mid = cs->read(cs);} void clocksource_verify_percpu(struct clocksource *cs){	int64_t cs_nsec, cs_nsec_max = 0, cs_nsec_min = LLONG_MAX;	u64 csnow_begin, csnow_end;	int cpu, testcpu;	s64 delta; 	if (verify_n_cpus == 0)		return;	cpumask_clear(&cpus_ahead);	cpumask_clear(&cpus_behind);	cpus_read_lock();	preempt_disable();	clocksource_verify_choose_cpus();	if (cpumask_empty(&cpus_chosen)) {		preempt_enable();		cpus_read_unlock();		pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name);		return;	}	testcpu = smp_processor_id();	pr_warn("Checking clocksource %s synchronization from CPU %d to CPUs %*pbl.\n", cs->name, testcpu, cpumask_pr_args(&cpus_chosen));	for_each_cpu(cpu, &cpus_chosen) {		if (cpu == testcpu)			continue;		csnow_begin = cs->read(cs);		smp_call_function_single(cpu, clocksource_verify_one_cpu, cs, 1);		csnow_end = cs->read(cs);		delta = (s64)((csnow_mid - csnow_begin) & cs->mask);		if (delta < 0)			cpumask_set_cpu(cpu, &cpus_behind);		delta = (csnow_end - csnow_mid) & cs->mask;		if (delta < 0)			cpumask_set_cpu(cpu, &cpus_ahead);		cs_nsec = cycles_to_nsec_safe(cs, csnow_begin, csnow_end);		if (cs_nsec > cs_nsec_max)			cs_nsec_max = cs_nsec;		if (cs_nsec < cs_nsec_min)			cs_nsec_min = cs_nsec;	}	preempt_enable();	cpus_read_unlock();	if (!cpumask_empty(&cpus_ahead))		pr_warn("        CPUs %*pbl ahead of CPU %d for clocksource %s.\n",			cpumask_pr_args(&cpus_ahead), testcpu, cs->name);	if (!cpumask_empty(&cpus_behind))		pr_warn("        CPUs %*pbl behind CPU %d for clocksource %s.\n",			cpumask_pr_args(&cpus_behind), testcpu, cs->name);	if (!cpumask_empty(&cpus_ahead) || !cpumask_empty(&cpus_behind))		pr_warn("        CPU %d check durations %lldns - %lldns for clocksource %s.\n",			testcpu, cs_nsec_min, cs_nsec_max, cs->name);}EXPORT_SYMBOL_GPL(clocksource_verify_percpu); static inline void clocksource_reset_watchdog(void){	struct clocksource *cs; 	list_for_each_entry(cs, &watchdog_list, wd_list)		cs->flags &= ~CLOCK_SOURCE_WATCHDOG;}  static void clocksource_watchdog(struct timer_list *unused){	int64_t wd_nsec, cs_nsec, interval;	u64 csnow, wdnow, cslast, wdlast;	int next_cpu, reset_pending;	struct clocksource *cs;	enum wd_read_status read_ret;	unsigned long extra_wait = 0;	u32 md; 	spin_lock(&watchdog_lock);	if (!watchdog_running)		goto out; 	reset_pending = atomic_read(&watchdog_reset_pending); 	list_for_each_entry(cs, &watchdog_list, wd_list) { 		/* Clocksource already marked unstable? */		if (cs->flags & CLOCK_SOURCE_UNSTABLE) {			if (finished_booting)				schedule_work(&watchdog_work);			continue;		} 		read_ret = cs_watchdog_read(cs, &csnow, &wdnow); 		if (read_ret == WD_READ_UNSTABLE) {			/* Clock readout unreliable, so give it up. */			__clocksource_unstable(cs);			continue;		} 		/*		 * When WD_READ_SKIP is returned, it means the system is likely		 * under very heavy load, where the latency of reading		 * watchdog/clocksource is very big, and affect the accuracy of		 * watchdog check. So give system some space and suspend the		 * watchdog check for 5 minutes.		 */		if (read_ret == WD_READ_SKIP) {			/*			 * As the watchdog timer will be suspended, and			 * cs->last could keep unchanged for 5 minutes, reset			 * the counters.			 */			clocksource_reset_watchdog();			extra_wait = HZ * 300;			break;		} 		/* Clocksource initialized ? */		if (!(cs->flags & CLOCK_SOURCE_WATCHDOG) ||		    atomic_read(&watchdog_reset_pending)) {			cs->flags |= CLOCK_SOURCE_WATCHDOG;			cs->wd_last = wdnow;			cs->cs_last = csnow;			continue;		} 		wd_nsec = cycles_to_nsec_safe(watchdog, cs->wd_last, wdnow);		cs_nsec = cycles_to_nsec_safe(cs, cs->cs_last, csnow);		wdlast = cs->wd_last; /* save these in case we print them */		cslast = cs->cs_last;		cs->cs_last = csnow;		cs->wd_last = wdnow; 		if (atomic_read(&watchdog_reset_pending))			continue; 		/*		 * The processing of timer softirqs can get delayed (usually		 * on account of ksoftirqd not getting to run in a timely		 * manner), which causes the watchdog interval to stretch.		 * Skew detection may fail for longer watchdog intervals		 * on account of fixed margins being used.		 * Some clocksources, e.g. acpi_pm, cannot tolerate		 * watchdog intervals longer than a few seconds.		 */		interval = max(cs_nsec, wd_nsec);		if (unlikely(interval > WATCHDOG_INTERVAL_MAX_NS)) {			if (system_state > SYSTEM_SCHEDULING &&			    interval > 2 * watchdog_max_interval) {				watchdog_max_interval = interval;				pr_warn("Long readout interval, skipping watchdog check: cs_nsec: %lld wd_nsec: %lld\n",					cs_nsec, wd_nsec);			}			watchdog_timer.expires = jiffies;			continue;		} 		/* Check the deviation from the watchdog clocksource. */		md = cs->uncertainty_margin + watchdog->uncertainty_margin;		if (abs(cs_nsec - wd_nsec) > md) {			s64 cs_wd_msec;			s64 wd_msec;

Lines 1–500 of 1526.