Subject: Driver for Enhanced SpeedStep
To: None <port-i386@netbsd.org>
From: Michael Eriksson <mer@klockrike.net>
List: port-i386
Date: 11/02/2003 23:25:37
--CdtdLcLzwN
Content-Type: text/plain; charset=us-ascii
Content-Description: message body text
Content-Transfer-Encoding: 7bit
Tjupp!
I have written a driver for Intel's new CPU frequency control
mechanism, Enhanced SpeedStep (EST), which is used in Pentium M
processors.
I have appended the patches, and welcome any feedback. The patches are
against 1.6X, but I think they should apply easily to the latest
-current.
The frequency control is done with sysctl, which gets these new
variables (the values are from my Compaq Presario X1007EA):
machdep.est_target_frequency = 800
machdep.est_current_frequency = 800
machdep.est_min_frequency = 600
machdep.est_max_frequency = 1400
Only machdep.est_target_frequency is writable. The current frequency
may be lower than the target frequency if the thermal monitor is
throttling the CPU to avoid overheating it.
To use the code:
- Apply the patches.
- Add the line below to the kernel config and rebuild.
options EST # Enhanced SpeedStep (Pentium M)
- Do "make includes" in /sys/arch/i386/include to install the new
sysctl list, and rebuild and install sysctl(8).
Some comments:
* Intel processors now put feature flags also in %ecx, including the
flag for Enhanced SpeedStep. Arguably, cpu_feature should be made an
u_int64_t, but for now I've added a cpu_feature2 variable for the %ecx
flags.
* I've made some additions to the boot-time CPU identification
printouts. This is the diff for my laptop:
cpu0 at mainbus0: (uniprocessor)
cpu0: Intel Pentium M (Banias) (686-class), 1395.54 MHz, id 0x695
cpu0: features a7e9f9bf<FPU,VME,DE,PSE,TSC,MSR,MCE,CX8,SEP,MTRR>
cpu0: features a7e9f9bf<PGE,MCA,CMOV,PAT,CFLUSH,DS,ACPI,MMX>
cpu0: features a7e9f9bf<FXSR,SSE,SSE2,TM,SBF>
+cpu0: features2 180<TM2,EST>
+cpu0: "Intel(R) Pentium(R) M processor 1400MHz"
+cpu0: using thermal monitor 2
+cpu0: Enhanced SpeedStep running at 1400 MHz (1484 mV)
+cpu0: available speeds: 1400, 1200, 1000, 800, 600 MHz
Note the new features2 flags. The kernel also prints out the processor
brand string, as reported by the CPUID instruction, and the current
thermal monitor mode if the processor has that feature.
* The EST driver uses the brand string for CPU identification, so
there is a kernel-wide global variable for it.
* The CPU brand string is also available with sysctl:
machdep.cpu_brand = Intel(R) Pentium(R) M processor 1400MHz
/Micke
--CdtdLcLzwN
Content-Type: text/plain
Content-Description: Enhanced SpeedStep diffs
Content-Disposition: inline;
filename="diff"
Content-Transfer-Encoding: 7bit
Index: sys/arch/i386/conf/files.i386
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/files.i386,v
retrieving revision 1.242
diff -u -r1.242 files.i386
--- sys/arch/i386/conf/files.i386 2003/07/27 01:19:26 1.242
+++ sys/arch/i386/conf/files.i386 2003/11/02 11:27:02
@@ -64,6 +64,9 @@
defparam opt_beep.h BEEP_ONHALT_COUNT
defparam opt_beep.h BEEP_ONHALT_PITCH BEEP_ONHALT_PERIOD
+# Enhanced SpeedStep
+defflag EST
+
file arch/i386/i386/autoconf.c
file arch/i386/i386/db_dbgreg.S ddb | kstack_check_dr0
file arch/i386/i386/db_disasm.c ddb
@@ -467,5 +470,8 @@
device vesatext
attach vesatext at vesabios
file arch/i386/bios/vesa_text.c vesatext
+
+# Enhanced SpeedStep
+file arch/i386/i386/est.c est
include "arch/i386/conf/majors.i386"
Index: sys/arch/i386/i386/cpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/cpu.c,v
retrieving revision 1.15
diff -u -r1.15 cpu.c
--- sys/arch/i386/i386/cpu.c 2003/07/14 22:13:10 1.15
+++ sys/arch/i386/i386/cpu.c 2003/11/02 11:27:05
@@ -578,6 +578,7 @@
cpu_probe_features(ci);
cpu_feature &= ci->ci_feature_flags;
+ cpu_feature2 &= ci->ci_feature2_flags;
#ifdef DEBUG
if (ci->ci_flags & CPUF_PRESENT)
--- /dev/null 2003-09-02 21:07:04.000000000 +0200
+++ sys/arch/i386/i386/est.c 2003-11-02 12:15:06.000000000 +0100
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2003 Michael Eriksson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * This is a driver for Intel's Enhanced SpeedStep, as implemented in
+ * Pentium M processors.
+ *
+ * Reference documentation:
+ *
+ * - IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+ * System Programming Guide.
+ * Section 13.14, Enhanced Intel SpeedStep technology.
+ * Table B-2, MSRs in Pentium M Processors.
+ * http://www.intel.com/design/pentium4/manuals/245472.htm
+ *
+ * - Intel Pentium M Processor Datasheet.
+ * Table 5, Voltage and Current Specifications.
+ * http://www.intel.com/design/mobile/datashts/252612.htm
+ *
+ * - Linux cpufreq patches, speedstep-centrino.c.
+ * Encoding of MSR_PERF_CTL and MSR_PERF_STATUS.
+ * http://www.codemonkey.org.uk/projects/cpufreq/cpufreq-2.4.22-pre6-1.gz
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <machine/cpu.h>
+#include <machine/specialreg.h>
+
+
+struct fq_info {
+ int mhz;
+ int mv;
+};
+
+/* Ultra Low Voltage Intel Pentium M processor 900 MHz */
+static const struct fq_info pentium_m_900[] = {
+ { 900, 1004 },
+ { 800, 988 },
+ { 600, 844 },
+};
+
+/* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */
+static const struct fq_info pentium_m_1000[] = {
+ { 1000, 1004 },
+ { 900, 988 },
+ { 800, 972 },
+ { 600, 844 },
+};
+
+/* Low Voltage Intel Pentium M processor 1.10 GHz */
+static const struct fq_info pentium_m_1100[] = {
+ { 1100, 1180 },
+ { 1000, 1164 },
+ { 900, 1100 },
+ { 800, 1020 },
+ { 600, 956 },
+};
+
+/* Low Voltage Intel Pentium M processor 1.20 GHz */
+static const struct fq_info pentium_m_1200[] = {
+ { 1200, 1180 },
+ { 1100, 1164 },
+ { 1000, 1100 },
+ { 900, 1020 },
+ { 800, 1004 },
+ { 600, 956 },
+};
+
+/* Intel Pentium M processor 1.30 GHz */
+static const struct fq_info pentium_m_1300[] = {
+ { 1300, 1388 },
+ { 1200, 1356 },
+ { 1000, 1292 },
+ { 800, 1260 },
+ { 600, 956 },
+};
+
+/* Intel Pentium M processor 1.40 GHz */
+static const struct fq_info pentium_m_1400[] = {
+ { 1400, 1484 },
+ { 1200, 1436 },
+ { 1000, 1308 },
+ { 800, 1180 },
+ { 600, 956 }
+};
+
+/* Intel Pentium M processor 1.50 GHz */
+static const struct fq_info pentium_m_1500[] = {
+ { 1500, 1484 },
+ { 1400, 1452 },
+ { 1200, 1356 },
+ { 1000, 1228 },
+ { 800, 1116 },
+ { 600, 956 }
+};
+
+/* Intel Pentium M processor 1.60 GHz */
+static const struct fq_info pentium_m_1600[] = {
+ { 1600, 1484 },
+ { 1400, 1420 },
+ { 1200, 1276 },
+ { 1000, 1164 },
+ { 800, 1036 },
+ { 600, 956 }
+};
+
+/* Intel Pentium M processor 1.70 GHz */
+static const struct fq_info pentium_m_1700[] = {
+ { 1700, 1484 },
+ { 1400, 1308 },
+ { 1200, 1228 },
+ { 1000, 1116 },
+ { 800, 1004 },
+ { 600, 956 }
+};
+
+
+struct fqlist {
+ const char *brand_tag;
+ int n;
+ const struct fq_info *table;
+};
+
+static const struct fqlist pentium_m[] = {
+#define ENTRY(s, v) { s, sizeof(v) / sizeof((v)[0]), v }
+ ENTRY(" 900", pentium_m_900),
+ ENTRY("1000", pentium_m_1000),
+ ENTRY("1100", pentium_m_1100),
+ ENTRY("1200", pentium_m_1200),
+ ENTRY("1300", pentium_m_1300),
+ ENTRY("1400", pentium_m_1400),
+ ENTRY("1500", pentium_m_1500),
+ ENTRY("1600", pentium_m_1600),
+ ENTRY("1700", pentium_m_1700),
+#undef ENTRY
+};
+
+
+struct est_cpu {
+ const char *brand_prefix;
+ const char *brand_suffix;
+ int n;
+ const struct fqlist *list;
+};
+
+static const struct est_cpu est_cpus[] = {
+ {
+ "Intel(R) Pentium(R) M processor ", "MHz",
+ (sizeof(pentium_m) / sizeof(pentium_m[0])),
+ pentium_m
+ },
+};
+
+#define NCPUS (sizeof(est_cpus) / sizeof(est_cpus[0]))
+
+
+#define MSRVALUE(mhz, mv) ((((mhz) / 100) << 8) | (((mv) - 700) / 16))
+#define MSR2MHZ(msr) ((((int) (msr) >> 8) & 0xff) * 100)
+#define MSR2MV(msr) (((int) (msr) & 0xff) * 16 + 700)
+
+static const struct fqlist *est_fqlist;
+
+
+void
+est_init(ci)
+ struct cpu_info *ci;
+{
+ int i, j, n, mhz, mv;
+ const struct est_cpu *cpu;
+ u_int64_t msr;
+ char *tag;
+ const struct fqlist *fql;
+
+ if ((cpu_feature2 & CPUID2_EST) == 0)
+ return;
+
+ msr = rdmsr(MSR_PERF_STATUS);
+ mhz = MSR2MHZ(msr);
+ mv = MSR2MV(msr);
+ printf("%s: Enhanced SpeedStep running at %d MHz (%d mV)\n",
+ ci->ci_dev->dv_xname, mhz, mv);
+
+ /*
+ * Look for a CPU matching cpu_brand_string.
+ */
+ for (i = 0; est_fqlist == NULL && i < NCPUS; i++) {
+ cpu = &est_cpus[i];
+ n = strlen(cpu->brand_prefix);
+ if (strncmp(cpu->brand_prefix, cpu_brand_string, n) != 0)
+ continue;
+ tag = cpu_brand_string + n;
+ for (j = 0; j < cpu->n; j++) {
+ fql = &cpu->list[j];
+ n = strlen(fql->brand_tag);
+ if (!strncmp(fql->brand_tag, tag, n) &&
+ !strcmp(cpu->brand_suffix, tag + n)) {
+ est_fqlist = fql;
+ break;
+ }
+ }
+ }
+ if (est_fqlist == NULL) {
+ printf("%s: unknown EST cpu\n", ci->ci_dev->dv_xname);
+ return;
+ }
+
+ /*
+ * Check that the current operating point is in our list.
+ */
+ for (i = est_fqlist->n - 1; i >= 0; i--)
+ if (est_fqlist->table[i].mhz == mhz &&
+ est_fqlist->table[i].mv == mv)
+ break;
+ if (i < 0) {
+ printf("%s: EST operating point not in table\n",
+ ci->ci_dev->dv_xname);
+ return;
+ }
+
+ /*
+ * OK, set the flag and tell the user the available frequencies.
+ */
+ i386_has_est = 1;
+ printf("%s: available speeds: ", ci->ci_dev->dv_xname);
+ for (i = 0; i < est_fqlist->n; i++)
+ printf("%d%s", est_fqlist->table[i].mhz,
+ i < est_fqlist->n - 1 ? ", " : " MHz\n");
+}
+
+
+int
+est_get_target_fq()
+{
+ return MSR2MHZ(rdmsr(MSR_PERF_CTL));
+}
+
+
+int
+est_set_target_fq(fq)
+ int fq;
+{
+ int i;
+ u_int64_t msr;
+
+ if (est_fqlist == NULL)
+ return EOPNOTSUPP;
+
+ for (i = est_fqlist->n - 1; i > 0; i--)
+ if (est_fqlist->table[i].mhz >= fq)
+ break;
+ fq = est_fqlist->table[i].mhz;
+ msr = (rdmsr(MSR_PERF_CTL) & ~0xffffULL) |
+ MSRVALUE(est_fqlist->table[i].mhz, est_fqlist->table[i].mv);
+ wrmsr(MSR_PERF_CTL, msr);
+
+ return 0;
+}
+
+
+int
+est_get_current_fq()
+{
+ return MSR2MHZ(rdmsr(MSR_PERF_STATUS));
+}
+
+
+int
+est_get_min_fq()
+{
+ if (est_fqlist == NULL)
+ return 0;
+ return est_fqlist->table[est_fqlist->n - 1].mhz;
+}
+
+
+int
+est_get_max_fq()
+{
+ if (est_fqlist == NULL)
+ return 0;
+ return est_fqlist->table[0].mhz;
+}
Index: sys/arch/i386/i386/identcpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/identcpu.c,v
retrieving revision 1.5
diff -u -r1.5 identcpu.c
--- sys/arch/i386/i386/identcpu.c 2003/07/14 22:13:10 1.5
+++ sys/arch/i386/i386/identcpu.c 2003/11/02 11:27:08
@@ -40,6 +40,7 @@
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.5 2003/07/14 22:13:10 lukem Exp $");
#include "opt_cputype.h"
+#include "opt_est.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -125,6 +126,7 @@
};
u_int cpu_serial[3];
+char cpu_brand_string[49];
static char amd_brand_name[48];
void cyrix6x86_cpu_setup __P((struct cpu_info *));
@@ -683,6 +685,7 @@
int iterations, i, j;
u_int8_t desc;
u_int32_t dummy1, dummy2, miscbytes;
+ u_int32_t brand[12];
if (ci->ci_cpuid_level < 0)
return;
@@ -693,10 +696,22 @@
ci->ci_vendor[1]);
ci->ci_vendor[3] = 0;
+ CPUID(0x80000000, brand[0], brand[1], brand[2], brand[3]);
+ if (brand[0] >= 0x80000004) {
+ CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
+ CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
+ CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
+ for (i = 0; i < 48; i++)
+ if (((char *) brand)[i] != ' ')
+ break;
+ memcpy(cpu_brand_string, ((char *) brand) + i, 48 - i);
+ }
+
if (ci->ci_cpuid_level < 1)
return;
- CPUID(1, ci->ci_signature, miscbytes, dummy1, ci->ci_feature_flags);
+ CPUID(1, ci->ci_signature, miscbytes, ci->ci_feature2_flags,
+ ci->ci_feature_flags);
/* Brand is low order 8 bits of ebx */
ci->ci_brand_id = miscbytes & 0xff;
@@ -792,7 +807,6 @@
{
u_int32_t lfunc;
u_int32_t descs[4];
- u_int32_t brand[12];
char *p;
int i;
@@ -806,15 +820,11 @@
ci->ci_feature_flags |= descs[3];
}
- if (lfunc < 0x80000004)
+ if (*cpu_brand_string == '\0')
return;
- CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
- CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
- CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
-
for (i = 1; i < sizeof(amd_brand) / sizeof(amd_brand[0]); i++)
- if ((p = strstr((char *)brand, amd_brand[i])) != NULL) {
+ if ((p = strstr(cpu_brand_string, amd_brand[i])) != NULL) {
ci->ci_brand_id = i;
strcpy(amd_brand_name, p);
break;
@@ -1202,8 +1212,31 @@
}
}
+ if (ci->ci_feature2_flags) {
+ bitmask_snprintf(ci->ci_feature2_flags,
+ CPUID2_FLAGS, buf, sizeof(buf));
+ printf("%s: features2 %s\n", cpuname, buf);
+ }
+
+ if (*cpu_brand_string != '\0')
+ printf("%s: \"%s\"\n", cpuname, cpu_brand_string);
+
x86_print_cacheinfo(ci);
+ if (cpu_feature & CPUID_TM) {
+ if (rdmsr(MSR_MISC_ENABLE) & (1 << 3)) {
+ if ((cpu_feature2 & CPUID2_TM2) &&
+ (rdmsr(MSR_THERM2_CTL) & (1 << 16)))
+ printf("%s: using thermal monitor 2\n",
+ cpuname);
+ else
+ printf("%s: using thermal monitor 1\n",
+ cpuname);
+ } else
+ printf("%s: running without thermal monitor!\n",
+ cpuname);
+ }
+
if (ci->ci_cpuid_level >= 3 && (ci->ci_feature_flags & CPUID_PN)) {
printf("%s: serial number %04X-%04X-%04X-%04X-%04X-%04X\n",
cpuname,
@@ -1313,4 +1346,15 @@
} else
i386_use_fxsave = 0;
#endif /* I686_CPU */
+
+#ifdef EST
+ if (cpu_feature2 & CPUID2_EST) {
+ if (rdmsr(MSR_MISC_ENABLE) & (1 << 16))
+ est_init(ci);
+ else
+ printf("%s: Enhanced SpeedStep disabled by BIOS\n",
+ cpuname);
+ }
+#endif /* EST */
+
}
Index: sys/arch/i386/i386/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.533
diff -u -r1.533 machdep.c
--- sys/arch/i386/i386/machdep.c 2003/08/24 17:52:30 1.533
+++ sys/arch/i386/i386/machdep.c 2003/11/02 11:27:12
@@ -88,6 +88,7 @@
#include "opt_mtrr.h"
#include "opt_multiprocessor.h"
#include "opt_beep.h"
+#include "opt_est.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -225,6 +226,7 @@
int dumpmem_low;
int dumpmem_high;
unsigned int cpu_feature;
+unsigned int cpu_feature2;
int cpu_class;
int i386_fpu_present;
int i386_fpu_exception;
@@ -233,6 +235,7 @@
int i386_use_fxsave;
int i386_has_sse;
int i386_has_sse2;
+int i386_has_est;
int tmx86_has_longrun;
@@ -505,6 +508,9 @@
dev_t consdev;
struct btinfo_bootpath *bibp;
int error, mode;
+#ifdef EST
+ int fq, oldfq;
+#endif
/* all sysctl names at this level are terminal */
if (namelen != 1)
@@ -576,6 +582,36 @@
return (EOPNOTSUPP);
tmx86_get_longrun_status_all();
return (sysctl_rdint(oldp, oldlenp, newp, crusoe_percentage));
+#ifdef EST
+ case CPU_EST_TARG_FREQUENCY:
+ if (!i386_has_est)
+ return (EOPNOTSUPP);
+ fq = oldfq = est_get_target_fq();
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &fq);
+ if (error)
+ return (error);
+ if (fq != oldfq)
+ error = est_set_target_fq(fq);
+ return (error);
+ case CPU_EST_CURR_FREQUENCY:
+ if (!i386_has_est)
+ return (EOPNOTSUPP);
+ return (sysctl_rdint(oldp, oldlenp, newp,
+ est_get_current_fq()));
+ case CPU_EST_MIN_FREQUENCY:
+ if (!i386_has_est)
+ return (EOPNOTSUPP);
+ return (sysctl_rdint(oldp, oldlenp, newp, est_get_min_fq()));
+ case CPU_EST_MAX_FREQUENCY:
+ if (!i386_has_est)
+ return (EOPNOTSUPP);
+ return (sysctl_rdint(oldp, oldlenp, newp, est_get_max_fq()));
+#endif
+ case CPU_BRAND:
+ if (*cpu_brand_string == '\0')
+ return (EOPNOTSUPP);
+ return (sysctl_rdstring(oldp, oldlenp, newp,
+ cpu_brand_string));
default:
return (EOPNOTSUPP);
}
@@ -1514,6 +1550,7 @@
cpu_probe_features(&cpu_info_primary);
cpu_feature = cpu_info_primary.ci_feature_flags;
+ cpu_feature2 = cpu_info_primary.ci_feature2_flags;
lwp0.l_addr = proc0paddr;
cpu_info_primary.ci_curpcb = &lwp0.l_addr->u_pcb;
Index: sys/arch/i386/include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/include/cpu.h,v
retrieving revision 1.103
diff -u -r1.103 cpu.h
--- sys/arch/i386/include/cpu.h 2003/08/07 16:27:58 1.103
+++ sys/arch/i386/include/cpu.h 2003/11/02 11:27:15
@@ -104,7 +104,8 @@
int32_t ci_cpuid_level;
u_int32_t ci_signature; /* X86 cpuid type */
- u_int32_t ci_feature_flags;/* X86 CPUID feature bits */
+ u_int32_t ci_feature_flags;/* X86 %edx CPUID feature bits */
+ u_int32_t ci_feature2_flags;/* X86 %ecx CPUID feature bits */
u_int32_t ci_cpu_class; /* CPU class */
u_int32_t ci_brand_id; /* Intel brand id */
u_int32_t ci_vendor[4]; /* vendor string */
@@ -325,14 +326,17 @@
extern int biosbasemem;
extern int biosextmem;
extern unsigned int cpu_feature;
+extern unsigned int cpu_feature2;
extern int cpu;
extern int cpu_class;
+extern char cpu_brand_string[];
extern const struct cpu_nocpuid_nameclass i386_nocpuid_cpus[];
extern const struct cpu_cpuid_nameclass i386_cpuid_cpus[];
extern int i386_use_fxsave;
extern int i386_has_sse;
extern int i386_has_sse2;
+extern int i386_has_est;
/* machdep.c */
void dumpconf __P((void));
@@ -426,6 +430,14 @@
void x86_bus_space_init __P((void));
void x86_bus_space_mallocok __P((void));
+/* est.c */
+void est_init __P((struct cpu_info *));
+int est_get_target_fq __P((void));
+int est_set_target_fq __P((int));
+int est_get_current_fq __P((void));
+int est_get_min_fq __P((void));
+int est_get_max_fq __P((void));
+
#endif /* _KERNEL */
#include <machine/psl.h>
@@ -453,7 +465,12 @@
#define CPU_TMLR_FREQUENCY 12 /* int: current frequency */
#define CPU_TMLR_VOLTAGE 13 /* int: curret voltage */
#define CPU_TMLR_PERCENTAGE 14 /* int: current clock percentage */
-#define CPU_MAXID 15 /* number of valid machdep ids */
+#define CPU_EST_TARG_FREQUENCY 15 /* int: target frequency */
+#define CPU_EST_CURR_FREQUENCY 16 /* int: current frequency */
+#define CPU_EST_MIN_FREQUENCY 17 /* int: min frequency */
+#define CPU_EST_MAX_FREQUENCY 18 /* int: max frequency */
+#define CPU_BRAND 19 /* string: cpu brand */
+#define CPU_MAXID 20 /* number of valid machdep ids */
#define CTL_MACHDEP_NAMES { \
{ 0, 0 }, \
@@ -471,6 +488,11 @@
{ "tm_longrun_frequency", CTLTYPE_INT }, \
{ "tm_longrun_voltage", CTLTYPE_INT }, \
{ "tm_longrun_percentage", CTLTYPE_INT }, \
+ { "est_target_frequency", CTLTYPE_INT }, \
+ { "est_current_frequency", CTLTYPE_INT }, \
+ { "est_min_frequency", CTLTYPE_INT }, \
+ { "est_max_frequency", CTLTYPE_INT }, \
+ { "cpu_brand", CTLTYPE_STRING }, \
}
Index: sys/arch/x86/include/specialreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/specialreg.h,v
retrieving revision 1.3
diff -u -r1.3 specialreg.h
--- sys/arch/x86/include/specialreg.h 2003/08/07 16:30:33 1.3
+++ sys/arch/x86/include/specialreg.h 2003/11/02 11:27:19
@@ -84,7 +84,7 @@
#define CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
/*
- * CPUID "features" bits:
+ * CPUID "features" bits in %edx
*/
#define CPUID_FPU 0x00000001 /* processor has an FPU? */
@@ -143,6 +143,16 @@
#define CPUID_EXT_FLAGS3 "\20\31FXSR\32SSE\33SSE2\34B27\35B28\36LONG" \
"\0373DNOW2\0403DNOW"
+/*
+ * CPUID "features" bits in %ecx
+ */
+
+#define CPUID2_TM2 0x00000080 /* Thermal Monitor 2 */
+#define CPUID2_EST 0x00000100 /* Enhanced SpeedStep Technology */
+#define CPUID2_CID 0x00000400 /* Context ID */
+
+#define CPUID2_FLAGS "\20\10TM2\11EST\13CID"
+
#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15)
#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15)
#define CPUID2STEPPING(cpuid) ((cpuid) & 15)
@@ -187,6 +197,13 @@
#define MSR_MCG_CTL 0x17b
#define MSR_EVNTSEL0 0x186
#define MSR_EVNTSEL1 0x187
+#define MSR_PERF_STATUS 0x198 /* Pentium M */
+#define MSR_PERF_CTL 0x199 /* Pentium M */
+#define MSR_THERM_CONTROL 0x19a
+#define MSR_THERM_INTERRUPT 0x19b
+#define MSR_THERM_STATUS 0x19c
+#define MSR_THERM2_CTL 0x19d /* Pentium M */
+#define MSR_MISC_ENABLE 0x1a0
#define MSR_DEBUGCTLMSR 0x1d9
#define MSR_LASTBRANCHFROMIP 0x1db
#define MSR_LASTBRANCHTOIP 0x1dc
--CdtdLcLzwN--