i386/145718: [PATCH] fix freq calculation from MSR for CPUs with
fractional multipliers
Andre Albsmeier
Andre.Albsmeier at siemens.com
Thu Apr 15 08:40:10 UTC 2010
>Number: 145718
>Category: i386
>Synopsis: [PATCH] fix freq calculation from MSR for CPUs with fractional multipliers
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-i386
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Apr 15 08:40:00 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator: Andre Albsmeier
>Release: FreeBSD 7.3-STABLE i386
>Organization:
>Environment:
System: FreeBSD 7.3-STABLE #6: Thu Apr 15 09:42:06 CEST 2010
using a Q9550 cpu
>Description:
When calculating the simple rate table in est_msr_info()
we have to observe bit 6 (0x40) of the multiplier which
denotes an additional 0.5 for the value. Examples:
FID Multiplier
--------------------
0x06 6
0x07 7
0x08 8
0x46 6.5
0x47 7.5
0x48 8.5
>How-To-Repeat:
Enable cpufreq on a cpu with a fractional multiplier (in
my case a Q9550 which uses 8.5), set hw.est.msr_info=1,
and watch dmesg spitting out insane low/high values for
the bus clock.
>Fix:
--- est.c.ORI 2009-07-14 08:57:29.000000000 +0200
+++ est.c 2010-04-15 10:29:11.000000000 +0200
@@ -1207,11 +1207,15 @@
freq = tsc_freq / 1000000;
id = msr >> 32;
bus = freq / (id >> 8);
+ if( id & 0x4000 )
+ bus = 2 * freq / ( (id >> 7 & 0x7e) + 1 );
device_printf(dev, "Guessed bus clock (high) of %d MHz\n", bus);
if (!bus_speed_ok(bus)) {
/* We may be running on the low frequency. */
id = msr >> 48;
bus = freq / (id >> 8);
+ if( id & 0x4000 )
+ bus = 2 * freq / ( (id >> 7 & 0x7e) + 1 );
device_printf(dev, "Guessed bus clock (low) of %d MHz\n", bus);
if (!bus_speed_ok(bus))
return (EOPNOTSUPP);
@@ -1219,6 +1223,8 @@
/* Calculate high frequency. */
id = msr >> 32;
freq = ((id >> 8) & 0xff) * bus;
+ if( id & 0x4000 )
+ freq =( (id >> 7 & 0x7e) + 1 ) * bus / 2;
}
/* Fill out a new freq table containing just the high and low freqs. */
@@ -1241,6 +1247,8 @@
/* Second, the low frequency. */
id = msr >> 48;
freq = ((id >> 8) & 0xff) * bus;
+ if( id & 0x4000 )
+ freq =( (id >> 7 & 0x7e) + 1 ) * bus / 2;
volts = id & 0xff;
if (volts != 0) {
volts <<= 4;
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-i386
mailing list