Make use of an msr available on recent Intel processors to obtain the
authorjsg <jsg@openbsd.org>
Mon, 19 Jan 2015 16:01:43 +0000 (16:01 +0000)
committerjsg <jsg@openbsd.org>
Mon, 19 Jan 2015 16:01:43 +0000 (16:01 +0000)
maximum supported temperature, Tj(Max).  As the temperature values are
relative to this value this should make the sensor values more accurate.

From Simon Mages.

sys/arch/amd64/amd64/identcpu.c
sys/arch/amd64/include/specialreg.h
sys/arch/i386/i386/machdep.c
sys/arch/i386/include/specialreg.h

index 1ddffa9..4e68ab3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: identcpu.c,v 1.57 2014/12/16 21:02:58 sf Exp $        */
+/*     $OpenBSD: identcpu.c,v 1.58 2015/01/19 16:01:43 jsg Exp $       */
 /*     $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $        */
 
 /*
@@ -180,12 +180,16 @@ void      intelcore_update_sensor(void *args);
 /*
  * 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.
+ * Refer to:
+ * 64-ia-32-architectures-software-developer-vol-3c-part-3-manual.pdf
+ * Section 35 and
+ * http://www.intel.com/content/dam/www/public/us/en/documents/
+ * white-papers/cpu-monitoring-dts-peci-paper.pdf
+ *
+ * The temperature on Intel CPUs can be between 70 and 105 degC, since
+ * Westmere we can read the TJmax from the die. For older CPUs we have
+ * to guess or use undocumented MSRs. Then we subtract the temperature
+ * portion of thermal status from max to get current temperature.
  */
 void
 intelcore_update_sensor(void *args)
@@ -195,10 +199,22 @@ intelcore_update_sensor(void *args)
        int max = 100;
 
        /* Only some Core family chips have MSR_TEMPERATURE_TARGET. */
-       if (ci->ci_model == 0xe &&
-           (rdmsr(MSR_TEMPERATURE_TARGET) & MSR_TEMPERATURE_TARGET_LOW_BIT))
+       if (ci->ci_model == 0x0e &&
+           (rdmsr(MSR_TEMPERATURE_TARGET_UNDOCUMENTED) &
+            MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED))
                max = 85;
 
