1477 lines · 41.3 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" /** * 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; /* * 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. */#ifdef CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US#define MAX_SKEW_USEC	CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US#else#define MAX_SKEW_USEC	100#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 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); /* * Interval: 0.5sec. */#define WATCHDOG_INTERVAL (HZ >> 1) 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);} ulong max_cswd_read_retries = 2;module_param(max_cswd_read_retries, ulong, 0644);EXPORT_SYMBOL_GPL(max_cswd_read_retries);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;	u64 wd_end, wd_end2, wd_delta;	int64_t wd_delay, wd_seq_delay; 	for (nretries = 0; nretries <= max_cswd_read_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_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask);		wd_delay = clocksource_cyc2ns(wd_delta, watchdog->mult,					      watchdog->shift);		if (wd_delay <= WATCHDOG_MAX_SKEW) {			if (nretries > 1 || nretries >= max_cswd_read_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_delta = clocksource_delta(wd_end2, wd_end, watchdog->mask);		wd_seq_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, watchdog->shift);		if (wd_seq_delay > WATCHDOG_MAX_SKEW/2)			goto skip_test;	} 	pr_warn("timekeeping watchdog on CPU%d: %s read-back delay of %lldns, attempt %d, marking unstable\n",		smp_processor_id(), watchdog->name, wd_delay, nretries);	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);		delta = clocksource_delta(csnow_end, csnow_begin, cs->mask);		cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);		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 void clocksource_watchdog(struct timer_list *unused){	u64 csnow, wdnow, cslast, wdlast, delta;	int next_cpu, reset_pending;	int64_t wd_nsec, cs_nsec;	struct clocksource *cs;	enum wd_read_status read_ret;	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_SUCCESS) {			if (read_ret == WD_READ_UNSTABLE)				/* Clock readout unreliable, so give it up. */				__clocksource_unstable(cs);			continue;		} 		/* 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;		} 		delta = clocksource_delta(wdnow, cs->wd_last, watchdog->mask);		wd_nsec = clocksource_cyc2ns(delta, watchdog->mult,					     watchdog->shift); 		delta = clocksource_delta(csnow, cs->cs_last, cs->mask);		cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);		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; 		/* Check the deviation from the watchdog clocksource. */		md = cs->uncertainty_margin + watchdog->uncertainty_margin;		if (abs(cs_nsec - wd_nsec) > md) {			pr_warn("timekeeping watchdog on CPU%d: Marking clocksource '%s' as unstable because the skew is too large:\n",				smp_processor_id(), cs->name);			pr_warn("                      '%s' wd_nsec: %lld wd_now: %llx wd_last: %llx mask: %llx\n",				watchdog->name, wd_nsec, wdnow, wdlast, watchdog->mask);			pr_warn("                      '%s' cs_nsec: %lld cs_now: %llx cs_last: %llx mask: %llx\n",				cs->name, cs_nsec, csnow, cslast, cs->mask);			if (curr_clocksource == cs)				pr_warn("                      '%s' is current clocksource.\n", cs->name);			else if (curr_clocksource)				pr_warn("                      '%s' (not '%s') is current clocksource.\n", curr_clocksource->name, cs->name);			else				pr_warn("                      No current clocksource.\n");			__clocksource_unstable(cs);			continue;		} 		if (cs == curr_clocksource && cs->tick_stable)			cs->tick_stable(cs); 		if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) &&		    (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&		    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {			/* Mark it valid for high-res. */			cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; 			/*			 * clocksource_done_booting() will sort it if			 * finished_booting is not set yet.			 */			if (!finished_booting)				continue; 			/*			 * If this is not the current clocksource let			 * the watchdog thread reselect it. Due to the			 * change to high res this clocksource might			 * be preferred now. If it is the current			 * clocksource let the tick code know about			 * that change.			 */			if (cs != curr_clocksource) {				cs->flags |= CLOCK_SOURCE_RESELECT;				schedule_work(&watchdog_work);			} else {				tick_clock_notify();			}		}	} 	/*	 * We only clear the watchdog_reset_pending, when we did a	 * full cycle through all clocksources.	 */	if (reset_pending)		atomic_dec(&watchdog_reset_pending);

Lines 1–500 of 1477.