diff options
author | delphij <delphij@FreeBSD.org> | 2010-07-29 19:08:22 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2010-07-29 19:08:22 +0000 |
commit | 7cbaa3e8e6d153c09e6a5a92a11f6b17529e1bca (patch) | |
tree | ad4719c73f7fa8cc8d6d65806e7966d6fed45576 /sys/dev | |
parent | 007376c918adfea0ab81ac43b33dc3f8297b4e6e (diff) | |
download | FreeBSD-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.c | 60 |
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. */ |