diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2003-12-20 18:23:19 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2003-12-20 18:23:19 +0000 |
commit | 5343ef6c9154245825c0d18aae6d26059b7dce1b (patch) | |
tree | 3882313f2f814cf5afc805b1c0354396c6cdda90 /sys | |
parent | 0412a2809fcc5d5122b8c46adf2ab135090da50a (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.i386 | 3 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 6 | ||||
-rw-r--r-- | sys/arch/i386/i386/p4tcc.c | 133 | ||||
-rw-r--r-- | sys/arch/i386/include/cpu.h | 8 |
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); |