Add coretemp(4). A new driver for Intel Core's on-die thermal sensor,

available on Intel Core or newer CPUs.

Ported from FreeBSD. Tested by rmind on i386 and joerg on amd64.

Enabled with "options INTEL_CORETEMP".
This commit is contained in:
xtraeme 2007-10-29 00:42:28 +00:00
parent 79606bd6fa
commit e3b08fdabe
9 changed files with 339 additions and 10 deletions

View File

@ -1,4 +1,4 @@
LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.938 $> LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.939 $>
[Note: This file does not mention every change made to the NetBSD source tree. [Note: This file does not mention every change made to the NetBSD source tree.
@ -226,3 +226,6 @@ Changes from NetBSD 4.0 to NetBSD 5.0:
msk(4): Add support for Marvell 88CO55 gigabit ethernet, which msk(4): Add support for Marvell 88CO55 gigabit ethernet, which
is used by newer iMacs [manu 20071022] is used by newer iMacs [manu 20071022]
shark: Removed pccons(4), obsoleted by wscons(4). [jmmv 20071028] shark: Removed pccons(4), obsoleted by wscons(4). [jmmv 20071028]
coretemp(4): Driver for Intel Core's on-die thermal sensor,
available on Core or newer CPUs. Ported from FreeBSD.
[xtraeme 20071029]

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.445 2007/10/25 17:32:23 christos Exp $ # $NetBSD: Makefile,v 1.446 2007/10/29 00:42:28 xtraeme Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93 # @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adbbt.4 adbkbd.4 adbms.4 \ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adbbt.4 adbkbd.4 adbms.4 \
@ -14,7 +14,7 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adbbt.4 adbkbd.4 adbms.4 \
btuart.4 cac.4 cardbus.4 carp.4 ccd.4 cd.4 \ btuart.4 cac.4 cardbus.4 carp.4 ccd.4 cd.4 \
cec.4 cgd.4 cfb.4 ch.4 chipsfb.4 ciphy.4 ciss.4 clcs.4 clct.4 clnp.4 \ cec.4 cgd.4 cfb.4 ch.4 chipsfb.4 ciphy.4 ciss.4 clcs.4 clct.4 clnp.4 \
clockctl.4 cltp.4 cmdide.4 cmpci.4 cms.4 cnw.4 \ clockctl.4 cltp.4 cmdide.4 cmpci.4 cms.4 cnw.4 \
com.4 crypto.4 cs80bus.4 cuda.4 cypide.4 geodeide.4 \ com.4 coretemp.4 crypto.4 cs80bus.4 cuda.4 cypide.4 geodeide.4 \
ddb.4 ddc.4 de.4 dge.4 dk.4 dmoverio.4 \ ddb.4 ddc.4 de.4 dge.4 dk.4 dmoverio.4 \
dmphy.4 dpt.4 dpti.4 drm.4 drum.4 eap.4 ebus.4 edc.4 \ dmphy.4 dpt.4 dpti.4 drm.4 drum.4 eap.4 ebus.4 edc.4 \
elmc.4 emuxki.4 en.4 envsys.4 ep.4 esh.4 esis.4 \ elmc.4 emuxki.4 en.4 envsys.4 ep.4 esh.4 esis.4 \

81
share/man/man4/coretemp.4 Normal file
View File

@ -0,0 +1,81 @@
.\" $NetBSD: coretemp.4,v 1.1 2007/10/29 00:42:28 xtraeme Exp $
.\"-
.\" Copyright (c) 2007 Juan Romero Pardines.
.\" Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
.\"
.\" $FreeBSD: src/share/man/man4/coretemp.4,v 1.4 2007/10/15 20:00:19 netchild Exp $
.\"
.Dd October 29, 2007
.Dt CORETEMP 4
.Os
.Sh NAME
.Nm coretemp
.Nd Intel Core on-die digital thermal sensor
.Sh SYNOPSIS
.Cd "options INTEL_CORETEMP"
.Sh DESCRIPTION
The
.Nm
driver provides support for the on-die digital thermal sensor present
on Intel Core and newer CPUs.
.Pp
The
.Nm
driver reports each core's temperature through the
.Xr envsys 4
API. The driver has only 1 temperature sensor:
.Bl -column "Sensor" "Units" "Typical" -offset indent
.It Sy "Sensor" Ta Sy "Units" Ta Sy "Typical Use"
.It Li "sensor0" Ta "uK" Ta "cpuN temperature"
.El
.Sh EVENTS
The
.Nm
driver is able to send a
.Em critical
event to the
.Fa /etc/powerd/scripts/sensor_temperature
.Xr powerd 8
script (if running) when the temperature has reached a critical state.
.Sh SEE ALSO
.Xr envstat 4 ,
.Xr powerd 8
.Sh HISTORY
The
.Nm
driver first appeared in
.Fx 7.0 .
And then was ported to
.Nx 5.0 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Rui Paulo Aq rpaulo@FreeBSD.org
as part of a Google Summer of Code project. It was adapted to
.Nx
by
.An Juan Romero Pardines .

View File

@ -1,4 +1,4 @@
/* $NetBSD: identcpu.c,v 1.26 2007/10/17 19:53:00 garbled Exp $ */ /* $NetBSD: identcpu.c,v 1.27 2007/10/29 00:42:29 xtraeme Exp $ */
/* /*
* Copyright (c) 2003 Wasabi Systems, Inc. * Copyright (c) 2003 Wasabi Systems, Inc.
@ -36,9 +36,10 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.26 2007/10/17 19:53:00 garbled Exp $"); __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.27 2007/10/29 00:42:29 xtraeme Exp $");
#include "opt_enhanced_speedstep.h" #include "opt_enhanced_speedstep.h"
#include "opt_intel_coretemp.h"
#include "opt_intel_odcm.h" #include "opt_intel_odcm.h"
#include "opt_powernow_k8.h" #include "opt_powernow_k8.h"
@ -178,6 +179,10 @@ identifycpu(struct cpu_info *ci)
} }
#endif #endif
#ifdef INTEL_CORETEMP
if (vendor == CPUVENDOR_INTEL)
coretemp_register(ci);
#endif
} }
void void

View File

@ -1,4 +1,4 @@
/* $NetBSD: identcpu.c,v 1.76 2007/10/17 19:54:45 garbled Exp $ */ /* $NetBSD: identcpu.c,v 1.77 2007/10/29 00:42:28 xtraeme Exp $ */
/*- /*-
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@ -37,11 +37,12 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.76 2007/10/17 19:54:45 garbled Exp $"); __KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.77 2007/10/29 00:42:28 xtraeme Exp $");
#include "opt_cputype.h" #include "opt_cputype.h"
#include "opt_enhanced_speedstep.h" #include "opt_enhanced_speedstep.h"
#include "opt_intel_odcm.h" #include "opt_intel_odcm.h"
#include "opt_intel_coretemp.h"
#include "opt_powernow_k7.h" #include "opt_powernow_k7.h"
#include "opt_powernow_k8.h" #include "opt_powernow_k8.h"
@ -1629,6 +1630,11 @@ identifycpu(struct cpu_info *ci)
} }
#endif /* ENHANCED_SPEEDSTEP */ #endif /* ENHANCED_SPEEDSTEP */
#ifdef INTEL_CORETEMP
if (cpu_vendor == CPUVENDOR_INTEL)
coretemp_register(ci);
#endif
#if defined(POWERNOW_K7) || defined(POWERNOW_K8) #if defined(POWERNOW_K7) || defined(POWERNOW_K8)
if (cpu_vendor == CPUVENDOR_AMD && powernow_probe(ci)) { if (cpu_vendor == CPUVENDOR_AMD && powernow_probe(ci)) {
switch (CPUID2FAMILY(ci->ci_signature)) { switch (CPUID2FAMILY(ci->ci_signature)) {

View File

@ -1,4 +1,4 @@
# $NetBSD: files.x86,v 1.32 2007/10/26 21:49:52 xtraeme Exp $ # $NetBSD: files.x86,v 1.33 2007/10/29 00:42:29 xtraeme Exp $
# options for MP configuration through the MP spec # options for MP configuration through the MP spec
defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
@ -14,6 +14,9 @@ defflag opt_pcifixup.h PCI_ADDR_FIXUP PCI_BUS_FIXUP
defflag ENHANCED_SPEEDSTEP defflag ENHANCED_SPEEDSTEP
defflag opt_est.h EST_FREQ_USERWRITE defflag opt_est.h EST_FREQ_USERWRITE
# Intel On Die Temperature sensor
defflag opt_intel_coretemp.h INTEL_CORETEMP: sysmon_envsys
# Pentium 4+ Thermal Monitor ODCM (aka On Demand Clock Modulation) # Pentium 4+ Thermal Monitor ODCM (aka On Demand Clock Modulation)
defflag opt_intel_odcm.h INTEL_ONDEMAND_CLOCKMOD defflag opt_intel_odcm.h INTEL_ONDEMAND_CLOCKMOD
@ -86,6 +89,9 @@ file arch/x86/x86/iclockmod.c intel_ondemand_clockmod
file arch/x86/x86/est.c enhanced_speedstep file arch/x86/x86/est.c enhanced_speedstep
file arch/x86/x86/intel_busclock.c enhanced_speedstep file arch/x86/x86/intel_busclock.c enhanced_speedstep
# Intel On-Die Temperature sensor
file arch/x86/x86/coretemp.c intel_coretemp
# IPMI device # IPMI device
device ipmi: sysmon_envsys, sysmon_wdog device ipmi: sysmon_envsys, sysmon_wdog
attach ipmi at ipmibus attach ipmi at ipmibus

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpuvar.h,v 1.15 2007/10/17 19:58:14 garbled Exp $ */ /* $NetBSD: cpuvar.h,v 1.16 2007/10/29 00:42:29 xtraeme Exp $ */
/*- /*-
* Copyright (c) 2000 The NetBSD Foundation, Inc. * Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -96,6 +96,7 @@ struct cpu_attach_args {
#include "opt_multiprocessor.h" #include "opt_multiprocessor.h"
#ifndef XEN #ifndef XEN
#include "opt_enhanced_speedstep.h" #include "opt_enhanced_speedstep.h"
#include "opt_intel_coretemp.h"
#include "opt_intel_odcm.h" #include "opt_intel_odcm.h"
#endif #endif
@ -112,6 +113,10 @@ void identifycpu(struct cpu_info *);
void cpu_init(struct cpu_info *); void cpu_init(struct cpu_info *);
void cpu_init_first(void); void cpu_init_first(void);
#ifdef INTEL_CORETEMP
void coretemp_register(struct cpu_info *);
#endif
#ifdef INTEL_ONDEMAND_CLOCKMOD #ifdef INTEL_ONDEMAND_CLOCKMOD
void clockmod_init(void); void clockmod_init(void);
#endif #endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: specialreg.h,v 1.20 2007/10/17 19:58:15 garbled Exp $ */ /* $NetBSD: specialreg.h,v 1.21 2007/10/29 00:42:29 xtraeme Exp $ */
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991 The Regents of the University of California.
@ -220,6 +220,7 @@
#define MSR_PERFCTR0 0x0c1 #define MSR_PERFCTR0 0x0c1
#define MSR_PERFCTR1 0x0c2 #define MSR_PERFCTR1 0x0c2
#define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */ #define MSR_FSB_FREQ 0x0cd /* Core Duo/Solo only */
#define MSR_IA32_EXT_CONFIG 0x0ee /* Undocumented. Core Solo/Duo only */
#define MSR_MTRRcap 0x0fe #define MSR_MTRRcap 0x0fe
#define MSR_BBL_CR_ADDR 0x116 /* PII+ only */ #define MSR_BBL_CR_ADDR 0x116 /* PII+ only */
#define MSR_BBL_CR_DECC 0x118 /* PII+ only */ #define MSR_BBL_CR_DECC 0x118 /* PII+ only */

222
sys/arch/x86/x86/coretemp.c Normal file
View File

@ -0,0 +1,222 @@
/* $NetBSD: coretemp.c,v 1.1 2007/10/29 00:42:29 xtraeme Exp $ */
/*-
* Copyright (c) 2007 Juan Romero Pardines.
* Copyright (c) 2007 Rui Paulo <rpaulo@FreeBSD.org>
* 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.
*
* $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.4 2007/10/15 20:00:21 netchild Exp $
*
*/
/*
* Device driver for Intel's On Die thermal sensor via MSR.
* First introduced in Intel's Core line of processors.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: coretemp.c,v 1.1 2007/10/29 00:42:29 xtraeme Exp $");
#include <sys/param.h>
#include <sys/kmem.h>
#include <sys/xcall.h>
#include <dev/sysmon/sysmonvar.h>
#include <machine/cpu.h>
#include <machine/cpuvar.h>
#include <machine/specialreg.h>
struct coretemp_softc {
struct cpu_info *sc_ci;
struct sysmon_envsys sc_sme;
envsys_data_t sc_sensor[1];
char sc_dvname[32];
int sc_tjmax;
};
static int coretemp_refresh(struct sysmon_envsys *, envsys_data_t *);
static void coretemp_refresh_xcall(void *, void *);
void
coretemp_register(struct cpu_info *ci)
{
struct coretemp_softc *sc;
uint32_t regs[4];
uint64_t msr;
int cpumodel, cpumask;
/*
* CPUID 0x06 returns 1 if the processor has on-die thermal
* sensors. EBX[0:3] contains the number of sensors.
*/
x86_cpuid(0x06, regs);
if ((regs[0] & 0x1) != 1)
return;
sc = kmem_zalloc(sizeof(*sc), KM_NOSLEEP);
if (!sc)
return;
(void)snprintf(sc->sc_dvname, sizeof(sc->sc_dvname), "coretemp%d",
(int)ci->ci_cpuid);
cpumodel = CPUID2MODEL(ci->ci_cpuid);
/* extended model */
cpumodel += CPUID2EXTMODEL(ci->ci_cpuid);
cpumask = ci->ci_cpuid & 15;
/*
* Check for errata AE18.
* "Processor Digital Thermal Sensor (DTS) Readout stops
* updating upon returning from C3/C4 state."
*
* Adapted from the Linux coretemp driver.
*/
if (cpumodel == 0xe && cpumask < 0xc) {
msr = rdmsr(MSR_BIOS_SIGN);
msr = msr >> 32;
if (msr < 0x39) {
aprint_debug("%s: not supported (Intel errata AE18), "
"try updating your BIOS\n", sc->sc_dvname);
kmem_free(sc, sizeof(*sc));
return;
}
}
/*
* On some Core 2 CPUs, there's an undocumented MSR that
* can tell us if Tj(max) is 100 or 85.
*
* The if-clause for CPUs having the MSR_IA32_EXT_CONFIG was adapted
* from the Linux coretemp driver.
*/
sc->sc_tjmax = 100;
if ((cpumodel == 0xf && cpumask >= 2) || cpumodel == 0xe) {
msr = rdmsr(MSR_IA32_EXT_CONFIG);
if (msr & (1 << 30))
sc->sc_tjmax = 85;
}
sc->sc_ci = ci;
/*
* Only a temperature sensor and monitor for a critical state.
*/
sc->sc_sensor[0].sensor = 0;
sc->sc_sensor[0].units = ENVSYS_STEMP;
sc->sc_sensor[0].state = ENVSYS_SVALID;
sc->sc_sensor[0].flags = ENVSYS_FMONCRITICAL;
sc->sc_sensor[0].monitor = true;
(void)snprintf(sc->sc_sensor[0].desc, sizeof(sc->sc_sensor[0].desc),
"cpu%d temperature", (int)ci->ci_cpuid);
/*
* Hook into the system monitor.
*/
sc->sc_sme.sme_name = sc->sc_dvname;
sc->sc_sme.sme_sensor_data = sc->sc_sensor;
sc->sc_sme.sme_cookie = sc;
sc->sc_sme.sme_gtredata = coretemp_refresh;
sc->sc_sme.sme_nsensors = 1;
if (sysmon_envsys_register(&sc->sc_sme)) {
aprint_error("%s: unable to register with sysmon\n",
sc->sc_dvname);
kmem_free(sc, sizeof(*sc));
}
}
static int
coretemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct coretemp_softc *sc = sme->sme_cookie;
/*
* No need to cross-call if we are running on the same CPU.
*/
if (curcpu() != sc->sc_ci)
(void)xc_unicast(0, coretemp_refresh_xcall,
sc, edata, sc->sc_ci);
else
coretemp_refresh_xcall(sc, edata);
return 0;
}
static void
coretemp_refresh_xcall(void *arg0, void *arg1)
{
struct coretemp_softc *sc = (struct coretemp_softc *)arg0;
envsys_data_t *edata = (envsys_data_t *)arg1;
uint64_t msr;
/*
* The digital temperature reading is located at bit 16
* of MSR_THERM_STATUS.
*
* There is a bit on that MSR that indicates whether the
* temperature is valid or not.
*
* The temperature is computed by subtracting the temperature
* reading by Tj(max).
*/
msr = rdmsr(MSR_THERM_STATUS);
/*
* Check for Thermal Status and Thermal Status Log.
*/
if ((msr & 0x3) == 0x3)
aprint_debug("%s: PROCHOT asserted\n", sc->sc_dvname);
/*
* Bit 31 contains "Reading valid"
*/
if (((msr >> 31) & 0x1) == 1) {
/*
* Starting on bit 16 and ending on bit 22.
*/
edata->value_cur = sc->sc_tjmax - ((msr >> 16) & 0x7f);
/*
* Convert to mK.
*/
edata->value_cur *= 1000000;
edata->value_cur += 273150000;
edata->state = ENVSYS_SVALID;
} else
edata->state = ENVSYS_SINVALID;
/*
* Check for Critical Temperature Status and Critical
* Temperature Log.
* It doesn't really matter if the current temperature is
* invalid because the "Critical Temperature Log" bit will
* tell us if the Critical Temperature has been reached in
* past. It's not directly related to the current temperature.
*
* If we reach a critical level, send a critical event to
* powerd(8) (if running).
*/
if (((msr >> 4) & 0x3) == 0x3)
edata->state = ENVSYS_SCRITICAL;
}