summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2010-07-29 19:08:22 +0000
committerdelphij <delphij@FreeBSD.org>2010-07-29 19:08:22 +0000
commit7cbaa3e8e6d153c09e6a5a92a11f6b17529e1bca (patch)
treead4719c73f7fa8cc8d6d65806e7966d6fed45576 /sys/dev
parent007376c918adfea0ab81ac43b33dc3f8297b4e6e (diff)
downloadFreeBSD-src-7cbaa3e8e6d153c09e6a5a92a11f6b17529e1bca.zip
FreeBSD-src-7cbaa3e8e6d153c09e6a5a92a11f6b17529e1bca.tar.gz
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
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/coretemp/coretemp.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/sys/dev/coretemp/coretemp.c b/sys/dev/coretemp/coretemp.c
index 0226c8f..99f1c75 100644
--- a/sys/dev/coretemp/coretemp.c
+++ b/sys/dev/coretemp/coretemp.c
@@ -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.
*/
OpenPOWER on IntegriCloud