All of lore.kernel.org
 help / color / mirror / Atom feed
From: john stultz <johnstul@us.ibm.com>
To: lkml <linux-kernel@vger.kernel.org>
Cc: Ingo Molnar <mingo@elte.hu>, Darren Hart <dvhltc@us.ibm.com>,
	Nishanth Aravamudan <nacc@us.ibm.com>,
	Frank Sorenson <frank@tuxrocks.com>,
	George Anzinger <george@mvista.com>,
	Roman Zippel <zippel@linux-m68k.org>,
	Ulrich Windl <ulrich.windl@rz.uni-regensburg.de>,
	Thomas Gleixner <tglx@linutronix.de>,
	john stultz <johnstul@us.ibm.com>,
	john stultz <johnstul@us.ibm.com>
Subject: [PATCH 13/13] Time: Generic Timekeeping Paraniod Debug Patch
Date: Mon, 21 Nov 2005 18:36:42 -0700	[thread overview]
Message-ID: <20051122013641.18537.74151.sendpatchset@cog.beaverton.ibm.com> (raw)
In-Reply-To: <20051122013515.18537.76463.sendpatchset@cog.beaverton.ibm.com>

All,
	This patch provides paranoid checking of the timekeeping code. It is
not intended to be submitted to mainline, but to allow developers and
testers using the timeofday patches to better find or rule-out potential
timekeeping problems.

thanks
-john

Signed-off-by: John Stultz <johnstul@us.ibm.com>

linux-2.6.15-rc1-mm2_timeofday-paranoid-debug_B11.patch
============================================
diff -ruN tod-mm_1/arch/i386/Kconfig tod-mm_2/arch/i386/Kconfig
--- tod-mm_1/arch/i386/Kconfig	2005-11-21 16:52:49.000000000 -0800
+++ tod-mm_2/arch/i386/Kconfig	2005-11-21 16:55:35.000000000 -0800
@@ -18,6 +18,9 @@
 	bool
 	default y
 
+config PARANOID_GENERIC_TIME
+	bool "Paraniod Timekeeping Checks"
+
 config SEMAPHORE_SLEEPERS
 	bool
 	default y
diff -ruN tod-mm_1/arch/i386/kernel/tsc.c tod-mm_2/arch/i386/kernel/tsc.c
--- tod-mm_1/arch/i386/kernel/tsc.c	2005-11-21 16:55:07.000000000 -0800
+++ tod-mm_2/arch/i386/kernel/tsc.c	2005-11-21 16:55:35.000000000 -0800
@@ -313,6 +313,46 @@
 static unsigned long current_tsc_khz = 0;
 static int tsc_update_callback(void);
 
+#ifdef CONFIG_PARANOID_GENERIC_TIME
+/* This will hurt performance! */
+DEFINE_SPINLOCK(checktsc_lock);
+cycle_t last_tsc;
+
+static cycle_t read_tsc(void)
+{
+	cycle_t ret;
+	unsigned long flags;
+	spin_lock_irqsave(&checktsc_lock, flags);
+
+	rdtscll(ret);
+
+	if(ret < last_tsc)
+		printk("read_tsc: ACK! TSC went backward! Unsynced TSCs?\n");
+	last_tsc = ret;
+
+	spin_unlock_irqrestore(&checktsc_lock, flags);
+	return ret;
+}
+
+static cycle_t read_tsc_c3(void)
+{
+	cycle_t ret;
+	unsigned long flags;
+	spin_lock_irqsave(&checktsc_lock, flags);
+
+	rdtscll(ret);
+	ret += tsc_read_c3_time();
+
+	if(ret < last_tsc)
+		printk("read_tsc_c3: ACK! TSC went backward! Unsynced TSCs?\n");
+	last_tsc = ret;
+
+	spin_unlock_irqrestore(&checktsc_lock, flags);
+	return ret;
+}
+
+#else /* CONFIG_PARANOID_GENERIC_TIME */
+
 static cycle_t read_tsc(void)
 {
 	cycle_t ret;
@@ -327,6 +367,7 @@
 	return ret + tsc_read_c3_time();
 }
 
