From 575aab549429c3333eb1c17cbe6f11f302480cd9 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Fri, 3 Jun 2011 14:42:50 +0200 Subject: [PATCH] coretemp(4): Sync with FreeBSD. --- share/man/man4/coretemp.4 | 7 +- sys/cpu/i386/include/specialreg.h | 1 + sys/cpu/x86_64/include/specialreg.h | 1 + sys/dev/powermng/coretemp/coretemp.c | 104 ++++++++++++++++++++++----- 4 files changed, 92 insertions(+), 21 deletions(-) diff --git a/share/man/man4/coretemp.4 b/share/man/man4/coretemp.4 index d140cfe01f..4ce5714031 100644 --- a/share/man/man4/coretemp.4 +++ b/share/man/man4/coretemp.4 @@ -1,5 +1,5 @@ .\"- -.\" Copyright (c) 2007 Dag-Erling Coïdan Smørgrav +.\" Copyright (c) 2007 Dag-Erling Coïdan Smørgrav .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -23,10 +23,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/share/man/man4/coretemp.4,v 1.1 2007/08/23 20:05:09 des Exp $ -.\" $DragonFly: src/share/man/man4/coretemp.4,v 1.2 2007/10/26 08:22:00 swildner Exp $ +.\" $FreeBSD: src/share/man/man4/coretemp.4,v 1.5 2011/05/22 14:03:30 uqs Exp $ .\" -.Dd September 13, 2007 +.Dd June 3, 2011 .Dt CORETEMP 4 .Os .Sh NAME diff --git a/sys/cpu/i386/include/specialreg.h b/sys/cpu/i386/include/specialreg.h index 1cafc55b0e..0f4845bbf5 100644 --- a/sys/cpu/i386/include/specialreg.h +++ b/sys/cpu/i386/include/specialreg.h @@ -263,6 +263,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 diff --git a/sys/cpu/x86_64/include/specialreg.h b/sys/cpu/x86_64/include/specialreg.h index 559ce6b00d..0af1428094 100644 --- a/sys/cpu/x86_64/include/specialreg.h +++ b/sys/cpu/x86_64/include/specialreg.h @@ -238,6 +238,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 diff --git a/sys/dev/powermng/coretemp/coretemp.c b/sys/dev/powermng/coretemp/coretemp.c index 5c9e542674..7de3b74687 100644 --- a/sys/dev/powermng/coretemp/coretemp.c +++ b/sys/dev/powermng/coretemp/coretemp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Rui Paulo + * Copyright (c) 2007, 2008 Rui Paulo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +23,7 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.2 2007/08/23 10:53:03 des Exp $ + * $FreeBSD: src/sys/dev/coretemp/coretemp.c,v 1.14 2011/05/05 19:15:15 delphij Exp $ */ /* @@ -94,8 +94,8 @@ coretemp_identify(driver_t *driver, device_t parent) if (device_find_child(parent, "coretemp", -1) != NULL) return; - /* Check that CPUID is supported and the vendor is Intel.*/ - if (cpu_high == 0 || cpu_vendor_id != CPU_VENDOR_INTEL) + /* Check that CPUID 0x06 is supported and the vendor is Intel.*/ + if (cpu_high < 6 || cpu_vendor_id != CPU_VENDOR_INTEL) return; /* * CPUID 0x06 returns 1 if the processor has on-die thermal @@ -131,15 +131,27 @@ 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 + * report them when the CPUID check is performed in + * coretemp_identify(). This leads to a later GPF when the sensor + * is queried via a MSR, so we stop here. + */ + if (cpu_model < 0xe) + return (ENXIO); + +#if 0 /* + * XXXrpaulo: I have this CPU model and when it returns from C3 + * coretemp continues to function properly. + */ /* * Check for errata AE18. @@ -148,7 +160,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) { @@ -157,20 +169,78 @@ coretemp_attach(device_t dev) return (ENXIO); } } +#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) { + + 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 = 105; + break; + default: /* Unknown stepping */ + break; + } + } else if (cpu_model == 0x1c) { + switch (cpu_stepping) { + case 0xa: /* 45nm Atom D400, N400 and D500 series */ + sc->sc_tjmax = 100; + break; + default: + sc->sc_tjmax = 90; + 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 hw.sensors.cpuN.temp0 MIB. */ -- 2.41.0