Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Jan 2004 10:59:59 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Kevin Oberman <oberman@es.net>
Cc:        freebsd-current@FreeBSD.org
Subject:   Re: ACPI issue with ASUS P5A motherboard on 5.2-RELEASE 
Message-ID:  <20040119100856.G5433@gamplex.bde.org>
In-Reply-To: <20040118214540.EFDD55D09@ptavv.es.net>
References:  <20040118214540.EFDD55D09@ptavv.es.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 18 Jan 2004, Kevin Oberman wrote:

> > From: Gregory Poudrel <chojin@chojin.info>
> > I recently had some problems with my ASUS P5A motherboard (K6-II 350) on
> > FreeBSD 5.2-RELEASE.
> > In fact, I had GENERIC kernel installed and ACPI activated.
> >
> > First problem:
> > Time flow was incorrect. In fact, 1 second meaned 0.5 second for FreeBSD.
> > Each minute I tested a ntpdate and there was 76 seconds difference.
> > When I rebooted and check in BIOS, time was correct and flowed independently.
>
> This is a known bug in the P5A. It's ACPI-Safe clock is broken and runs
> at double speed.

If that is the only problem with it, then it is easy to fix by telling
it what its actual speed is (sysctl machdep.acpi_timer_freq=whatever).
This can be done automatically by calibrating the frequency relative to
any non-broken clock with a known frequency, as is done for the TSC
timecounter.

> Use the TSC clock by putting the line:
> kern.timecounter.hardware=TSC
> into /etc/sysctl.conf.

But using the TSC is better anyway, since it has a higher quality than the
acpi timer if thermal control mechanisms are not used (usually the same
accuracy, and always a lower overhead).

I use the following in /etc/rc.local to micro-adjust the clocks.  It could
be used to adjust by a factor of 2, but then they would have drifted by
a lot before they are adjusted.

%%%
multiplier=0

# [Settings for other systems deleted.]

# delplex is quite like a P5A, but 1 generation earlier (K6-233 on a
# FIC-mumble Super7 motherboard).
if test `hostname` = delplex.bde.org; then
# Multiplier 196 @ 233MHz
# Goal: 1193182 -> 1193276, 233863672 -> 233882119
	multiplier=196
	scale=1.00007888
fi

if test "$scale" != ""; then
	if freq=`sysctl -n machdep.i8254_freq`; then
		freq=1193182	# XXX avoid multiple scaling
		newfreq=`echo $freq $scale |
		    awk '{ printf("%.0f\n", $1 * $2) }'`
		sysctl machdep.i8254_freq=$newfreq
	fi
	for clock in acpi_timer piix;
	do
		if freq=`sysctl -n machdep.${clock}_freq 2>/dev/null`; then
			# XXX fix up, and avoid multiple scaling
			freq=$((3 * 1193182))
			newfreq=`echo $freq $scale |
			    awk '{ printf("%.0f\n", $1 * $2) }'`
			sysctl machdep.${clock}_freq=$newfreq
		fi
	done
	if freq=`sysctl -n machdep.tsc_freq 2>/dev/null`; then
		newfreq=`echo $freq $multiplier $scale | awk '
		{
			freq = $1
			nomfreq = $2 * 1193182
			scale = $3
			# This is fragile, but always scaling relative to
			# the current frequency is worse since we dont (sic)
			# know if the frequency has already been scaled.
			if (freq > nomfreq * 0.999 && freq <= nomfreq * 1.001)
				freq = nomfreq
			printf("%.0f\n", freq * scale)
		}'`
		sysctl machdep.tsc_freq=$newfreq
	fi
fi
%%%

Here `scale' is the micro-adjustment factor.  On all active my systems (all
undermydesktops), all of the i8254, TSC, PIIX (if available) and acpi (if
available) are exact fractional multipliers of a common clock.  The common
clock is usually fairly precise (about 1 ppm per degree Centigrade drift)
but very innaccurate (wrong by 78 ppm for delplex).  `scale' adjusts for
the innaccuracy.  Its value was determined by running ntp for several weeks
or months (scale := 1 + average_ntp_drift).

`multiplier' is the fractional multipler to convert from the i8254 clock
to the TSC.  It is precisely 196 on delplex (provided I don't change the
frequency in the BIOS).  The kernel does a low quality calibration of the
TSC frequency relative to the i8254 frequency, and the above throws this
away and sets the TSC frequency to (multiplier * i2854_freq) provided the
ratio is approximately `multiplier', so that the TSC is always infinitely
precise relative to the i8254 and a common scale factor can be used for
both.  Having a common scale factor is more useful on other systems where
I change the BIOS frequency a lot.  The multiplier is usually integral
on older systems, but newer systems that support all FSB frequencies
between about 100 and 256 need lots of fraction multiplers.  E.g., on
an ASUS A7V266-E (2+ years old), the multipler for 1532MHz is
1284+15/23 and the multipler for 1544MHz is 1294+41/93.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040119100856.G5433>