+#endif /* CONFIG_PARANOID_GENERIC_TIME */
 
 static struct clocksource clocksource_tsc = {
 	.name = "tsc",
diff -ruN tod-mm_1/arch/x86_64/Kconfig tod-mm_2/arch/x86_64/Kconfig
--- tod-mm_1/arch/x86_64/Kconfig	2005-11-21 16:53:42.000000000 -0800
+++ tod-mm_2/arch/x86_64/Kconfig	2005-11-21 16:55:35.000000000 -0800
@@ -32,6 +32,9 @@
        bool
        default y
 
+config PARANOID_GENERIC_TIME
+	bool "Paraniod Timekeeping Checks"
+
 config SEMAPHORE_SLEEPERS
 	bool
 	default y
diff -ruN tod-mm_1/arch/x86_64/kernel/time.c tod-mm_2/arch/x86_64/kernel/time.c
--- tod-mm_1/arch/x86_64/kernel/time.c	2005-11-21 16:53:42.000000000 -0800
+++ tod-mm_2/arch/x86_64/kernel/time.c	2005-11-21 16:55:35.000000000 -0800
@@ -1049,6 +1049,53 @@
 static unsigned long current_tsc_khz = 0;
 static int tsc_update_callback(void);
 
+#ifdef CONFIG_PARANOID_GENERIC_TIME
+/* This will hurt performance! */
+DEFINE_SPINLOCK(checktsc_lock);
+cycle_t last_tsc;
+
+static cycle_t read_tsc(void)
+{
+	cycle_t ret;
+	unsigned long flags;
+	spin_lock_irqsave(&checktsc_lock, flags);
+
+	rdtscll(ret);
+
+	if(ret < last_tsc)
+		printk("read_tsc: ACK! TSC went backward! Unsynced TSCs?\n");
+	last_tsc = ret;
+
+	spin_unlock_irqrestore(&checktsc_lock, flags);
+	return ret;
+}
+
+static cycle_t __vsyscall_fn vread_tsc(void* unused)
+{
+	cycle_t ret;
+	rdtscll(ret);
+	return ret;
+}
+
+static cycle_t read_tsc_c3(void)
+{
+	cycle_t ret;
+	unsigned long flags;
+	spin_lock_irqsave(&checktsc_lock, flags);
+
+	rdtscll(ret);
+	ret += tsc_read_c3_time();
+
+	if(ret < last_tsc)
+		printk("read_tsc_c3: ACK! TSC went backward! Unsynced TSCs?\n");
+	last_tsc = ret;
+
+	spin_unlock_irqrestore(&checktsc_lock, flags);
+	return ret;
+}
+
+#else /* CONFIG_PARANOID_GENERIC_TIME */
+
 static cycle_t read_tsc(void)
 {
 	cycle_t ret;
@@ -1070,6 +1117,8 @@
 	return ret + tsc_read_c3_time();
 }
 
+#endif /* CONFIG_PARANOID_GENERIC_TIME */
+
 static struct clocksource clocksource_tsc = {
 	.name = "tsc",
 	.rating = 300,
diff -ruN tod-mm_1/kernel/time/timeofday.c tod-mm_2/kernel/time/timeofday.c
--- tod-mm_1/kernel/time/timeofday.c	2005-11-21 16:47:12.000000000 -0800
+++ tod-mm_2/kernel/time/timeofday.c	2005-11-21 16:55:35.000000000 -0800
@@ -120,6 +120,117 @@
  */
 struct ktimer timeofday_timer;
 
+
+#ifdef CONFIG_PARANOID_GENERIC_TIME
+/* This will hurt performance! */
+DEFINE_SPINLOCK(check_monotonic_lock);
+ktime_t last_monotonic_ktime;
+
+ktime_t get_check_value(void)
+{
+	ktime_t ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&check_monotonic_lock, flags);
+	ret = last_monotonic_ktime;
+	spin_unlock_irqrestore(&check_monotonic_lock, flags);
+	return ret;
+}
+
+void check_monotonic_clock(ktime_t prev, ktime_t now)
+{
+	unsigned long flags;
+
+	/* check for monotonic inconsistencies */
+	if(ktime_cmp(now, <, prev)) {
+		static int warn_count = 10;
+		if (warn_count > 0) {
+			warn_count--;
+			printk("check_monotonic_clock: monotonic inconsistency"
+					" detected!\n");
+			printk("	from %16Lx (%llu) to %16Lx (%llu).\n",
+					ktime_to_ns(prev),
+					ktime_to_ns(prev),
+					ktime_to_ns(now),
+					ktime_to_ns(now));
+			WARN_ON(1);
+		}
+	}
+	spin_lock_irqsave(&check_monotonic_lock, flags);
+	last_monotonic_ktime = now;
+	spin_unlock_irqrestore(&check_monotonic_lock, flags);
+}
+/* timespec version */
+#define check_monotonic_clock_ts(prev, now) \
+	check_monotonic_clock(prev, timespec_to_ktime(now))
+
+/* Call holding atleast a readlock on system_time_lock */
+void verify_timekeeping_state(void)
+{
+	static int warn_count = 10;
+	if (warn_count <= 0)
+		return;
+	/* insure all the timespec and ktime values are consistent */
+	if (ktime_cmp(system_time, !=, timespec_to_ktime(mono_time_ts))) {
+		printk("verify_timekeeping_state: system_time != mono_time_ts\n");
+		warn_count--;
+	}
+
+	if (ktime_cmp(ktime_add(system_time, wall_time_offset), !=,
+					 timespec_to_ktime(wall_time_ts))) {
+		printk("verify_timekeeping_state: system_time + wall_time_offset "
+				"!= wall_time_ts\n");
+		warn_count--;
+	}
+
+	if (ktime_cmp(wall_time_offset, !=,
+					 timespec_to_ktime(monotonic_time_offset_ts))) {
+		printk("verify_timekeeping_state: wall_time_offset "
+				"!= monotonic_time_offset_ts\n");
+		warn_count--;
+	}
+}
+
+void check_periodic_interval(cycle_t now)
+{
+	static cycle_t last;
+	cycle_t delta;
+	nsec_t ns_offset;
+	if (last != 0 && now != 0) {
+		delta = (now - last)& clock->mask;
+
+		ns_offset = cyc2ns(clock, ntp_adj, delta);
+
+		if(ns_offset > (nsec_t)2*PERIODIC_INTERVAL_MS *1000000) {
+			static int warn_count = 10;
+			if (warn_count > 0) {
+				warn_count--;
+				printk("check_periodic_interval: Long interval! %llu.\n",
+								ns_offset);
+				printk("		Something may be blocking interrupts.\n");
+			}
+		}
+		if(ns_offset < (nsec_t)PERIODIC_INTERVAL_MS *1000000) {
+			static int warn_count = 10;
+			if (warn_count > 0) {
+				warn_count--;
+				printk("check_periodic_interval: short interval! %llu.\n",
+								ns_offset);
+				printk("		bad calibration or ktimers may be broken.\n");
+			}
+		}
+	}
+	last = now;
+}
+
+#else /* CONFIG_PARANOID_GENERIC_TIME */
+#define get_check_value(void) ktime_set(0,0) /* XXX can we optimize this out? */
+#define check_monotonic_clock(x,y) {}
+#define check_monotonic_clock_ts(x,ts)
+#define verify_timekeeping_state()
+#define check_periodic_interval(x)
+#endif /* CONFIG_PARANOID_GENERIC_TIME */
+
 /**
  * update_legacy_time_values - sync legacy time values
  *
@@ -184,8 +295,12 @@
  */
 static inline ktime_t __get_monotonic_clock(void)
 {
+	ktime_t ret;
+	ktime_t check = get_check_value();
 	nsec_t offset = __get_nsec_offset();
-	return ktime_add_ns(system_time, offset);
+	ret = ktime_add_ns(system_time, offset);
+	check_monotonic_clock(check,ret);
+	return ret;
 }
 
 /**
@@ -269,6 +384,7 @@
 {
 	unsigned long seq;
 	nsec_t offset;
+	ktime_t check = get_check_value();
 
 	do {
 		seq = read_seqbegin(&system_time_lock);
@@ -278,6 +394,7 @@
 	} while (read_seqretry(&system_time_lock, seq));
 
 	timespec_add_ns(ts, offset);
+	check_monotonic_clock_ts(check, *ts);
 }
 
 /**
@@ -362,7 +479,9 @@
 	update_legacy_time_values();
 
 	write_sequnlock_irqrestore(&system_time_lock, flags);
-
+#ifdef CONFIG_PARANOID_GENERIC_TIME
+	printk("do_settimeofday() was called!\n");
+#endif
 	/* signal ktimers about time change */
 	clock_was_set();
 
@@ -518,6 +637,7 @@
 
 	/* read time source & calc time since last call*/
 	cycle_now = read_clocksource(clock);
+	check_periodic_interval(cycle_now);
 	cycle_delta = (cycle_now - cycle_last) & clock->mask;
 
 	delta_nsec = cyc2ns_fixed_rem(ts_interval, &cycle_delta, &remainder);
@@ -562,6 +682,7 @@
 		ntp_adj = 0;
 		remainder = 0;
 		something_changed = 1;
+		check_periodic_interval(0);
 	}
 
 	/* now is a safe time, so allow clocksource to adjust
@@ -609,6 +730,8 @@
 
 	update_legacy_time_values();
 
+	verify_timekeeping_state();
+
 	write_sequnlock_irqrestore(&system_time_lock, flags);
 
 	/* Set us up to go off on the next interval */

  parent reply	other threads:[~2005-11-22  1:37 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-11-22  1:35 [PATCH 0/13] Time: Generic Timeofday Subsystem (v B11) john stultz
2005-11-22  1:35 ` [PATCH 1/13] Time: Reduced NTP rework (part 1) john stultz
2005-11-26 14:52   ` [patch] warn-on-once.patch Ingo Molnar
2005-11-26 15:03     ` Tim Schmielau
2005-11-26 15:03     ` Michal Schmidt
2005-11-26 15:17     ` Ingo Molnar
2005-11-26 15:21       ` Ingo Molnar
2005-11-26 14:52   ` [PATCH 1/13] Time: Reduced NTP rework (part 1) Ingo Molnar
2005-11-22  1:35 ` [PATCH 2/13] Time: Reduced NTP Rework (part 2) john stultz
2005-11-26 14:53   ` Ingo Molnar
2005-11-22  1:35 ` [PATCH 3/13] Time: Clocksource Infrastructure john stultz
2005-11-26 14:53   ` Ingo Molnar
2005-11-22  1:35 ` [PATCH 4/13] Time: Generic Timekeeping Infrastructure john stultz
2005-11-26 14:54   ` Ingo Molnar
2005-11-22  1:35 ` [PATCH 5/13] Time: i386 Conversion - part 1: Move timer_pit.c to i8253.c john stultz
2005-11-26 14:54   ` Ingo Molnar
2005-11-22  1:35 ` [PATCH 6/13] Time: i386 Conversion - part 2: Move timer_tsc.c to tsc.c john stultz
2005-11-26 14:54   ` Ingo Molnar
2005-11-22  1:36 ` [PATCH 7/13] Time: i386 Conversion - part 3: Rework TSC Support john stultz
2005-11-22  1:36 ` [PATCH 8/13] Time: i386 Conversion - part 4: ACPI PM variable renaming john stultz
2005-11-22  1:36 ` [PATCH 9/13] Time: i386 Conversion - part 5: Enable Generic Timekeeping john stultz
2005-11-26 14:55   ` Ingo Molnar
2005-11-22  1:36 ` [PATCH 10/13] Time: i386 Conversion - part 6: Remove Old Code john stultz
2005-11-22  1:36 ` [PATCH 11/13] Time: x86-64 Conversion to Generic Timekeeping john stultz
2005-11-26 14:55   ` Ingo Molnar
2005-11-26 15:11     ` Ingo Molnar
2005-11-22  1:36 ` [PATCH 12/13] Time: i386/x86-64 Clocksource Drivers john stultz
2005-11-26 14:55   ` Ingo Molnar
2005-11-22  1:36 ` john stultz [this message]
2005-11-22  2:03 ` [PATCH 0/13] Time: Generic Timeofday Subsystem (v B11) john stultz
2005-11-26 14:50 ` Ingo Molnar
2005-11-26 14:58   ` Ingo Molnar
  -- strict thread matches above, loose matches on Subject: below --
2005-12-15  2:00 [PATCH 0/13] Time: Generic Timeofday Subsystem (v B14) john stultz
2005-12-15  2:01 ` [PATCH 13/13] Time: Generic Timekeeping Paraniod Debug Patch john stultz
2005-12-06  4:13 [PATCH 0/13] Time: Generic Timeofday Subsystem (v B13) john stultz
2005-12-06  4:15 ` [PATCH 13/13] Time: Generic Timekeeping Paraniod Debug Patch john stultz
2005-12-02  3:25 [PATCH 0/13] Time: Generic Timeofday Subsystem (v B12) john stultz
2005-12-02  3:27 ` [PATCH 13/13] Time: Generic Timekeeping Paraniod Debug Patch john stultz
2005-11-12  4:48 [PATCH 0/13] Time: Generic Timeofday Subsystem (v B10) john stultz
2005-11-12  4:50 ` [PATCH 13/13] Time: Generic Timekeeping Paraniod Debug Patch john stultz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20051122013641.18537.74151.sendpatchset@cog.beaverton.ibm.com \
    --to=johnstul@us.ibm.com \
    --cc=dvhltc@us.ibm.com \
    --cc=frank@tuxrocks.com \
    --cc=george@mvista.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=nacc@us.ibm.com \
    --cc=tglx@linutronix.de \
    --cc=ulrich.windl@rz.uni-regensburg.de \
    --cc=zippel@linux-m68k.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.