svn commit: r212007 - in stable/7/sys: amd64/include dev/coretemp
i386/include
Xin LI
delphij at FreeBSD.org
Mon Aug 30 18:53:12 UTC 2010
Author: delphij
Date: Mon Aug 30 18:53:12 2010
New Revision: 212007
URL: http://svn.freebsd.org/changeset/base/212007
Log:
MFC r210624 and r210833:
Improve cputemp(4) driver wrt newer Intel processors, especially
Xeon 5500/5600 series:
- Utilize IA32_TEMPERATURE_TARGET, a.k.a. Tj(target) in place
of Tj(max) when a sane value is available, as documented
in Intel whitepaper "CPU Monitoring With DTS/PECI"; (By sane
value we mean 70C - 100C for now);
- Print the probe results when booting verbose;
- Replace cpu_mask with cpu_stepping;
- Use CPUID_* macros instead of rolling our own.
Catch known CPUs before using IA32_TEMPERATURE_TARGET.
This way we would have an opportunity to hide the
Tj(target) value doesn't seem right stuff if we know
it's not working there.
Add temperature value for Core2 Duo Extreme Mobile that
I have access to.
Modified:
stable/7/sys/amd64/include/specialreg.h
stable/7/sys/dev/coretemp/coretemp.c
stable/7/sys/i386/include/specialreg.h
Directory Properties:
stable/7/sys/ (props changed)
stable/7/sys/cddl/contrib/opensolaris/ (props changed)
stable/7/sys/contrib/dev/acpica/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
Modified: stable/7/sys/amd64/include/specialreg.h
==============================================================================
--- stable/7/sys/amd64/include/specialreg.h Mon Aug 30 18:50:18 2010 (r212006)
+++ stable/7/sys/amd64/include/specialreg.h Mon Aug 30 18:53:12 2010 (r212007)
@@ -249,6 +249,7 @@
#define MSR_THERM_INTERRUPT 0x19b
#define MSR_THERM_STATUS 0x19c
#define MSR_IA32_MISC_ENABLE 0x1a0
+#define MSR_IA32_TEMPERATURE_TARGET 0x1a2
#define MSR_DEBUGCTLMSR 0x1d9
#define MSR_LASTBRANCHFROMIP 0x1db
#define MSR_LASTBRANCHTOIP 0x1dc
Modified: stable/7/sys/dev/coretemp/coretemp.c
==============================================================================
--- stable/7/sys/dev/coretemp/coretemp.c Mon Aug 30 18:50:18 2010 (r212006)
+++ stable/7/sys/dev/coretemp/coretemp.c Mon Aug 30 18:53:12 2010 (r212007)
@@ -131,15 +131,13 @@ coretemp_attach(device_t dev)
struct coretemp_softc *sc = device_get_softc(dev);
device_t pdev;
uint64_t msr;
- int cpu_model;
- int cpu_mask;
+ int cpu_model, cpu_stepping;
+ int ret, tjtarget;
sc->sc_dev = dev;
pdev = device_get_parent(dev);
- cpu_model = (cpu_id >> 4) & 15;
- /* extended model */
- cpu_model += ((cpu_id >> 16) & 0xf) << 4;
- cpu_mask = cpu_id & 15;
+ cpu_model = CPUID_TO_MODEL(cpu_id);
+ cpu_stepping = cpu_id & CPUID_STEPPING;
/*
* Some CPUs, namely the PIII, don't have thermal sensors, but
@@ -157,7 +155,7 @@ coretemp_attach(device_t dev)
*
* Adapted from the Linux coretemp driver.
*/
- if (cpu_model == 0xe && cpu_mask < 0xc) {
+ if (cpu_model == 0xe && cpu_stepping < 0xc) {
msr = rdmsr(MSR_BIOS_SIGN);
msr = msr >> 32;
if (msr < 0x39) {
@@ -166,20 +164,68 @@ coretemp_attach(device_t dev)
return (ENXIO);
}
}
+
/*
- * 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.
+ * Use 100C as the initial value.
*/
sc->sc_tjmax = 100;
- if ((cpu_model == 0xf && cpu_mask >= 2) || cpu_model == 0xe) {
+
+ if ((cpu_model == 0xf && cpu_stepping >= 2) || cpu_model == 0xe) {
+ /*
+ * 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.
+ */
msr = rdmsr(MSR_IA32_EXT_CONFIG);
if (msr & (1 << 30))
sc->sc_tjmax = 85;
+ } else if (cpu_model == 0x17) {
+ switch (cpu_stepping) {
+ case 0x6: /* Mobile Core 2 Duo */
+ sc->sc_tjmax = 104;
+ break;
+ default: /* Unknown stepping */
+ break;
+ }
+ } else {
+ /*
+ * Attempt to get Tj(max) from MSR IA32_TEMPERATURE_TARGET.
+ *
+ * This method is described in Intel white paper "CPU
+ * Monitoring With DTS/PECI". (#322683)
+ */
+ ret = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &msr);
+ if (ret == 0) {
+ tjtarget = (msr >> 16) & 0xff;
+
+ /*
+ * On earlier generation of processors, the value
+ * obtained from IA32_TEMPERATURE_TARGET register is
+ * an offset that needs to be summed with a model
+ * specific base. It is however not clear what
+ * these numbers are, with the publicly available
+ * documents from Intel.
+ *
+ * For now, we consider [70, 100]C range, as
+ * described in #322683, as "reasonable" and accept
+ * these values whenever the MSR is available for
+ * read, regardless the CPU model.
+ */
+ if (tjtarget >= 70 && tjtarget <= 100)
+ sc->sc_tjmax = tjtarget;
+ else
+ device_printf(dev, "Tj(target) value %d "
+ "does not seem right.\n", tjtarget);
+ } else
+ device_printf(dev, "Can not get Tj(target) "
+ "from your CPU, using 100C.\n");
}
+ if (bootverbose)
+ device_printf(dev, "Setting TjMax=%d\n", sc->sc_tjmax);
+
/*
* Add the "temperature" MIB to dev.cpu.N.
*/
Modified: stable/7/sys/i386/include/specialreg.h
==============================================================================
--- stable/7/sys/i386/include/specialreg.h Mon Aug 30 18:50:18 2010 (r212006)
+++ stable/7/sys/i386/include/specialreg.h Mon Aug 30 18:53:12 2010 (r212007)
@@ -255,6 +255,7 @@
#define MSR_THERM_INTERRUPT 0x19b
#define MSR_THERM_STATUS 0x19c
#define MSR_IA32_MISC_ENABLE 0x1a0
+#define MSR_IA32_TEMPERATURE_TARGET 0x1a2
#define MSR_DEBUGCTLMSR 0x1d9
#define MSR_LASTBRANCHFROMIP 0x1db
#define MSR_LASTBRANCHTOIP 0x1dc
More information about the svn-src-stable-7
mailing list