[Midnightbsd-cvs] src [7754] trunk/sys/dev/coretemp/coretemp.c: Improve cputemp(4) driver wrt newer Intel processors, especially

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Aug 21 00:32:09 EDT 2016


Revision: 7754
          http://svnweb.midnightbsd.org/src/?rev=7754
Author:   laffer1
Date:     2016-08-21 00:32:09 -0400 (Sun, 21 Aug 2016)
Log Message:
-----------
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.

Obtained from: FreeBSD SVN 210624

Modified Paths:
--------------
    trunk/sys/dev/coretemp/coretemp.c

Modified: trunk/sys/dev/coretemp/coretemp.c
===================================================================
--- trunk/sys/dev/coretemp/coretemp.c	2016-08-21 04:26:11 UTC (rev 7753)
+++ trunk/sys/dev/coretemp/coretemp.c	2016-08-21 04:32:09 UTC (rev 7754)
@@ -135,15 +135,13 @@
 	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;
 
 #if 0 /*
        * XXXrpaulo: I have this CPU model and when it returns from C3
@@ -166,7 +164,7 @@
 	 *
 	 * 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) {
@@ -176,20 +174,56 @@
 		}
 	}
 #endif
+
 	/*
-	 * On some Core 2 CPUs, there's an undocumented MSR that
-	 * can tell us if Tj(max) is 100 or 85.
+	 * Use 100C as the initial value.
+	 */
+	sc->sc_tjmax = 100;
+
+	/*
+	 * Attempt to get Tj(max) from MSR IA32_TEMPERATURE_TARGET.
 	 *
-	 * The if-clause for CPUs having the MSR_IA32_EXT_CONFIG was adapted
-	 * from the Linux coretemp driver.
+	 * This method is described in Intel white paper
+	 * "CPU Monitoring With DTS/PECI". (#322683)
 	 */
-	sc->sc_tjmax = 100;
-	if ((cpu_model == 0xf && cpu_mask >= 2) || cpu_model == 0xe) {
+	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 hw.sensors.cpuN.temp0 MIB.
 	 */



More information about the Midnightbsd-cvs mailing list