diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2007-05-29 21:01:57 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2007-05-29 21:01:57 +0000 |
commit | ffbfea5690bb3c06fe441fe0404d80e41506c942 (patch) | |
tree | a2050d63dd440131182dbc3d977c815d8c011706 /sys/arch/i386 | |
parent | 55187efb81b68b264fb98d8164e670360a84266d (diff) |
add support for core cpu temperature sensors.
from a diff by pierre riteau, but updated to look like the amd64 version
ok deraadt
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 66 | ||||
-rw-r--r-- | sys/arch/i386/i386/mainbus.c | 6 | ||||
-rw-r--r-- | sys/arch/i386/include/cpu.h | 8 | ||||
-rw-r--r-- | sys/arch/i386/include/specialreg.h | 6 |
4 files changed, 81 insertions, 5 deletions
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index f38be5e30e3..75a4c3bc0ac 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.397 2007/05/29 21:00:50 jason Exp $ */ +/* $OpenBSD: machdep.c,v 1.398 2007/05/29 21:01:56 tedu Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -97,6 +97,7 @@ #include <sys/syscallargs.h> #include <sys/core.h> #include <sys/kcore.h> +#include <sys/sensors.h> #ifdef SYSVMSG #include <sys/msg.h> #endif @@ -244,6 +245,8 @@ int bus_clock; void (*setperf_setup)(struct cpu_info *); int setperf_prio = 0; /* for concurrent handlers */ +void (*cpusensors_setup)(struct cpu_info *); + void (*delay_func)(int) = i8254_delay; void (*initclock_func)(void) = i8254_initclocks; @@ -322,10 +325,12 @@ void cyrix3_cpu_setup(struct cpu_info *); void cyrix6x86_cpu_setup(struct cpu_info *); void natsem6x86_cpu_setup(struct cpu_info *); void intel586_cpu_setup(struct cpu_info *); +void intel686_cpusensors_setup(struct cpu_info *); void intel686_setperf_setup(struct cpu_info *); void intel686_common_cpu_setup(struct cpu_info *); void intel686_cpu_setup(struct cpu_info *); void intel686_p4_cpu_setup(struct cpu_info *); +void intelcore_update_sensor(void *); void tm86_cpu_setup(struct cpu_info *); char * intel686_cpu_name(int); char * cyrix3_cpu_name(int, int); @@ -1317,6 +1322,64 @@ amd_family6_setup(struct cpu_info *ci) } #if !defined(SMALL_KERNEL) && defined(I686_CPU) +/* + * Temperature read on the CPU is relative to the maximum + * temperature supported by the CPU, Tj(Max). + * Poorly documented, refer to: + * http://softwarecommunity.intel.com/isn/Community/ + * en-US/forums/thread/30228638.aspx + * Basically, depending on a bit in one msr, the max is either 85 or 100. + * Then we subtract the temperature portion of thermal status from + * max to get current temperature. + */ +void +intelcore_update_sensor(void *args) +{ + struct cpu_info *ci = (struct cpu_info *) args; + u_int64_t msr; + int max = 100; + + if (rdmsr(MSR_TEMPERATURE_TARGET) & MSR_TEMPERATURE_TARGET_LOW_BIT) + max = 85; + + msr = rdmsr(MSR_THERM_STATUS); + if (msr & MSR_THERM_STATUS_VALID_BIT) { + ci->ci_sensor.value = max - MSR_THERM_STATUS_TEMP(msr); + /* micro degrees */ + ci->ci_sensor.value *= 1000000; + /* kelvin */ + ci->ci_sensor.value += 273150000; + ci->ci_sensor.flags &= ~SENSOR_FINVALID; + } else { + ci->ci_sensor.value = 0; + ci->ci_sensor.flags |= SENSOR_FINVALID; + } +} + +void +intel686_cpusensors_setup(struct cpu_info *ci) +{ + u_int regs[4]; + + if (cpuid_level < 0x06) + return; + + /* CPUID.06H.EAX[0] = 1 tells us if we have on-die sensor */ + cpuid(0x06, regs); + if ((regs[0] & 0x01) != 1) + return; + + /* Setup the sensors structures */ + strlcpy(ci->ci_sensordev.xname, ci->ci_dev.dv_xname, + sizeof(ci->ci_sensordev.xname)); + ci->ci_sensor.type = SENSOR_TEMP; + sensor_task_register(ci, intelcore_update_sensor, 5); + sensor_attach(&ci->ci_sensordev, &ci->ci_sensor); + sensordev_install(&ci->ci_sensordev); +} +#endif + +#if !defined(SMALL_KERNEL) && defined(I686_CPU) void intel686_setperf_setup(struct cpu_info *ci) { @@ -1341,6 +1404,7 @@ intel686_common_cpu_setup(struct cpu_info *ci) #if !defined(SMALL_KERNEL) && defined(I686_CPU) setperf_setup = intel686_setperf_setup; + cpusensors_setup = intel686_cpusensors_setup; { extern void (*pagezero)(void *, size_t); extern void sse2_pagezero(void *, size_t); diff --git a/sys/arch/i386/i386/mainbus.c b/sys/arch/i386/i386/mainbus.c index b8700725270..c5b8dc46439 100644 --- a/sys/arch/i386/i386/mainbus.c +++ b/sys/arch/i386/i386/mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mainbus.c,v 1.37 2007/05/09 23:13:16 todd Exp $ */ +/* $OpenBSD: mainbus.c,v 1.38 2007/05/29 21:01:56 tedu Exp $ */ /* $NetBSD: mainbus.c,v 1.21 1997/06/06 23:14:20 thorpej Exp $ */ /* @@ -143,6 +143,7 @@ mainbus_attach(struct device *parent, struct device *self, void *aux) { union mainbus_attach_args mba; extern void (*setperf_setup)(struct cpu_info *); + extern void (*cpusensors_setup)(struct cpu_info *); printf("\n"); @@ -211,6 +212,9 @@ mainbus_attach(struct device *parent, struct device *self, void *aux) mp_setperf_init(); #endif + if (cpusensors_setup != NULL) + cpusensors_setup(&cpu_info_primary); + #if NVESABIOS > 0 if (vbeprobe()) { mba.mba_busname = "vesabios"; diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h index e74c7ace152..7f4dfae2fc8 100644 --- a/sys/arch/i386/include/cpu.h +++ b/sys/arch/i386/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.93 2007/05/26 22:09:17 weingart Exp $ */ +/* $OpenBSD: cpu.h,v 1.94 2007/05/29 21:01:56 tedu Exp $ */ /* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ /*- @@ -67,9 +67,11 @@ #include <sys/device.h> #include <sys/lock.h> /* will also get LOCKDEBUG */ #include <sys/sched.h> +#include <sys/sensors.h> struct intrsource; +#ifdef _KERNEL /* XXX stuff to move to cpuvar.h later */ struct cpu_info { struct device ci_dev; /* our device */ @@ -141,6 +143,9 @@ struct cpu_info { #define CI_SETPERF_SHOULDSTOP 1 #define CI_SETPERF_INTRANSIT 2 #define CI_SETPERF_DONE 3 + + struct ksensordev ci_sensordev; + struct ksensor ci_sensor; }; /* @@ -295,7 +300,6 @@ struct cpu_cpuid_feature { const char *feature_name; }; -#ifdef _KERNEL /* locore.s */ extern int cpu; extern int cpu_id; diff --git a/sys/arch/i386/include/specialreg.h b/sys/arch/i386/include/specialreg.h index cc64e01a069..bc186de981f 100644 --- a/sys/arch/i386/include/specialreg.h +++ b/sys/arch/i386/include/specialreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: specialreg.h,v 1.30 2007/02/17 17:38:37 tom Exp $ */ +/* $OpenBSD: specialreg.h,v 1.31 2007/05/29 21:01:56 tedu Exp $ */ /* $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $ */ /*- @@ -162,6 +162,8 @@ #define P6MSR_CTR0 0x0c1 #define P6MSR_CTR1 0x0c2 #define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */ +#define MSR_TEMPERATURE_TARGET 0x0ee +#define MSR_TEMPERATURE_TARGET_LOW_BIT 0x40000000 #define MSR_MTRRcap 0x0fe #define MSR_BBL_CR_ADDR 0x116 /* PII+ only */ #define MSR_BBL_CR_DECC 0x118 /* PII+ only */ @@ -182,6 +184,8 @@ #define MSR_THERM_CONTROL 0x19a #define MSR_THERM_INTERRUPT 0x19b #define MSR_THERM_STATUS 0x19c +#define MSR_THERM_STATUS_VALID_BIT 0x80000000 +#define MSR_THERM_STATUS_TEMP(msr) ((msr >> 16) & 0x7f) #define MSR_THERM2_CTL 0x19d /* Pentium M */ #define MSR_MISC_ENABLE 0x1a0 #define MSR_DEBUGCTLMSR 0x1d9 |