summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorGordon Willem Klok <gwk@cvs.openbsd.org>2009-06-06 23:21:44 +0000
committerGordon Willem Klok <gwk@cvs.openbsd.org>2009-06-06 23:21:44 +0000
commitd0ca62a445230166bc924e68e43e6e53ceebac82 (patch)
tree98dcc0ab0af09ba05a467252c3e4b9047abe38da /sys/arch
parent9cb1e5ced8a3c4590f197ee60a7b0464a8533d07 (diff)
Update est.c, make it capable of using ACPI if the PSS is available but
still support all different methods of getting states without e.g. (highest/lowest state), and on i386 use the tables. The only change should be the deletion of the mV from the printf at boot. ok jsg@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/amd64/est.c227
-rw-r--r--sys/arch/i386/i386/est.c423
2 files changed, 447 insertions, 203 deletions
diff --git a/sys/arch/amd64/amd64/est.c b/sys/arch/amd64/amd64/est.c
index 7f54997c322..082f89bd05c 100644
--- a/sys/arch/amd64/amd64/est.c
+++ b/sys/arch/amd64/amd64/est.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: est.c,v 1.11 2009/04/23 07:30:03 jsg Exp $ */
+/* $OpenBSD: est.c,v 1.12 2009/06/06 23:21:43 gwk Exp $ */
/*
* Copyright (c) 2003 Michael Eriksson.
* All rights reserved.
@@ -56,14 +56,22 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
+#include <sys/malloc.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
+#include <machine/bus.h>
#define CPUVENDOR_INTEL 0
#define CPUVENDOR_VIA 8
+#include "acpicpu.h"
+
+#if NACPICPU > 0
+#include <dev/acpi/acpidev.h>
+#include <dev/acpi/acpivar.h>
+#endif
/* Convert MHz and mV into IDs for passing to the MSR. */
#define ID16(MHz, mV, bus_clk) \
@@ -78,21 +86,22 @@
#define BUS333 33333
#define MSR2MHZ(msr, bus) \
- (((((int) (msr) >> 8) & 0xff) * (bus) + 50) / 100)
-#define MSR2MV(msr) \
- (((int) (msr) & 0xff) * 16 + 700)
+ (((((int)(msr) >> 8) & 0xff) * (bus) + 50) / 100)
+
+struct est_op {
+ uint16_t ctrl;
+ uint16_t mhz;
+};
struct fqlist {
int vendor: 5;
unsigned bus_clk : 1;
unsigned n : 5;
- const u_int16_t *table;
+ struct est_op *table;
};
-static const struct fqlist *est_fqlist;
-static u_int16_t fake_table[3];
-static struct fqlist fake_fqlist;
+static struct fqlist *est_fqlist;
extern int setperf_prio;
extern int perflevel;
@@ -206,21 +215,106 @@ p3_get_bus_clock(struct cpu_info *ci)
break;
}
break;
- default:
+ default:
printf("%s: unknown i686 model 0x%x, can't get bus clock\n",
ci->ci_dev->dv_xname, ci->ci_model);
}
}
+#if NACPICPU > 0
+struct fqlist * est_acpi_init(void);
+void est_acpi_pss_changed(struct acpicpu_pss *, int);
+
+struct fqlist *
+est_acpi_init()
+{
+ struct acpicpu_pss *pss;
+ struct fqlist *acpilist;
+ int nstates, i;
+
+ if ((nstates = acpicpu_fetch_pss(&pss)) == 0)
+ goto nolist;
+
+ if ((acpilist = malloc(sizeof(struct fqlist), M_DEVBUF, M_NOWAIT))
+ == NULL)
+ goto nolist;
+
+ if ((acpilist->table = malloc(sizeof(struct est_op) * nstates,
+ M_DEVBUF, M_NOWAIT)) == NULL)
+ goto notable;
+
+ acpilist->n = nstates;
+
+ for (i = 0; i < nstates; i++) {
+ acpilist->table[i].mhz = pss[i].pss_core_freq;
+ acpilist->table[i].ctrl = pss[i].pss_ctrl;
+ }
+
+ acpicpu_set_notify(est_acpi_pss_changed);
+
+ return acpilist;
+
+notable:
+ free(acpilist, M_DEVBUF);
+ acpilist = NULL;
+nolist:
+ return NULL;
+}
+
+void
+est_acpi_pss_changed(struct acpicpu_pss *pss, int npss)
+{
+ struct fqlist *acpilist;
+ int needtran = 1, nstates, i;
+ u_int64_t msr;
+ u_int16_t cur;
+
+ msr = rdmsr(MSR_PERF_STATUS);
+ cur = msr & 0xffff;
+
+ if ((acpilist = malloc(sizeof(struct fqlist), M_DEVBUF, M_NOWAIT))
+ == NULL) {
+ printf("est_acpi_pss_changed: cannot allocate memory for new"
+ " est state");
+ return;
+ }
+
+ if ((acpilist->table = malloc(sizeof(struct est_op) * nstates,
+ M_DEVBUF, M_NOWAIT)) == NULL) {
+ printf("est_acpi_pss_changed: cannot allocate memory for new"
+ " operating points");
+ free(acpilist, M_DEVBUF);
+ return;
+ }
+
+ for (i = 0; i < nstates; i++) {
+ acpilist->table[i].mhz = pss[i].pss_core_freq;
+ acpilist->table[i].ctrl = pss[i].pss_ctrl;
+ if (pss[i].pss_ctrl == cur)
+ needtran = 0;
+ }
+
+ free(est_fqlist->table, M_DEVBUF);
+ free(est_fqlist, M_DEVBUF);
+ est_fqlist = acpilist;
+
+ if (needtran) {
+ est_setperf(perflevel);
+ }
+}
+#endif
+
void
est_init(struct cpu_info *ci)
{
const char *cpu_device = ci->ci_dev->dv_xname;
int vendor = -1;
- int i, mhz, mv, low, high, family;
+ int i, low, high, family;
u_int64_t msr;
u_int16_t idhi, idlo, cur;
u_int8_t crhi, crlo, crcur;
+ struct fqlist *fake_fqlist;
+ struct est_op *fake_table;
if (setperf_prio > 3)
return;
@@ -243,68 +337,98 @@ est_init(struct cpu_info *ci)
crhi = (idhi >> 8) & 0xff;
crlo = (idlo >> 8) & 0xff;
crcur = (cur >> 8) & 0xff;
- if (crlo == 0 || crhi == crlo) {
- /*
- * Don't complain about these cases, and silently disable EST:
- * - A lowest clock ratio of 0, which seems to happen on all
- * Pentium 4's that report EST.
- * - An equal highest and lowest clock ratio, which happens on
- * at least the Core 2 Duo X6800, maybe on newer models too.
- */
- return;
- }
- if (crhi == 0 || crcur == 0 || crlo > crhi ||
- crcur < crlo || crcur > crhi) {
- /*
- * Do complain about other weirdness, because we first want to
- * know about it, before we decide what to do with it.
- */
- printf("%s: EST: strange msr value 0x%016llx\n",
- cpu_device, msr);
- return;
- }
+
+#if NACPICPU > 0
+ est_fqlist = est_acpi_init();
+#endif
+
if (est_fqlist == NULL) {
+ if (crhi == 0 || crcur == 0 || crlo > crhi ||
+ crcur < crlo || crcur > crhi) {
+ /*
+ * Do complain about other weirdness, because we first
+ * want to know about it, before we decide what to do
+ * with it.
+ */
+ printf("%s: EST: strange msr value 0x%016llx\n",
+ cpu_device, msr);
+ return;
+ }
+ if (crlo == 0 || crhi == crlo) {
+ /*
+ * Don't complain about these cases, and silently
+ * disable EST: - A lowest clock ratio of 0, which
+ * seems to happen on all Pentium 4's that report EST.
+ * - An equal highest and lowest clock ratio, which
+ * happens on at least the Core 2 Duo X6800, maybe on
+ * newer models too.
+ */
+ return;
+ }
+
printf("%s: unknown Enhanced SpeedStep CPU, msr 0x%016llx\n",
cpu_device, msr);
-
/*
* Generate a fake table with the power states we know.
*/
- fake_table[0] = idhi;
+
+ if ((fake_fqlist = malloc(sizeof(struct fqlist), M_DEVBUF,
+ M_NOWAIT)) == NULL) {
+ printf("%s: cannot allocate memory for fake list",
+ cpu_device);
+ return;
+ }
+
+
+ if ((fake_table = malloc(sizeof(struct est_op) * 3, M_DEVBUF,
+ M_NOWAIT)) == NULL) {
+ free(fake_fqlist, M_DEVBUF);
+ printf("%s: cannot allocate memory for fake table",
+ cpu_device);
+ return;
+ }
+ fake_table[0].ctrl = idhi;
+ fake_table[0].mhz = MSR2MHZ(idhi, bus_clock);
if (cur == idhi || cur == idlo) {
printf("%s: using only highest and lowest power "
- "states\n", cpu_device);
+ "states\n", cpu_device);
- fake_table[1] = idlo;
- fake_fqlist.n = 2;
+ fake_table[1].ctrl = idlo;
+ fake_table[1].mhz = MSR2MHZ(idlo, bus_clock);
+ 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;
+ fake_table[1].ctrl = cur;
+ fake_table[1].mhz = MSR2MHZ(cur, bus_clock);
+
+ fake_table[2].ctrl = idlo;
+ fake_table[2].mhz = MSR2MHZ(idlo, bus_clock);
+ fake_fqlist->n = 3;
}
- fake_fqlist.vendor = vendor;
- fake_fqlist.table = fake_table;
- est_fqlist = &fake_fqlist;
+
+ fake_fqlist->vendor = vendor;
+ fake_fqlist->table = fake_table;
+ est_fqlist = fake_fqlist;
}
- mhz = MSR2MHZ(cur, bus_clock);
- mv = MSR2MV(cur);
- printf("%s: Enhanced SpeedStep %d MHz (%d mV)", cpu_device, mhz, mv);
+ if (est_fqlist == NULL)
+ return;
+
+ printf("%s: Enhanced SpeedStep %d MHz", cpu_device, cpuspeed);
- low = MSR2MHZ(est_fqlist->table[est_fqlist->n - 1], bus_clock);
- high = MSR2MHZ(est_fqlist->table[0], bus_clock);
- perflevel = (mhz - low) * 100 / (high - low);
+ low = est_fqlist->table[est_fqlist->n - 1].mhz;
+ high = est_fqlist->table[0].mhz;
+ perflevel = (cpuspeed - low) * 100 / (high - low);
/*
* OK, tell the user the available frequencies.
*/
printf(": speeds: ");
for (i = 0; i < est_fqlist->n; i++)
- printf("%d%s", MSR2MHZ(est_fqlist->table[i], bus_clock),
- i < est_fqlist->n - 1 ? ", " : " MHz\n");
+ printf("%d%s", est_fqlist->table[i].mhz, i < est_fqlist->n - 1
+ ? ", " : " MHz\n");
cpu_setperf = est_setperf;
setperf_prio = 3;
@@ -326,7 +450,8 @@ est_setperf(int level)
msr = rdmsr(MSR_PERF_CTL);
msr &= ~0xffffULL;
- msr |= est_fqlist->table[i];
+ msr |= est_fqlist->table[i].ctrl;
+
wrmsr(MSR_PERF_CTL, msr);
- cpuspeed = MSR2MHZ(est_fqlist->table[i], bus_clock);
+ cpuspeed = est_fqlist->table[i].mhz;
}
diff --git a/sys/arch/i386/i386/est.c b/sys/arch/i386/i386/est.c
index dfc27c6fd43..cadb224ecbf 100644
--- a/sys/arch/i386/i386/est.c
+++ b/sys/arch/i386/i386/est.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: est.c,v 1.30 2007/06/07 11:20:58 dim Exp $ */
+/* $OpenBSD: est.c,v 1.31 2009/06/06 23:21:43 gwk Exp $ */
/*
* Copyright (c) 2003 Michael Eriksson.
* All rights reserved.
@@ -56,26 +56,39 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
+#include <sys/malloc.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
+#include <machine/bus.h>
+#include "acpicpu.h"
+
+#if NACPICPU > 0
+#include <dev/acpi/acpidev.h>
+#include <dev/acpi/acpivar.h>
+#endif
/* Convert MHz and mV into IDs for passing to the MSR. */
#define ID16(MHz, mV, bus_clk) \
- ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
+ { ((((MHz * 100 + 50) / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4)), \
+ MHz }
+struct est_op {
+ uint16_t ctrl;
+ uint16_t mhz;
+};
/* Ultra Low Voltage Intel Pentium M processor 900 MHz */
-static const u_int16_t pm130_900_ulv[] = {
+static struct est_op pm130_900_ulv[] = {
ID16( 900, 1004, BUS100),
ID16( 800, 988, BUS100),
ID16( 600, 844, BUS100),
};
/* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */
-static const u_int16_t pm130_1000_ulv[] = {
+static struct est_op pm130_1000_ulv[] = {
ID16(1000, 1004, BUS100),
ID16( 900, 988, BUS100),
ID16( 800, 972, BUS100),
@@ -83,7 +96,7 @@ static const u_int16_t pm130_1000_ulv[] = {
};
/* Ultra Low Voltage Intel Pentium M processor 1.10 GHz */
-static const u_int16_t pm130_1100_ulv[] = {
+static struct est_op pm130_1100_ulv[] = {
ID16(1100, 1004, BUS100),
ID16(1000, 988, BUS100),
ID16( 900, 972, BUS100),
@@ -92,7 +105,7 @@ static const u_int16_t pm130_1100_ulv[] = {
};
/* Low Voltage Intel Pentium M processor 1.10 GHz */
-static const u_int16_t pm130_1100_lv[] = {
+static struct est_op pm130_1100_lv[] = {
ID16(1100, 1180, BUS100),
ID16(1000, 1164, BUS100),
ID16( 900, 1100, BUS100),
@@ -101,7 +114,7 @@ static const u_int16_t pm130_1100_lv[] = {
};
/* Low Voltage Intel Pentium M processor 1.20 GHz */
-static const u_int16_t pm130_1200_lv[] = {
+static struct est_op pm130_1200_lv[] = {
ID16(1200, 1180, BUS100),
ID16(1100, 1164, BUS100),
ID16(1000, 1100, BUS100),
@@ -111,7 +124,7 @@ static const u_int16_t pm130_1200_lv[] = {
};
/* Low Voltage Intel Pentium M processor 1.30 GHz */
-static const u_int16_t pm130_1300_lv[] = {
+static struct est_op pm130_1300_lv[] = {
ID16(1300, 1180, BUS100),
ID16(1200, 1164, BUS100),
ID16(1100, 1100, BUS100),
@@ -122,7 +135,7 @@ static const u_int16_t pm130_1300_lv[] = {
};
/* Intel Pentium M processor 1.30 GHz */
-static const u_int16_t pm130_1300[] = {
+static struct est_op pm130_1300[] = {
ID16(1300, 1388, BUS100),
ID16(1200, 1356, BUS100),
ID16(1000, 1292, BUS100),
@@ -131,7 +144,7 @@ static const u_int16_t pm130_1300[] = {
};
/* Intel Pentium M processor 1.40 GHz */
-static const u_int16_t pm130_1400[] = {
+static struct est_op pm130_1400[] = {
ID16(1400, 1484, BUS100),
ID16(1200, 1436, BUS100),
ID16(1000, 1308, BUS100),
@@ -140,7 +153,7 @@ static const u_int16_t pm130_1400[] = {
};
/* Intel Pentium M processor 1.50 GHz */
-static const u_int16_t pm130_1500[] = {
+static struct est_op pm130_1500[] = {
ID16(1500, 1484, BUS100),
ID16(1400, 1452, BUS100),
ID16(1200, 1356, BUS100),
@@ -150,7 +163,7 @@ static const u_int16_t pm130_1500[] = {
};
/* Intel Pentium M processor 1.60 GHz */
-static const u_int16_t pm130_1600[] = {
+static struct est_op pm130_1600[] = {
ID16(1600, 1484, BUS100),
ID16(1400, 1420, BUS100),
ID16(1200, 1276, BUS100),
@@ -160,7 +173,7 @@ static const u_int16_t pm130_1600[] = {
};
/* Intel Pentium M processor 1.70 GHz */
-static const u_int16_t pm130_1700[] = {
+static struct est_op pm130_1700[] = {
ID16(1700, 1484, BUS100),
ID16(1400, 1308, BUS100),
ID16(1200, 1228, BUS100),
@@ -170,7 +183,7 @@ static const u_int16_t pm130_1700[] = {
};
/* Intel Pentium M processor 723 1.0 GHz */
-static const u_int16_t pm90_n723[] = {
+static struct est_op pm90_n723[] = {
ID16(1000, 940, BUS100),
ID16( 900, 908, BUS100),
ID16( 800, 876, BUS100),
@@ -178,7 +191,7 @@ static const u_int16_t pm90_n723[] = {
};
/* Intel Pentium M processor 733 1.1 GHz, VID #G */
-static const u_int16_t pm90_n733g[] = {
+static struct est_op pm90_n733g[] = {
ID16(1100, 956, BUS100),
ID16(1000, 940, BUS100),
ID16( 900, 908, BUS100),
@@ -187,7 +200,7 @@ static const u_int16_t pm90_n733g[] = {
};
/* Intel Pentium M processor 733 1.1 GHz, VID #H */
-static const u_int16_t pm90_n733h[] = {
+static struct est_op pm90_n733h[] = {
ID16(1100, 940, BUS100),
ID16(1000, 924, BUS100),
ID16( 900, 892, BUS100),
@@ -196,7 +209,7 @@ static const u_int16_t pm90_n733h[] = {
};
/* Intel Pentium M processor 733 1.1 GHz, VID #I */
-static const u_int16_t pm90_n733i[] = {
+static struct est_op pm90_n733i[] = {
ID16(1100, 924, BUS100),
ID16(1000, 908, BUS100),
ID16( 900, 892, BUS100),
@@ -205,7 +218,7 @@ static const u_int16_t pm90_n733i[] = {
};
/* Intel Pentium M processor 733 1.1 GHz, VID #J */
-static const u_int16_t pm90_n733j[] = {
+static struct est_op pm90_n733j[] = {
ID16(1100, 908, BUS100),
ID16(1000, 892, BUS100),
ID16( 900, 876, BUS100),
@@ -214,7 +227,7 @@ static const u_int16_t pm90_n733j[] = {
};
/* Intel Pentium M processor 733 1.1 GHz, VID #K */
-static const u_int16_t pm90_n733k[] = {
+static struct est_op pm90_n733k[] = {
ID16(1100, 892, BUS100),
ID16(1000, 876, BUS100),
ID16( 900, 860, BUS100),
@@ -223,7 +236,7 @@ static const u_int16_t pm90_n733k[] = {
};
/* Intel Pentium M processor 733 1.1 GHz, VID #L */
-static const u_int16_t pm90_n733l[] = {
+static struct est_op pm90_n733l[] = {
ID16(1100, 876, BUS100),
ID16(1000, 876, BUS100),
ID16( 900, 860, BUS100),
@@ -232,7 +245,7 @@ static const u_int16_t pm90_n733l[] = {
};
/* Intel Pentium M processor 753 1.2 GHz, VID #G */
-static const u_int16_t pm90_n753g[] = {
+static struct est_op pm90_n753g[] = {
ID16(1200, 956, BUS100),
ID16(1100, 940, BUS100),
ID16(1000, 908, BUS100),
@@ -242,7 +255,7 @@ static const u_int16_t pm90_n753g[] = {
};
/* Intel Pentium M processor 753 1.2 GHz, VID #H */
-static const u_int16_t pm90_n753h[] = {
+static struct est_op pm90_n753h[] = {
ID16(1200, 940, BUS100),
ID16(1100, 924, BUS100),
ID16(1000, 908, BUS100),
@@ -252,7 +265,7 @@ static const u_int16_t pm90_n753h[] = {
};
/* Intel Pentium M processor 753 1.2 GHz, VID #I */
-static const u_int16_t pm90_n753i[] = {
+static struct est_op pm90_n753i[] = {
ID16(1200, 924, BUS100),
ID16(1100, 908, BUS100),
ID16(1000, 892, BUS100),
@@ -262,7 +275,7 @@ static const u_int16_t pm90_n753i[] = {
};
/* Intel Pentium M processor 753 1.2 GHz, VID #J */
-static const u_int16_t pm90_n753j[] = {
+static struct est_op pm90_n753j[] = {
ID16(1200, 908, BUS100),
ID16(1100, 892, BUS100),
ID16(1000, 876, BUS100),
@@ -272,7 +285,7 @@ static const u_int16_t pm90_n753j[] = {
};
/* Intel Pentium M processor 753 1.2 GHz, VID #K */
-static const u_int16_t pm90_n753k[] = {
+static struct est_op pm90_n753k[] = {
ID16(1200, 892, BUS100),
ID16(1100, 892, BUS100),
ID16(1000, 876, BUS100),
@@ -282,7 +295,7 @@ static const u_int16_t pm90_n753k[] = {
};
/* Intel Pentium M processor 753 1.2 GHz, VID #L */
-static const u_int16_t pm90_n753l[] = {
+static struct est_op pm90_n753l[] = {
ID16(1200, 876, BUS100),
ID16(1100, 876, BUS100),
ID16(1000, 860, BUS100),
@@ -292,7 +305,7 @@ static const u_int16_t pm90_n753l[] = {
};
/* Intel Pentium M processor 773 1.3 GHz, VID #G */
-static const u_int16_t pm90_n773g[] = {
+static struct est_op pm90_n773g[] = {
ID16(1300, 956, BUS100),
ID16(1200, 940, BUS100),
ID16(1100, 924, BUS100),
@@ -303,7 +316,7 @@ static const u_int16_t pm90_n773g[] = {
};
/* Intel Pentium M processor 773 1.3 GHz, VID #H */
-static const u_int16_t pm90_n773h[] = {
+static struct est_op pm90_n773h[] = {
ID16(1300, 940, BUS100),
ID16(1200, 924, BUS100),
ID16(1100, 908, BUS100),
@@ -314,7 +327,7 @@ static const u_int16_t pm90_n773h[] = {
};
/* Intel Pentium M processor 773 1.3 GHz, VID #I */
-static const u_int16_t pm90_n773i[] = {
+static struct est_op pm90_n773i[] = {
ID16(1300, 924, BUS100),
ID16(1200, 908, BUS100),
ID16(1100, 892, BUS100),
@@ -325,7 +338,7 @@ static const u_int16_t pm90_n773i[] = {
};
/* Intel Pentium M processor 773 1.3 GHz, VID #J */
-static const u_int16_t pm90_n773j[] = {
+static struct est_op pm90_n773j[] = {
ID16(1300, 908, BUS100),
ID16(1200, 908, BUS100),
ID16(1100, 892, BUS100),
@@ -336,7 +349,7 @@ static const u_int16_t pm90_n773j[] = {
};
/* Intel Pentium M processor 773 1.3 GHz, VID #K */
-static const u_int16_t pm90_n773k[] = {
+static struct est_op pm90_n773k[] = {
ID16(1300, 892, BUS100),
ID16(1200, 892, BUS100),
ID16(1100, 876, BUS100),
@@ -347,7 +360,7 @@ static const u_int16_t pm90_n773k[] = {
};
/* Intel Pentium M processor 773 1.3 GHz, VID #L */
-static const u_int16_t pm90_n773l[] = {
+static struct est_op pm90_n773l[] = {
ID16(1300, 876, BUS100),
ID16(1200, 876, BUS100),
ID16(1100, 860, BUS100),
@@ -358,7 +371,7 @@ static const u_int16_t pm90_n773l[] = {
};
/* Intel Pentium M processor 738 1.4 GHz */
-static const u_int16_t pm90_n738[] = {
+static struct est_op pm90_n738[] = {
ID16(1400, 1116, BUS100),
ID16(1300, 1116, BUS100),
ID16(1200, 1100, BUS100),
@@ -370,7 +383,7 @@ static const u_int16_t pm90_n738[] = {
};
/* Intel Pentium M processor 758 1.5 GHz */
-static const u_int16_t pm90_n758[] = {
+static struct est_op pm90_n758[] = {
ID16(1500, 1116, BUS100),
ID16(1400, 1116, BUS100),
ID16(1300, 1100, BUS100),
@@ -383,7 +396,7 @@ static const u_int16_t pm90_n758[] = {
};
/* Intel Pentium M processor 778 1.6 GHz */
-static const u_int16_t pm90_n778[] = {
+static struct est_op pm90_n778[] = {
ID16(1600, 1116, BUS100),
ID16(1500, 1116, BUS100),
ID16(1400, 1100, BUS100),
@@ -397,7 +410,7 @@ static const u_int16_t pm90_n778[] = {
};
/* Intel Pentium M processor 710 1.4 GHz, 533 MHz FSB */
-static const u_int16_t pm90_n710[] = {
+static struct est_op pm90_n710[] = {
ID16(1400, 1340, BUS133),
ID16(1200, 1228, BUS133),
ID16(1000, 1148, BUS133),
@@ -406,7 +419,7 @@ static const u_int16_t pm90_n710[] = {
};
/* Intel Pentium M processor 715 1.5 GHz, VID #A */
-static const u_int16_t pm90_n715a[] = {
+static struct est_op pm90_n715a[] = {
ID16(1500, 1340, BUS100),
ID16(1200, 1228, BUS100),
ID16(1000, 1148, BUS100),
@@ -415,7 +428,7 @@ static const u_int16_t pm90_n715a[] = {
};
/* Intel Pentium M processor 715 1.5 GHz, VID #B */
-static const u_int16_t pm90_n715b[] = {
+static struct est_op pm90_n715b[] = {
ID16(1500, 1324, BUS100),
ID16(1200, 1212, BUS100),
ID16(1000, 1148, BUS100),
@@ -424,7 +437,7 @@ static const u_int16_t pm90_n715b[] = {
};
/* Intel Pentium M processor 715 1.5 GHz, VID #C */
-static const u_int16_t pm90_n715c[] = {
+static struct est_op pm90_n715c[] = {
ID16(1500, 1308, BUS100),
ID16(1200, 1212, BUS100),
ID16(1000, 1132, BUS100),
@@ -433,7 +446,7 @@ static const u_int16_t pm90_n715c[] = {
};
/* Intel Pentium M processor 715 1.5 GHz, VID #D */
-static const u_int16_t pm90_n715d[] = {
+static struct est_op pm90_n715d[] = {
ID16(1500, 1276, BUS100),
ID16(1200, 1180, BUS100),
ID16(1000, 1116, BUS100),
@@ -442,7 +455,7 @@ static const u_int16_t pm90_n715d[] = {
};
/* Intel Pentium M processor 725 1.6 GHz, VID #A */
-static const u_int16_t pm90_n725a[] = {
+static struct est_op pm90_n725a[] = {
ID16(1600, 1340, BUS100),
ID16(1400, 1276, BUS100),
ID16(1200, 1212, BUS100),
@@ -452,7 +465,7 @@ static const u_int16_t pm90_n725a[] = {
};
/* Intel Pentium M processor 725 1.6 GHz, VID #B */
-static const u_int16_t pm90_n725b[] = {
+static struct est_op pm90_n725b[] = {
ID16(1600, 1324, BUS100),
ID16(1400, 1260, BUS100),
ID16(1200, 1196, BUS100),
@@ -462,7 +475,7 @@ static const u_int16_t pm90_n725b[] = {
};
/* Intel Pentium M processor 725 1.6 GHz, VID #C */
-static const u_int16_t pm90_n725c[] = {
+static struct est_op pm90_n725c[] = {
ID16(1600, 1308, BUS100),
ID16(1400, 1244, BUS100),
ID16(1200, 1180, BUS100),
@@ -472,7 +485,7 @@ static const u_int16_t pm90_n725c[] = {
};
/* Intel Pentium M processor 725 1.6 GHz, VID #D */
-static const u_int16_t pm90_n725d[] = {
+static struct est_op pm90_n725d[] = {
ID16(1600, 1276, BUS100),
ID16(1400, 1228, BUS100),
ID16(1200, 1164, BUS100),
@@ -482,7 +495,7 @@ static const u_int16_t pm90_n725d[] = {
};
/* Intel Pentium M processor 730 1.6 GHz, 533 MHz FSB */
-static const u_int16_t pm90_n730[] = {
+static struct est_op pm90_n730[] = {
ID16(1600, 1308, BUS133),
ID16(1333, 1260, BUS133),
ID16(1200, 1212, BUS133),
@@ -491,7 +504,7 @@ static const u_int16_t pm90_n730[] = {
};
/* Intel Pentium M processor 735 1.7 GHz, VID #A */
-static const u_int16_t pm90_n735a[] = {
+static struct est_op pm90_n735a[] = {
ID16(1700, 1340, BUS100),
ID16(1400, 1244, BUS100),
ID16(1200, 1180, BUS100),
@@ -501,7 +514,7 @@ static const u_int16_t pm90_n735a[] = {
};
/* Intel Pentium M processor 735 1.7 GHz, VID #B */
-static const u_int16_t pm90_n735b[] = {
+static struct est_op pm90_n735b[] = {
ID16(1700, 1324, BUS100),
ID16(1400, 1244, BUS100),
ID16(1200, 1180, BUS100),
@@ -511,7 +524,7 @@ static const u_int16_t pm90_n735b[] = {
};
/* Intel Pentium M processor 735 1.7 GHz, VID #C */
-static const u_int16_t pm90_n735c[] = {
+static struct est_op pm90_n735c[] = {
ID16(1700, 1308, BUS100),
ID16(1400, 1228, BUS100),
ID16(1200, 1164, BUS100),
@@ -521,7 +534,7 @@ static const u_int16_t pm90_n735c[] = {
};
/* Intel Pentium M processor 735 1.7 GHz, VID #D */
-static const u_int16_t pm90_n735d[] = {
+static struct est_op pm90_n735d[] = {
ID16(1700, 1276, BUS100),
ID16(1400, 1212, BUS100),
ID16(1200, 1148, BUS100),
@@ -531,7 +544,7 @@ static const u_int16_t pm90_n735d[] = {
};
/* Intel Pentium M processor 740 1.73 GHz, 533 MHz FSB */
-static const u_int16_t pm90_n740[] = {
+static struct est_op pm90_n740[] = {
ID16(1733, 1356, BUS133),
ID16(1333, 1212, BUS133),
ID16(1067, 1100, BUS133),
@@ -539,7 +552,7 @@ static const u_int16_t pm90_n740[] = {
};
/* Intel Pentium M processor 745 1.8 GHz, VID #A */
-static const u_int16_t pm90_n745a[] = {
+static struct est_op pm90_n745a[] = {
ID16(1800, 1340, BUS100),
ID16(1600, 1292, BUS100),
ID16(1400, 1228, BUS100),
@@ -550,7 +563,7 @@ static const u_int16_t pm90_n745a[] = {
};
/* Intel Pentium M processor 745 1.8 GHz, VID #B */
-static const u_int16_t pm90_n745b[] = {
+static struct est_op pm90_n745b[] = {
ID16(1800, 1324, BUS100),
ID16(1600, 1276, BUS100),
ID16(1400, 1212, BUS100),
@@ -561,7 +574,7 @@ static const u_int16_t pm90_n745b[] = {
};
/* Intel Pentium M processor 745 1.8 GHz, VID #C */
-static const u_int16_t pm90_n745c[] = {
+static struct est_op pm90_n745c[] = {
ID16(1800, 1308, BUS100),
ID16(1600, 1260, BUS100),
ID16(1400, 1212, BUS100),
@@ -572,7 +585,7 @@ static const u_int16_t pm90_n745c[] = {
};
/* Intel Pentium M processor 745 1.8 GHz, VID #D */
-static const u_int16_t pm90_n745d[] = {
+static struct est_op pm90_n745d[] = {
ID16(1800, 1276, BUS100),
ID16(1600, 1228, BUS100),
ID16(1400, 1180, BUS100),
@@ -584,7 +597,7 @@ static const u_int16_t pm90_n745d[] = {
/* Intel Pentium M processor 750 1.86 GHz, 533 MHz FSB */
/* values extracted from \_PR\NPSS (via _PSS) SDST ACPI table */
-static const u_int16_t pm90_n750[] = {
+static struct est_op pm90_n750[] = {
ID16(1867, 1308, BUS133),
ID16(1600, 1228, BUS133),
ID16(1333, 1148, BUS133),
@@ -593,7 +606,7 @@ static const u_int16_t pm90_n750[] = {
};
/* Intel Pentium M processor 755 2.0 GHz, VID #A */
-static const u_int16_t pm90_n755a[] = {
+static struct est_op pm90_n755a[] = {
ID16(2000, 1340, BUS100),
ID16(1800, 1292, BUS100),
ID16(1600, 1244, BUS100),
@@ -605,7 +618,7 @@ static const u_int16_t pm90_n755a[] = {
};
/* Intel Pentium M processor 755 2.0 GHz, VID #B */
-static const u_int16_t pm90_n755b[] = {
+static struct est_op pm90_n755b[] = {
ID16(2000, 1324, BUS100),
ID16(1800, 1276, BUS100),
ID16(1600, 1228, BUS100),
@@ -617,7 +630,7 @@ static const u_int16_t pm90_n755b[] = {
};
/* Intel Pentium M processor 755 2.0 GHz, VID #C */
-static const u_int16_t pm90_n755c[] = {
+static struct est_op pm90_n755c[] = {
ID16(2000, 1308, BUS100),
ID16(1800, 1276, BUS100),
ID16(1600, 1228, BUS100),
@@ -629,7 +642,7 @@ static const u_int16_t pm90_n755c[] = {
};
/* Intel Pentium M processor 755 2.0 GHz, VID #D */
-static const u_int16_t pm90_n755d[] = {
+static struct est_op pm90_n755d[] = {
ID16(2000, 1276, BUS100),
ID16(1800, 1244, BUS100),
ID16(1600, 1196, BUS100),
@@ -641,7 +654,7 @@ static const u_int16_t pm90_n755d[] = {
};
/* Intel Pentium M processor 760 2.0 GHz, 533 MHz FSB */
-static const u_int16_t pm90_n760[] = {
+static struct est_op pm90_n760[] = {
ID16(2000, 1356, BUS133),
ID16(1600, 1244, BUS133),
ID16(1333, 1164, BUS133),
@@ -650,7 +663,7 @@ static const u_int16_t pm90_n760[] = {
};
/* Intel Pentium M processor 765 2.1 GHz, VID #A */
-static const u_int16_t pm90_n765a[] = {
+static struct est_op pm90_n765a[] = {
ID16(2100, 1340, BUS100),
ID16(1800, 1276, BUS100),
ID16(1600, 1228, BUS100),
@@ -662,7 +675,7 @@ static const u_int16_t pm90_n765a[] = {
};
/* Intel Pentium M processor 765 2.1 GHz, VID #B */
-static const u_int16_t pm90_n765b[] = {
+static struct est_op pm90_n765b[] = {
ID16(2100, 1324, BUS100),
ID16(1800, 1260, BUS100),
ID16(1600, 1212, BUS100),
@@ -674,7 +687,7 @@ static const u_int16_t pm90_n765b[] = {
};
/* Intel Pentium M processor 765 2.1 GHz, VID #C */
-static const u_int16_t pm90_n765c[] = {
+static struct est_op pm90_n765c[] = {
ID16(2100, 1308, BUS100),
ID16(1800, 1244, BUS100),
ID16(1600, 1212, BUS100),
@@ -686,7 +699,7 @@ static const u_int16_t pm90_n765c[] = {
};
/* Intel Pentium M processor 765 2.1 GHz, VID #E */
-static const u_int16_t pm90_n765e[] = {
+static struct est_op pm90_n765e[] = {
ID16(2100, 1356, BUS100),
ID16(1800, 1292, BUS100),
ID16(1600, 1244, BUS100),
@@ -698,7 +711,7 @@ static const u_int16_t pm90_n765e[] = {
};
/* Intel Pentium M processor 770 2.13 GHz */
-static const u_int16_t pm90_n770[] = {
+static struct est_op pm90_n770[] = {
ID16(2133, 1356, BUS133),
ID16(1867, 1292, BUS133),
ID16(1600, 1212, BUS133),
@@ -713,7 +726,7 @@ static const u_int16_t pm90_n770[] = {
*/
/* 1.00GHz Centaur C7-M ULV */
-static const u_int16_t C7M_770_ULV[] = {
+static struct est_op C7M_770_ULV[] = {
ID16(1000, 844, BUS100),
ID16( 800, 796, BUS100),
ID16( 600, 796, BUS100),
@@ -721,7 +734,7 @@ static const u_int16_t C7M_770_ULV[] = {
};
/* 1.00GHz Centaur C7-M ULV */
-static const u_int16_t C7M_779_ULV[] = {
+static struct est_op C7M_779_ULV[] = {
ID16(1000, 796, BUS100),
ID16( 800, 796, BUS100),
ID16( 600, 796, BUS100),
@@ -729,7 +742,7 @@ static const u_int16_t C7M_779_ULV[] = {
};
/* 1.20GHz Centaur C7-M ULV */
-static const u_int16_t C7M_772_ULV[] = {
+static struct est_op C7M_772_ULV[] = {
ID16(1200, 844, BUS100),
ID16(1000, 844, BUS100),
ID16( 800, 828, BUS100),
@@ -738,7 +751,7 @@ static const u_int16_t C7M_772_ULV[] = {
};
/* 1.50GHz Centaur C7-M ULV */
-static const u_int16_t C7M_775_ULV[] = {
+static struct est_op C7M_775_ULV[] = {
ID16(1500, 956, BUS100),
ID16(1400, 940, BUS100),
ID16(1000, 860, BUS100),
@@ -748,7 +761,7 @@ static const u_int16_t C7M_775_ULV[] = {
};
/* 1.20GHz Centaur C7-M 400 MHz FSB */
-static const u_int16_t C7M_771[] = {
+static struct est_op C7M_771[] = {
ID16(1200, 860, BUS100),
ID16(1000, 860, BUS100),
ID16( 800, 844, BUS100),
@@ -757,7 +770,7 @@ static const u_int16_t C7M_771[] = {
};
/* 1.50GHz Centaur C7-M 400 MHz FSB */
-static const u_int16_t C7M_754[] = {
+static struct est_op C7M_754[] = {
ID16(1500, 1004, BUS100),
ID16(1400, 988, BUS100),
ID16(1000, 940, BUS100),
@@ -767,7 +780,7 @@ static const u_int16_t C7M_754[] = {
};
/* 1.60GHz Centaur C7-M 400 MHz FSB */
-static const u_int16_t C7M_764[] = {
+static struct est_op C7M_764[] = {
ID16(1600, 1084, BUS100),
ID16(1400, 1052, BUS100),
ID16(1000, 1004, BUS100),
@@ -777,7 +790,7 @@ static const u_int16_t C7M_764[] = {
};
/* 1.80GHz Centaur C7-M 400 MHz FSB */
-static const u_int16_t C7M_784[] = {
+static struct est_op C7M_784[] = {
ID16(1800, 1148, BUS100),
ID16(1600, 1100, BUS100),
ID16(1400, 1052, BUS100),
@@ -788,7 +801,7 @@ static const u_int16_t C7M_784[] = {
};
/* 2.00GHz Centaur C7-M 400 MHz FSB */
-static const u_int16_t C7M_794[] = {
+static struct est_op C7M_794[] = {
ID16(2000, 1148, BUS100),
ID16(1800, 1132, BUS100),
ID16(1600, 1100, BUS100),
@@ -800,7 +813,7 @@ static const u_int16_t C7M_794[] = {
};
/* 1.60GHz Centaur C7-M 533 MHz FSB */
-static const u_int16_t C7M_765[] = {
+static struct est_op C7M_765[] = {
ID16(1600, 1084, BUS133),
ID16(1467, 1052, BUS133),
ID16(1200, 1004, BUS133),
@@ -810,7 +823,7 @@ static const u_int16_t C7M_765[] = {
};
/* 2.00GHz Centaur C7-M 533 MHz FSB */
-static const u_int16_t C7M_785[] = {
+static struct est_op C7M_785[] = {
ID16(1867, 1148, BUS133),
ID16(1600, 1100, BUS133),
ID16(1467, 1052, BUS133),
@@ -821,7 +834,7 @@ static const u_int16_t C7M_785[] = {
};
/* 2.00GHz Centaur C7-M 533 MHz FSB */
-static const u_int16_t C7M_795[] = {
+static struct est_op C7M_795[] = {
ID16(2000, 1148, BUS133),
ID16(1867, 1132, BUS133),
ID16(1600, 1100, BUS133),
@@ -833,18 +846,19 @@ static const u_int16_t C7M_795[] = {
};
/* 1.00GHz VIA Eden 90nm 'Esther' */
-static const u_int16_t eden90_1000[] = {
+static struct est_op eden90_1000[] = {
ID16(1000, 844, BUS100),
ID16( 800, 844, BUS100),
ID16( 600, 844, BUS100),
ID16( 400, 844, BUS100),
};
+
struct fqlist {
- int vendor : 5;
+ int vendor: 5;
unsigned bus_clk : 1;
unsigned n : 5;
- const u_int16_t *table;
+ struct est_op *table;
};
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
@@ -854,7 +868,7 @@ struct fqlist {
#define BUS_CLK(fqp) ((fqp)->bus_clk ? BUS133 : BUS100)
-static const struct fqlist est_cpus[] = {
+static struct fqlist est_cpus[] = {
ENTRY(INTEL, BUS100, pm130_900_ulv),
ENTRY(INTEL, BUS100, pm130_1000_ulv),
ENTRY(INTEL, BUS100, pm130_1100_ulv),
@@ -937,28 +951,109 @@ static const struct fqlist est_cpus[] = {
ENTRY(VIA, BUS100, eden90_1000),
};
-
#define MSR2MHZ(msr, bus) \
(((((int) (msr) >> 8) & 0xff) * (bus) + 50) / 100)
#define MSR2MV(msr) \
(((int) (msr) & 0xff) * 16 + 700)
-static const struct fqlist *est_fqlist;
-
-static u_int16_t fake_table[3];
-static struct fqlist fake_fqlist;
+static struct fqlist *est_fqlist;
extern int setperf_prio;
extern int perflevel;
+#if NACPICPU > 0
+struct fqlist * est_acpi_init(void);
+void est_acpi_pss_changed(struct acpicpu_pss *, int);
+
+struct fqlist *
+est_acpi_init()
+{
+ struct acpicpu_pss *pss;
+ struct fqlist *acpilist;
+ int nstates, i;
+
+ if ((nstates = acpicpu_fetch_pss(&pss)) == 0)
+ goto nolist;
+
+ if ((acpilist = malloc(sizeof(struct fqlist), M_DEVBUF, M_NOWAIT))
+ == NULL)
+ goto nolist;
+
+ if ((acpilist->table = malloc(sizeof( struct est_op) * nstates,
+ M_DEVBUF, M_NOWAIT)) == NULL)
+ goto notable;
+
+ acpilist->n = nstates;
+
+ for (i = 0; i < nstates; i++) {
+ acpilist->table[i].mhz = pss[i].pss_core_freq;
+ acpilist->table[i].ctrl = pss[i].pss_ctrl;
+ }
+
+ acpicpu_set_notify(est_acpi_pss_changed);
+
+ return acpilist;
+
+notable:
+ free(acpilist, M_DEVBUF);
+ acpilist = NULL;
+nolist:
+ return NULL;
+}
+
+void
+est_acpi_pss_changed(struct acpicpu_pss *pss, int npss)
+{
+ struct fqlist *acpilist;
+ int needtran = 1, nstates, i;
+ u_int64_t msr;
+ u_int16_t cur;
+
+ msr = rdmsr(MSR_PERF_STATUS);
+ cur = msr & 0xffff;
+
+ if ((acpilist = malloc(sizeof(struct fqlist), M_DEVBUF, M_NOWAIT))
+ == NULL) {
+ printf("est_acpi_pss_changed: cannot allocate memory for new "
+ "est state");
+ return;
+ }
+
+ if ((acpilist->table = malloc(sizeof( struct est_op) * nstates,
+ M_DEVBUF, M_NOWAIT)) == NULL) {
+ printf("est_acpi_pss_changed: cannot allocate memory for new "
+ "operating points");
+ free(acpilist, M_DEVBUF);
+ return;
+ }
+
+ for (i = 0; i < nstates; i++) {
+ acpilist->table[i].mhz = pss[i].pss_core_freq;
+ acpilist->table[i].ctrl = pss[i].pss_ctrl;
+ if (pss[i].pss_ctrl == cur)
+ needtran = 0;
+ }
+
+ free(est_fqlist->table, M_DEVBUF);
+ free(est_fqlist, M_DEVBUF);
+ est_fqlist = acpilist;
+
+ if (needtran) {
+ est_setperf(perflevel);
+ }
+}
+#endif
+
void
est_init(const char *cpu_device, int vendor)
{
- int i, mhz, mv, low, high;
+ int i, low, high;
u_int64_t msr;
u_int16_t idhi, idlo, cur;
u_int8_t crhi, crlo, crcur;
- const struct fqlist *fql;
+ struct fqlist *fql;
+ struct fqlist *fake_fqlist;
+ struct est_op *fake_table;
if (setperf_prio > 3)
return;
@@ -966,11 +1061,6 @@ est_init(const char *cpu_device, int vendor)
if ((cpu_ecxfeature & CPUIDECX_EST) == 0)
return;
- if (bus_clock == 0) {
- printf("%s: EST: unknown system bus clock\n", cpu_device);
- return;
- }
-
msr = rdmsr(MSR_PERF_STATUS);
idhi = (msr >> 32) & 0xffff;
idlo = (msr >> 48) & 0xffff;
@@ -978,90 +1068,118 @@ est_init(const char *cpu_device, int vendor)
crhi = (idhi >> 8) & 0xff;
crlo = (idlo >> 8) & 0xff;
crcur = (cur >> 8) & 0xff;
- if (crlo == 0 || crhi == crlo) {
- /*
- * Don't complain about these cases, and silently disable EST:
- * - A lowest clock ratio of 0, which seems to happen on all
- * Pentium 4's that report EST.
- * - An equal highest and lowest clock ratio, which happens on
- * at least the Core 2 Duo X6800, maybe on newer models too.
- */
- return;
- }
- if (crhi == 0 || crcur == 0 || crlo > crhi ||
- crcur < crlo || crcur > crhi) {
+
+#if NACPICPU > 0
+ est_fqlist = est_acpi_init();
+#endif
+
+ if (est_fqlist == NULL) {
/*
- * Do complain about other weirdness, because we first want to
- * know about it, before we decide what to do with it.
+ * Find an entry which matches (vendor, bus_clock, idhi, idlo)
*/
- printf("%s: EST: strange msr value 0x%016llx\n",
- cpu_device, msr);
- return;
- }
- /*
- * Find an entry which matches (vendor, bus_clock, idhi, idlo)
- */
- for (i = 0; i < NELEM(est_cpus); i++) {
- fql = &est_cpus[i];
- if (vendor == fql->vendor && bus_clock == BUS_CLK(fql) &&
- idhi == fql->table[0] && idlo == fql->table[fql->n - 1]) {
- est_fqlist = fql;
- break;
+ for (i = 0; i < NELEM(est_cpus); i++) {
+ fql = &est_cpus[i];
+ if (vendor == fql->vendor && bus_clock == BUS_CLK(fql)
+ && idhi == fql->table[0].ctrl
+ && idlo == fql->table[fql->n - 1].ctrl) {
+ est_fqlist = fql;
+ break;
+ }
}
}
+
if (est_fqlist == NULL) {
+ if (bus_clock == 0) {
+ printf("%s: EST: unknown system bus clock\n",
+ cpu_device);
+ return;
+ }
+ if (crhi == 0 || crcur == 0 || crlo > crhi ||
+ crcur < crlo || crcur > crhi) {
+ /*
+ * Do complain about other weirdness, because we first
+ * want to know about it, before we decide what to do
+ * with it.
+ */
+ printf("%s: EST: strange msr value 0x%016llx\n",
+ cpu_device, msr);
+ return;
+ }
+ if (crlo == 0 || crhi == crlo) {
+ /*
+ * Don't complain about these cases, and silently
+ * disable EST: - A lowest clock ratio of 0, which
+ * seems to happen on all Pentium 4's that report EST.
+ * - And equal highest and lowest clock ratio, which
+ * happens on at least the Core 2 Duo X6800, maybe on
+ * newer models too.
+ */
+ return;
+ }
+
printf("%s: unknown Enhanced SpeedStep CPU, msr 0x%016llx\n",
cpu_device, msr);
-
/*
* Generate a fake table with the power states we know.
*/
- fake_table[0] = idhi;
+
+ if ((fake_fqlist = malloc(sizeof(struct fqlist), M_DEVBUF,
+ M_NOWAIT)) == NULL) {
+ printf("%s: EST: cannot allocate memory for fake list",
+ cpu_device);
+ return;
+ }
+
+
+ if ((fake_table = malloc(sizeof(struct est_op) * 3, M_DEVBUF,
+ M_NOWAIT)) == NULL) {
+ free(fake_fqlist, M_DEVBUF);
+ printf("%s: EST: cannot allocate memory for fake "
+ "table\n", cpu_device);
+ return;
+ }
+ fake_table[0].ctrl = idhi;
+ fake_table[0].mhz = MSR2MHZ(idhi, bus_clock);
if (cur == idhi || cur == idlo) {
printf("%s: using only highest and lowest power "
- "states\n", cpu_device);
+ "states\n", cpu_device);
- fake_table[1] = idlo;
- fake_fqlist.n = 2;
+ fake_table[1].ctrl = idlo;
+ fake_table[1].mhz = MSR2MHZ(idlo, bus_clock);
+ 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;
- }
- fake_fqlist.vendor = vendor;
- fake_fqlist.table = fake_table;
- est_fqlist = &fake_fqlist;
- }
+ fake_table[1].ctrl = cur;
+ fake_table[1].mhz = MSR2MHZ(cur, bus_clock);
- mhz = MSR2MHZ(cur, bus_clock);
- mv = MSR2MV(cur);
- printf("%s: Enhanced SpeedStep %d MHz (%d mV)", cpu_device, mhz, mv);
+ fake_table[2].ctrl = idlo;
+ fake_table[2].mhz = MSR2MHZ(idlo, bus_clock);
+ fake_fqlist->n = 3;
+ }
- /*
- * Check that the current operating point is in our list.
- */
- for (i = est_fqlist->n - 1; i >= 0; i--) {
- if (cur == est_fqlist->table[i])
- break;
+ fake_fqlist->vendor = vendor;
+ fake_fqlist->table = fake_table;
+ est_fqlist = fake_fqlist;
}
- if (i < 0) {
- printf(" (not in table, msr 0x%016llx)\n", msr);
+
+ if (est_fqlist == NULL)
return;
- }
- low = MSR2MHZ(est_fqlist->table[est_fqlist->n - 1], bus_clock);
- high = MSR2MHZ(est_fqlist->table[0], bus_clock);
- perflevel = (mhz - low) * 100 / (high - low);
+
+ printf("%s: Enhanced SpeedStep %d MHz", cpu_device, cpuspeed);
+
+ low = est_fqlist->table[est_fqlist->n - 1].mhz;
+ high = est_fqlist->table[0].mhz;
+ perflevel = (cpuspeed - low) * 100 / (high - low);
/*
* OK, tell the user the available frequencies.
*/
printf(": speeds: ");
for (i = 0; i < est_fqlist->n; i++)
- printf("%d%s", MSR2MHZ(est_fqlist->table[i], bus_clock),
- i < est_fqlist->n - 1 ? ", " : " MHz\n");
+ printf("%d%s", est_fqlist->table[i].mhz, i < est_fqlist->n - 1
+ ? ", " : " MHz\n");
cpu_setperf = est_setperf;
setperf_prio = 3;
@@ -1083,7 +1201,8 @@ est_setperf(int level)
msr = rdmsr(MSR_PERF_CTL);
msr &= ~0xffffULL;
- msr |= est_fqlist->table[i];
+ msr |= est_fqlist->table[i].ctrl;
+
wrmsr(MSR_PERF_CTL, msr);
- cpuspeed = MSR2MHZ(est_fqlist->table[i], bus_clock);
+ cpuspeed = est_fqlist->table[i].mhz;
}