From: jsg Date: Mon, 19 Jan 2015 16:01:43 +0000 (+0000) Subject: Make use of an msr available on recent Intel processors to obtain the X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7a17d89036f5acd55e5b8a36cdf825af51f9a7a9;p=openbsd Make use of an msr available on recent Intel processors to obtain the 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. --- diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c index 1ddffa9d540..4e68ab3d59d 100644 --- a/sys/arch/amd64/amd64/identcpu.c +++ b/sys/arch/amd64/amd64/identcpu.c @@ -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); diff --git a/sys/arch/amd64/include/specialreg.h b/sys/arch/amd64/include/specialreg.h index da3febd9b1b..f35fcdeaddf 100644 --- a/sys/arch/amd64/include/specialreg.h +++ b/sys/arch/amd64/include/specialreg.h @@ -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 $ */ @@ -279,9 +279,19 @@ #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 */ diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 8092e8ca97c..bb8cc6664a7 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -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); diff --git a/sys/arch/i386/include/specialreg.h b/sys/arch/i386/include/specialreg.h index da22d51b8e5..fb660558f1f 100644 --- a/sys/arch/i386/include/specialreg.h +++ b/sys/arch/i386/include/specialreg.h @@ -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 $ */ /*- @@ -278,8 +278,19 @@ #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 */