> 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;
}