mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: john stultz <johnstul@us.ibm.com>
To: Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Cc: linux-kernel@vger.kernel.org
Subject: Re: 2.6.14-rt21: slow-running clock
Date: Mon, 12 Dec 2005 17:56:41 -0800	[thread overview]
Message-ID: <1134439002.14627.28.camel@cog.beaverton.ibm.com> (raw)
In-Reply-To: <200512090219.jB92JxtV006757@auster.physics.adelaide.edu.au>

[-- Attachment #1: Type: text/plain, Size: 1308 bytes --]

On Fri, 2005-12-09 at 12:49 +1030, Jonathan Woithe wrote:
> > Ok, I went digging further and found the c3tsc selection is correct on
> > your hardware. I'm just too used to my own laptop where the TSC varies
> > with cpu speed and we lower the rating value. So that should be ok.
> 
> Ok, good.  That leaves the c3tsc slowdown as the only outstanding issue at
> this stage.
> 
> > I'm now working on why we mis-compensate the c3tsc clocksource in the
> > -RT tree. 
> 
> No problem.  Let me know when you have something to test or need further
> info.

Hey Jonathan,

	Attached is a test patch to see if it doesn't resolve the issue for
you. I get a maximum change in drift of 30ppm when idling between C3
states by being more careful with the C3 TSC compensation and I also
force timekeeping updates when cpufreq events occur. 

I'm not sure if this is the right fix yet, but it might help narrow down
the problem.


Also attached is a python script that will spit out the offset value
from an ntp server and calculate the drift. This also will give us a
better idea of what is going on. If you could run it with and without
the patch, that would be great!


First shutdown NTPd then run:
	./drift-test.py [-s] <timeserver> <polling interval>

Where -s will sync the clock before running.


thanks
-john




[-- Attachment #2: c3fix-test.diff --]
[-- Type: text/x-patch, Size: 3655 bytes --]

diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -66,13 +66,13 @@ void mark_tsc_unstable(void)
 /* Code to compensate for C3 stalls */
 static u64 tsc_c3_offset;
 
-void tsc_c3_compensate(unsigned long nsecs)
+void tsc_c3_compensate(unsigned long nsecs, u64 tsc_offset)
 {
 	/* this could def be optimized */
 	u64 cycles = ((u64)nsecs * tsc_khz);
 
 	do_div(cycles, 1000000);
-	tsc_c3_offset += cycles;
+	tsc_c3_offset += cycles - tsc_offset;
 }
 
 EXPORT_SYMBOL_GPL(tsc_c3_compensate);
@@ -263,6 +263,7 @@ static int
 time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
 {
 	struct cpufreq_freqs *freq = data;
+	unsigned long old_tsc_khz = tsc_khz;
 
 	if (val != CPUFREQ_RESUMECHANGE)
 		write_seqlock_irq(&xtime_lock);
@@ -299,6 +300,9 @@ time_cpufreq_notifier(struct notifier_bl
 	if (val != CPUFREQ_RESUMECHANGE)
 		write_sequnlock_irq(&xtime_lock);
 
+	if(old_tsc_khz != tsc_khz)
+		timeofday_force_update();
+
 	return 0;
 }
 
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -177,7 +177,7 @@ static void acpi_safe_halt(void)
 }
 
 static atomic_t c3_cpu_count;
-extern void tsc_c3_compensate(unsigned long nsecs);
+extern void tsc_c3_compensate(unsigned long nsecs, u64 tsc_offset);
 
 static void acpi_processor_idle(void)
 {
@@ -186,6 +186,7 @@ static void acpi_processor_idle(void)
 	struct acpi_processor_cx *next_state = NULL;
 	int sleep_ticks = 0;
 	u32 t1, t2 = 0;
+	u64 tsc1, tsc2, tsc3;
 
 	pr = processors[smp_processor_id()];
 	if (!pr)
@@ -359,12 +360,15 @@ static void acpi_processor_idle(void)
 
 		/* Get start time (ticks) */
 		t1 = inl(acpi_fadt.xpm_tmr_blk.address);
+		rdtscll(tsc1);
 		/* Invoke C3 */
 		inb(cx->address);
 		/* Dummy op - must do something useless after P_LVL3 read */
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Get end time (ticks) */
+		rdtscll(tsc2);
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
+		rdtscll(tsc3);
 		if (pr->flags.bm_check) {
 			/* Enable bus master arbitration */
 			atomic_dec(&c3_cpu_count);
@@ -374,7 +378,7 @@ static void acpi_processor_idle(void)
 
 #ifdef CONFIG_GENERIC_TIME
 		/* compensate for TSC pause */
-		tsc_c3_compensate((u32)(((u64)((t2-t1)&0xFFFFFF)*286070)>>10));
+		tsc_c3_compensate((u32)(((u64)((t2-t1)&0xFFFFFF)*286070)>>10), tsc3-tsc1);
 #endif
 
 		/* Re-enable interrupts */
diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h
--- a/include/asm-i386/tsc.h
+++ b/include/asm-i386/tsc.h
@@ -44,7 +44,7 @@ static inline cycles_t get_cycles(void)
 }
 
 extern void tsc_init(void);
-extern void tsc_c3_compensate(unsigned long usecs);
+extern void tsc_c3_compensate(unsigned long usecs, unsigned long long tsc_offset);
 extern void mark_tsc_unstable(void);
 
 #endif
diff --git a/include/linux/timeofday.h b/include/linux/timeofday.h
--- a/include/linux/timeofday.h
+++ b/include/linux/timeofday.h
@@ -30,6 +30,7 @@ extern int do_settimeofday(struct timesp
 
 /* Internal functions */
 extern int timeofday_is_continuous(void);
+extern void timeofday_force_update(void);
 extern void timeofday_init(void);
 
 #ifndef CONFIG_IS_TICK_BASED
diff --git a/kernel/time/timeofday.c b/kernel/time/timeofday.c
--- a/kernel/time/timeofday.c
+++ b/kernel/time/timeofday.c
@@ -745,6 +745,12 @@ static void timeofday_periodic_hook(unsi
 		jiffies + 1 + msecs_to_jiffies(PERIODIC_INTERVAL_MS));
 }
 
+
+void timeofday_force_update(void)
+{
+	timeofday_periodic_hook(0);
+}
+
 /**
  * timeofday_is_continuous - check to see if timekeeping is free running
  */

[-- Attachment #3: drift-test.py --]
[-- Type: text/x-python, Size: 1523 bytes --]

#!/usr/bin/python

# Time Drift Script
#		Periodically checks and displays time drift
#		by john stultz (jstultz@us.ibm.com)

import commands
import sys
import string
import time

server_default = "yourserverhere"
sleep_time_default  = 60

server = ""
sleep_time = 0
set_time = 0

#parse args
for arg in sys.argv[1:]:
	if arg == "-s":
		set_time = 1
	elif server == "":
		server = arg
	elif sleep_time == 0:
		sleep_time = string.atoi(arg)

if server == "":
	server = server_default
if sleep_time == 0:
	sleep_time = sleep_time_default

#set time
if (set_time == 1):
	cmd = commands.getoutput('/usr/sbin/ntpdate -ub ' + server)

cmd = commands.getoutput('/usr/sbin/ntpdate -uq ' + server)
line = string.split(cmd)

#parse original offset
start_offset = string.atof(line[-2]);
#parse original time
start_time = time.localtime(time.time())
datestr = time.strftime("%d %b %Y %H:%M:%S", start_time)

time.sleep(1)
while 1:
	cmd = commands.getoutput('/usr/sbin/ntpdate -uq ' + server)
	line = string.split(cmd)

	#parse offset
	now_offset = string.atof(line[-2]);

	#parse time
	now_time = time.localtime(time.time())
	datestr = time.strftime("%d %b %Y %H:%M:%S", now_time)

	# calculate drift
	delta_time = time.mktime(now_time) - time.mktime(start_time)
	delta_offset = now_offset - start_offset
	drift =  delta_offset / delta_time * 1000000

	#print output
	print time.strftime("%d %b %H:%M:%S",now_time), 
	print "	offset:", now_offset , 
	print "	drift:", drift ,"ppm"
	sys.stdout.flush()

	#sleep 
	time.sleep(sleep_time)

  reply	other threads:[~2005-12-13  1:56 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-12-05  6:26 Jonathan Woithe
2005-12-05 19:42 ` john stultz
2005-12-07  3:39   ` Jonathan Woithe
2005-12-07  4:01     ` john stultz
2005-12-07  4:25       ` Jonathan Woithe
2005-12-07 22:54       ` Jonathan Woithe
2005-12-08  2:45         ` john stultz
2005-12-08  3:02           ` Jonathan Woithe
2005-12-08  3:22             ` john stultz
2005-12-08  4:11               ` Jonathan Woithe
2005-12-09  0:19               ` Jonathan Woithe
2005-12-09  2:11                 ` john stultz
2005-12-09  2:19                   ` Jonathan Woithe
2005-12-13  1:56                     ` john stultz [this message]
2005-12-14  1:22                       ` Jonathan Woithe
2005-12-15  1:41                         ` john stultz
2005-12-15  3:18                           ` Jonathan Woithe

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=1134439002.14627.28.camel@cog.beaverton.ibm.com \
    --to=johnstul@us.ibm.com \
    --cc=jwoithe@physics.adelaide.edu.au \
    --cc=linux-kernel@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®