+       /*
+        * Newer CPUs can tell you what their max temperature is.
+        * See: '64-ia-32-architectures-software-developer-
+        * vol-3c-part-3-manual.pdf'
+        */
+       if (ci->ci_model > 0x17 && ci->ci_model != 0x1c &&
+           ci->ci_model != 0x26 && ci->ci_model != 0x27 &&
+           ci->ci_model != 0x35 && ci->ci_model != 0x36)
+               max = MSR_TEMPERATURE_TARGET_TJMAX(
+                   rdmsr(MSR_TEMPERATURE_TARGET));
+
        msr = rdmsr(MSR_THERM_STATUS);
        if (msr & MSR_THERM_STATUS_VALID_BIT) {
                ci->ci_sensor.value = max - MSR_THERM_STATUS_TEMP(msr);
index da3febd..f35fcde 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: specialreg.h,v 1.31 2014/12/22 22:33:51 mlarkin Exp $ */
+/*     $OpenBSD: specialreg.h,v 1.32 2015/01/19 16:01:43 jsg Exp $     */
 /*     $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $      */
 /*     $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $  */
 
 #define MSR_PERFCTR0           0x0c1
 #define MSR_PERFCTR1           0x0c2
 #define MSR_FSB_FREQ           0x0cd   /* Core Duo/Solo only */   
-/* not documented anywhere, see intelcore_update_sensor() */
-#define MSR_TEMPERATURE_TARGET 0x0ee
-#define MSR_TEMPERATURE_TARGET_LOW_BIT 0x40000000
+/*
+ * for Core i Series and newer Xeons, see
+ * http://www.intel.com/content/dam/www/public/us/en/
+ * documents/white-papers/cpu-monitoring-dts-peci-paper.pdf
+ */
+#define MSR_TEMPERATURE_TARGET 0x1a2   /* Core i Series, Newer Xeons */
+#define MSR_TEMPERATURE_TARGET_TJMAX(msr) (((msr) >> 16) & 0xff)
+/*
+ * not documented anywhere, see intelcore_update_sensor()
+ * only available Core Duo and Core Solo Processors
+ */
+#define MSR_TEMPERATURE_TARGET_UNDOCUMENTED    0x0ee
+#define MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED    0x40000000
 #define MSR_MTRRcap            0x0fe
 #define        MSR_BBL_CR_ADDR         0x116   /* PII+ only */
 #define        MSR_BBL_CR_DECC         0x118   /* PII+ only */
index 8092e8c..bb8cc66 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: machdep.c,v 1.562 2015/01/15 13:58:55 sf Exp $        */
+/*     $OpenBSD: machdep.c,v 1.563 2015/01/19 16:01:44 jsg Exp $       */
 /*     $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $    */
 
 /*-
@@ -1427,12 +1427,16 @@ amd_family6_setup(struct cpu_info *ci)
 /*
  * 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.
+ * Refer to:
+ * 64-ia-32-architectures-software-developer-vol-3c-part-3-manual.pdf
+ * Section 35 and
+ * http://www.intel.com/content/dam/www/public/us/en/documents/
+ * white-papers/cpu-monitoring-dts-peci-paper.pdf
+ *
+ * The temperature on Intel CPUs can be between 70 and 105 degC, since
+ * Westmere we can read the TJmax from the die. For older CPUs we have
+ * to guess or use undocumented MSRs. Then we subtract the temperature
+ * portion of thermal status from max to get current temperature.
  */
 void
 intelcore_update_sensor(void *args)
@@ -1442,10 +1446,22 @@ intelcore_update_sensor(void *args)
        int max = 100;
 
        /* Only some Core family chips have MSR_TEMPERATURE_TARGET. */
-       if (ci->ci_model == 0xe &&
-           (rdmsr(MSR_TEMPERATURE_TARGET) & MSR_TEMPERATURE_TARGET_LOW_BIT))
+       if (ci->ci_model == 0x0e &&
+           (rdmsr(MSR_TEMPERATURE_TARGET_UNDOCUMENTED) &
+            MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED))
                max = 85;
 
+       /*
+        * Newer CPUs can tell you what their max temperature is.
+        * See: '64-ia-32-architectures-software-developer-
+        * vol-3c-part-3-manual.pdf'
+        */
+       if (ci->ci_model > 0x17 && ci->ci_model != 0x1c &&
+           ci->ci_model != 0x26 && ci->ci_model != 0x27 &&
+           ci->ci_model != 0x35 && ci->ci_model != 0x36)
+               max = MSR_TEMPERATURE_TARGET_TJMAX(
+                   rdmsr(MSR_TEMPERATURE_TARGET));
+
        msr = rdmsr(MSR_THERM_STATUS);
        if (msr & MSR_THERM_STATUS_VALID_BIT) {
                ci->ci_sensor.value = max - MSR_THERM_STATUS_TEMP(msr);
index da22d51..fb66055 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: specialreg.h,v 1.48 2015/01/15 13:58:55 sf Exp $      */
+/*     $OpenBSD: specialreg.h,v 1.49 2015/01/19 16:01:43 jsg Exp $     */
 /*     $NetBSD: specialreg.h,v 1.7 1994/10/27 04:16:26 cgd Exp $       */
 
 /*-
 #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
+/*
+ * for Core i Series and newer Xeons, see
+ * http://www.intel.com/content/dam/www/public/us/en/
+ * documents/white-papers/cpu-monitoring-dts-peci-paper.pdf
+ */
+#define MSR_TEMPERATURE_TARGET 0x1a2   /* Core i Series, Newer Xeons */
+#define MSR_TEMPERATURE_TARGET_TJMAX(r) (((r) >> 16) & 0xff)
+/*
+ * not documented anywhere, see intelcore_update_sensor()
+ * only available Core Duo and Core Solo Processors
+ */
+#define MSR_TEMPERATURE_TARGET_UNDOCUMENTED    0x0ee
+#define MSR_TEMPERATURE_TARGET_LOW_BIT_UNDOCUMENTED    0x40000000
 #define MSR_MTRRcap            0x0fe
 #define        MSR_BBL_CR_ADDR         0x116   /* PII+ only */
 #define        MSR_BBL_CR_DECC         0x118   /* PII+ only */