Avoid timecounter "TSC" on modern PCs and laptops!

Most times when I boot NetBSD, the system time runs at only about half the real speed, meaning the time displayed by date is way behind. This would only be a nuisance if it didn't also mean that my e-mail client puts the wrong timestamps on every e-mail I send, which can be confusing or even embarrassing. Sometimes, very rarely, all is fine and the clock runs quite accurately.

I managed to capture the dmesg output for both cases, and this is the relevant difference:

--- ./dmesg.accurateclock       2009-09-08 16:20:59.000000000 +0100
+++ ./dmesg.clockslow   2009-09-07 09:49:39.000000000 +0100
@@ -12,14 +12,14 @@
 timecounter: Timecounter "i8254" frequency 1193182 Hz quality 100
 System manufacturer System Product Name (System Version)
 mainbus0 (root)
-cpu0 at mainbus0 apid 0: Intel 686-class, 2672MHz, id 0x106a5
-cpu1 at mainbus0 apid 2: Intel 686-class, 2672MHz, id 0x106a5
-cpu2 at mainbus0 apid 4: Intel 686-class, 2672MHz, id 0x106a5
-cpu3 at mainbus0 apid 6: Intel 686-class, 2672MHz, id 0x106a5
-cpu4 at mainbus0 apid 1: Intel 686-class, 2672MHz, id 0x106a5
-cpu5 at mainbus0 apid 3: Intel 686-class, 2672MHz, id 0x106a5
-cpu6 at mainbus0 apid 5: Intel 686-class, 2672MHz, id 0x106a5
-cpu7 at mainbus0 apid 7: Intel 686-class, 2672MHz, id 0x106a5
+cpu0 at mainbus0 apid 0: Intel 686-class, 3741MHz, id 0x106a5
+cpu1 at mainbus0 apid 2: Intel 686-class, 3741MHz, id 0x106a5
+cpu2 at mainbus0 apid 4: Intel 686-class, 3741MHz, id 0x106a5
+cpu3 at mainbus0 apid 6: Intel 686-class, 3741MHz, id 0x106a5
+cpu4 at mainbus0 apid 1: Intel 686-class, 3741MHz, id 0x106a5
+cpu5 at mainbus0 apid 3: Intel 686-class, 3741MHz, id 0x106a5
+cpu6 at mainbus0 apid 5: Intel 686-class, 3741MHz, id 0x106a5
+cpu7 at mainbus0 apid 7: Intel 686-class, 3741MHz, id 0x106a5
 ioapic0 at mainbus0 apid 8: pa 0xfec00000, version 20, 24 pins
 ioapic1 at mainbus0 apid 9: pa 0xfec8a000, version 20, 24 pins
 acpi0 at mainbus0: Intel ACPICA 20090730
@@ -170,7 +170,7 @@
 ieee1394if0: 1 nodes, maxhop <= 0, cable IRM = 0 (me)
 ieee1394if0: bus manager 0 (me)
 timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
-timecounter: Timecounter "TSC" frequency 2672861800 Hz quality 3000
+timecounter: Timecounter "TSC" frequency 3741967920 Hz quality 3000
 azalia0: codec[0]: ATI R600 HDMI (rev. 1.0), HDA rev. 1.0
 audio0 at azalia0: full duplex, independent
 azalia1: codec[0]: Realtek ALC888 (rev. 1.1), HDA rev. 1.0
This shows that the processor clock is detected differently in the two cases: in the cases when my clock runs slow, the processor is detected to be running at 3.7GHz, otherwise it's 2.6GHz. As a consequence of misdetecting the processor clock, the kernel also assumes the incorrect frequency for the "TSC" timecounter.

The reason this happens is that my CPU is an Intel i7 which uses the a technology called Turbo Boost. Basically, when there isn't much work to do the processor gets clocked down to save energy. Processors designed for mobile devices have been doing this for quite a while.

The manual page timecounter(9) indicates that it originated on FreeBSD, and in fact I found the solution to my problem in the FreeBSD FAQ.

Luckily, the "TSC" timecounter isn't my only timing source on this machine. As a matter of fact, the kernel variable kern.timecounter.choice offers plenty of such:

kern.timecounter.choice = TSC(q=3000, f=3741919640 Hz)
        clockinterrupt(q=0, f=100 Hz) hpet0(q=2000, f=14318179 Hz)
        ACPI-Fast(q=1000, f=3579545 Hz) lapic(q=-100, f=133687675 Hz)
        i8254(q=100, f=1193182 Hz) dummy(q=-1000000, f=1000000 Hz)
NetBSD has even already gone to the trouble of rating the quality of each of these, so all I need to do is to pick the one with the next lower value:
# sysctl -w kern.timecounter.hardware=hpet0
kern.timecounter.hardware: TSC -> hpet0
This seems to have solved the problem.

I think the code for the "TSC" timecounter should either be adapted to modern hardware with changing processor speeds. At the very least, the quality rating should be lowered significantly if such hardware is detected so it isn't chosen as the default time source.

Comments