summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2003-12-20 18:23:19 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2003-12-20 18:23:19 +0000
commit5343ef6c9154245825c0d18aae6d26059b7dce1b (patch)
tree3882313f2f814cf5afc805b1c0354396c6cdda90 /sys
parent0412a2809fcc5d5122b8c46adf2ab135090da50a (diff)
add pentium 4 thermal control circuit (tcc) driver. can use this to
limit power consumption with the hw.setperf sysctl. tested by beck and grange
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/i386/conf/files.i3863
-rw-r--r--sys/arch/i386/i386/machdep.c6
-rw-r--r--sys/arch/i386/i386/p4tcc.c133
-rw-r--r--sys/arch/i386/include/cpu.h8
4 files changed, 146 insertions, 4 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index 0b11c68a493..2a2b58a6abc 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.110 2003/12/18 23:46:19 tedu Exp $
+# $OpenBSD: files.i386,v 1.111 2003/12/20 18:23:17 tedu Exp $
# $NetBSD: files.i386,v 1.73 1996/05/07 00:58:36 thorpej Exp $
#
# new style config file for i386 architecture
@@ -31,6 +31,7 @@ file arch/i386/i386/i686_mem.c mtrr
file arch/i386/i386/k6_mem.c mtrr
file arch/i386/i386/microtime.s
file arch/i386/i386/ns_cksum.c ns
+file arch/i386/i386/p4tcc.c !small_kernel & i686_cpu
file arch/i386/i386/pmap.c
file arch/i386/i386/process_machdep.c
file arch/i386/i386/procfs_machdep.c procfs
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 48a79a4b5a8..20c64b4dd6b 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.256 2003/12/19 22:42:13 tedu Exp $ */
+/* $OpenBSD: machdep.c,v 1.257 2003/12/20 18:23:18 tedu Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -1659,7 +1659,9 @@ intel686_cpu_setup(cpu_device, model, step)
else
printf("%s: Enhanced SpeedStep disabled by BIOS\n",
cpu_device);
- }
+ } else if ((cpu_feature & (CPUID_ACPI | CPUID_TM)) ==
+ (CPUID_ACPI | CPUID_TM))
+ p4tcc_init(model, step);
#endif
}
diff --git a/sys/arch/i386/i386/p4tcc.c b/sys/arch/i386/i386/p4tcc.c
new file mode 100644
index 00000000000..1fc96f81423
--- /dev/null
+++ b/sys/arch/i386/i386/p4tcc.c
@@ -0,0 +1,133 @@
+/* $OpenBSD: p4tcc.c,v 1.1 2003/12/20 18:23:18 tedu Exp $ */
+/*
+ * Copyright (c) 2003 Ted Unangst
+ * 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.
+ *
+ * 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.
+ */
+/*
+ * Restrict power consumption by using thermal control circuit.
+ * This operates independently of speedstep.
+ * Found on Pentium 4 and later models (feature TM).
+ *
+ * References:
+ * Intel Developer's manual v.3 #245472-012
+ *
+ * On some models, the cpu can hang if it's running at a slow speed.
+ * Workarounds included below.
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+
+static struct {
+ u_short level;
+ u_short reg;
+} tcc[] = {
+ { 88, 0 },
+ { 75, 7 },
+ { 63, 6 },
+ { 50, 5 },
+ { 38, 4 },
+ { 25, 3 },
+ { 13, 2 },
+ { 0, 1 }
+};
+
+#define TCC_LEVELS sizeof(tcc) / sizeof(tcc[0])
+
+extern int (*cpu_cpuspeed)(void *, size_t *, void *, size_t);
+extern int (*cpu_setperf)(void *, size_t *, void *, size_t);
+
+void
+p4tcc_init(int model, int step)
+{
+
+ switch (step) {
+ case 0x22: /* errata O50 P44 and Z21 */
+ case 0x24:
+ case 0x25:
+ case 0x27:
+ case 0x29:
+ /* hang with 12.5 */
+ tcc[TCC_LEVELS - 1].reg = 2;
+ break;
+ case 0x07: /* errata N44 and P18 */
+ case 0x0a:
+ case 0x12:
+ case 0x13:
+ /* hang at 12.5 and 25 */
+ tcc[TCC_LEVELS - 1].reg = 3;
+ tcc[TCC_LEVELS - 2].reg = 3;
+ break;
+ default:
+ break;
+ }
+
+ cpu_setperf = p4tcc_setperf;
+
+}
+
+#if 0
+/* possible? not sure */
+int
+p4tcc_cpuspeed(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
+{
+
+ return EINVAL;
+}
+#endif
+
+int
+p4tcc_setperf(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
+{
+ int i, error;
+ uint64_t msreg;
+ static uint level = 100;
+ uint olevel;
+
+ olevel = level;
+ if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)))
+ return (error);
+ if (level == olevel)
+ return (0);
+
+ if (level > 100)
+ level = 100;
+
+ for (i = 0; i < TCC_LEVELS; i++) {
+ if (level >= tcc[i].level)
+ break;
+ }
+
+ msreg = rdmsr(MSR_THERM_CONTROL);
+ msreg &= ~0x1e; /* bit 0 reserved */
+ if (tcc[i].reg != 0) /* enable it */
+ msreg |= tcc[i].reg << 1 | 1 << 4;
+ wrmsr(MSR_THERM_CONTROL, msreg);
+
+ return (0);
+}
diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h
index 3a6fbcb88ee..482815dd27b 100644
--- a/sys/arch/i386/include/cpu.h
+++ b/sys/arch/i386/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.53 2003/12/19 22:42:13 tedu Exp $ */
+/* $OpenBSD: cpu.h,v 1.54 2003/12/20 18:23:18 tedu Exp $ */
/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */
/*-
@@ -197,6 +197,12 @@ int longrun_cpuspeed(void *, size_t *, void *, size_t);
int longrun_setperf(void *, size_t *, void *, size_t);
#endif
+/* p4tcc.c */
+#if !defined(SMALL_KERNEL) && defined(I686_CPU)
+void p4tcc_init(int, int);
+int p4tcc_setperf(void *, size_t *, void *, size_t);
+#endif
+
/* npx.c */
void npxdrop(void);
void npxsave(void);