Date: Tue, 13 Jul 2010 10:52:42 +0300 From: Alexander Motin <mav@FreeBSD.org> To: Bruce Evans <brde@optusnet.com.au> Cc: svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org Subject: Re: svn commit: r209900 - head/sys/kern Message-ID: <4C3C1B4A.5070501@FreeBSD.org> In-Reply-To: <20100713162403.T62787@delplex.bde.org> References: <201007111647.o6BGlk0O033551@svn.freebsd.org> <201007120813.19223.jhb@freebsd.org> <4C3B0F63.6000905@FreeBSD.org> <20100713162403.T62787@delplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Bruce Evans wrote:
> Fix for cputick calibration:
>
> % diff -c2 ./kern/kern_tc.c~ ./kern/kern_tc.c
> % *** ./kern/kern_tc.c~ Thu Mar 20 01:05:27 2008
> % --- ./kern/kern_tc.c Thu Mar 20 01:05:29 2008
> % ***************
> % *** 884,888 ****
> % return;
> % % ! getbinuptime(&t_this);
> % c_this = cpu_ticks();
> % if (t_last.sec != 0) {
> % --- 884,888 ----
> % return;
> % % ! binuptime(&t_this);
> % c_this = cpu_ticks();
> % if (t_last.sec != 0) {
>
> Minor fix for accuracy.
>
> % ***************
> % *** 922,931 ****
> % c_delta <<= 20;
> % c_delta /= divi;
> % ! if (c_delta > cpu_tick_frequency) {
> % ! if (0 && bootverbose)
> % ! printf("cpu_tick increased to %ju Hz\n",
> % ! c_delta);
> % ! cpu_tick_frequency = c_delta;
> % ! }
> % }
> % }
> % --- 922,930 ----
> % c_delta <<= 20;
> % c_delta /= divi;
> % ! if (0 && bootverbose)
> % ! printf(
> % ! "cpu_tick_frequency changed from %ju to %ju Hz\n",
> % ! cpu_tick_frequency, c_delta);
> % ! cpu_tick_frequency = c_delta;
> % }
> % }
>
> Variable frequencies have the interesting capability of varying in
> both positive and negative directions. This fixes the case of
> negative-going changes. Without this, the overflowing timecounter
> cases caused cpu_tick_frequency to become huge (100's of times the
> correct value), and it was clamped to the hugest value ever seen. The
> way this mostly fixes the problem is that cpu_tick_frequency can be
> off by a factor of 100, but only for 16 seconds or so until the next
> calibration fixes it.
I have no hardware to check, but I have feeling that calibration didn't
work well also for older CPUs with variable TSC frequency, when
frequency is decreasing. I see TSC timecounter frequency changed at
tsc_freq_changed(), but set_cputicker() is not called there to adopt it,
neither calibration can reduce it by itself.
> I don't use this in the same kernels that have the fix for the
> timecounters. An integrated fix would prevent recalibration until 16
> seconds after the timecounter has been restored.
>
> Setting cpu_tick_variable to 0 is an even simpler fix if the cputicker
> is not very variable.
Yes. In fact cputicker is invariable for the most of modern x86 CPUs.
But it's frequency is not always precisely known.
> Without this, normal frequency drift due to temperature changes caused
> cpu_tick frequency to become larger than the correct value by a few
> ppm. Again it was clamped to the largest value ever seen, but errors
> of a few ppm are hard to see.
--
Alexander Motin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4C3C1B4A.5070501>
