> WARNING: 16384 bytes not available for msgbuf in last cluster (4096
> used)
> [ using 682848 bytes of bsd ELF symbol table ]

for now you can put 'option MSGBUFSIZE=4096' in your kernel config
just to stop it from misbehaving.

> The P8600 Core2Duo is not regognized by the speedstep code.
> 
> Adding the model 0x7 to est.c results in:
> cpu0: unknown Enhanced SpeedStep CPU, msr 0x0617091f06000091f
> cpu0: using only highest and lowest powerstates
> cpu0: Enhanced SpeedStep 2400 MHz (1196mV): speeds: 2400, 2600 MHz
> 
> Now i just have to find out how to populate fqlist with the right data.

try this, it works on my x200 and gives me 2400, 2133, 1867, and
1600 mhz.


Index: est.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/est.c,v
retrieving revision 1.7
diff -u -r1.7 est.c
--- est.c       6 Aug 2008 05:24:44 -0000       1.7
+++ est.c       22 Sep 2008 17:42:33 -0000
@@ -55,6 +55,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/malloc.h>
 #include <sys/sysctl.h>
 
 #include <machine/cpu.h>
@@ -77,10 +78,11 @@
 #define BUS266 26667
 #define BUS333 33333
 
-#define MSR2MHZ(msr, bus) \
-       (((((int) (msr) >> 8) & 0xff) * (bus) + 50) / 100)
-#define MSR2MV(msr) \
-       (((int) (msr) & 0xff) * 16 + 700)
+#define MSR2FREQINC(msr)       (((int) (msr) >> 8) & 0xff)
+#define MSR2VOLTINC(msr)       ((int) (msr) & 0xff)
+
+#define MSR2MHZ(msr, bus)      ((MSR2FREQINC((msr)) * (bus) + 50) / 100)
+#define MSR2MV(msr)            (MSR2VOLTINC(msr) * 16 + 700)
 
 struct fqlist {
        int vendor: 5;
@@ -91,7 +93,7 @@
 
 static const struct fqlist *est_fqlist;
 
-static u_int16_t fake_table[3];
+static u_int16_t *fake_table;
 static struct fqlist fake_fqlist;
 
 extern int setperf_prio;
@@ -158,6 +160,7 @@
        model = (ci->ci_signature >> 4) & 15;
        switch (model) {
        case 0xe: /* Core Duo/Solo */
+       case 0x7: /* Core 2 Duo */
        case 0xf: /* Core Xeon */
                msr = rdmsr(MSR_FSB_FREQ);
                bus = (msr >> 0) & 0x7;
@@ -244,29 +247,74 @@
                return;
        }
        if (est_fqlist == NULL) {
-               printf("%s: unknown Enhanced SpeedStep CPU, msr 0x%016llx\n",
-                   cpu_device, msr);
+               int j, tablesize, freq, volt;
+               int minfreq, minvolt, maxfreq, maxvolt, freqinc, voltinc;
 
-               /*
-                * Generate a fake table with the power states we know.
-                */
-               fake_table[0] = idhi;
-               if (cur == idhi || cur == idlo) {
-                       printf("%s: using only highest and lowest power "
-                           "states\n", cpu_device);
-
-                       fake_table[1] = idlo;
-                       fake_fqlist.n = 2;
-               } else {
-                       printf("%s: using only highest, current and lowest "
-                           "power states\n", cpu_device);
-
-                       fake_table[1] = cur;
-                       fake_table[2] = idlo;
-                       fake_fqlist.n = 3;
+#ifdef EST_DEBUG
+               printf("%s: bus_clock = %d\n", __func__, bus_clock);
+               printf("%s: idlo = 0x%x\n", __func__, idlo);
+               printf("%s: lo  %4d mV, %4d MHz\n", __func__,
+                   MSR2MV(idlo), MSR2MHZ(idlo, bus_clock));
+               printf("%s: raw %4d   , %4d    \n", __func__,
+                   (idlo & 0xff), ((idlo >> 8) & 0xff));
+               printf("%s: idhi = 0x%x\n", __func__, idhi);
+               printf("%s: hi  %4d mV, %4d MHz\n", __func__,
+                   MSR2MV(idhi), MSR2MHZ(idhi, bus_clock));
+               printf("%s: raw %4d   , %4d    \n", __func__,
+                   (idhi & 0xff), ((idhi >> 8) & 0xff));
+               printf("%s: cur  = 0x%x\n", __func__, cur);
+#endif
+
+                /*
+                 * Generate a fake table with the power states we know,
+                * interpolating the voltages and frequencies between the
+                * high and low values.  The (milli)voltages are always
+                * rounded up when computing the table.
+                */
+               minfreq = MSR2FREQINC(idlo);
+               maxfreq = MSR2FREQINC(idhi);
+               minvolt = MSR2VOLTINC(idlo);
+               maxvolt = MSR2VOLTINC(idhi);
+               freqinc = maxfreq - minfreq;
+               voltinc = maxvolt - minvolt;
+
+               /* Avoid diving by zero. */
+               if (freqinc == 0 || voltinc == 0)
+                       return;
+
+               if (freqinc < voltinc || voltinc == 0) {
+                       tablesize = maxfreq - minfreq + 1;
+                       if (voltinc != 0)
+                               voltinc = voltinc * 100 / freqinc - 1;
+                       freqinc = 100;
+               } else {
+                       tablesize = maxvolt - minvolt + 1;
+                       freqinc = freqinc * 100 / voltinc - 1;
+                       voltinc = 100;
                }
-               fake_fqlist.vendor = vendor;
-               fake_fqlist.table = fake_table;
+ 
+               fake_table = malloc(tablesize * sizeof(uint16_t), M_DEVBUF,
+                   M_WAITOK);
+               fake_fqlist.n = tablesize;
+
+               /* The frequency/voltage table is highest frequency first */
+               freq = maxfreq * 100;
+               volt = maxvolt * 100;
+               for (j = 0; j < tablesize; j++) {
+                       fake_table[j] = (((freq + 99) / 100) << 8) +
+                           (volt + 99) / 100;
+#ifdef EST_DEBUG
+                       printf("%s: fake entry %d: %4d mV, %4d MHz  "
+                           "MSR*100 mV = %4d freq = %4d\n",
+                           __func__, j, MSR2MV(fake_table[j]),
+                           MSR2MHZ(fake_table[j], bus_clock),
+                           volt, freq);
+#endif /* EST_DEBUG */
+                       freq -= freqinc;
+                       volt -= voltinc;
+               }
+               fake_fqlist.vendor = vendor;
+               fake_fqlist.table = fake_table;
                est_fqlist = &fake_fqlist;
        }

Reply via email to