svn commit: r210624 - in head/sys: amd64/include dev/coretemp i386/include

Xin LI delphij at FreeBSD.org
Thu Jul 29 19:08:22 UTC 2010


Author: delphij
Date: Thu Jul 29 19:08:22 2010
New Revision: 210624
URL: http://svn.freebsd.org/changeset/base/210624

Log:
  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.
  
  Approved by:	rpaulo
  MFC after:	1 month

Modified:
  head/sys/amd64/include/specialreg.h
  head/sys/dev/coretemp/coretemp.c
  head/sys/i386/include/specialreg.h

Modified: head/sys/amd64/include/specialreg.h
==============================================================================
--- head/sys/amd64/include/specialreg.h	Thu Jul 29 18:44:10 2010	(r210623)
+++ head/sys/amd64/include/specialreg.h	Thu Jul 29 19:08:22 2010	(r210624)
@@ -258,6 +258,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: head/sys/dev/coretemp/coretemp.c
==============================================================================
--- head/sys/dev/coretemp/coretemp.c	Thu Jul 29 18:44:10 2010	(r210623)
+++ head/sys/dev/coretemp/coretemp.c	Thu Jul 29 19:08:22 2010	(r210624)
@@ -133,15 +133,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
@@ -164,7 +162,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) {
@@ -174,20 +172,56 @@ coretemp_attach(device_t dev)
 		}
 	}
 #endif
+
 	/*
-	 * 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) {
+
+	/*
+	 * 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);
+	}
+
+	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;
 	}
 
+	if (bootverbose)
+		device_printf(dev, "Setting TjMax=%d\n", sc->sc_tjmax);
+
 	/*
 	 * Add the "temperature" MIB to dev.cpu.N.
 	 */

Modified: head/sys/i386/include/specialreg.h
==============================================================================
--- head/sys/i386/include/specialreg.h	Thu Jul 29 18:44:10 2010	(r210623)
+++ head/sys/i386/include/specialreg.h	Thu Jul 29 19:08:22 2010	(r210624)
@@ -264,6 +264,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-all mailing list