Fixed AMD family 0Fh temperature reading of first core.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 The contents of this file are subject to the Mozilla Public License Version
6 1.1 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 for the specific language governing rights and limitations under the License.
15 The Original Code is the Open Hardware Monitor code.
17 The Initial Developer of the Original Code is
18 Michael Möller <m.moeller@gmx.ch>.
19 Portions created by the Initial Developer are Copyright (C) 2009-2010
20 the Initial Developer. All Rights Reserved.
24 Alternatively, the contents of this file may be used under the terms of
25 either the GNU General Public License Version 2 or later (the "GPL"), or
26 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 in which case the provisions of the GPL or the LGPL are applicable instead
28 of those above. If you wish to allow use of your version of this file only
29 under the terms of either the GPL or the LGPL, and not to allow others to
30 use your version of this file under the terms of the MPL, indicate your
31 decision by deleting the provisions above and replace them with the notice
32 and other provisions required by the GPL or the LGPL. If you do not delete
33 the provisions above, a recipient may use your version of this file under
34 the terms of any one of the MPL, the GPL or the LGPL.
39 using System.Collections.Generic;
41 using System.Diagnostics;
42 using System.Reflection;
45 namespace OpenHardwareMonitor.Hardware.CPU {
46 public class IntelCPU : Hardware, IHardware {
53 private uint stepping;
55 private Sensor[] coreTemperatures;
56 private Sensor totalLoad;
57 private Sensor[] coreLoads;
58 private Sensor[] coreClocks;
59 private Sensor busClock;
61 private float tjMax = 0;
62 private uint logicalProcessors;
63 private uint logicalProcessorsPerCore;
64 private uint coreCount;
66 private CPULoad cpuLoad;
68 private ulong lastCount;
69 private long lastTime;
70 private uint maxNehalemMultiplier = 0;
72 private const uint IA32_THERM_STATUS_MSR = 0x019C;
73 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
74 private const uint IA32_PERF_STATUS = 0x0198;
75 private const uint MSR_PLATFORM_INFO = 0xCE;
77 private string CoreString(int i) {
81 return "CPU Core #" + (i + 1);
84 public IntelCPU(string name, uint family, uint model, uint stepping,
85 uint[,] cpuidData, uint[,] cpuidExtData) {
88 this.icon = Utilities.EmbeddedResources.GetImage("cpu.png");
92 this.stepping = stepping;
94 logicalProcessors = 0;
95 if (cpuidData.GetLength(0) > 0x0B) {
96 uint eax, ebx, ecx, edx;
97 WinRing0.CpuidEx(0x0B, 0, out eax, out ebx, out ecx, out edx);
98 logicalProcessorsPerCore = ebx & 0xFF;
99 if (logicalProcessorsPerCore > 0) {
100 WinRing0.CpuidEx(0x0B, 1, out eax, out ebx, out ecx, out edx);
101 logicalProcessors = ebx & 0xFF;
104 if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x04) {
105 uint coresPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
106 uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
107 logicalProcessorsPerCore = logicalPerPackage / coresPerPackage;
108 logicalProcessors = logicalPerPackage;
110 if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x01) {
111 uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
112 logicalProcessorsPerCore = logicalPerPackage;
113 logicalProcessors = logicalPerPackage;
115 if (logicalProcessors <= 0) {
116 logicalProcessors = 1;
117 logicalProcessorsPerCore = 1;
120 coreCount = logicalProcessors / logicalProcessorsPerCore;
125 case 0x0F: // Intel Core (65nm)
144 case 0x17: // Intel Core (45nm)
146 case 0x1C: // Intel Atom
148 case 0x1A: // Intel Core i7 LGA1366 (45nm)
149 case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
150 case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
152 if (WinRing0.Rdmsr(IA32_TEMPERATURE_TARGET, out eax, out edx)) {
153 tjMax = (eax >> 16) & 0xFF;
157 if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
158 maxNehalemMultiplier = (eax >> 8) & 0xff;
165 default: tjMax = 100; break;
168 // check if processor supports a digital thermal sensor
169 if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) {
170 coreTemperatures = new Sensor[coreCount];
171 for (int i = 0; i < coreTemperatures.Length; i++) {
172 coreTemperatures[i] = new Sensor(CoreString(i), i, tjMax,
173 SensorType.Temperature, this);
176 coreTemperatures = new Sensor[0];
180 totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);
183 coreLoads = new Sensor[coreCount];
184 for (int i = 0; i < coreLoads.Length; i++)
185 coreLoads[i] = new Sensor(CoreString(i), i + 1,
186 SensorType.Load, this);
187 cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore);
188 if (cpuLoad.IsAvailable) {
189 foreach (Sensor sensor in coreLoads)
190 ActivateSensor(sensor);
191 if (totalLoad != null)
192 ActivateSensor(totalLoad);
197 busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this);
198 coreClocks = new Sensor[coreCount];
199 for (int i = 0; i < coreClocks.Length; i++) {
201 new Sensor(CoreString(i), i + 1, SensorType.Clock, this);
202 ActivateSensor(coreClocks[i]);
212 public string Identifier {
213 get { return "/intelcpu/0"; }
220 private void AppendMSRData(StringBuilder r, uint msr, int core) {
222 if (WinRing0.RdmsrTx(msr, out eax, out edx,
223 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * core)))) {
225 r.Append((msr).ToString("X8"));
227 r.Append((edx).ToString("X8"));
229 r.Append((eax).ToString("X8"));
234 public string GetReport() {
235 StringBuilder r = new StringBuilder();
237 r.AppendLine("Intel CPU");
239 r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
240 r.AppendFormat("Number of cores: {0}{1}", coreCount,
241 Environment.NewLine);
242 r.AppendFormat("Threads per core: {0}{1}", logicalProcessorsPerCore,
243 Environment.NewLine);
244 r.AppendFormat("TjMax: {0}{1}", tjMax, Environment.NewLine);
247 for (int i = 0; i < coreCount; i++) {
248 r.AppendLine("MSR Core #" + (i + 1));
250 r.AppendLine(" MSR EDX EAX");
251 AppendMSRData(r, MSR_PLATFORM_INFO, i);
252 AppendMSRData(r, IA32_PERF_STATUS, i);
253 AppendMSRData(r, IA32_THERM_STATUS_MSR, i);
254 AppendMSRData(r, IA32_TEMPERATURE_TARGET, i);
261 public void Update() {
263 for (int i = 0; i < coreTemperatures.Length; i++) {
265 if (WinRing0.RdmsrTx(
266 IA32_THERM_STATUS_MSR, out eax, out edx,
267 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i))))
269 // if reading is valid
270 if ((eax & 0x80000000) != 0) {
271 // get the dist from tjMax from bits 22:16
272 coreTemperatures[i].Value = tjMax - ((eax & 0x007F0000) >> 16);
273 ActivateSensor(coreTemperatures[i]);
275 DeactivateSensor(coreTemperatures[i]);
280 if (cpuLoad.IsAvailable) {
282 for (int i = 0; i < coreLoads.Length; i++)
283 coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
284 if (totalLoad != null)
285 totalLoad.Value = cpuLoad.GetTotalLoad();
289 bool valid = WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
290 long time = Stopwatch.GetTimestamp();
291 ulong count = ((ulong)msb << 32) | lsb;
292 double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
293 if (valid && delta > 0.5) {
294 double maxClock = (count - lastCount) / (1e6 * delta);
297 for (int i = 0; i < coreClocks.Length; i++) {
298 System.Threading.Thread.Sleep(1);
299 if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
300 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
301 if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
302 uint nehalemMultiplier = eax & 0xff;
303 coreClocks[i].Value =
304 (float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
305 busClock = (float)(maxClock / maxNehalemMultiplier);
307 uint multiplier = (eax >> 8) & 0x1f;
308 uint maxMultiplier = (edx >> 8) & 0x1f;
309 // factor = multiplier * 2 to handle non integer multipliers
310 uint factor = (multiplier << 1) | ((eax >> 14) & 1);
311 uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
313 coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
314 busClock = (float)(2 * maxClock / maxFactor);
317 } else { // Intel Pentium 4
318 // if IA32_PERF_STATUS is not available, assume maxClock
319 coreClocks[i].Value = (float)maxClock;
323 this.busClock.Value = (float)busClock;
324 ActivateSensor(this.busClock);