summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2007-05-29 21:01:57 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2007-05-29 21:01:57 +0000
commitffbfea5690bb3c06fe441fe0404d80e41506c942 (patch)
treea2050d63dd440131182dbc3d977c815d8c011706 /sys/arch/i386
parent55187efb81b68b264fb98d8164e670360a84266d (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.c66
-rw-r--r--sys/arch/i386/i386/mainbus.c6
-rw-r--r--sys/arch/i386/include/cpu.h8
-rw-r--r--sys/arch/i386/include/specialreg.h6
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