Fixed Issue 11.
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;
43 using System.Runtime.InteropServices;
44 using System.Threading;
47 namespace OpenHardwareMonitor.Hardware.CPU {
48 public class IntelCPU : Hardware, IHardware {
55 private uint stepping;
57 private Sensor[] coreTemperatures;
59 private Sensor totalLoad;
60 private Sensor[] coreLoads;
61 private Sensor[] coreClocks;
62 private Sensor busClock;
63 private uint logicalProcessors;
64 private uint logicalProcessorsPerCore;
65 private uint coreCount;
66 private ulong affinityMask;
68 private CPULoad cpuLoad;
70 private ulong lastCount;
71 private long lastTime;
72 private uint maxNehalemMultiplier = 0;
74 private const uint IA32_THERM_STATUS_MSR = 0x019C;
75 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
76 private const uint IA32_PERF_STATUS = 0x0198;
77 private const uint MSR_PLATFORM_INFO = 0xCE;
79 private string CoreString(int i) {
83 return "CPU Core #" + (i + 1);
86 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
87 private static extern bool GetProcessAffinityMask(IntPtr handle,
88 out IntPtr processMask, out IntPtr systemMask);
90 private float[] Floats(float f) {
91 float[] result = new float[coreCount];
92 for (int i = 0; i < coreCount; i++)
97 public IntelCPU(string name, uint family, uint model, uint stepping,
98 uint[,] cpuidData, uint[,] cpuidExtData) {
101 this.icon = Utilities.EmbeddedResources.GetImage("cpu.png");
103 this.family = family;
105 this.stepping = stepping;
107 logicalProcessors = 0;
108 if (cpuidData.GetLength(0) > 0x0B) {
109 uint eax, ebx, ecx, edx;
110 WinRing0.CpuidEx(0x0B, 0, out eax, out ebx, out ecx, out edx);
111 logicalProcessorsPerCore = ebx & 0xFF;
112 if (logicalProcessorsPerCore > 0) {
113 WinRing0.CpuidEx(0x0B, 1, out eax, out ebx, out ecx, out edx);
114 logicalProcessors = ebx & 0xFF;
117 if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x04) {
118 uint coresPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
119 uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
120 logicalProcessorsPerCore = logicalPerPackage / coresPerPackage;
121 logicalProcessors = logicalPerPackage;
123 if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x01) {
124 uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
125 logicalProcessorsPerCore = logicalPerPackage;
126 logicalProcessors = logicalPerPackage;
128 if (logicalProcessors <= 0) {
129 logicalProcessors = 1;
130 logicalProcessorsPerCore = 1;
133 IntPtr processMask, systemMask;
134 GetProcessAffinityMask(Process.GetCurrentProcess().Handle,
135 out processMask, out systemMask);
136 affinityMask = (ulong)systemMask;
138 // correct values in case HypeThreading is disabled
139 if (logicalProcessorsPerCore > 1) {
140 ulong affinity = affinityMask;
141 int availableLogicalProcessors = 0;
142 while (affinity != 0) {
143 if ((affinity & 0x1) > 0)
144 availableLogicalProcessors++;
147 while (logicalProcessorsPerCore > 1 &&
148 availableLogicalProcessors < logicalProcessors) {
149 logicalProcessors >>= 1;
150 logicalProcessorsPerCore >>= 1;
154 coreCount = logicalProcessors / logicalProcessorsPerCore;
160 case 0x0F: // Intel Core (65nm)
165 tjMax = Floats(80 + 10); break;
167 tjMax = Floats(90 + 10); break;
169 tjMax = Floats(85 + 10); break;
171 tjMax = Floats(80 + 10); break;
173 tjMax = Floats(90 + 10); break;
175 tjMax = Floats(85 + 10); break;
177 tjMax = Floats(85 + 10); break;
179 case 0x17: // Intel Core (45nm)
180 tjMax = Floats(100); break;
181 case 0x1C: // Intel Atom
182 tjMax = Floats(90); break;
183 case 0x1A: // Intel Core i7 LGA1366 (45nm)
184 case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
185 case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
187 tjMax = new float[coreCount];
188 for (int i = 0; i < coreCount; i++) {
189 if (WinRing0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
191 1 << (int)(logicalProcessorsPerCore * i))))
193 tjMax[i] = (eax >> 16) & 0xFF;
198 if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
199 maxNehalemMultiplier = (eax >> 8) & 0xff;
203 tjMax = Floats(100); break;
206 default: tjMax = Floats(100); break;
209 // check if processor supports a digital thermal sensor
210 if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) {
211 coreTemperatures = new Sensor[coreCount];
212 for (int i = 0; i < coreTemperatures.Length; i++) {
213 coreTemperatures[i] = new Sensor(CoreString(i), i, tjMax[i],
214 SensorType.Temperature, this, new ParameterDescription[] {
215 new ParameterDescription(
216 "TjMax", "TjMax temperature of the core.\n" +
217 "Temperature = TjMax - TSlope * Value.", tjMax[i]),
218 new ParameterDescription(
219 "TSlope", "Temperature slope of the digital thermal sensor.\n" +
220 "Temperature = TjMax - TSlope * Value.", 1)});
223 coreTemperatures = new Sensor[0];
227 totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);
230 coreLoads = new Sensor[coreCount];
231 for (int i = 0; i < coreLoads.Length; i++)
232 coreLoads[i] = new Sensor(CoreString(i), i + 1,
233 SensorType.Load, this);
234 cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore);
235 if (cpuLoad.IsAvailable) {
236 foreach (Sensor sensor in coreLoads)
237 ActivateSensor(sensor);
238 if (totalLoad != null)
239 ActivateSensor(totalLoad);
244 busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this);
245 coreClocks = new Sensor[coreCount];
246 for (int i = 0; i < coreClocks.Length; i++) {
248 new Sensor(CoreString(i), i + 1, SensorType.Clock, this);
249 ActivateSensor(coreClocks[i]);
259 public string Identifier {
260 get { return "/intelcpu/0"; }
267 private void AppendMSRData(StringBuilder r, uint msr, int core) {
269 if (WinRing0.RdmsrTx(msr, out eax, out edx,
270 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * core)))) {
272 r.Append((msr).ToString("X8"));
274 r.Append((edx).ToString("X8"));
276 r.Append((eax).ToString("X8"));
281 public string GetReport() {
282 StringBuilder r = new StringBuilder();
284 r.AppendLine("Intel CPU");
286 r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
287 r.AppendFormat("Number of Cores: {0}{1}", coreCount,
288 Environment.NewLine);
289 r.AppendFormat("Threads per Core: {0}{1}", logicalProcessorsPerCore,
290 Environment.NewLine);
291 r.AppendFormat("Affinity Mask: 0x{0}{1}", affinityMask.ToString("X"),
292 Environment.NewLine);
295 for (int i = 0; i < coreCount; i++) {
296 r.AppendLine("MSR Core #" + (i + 1));
298 r.AppendLine(" MSR EDX EAX");
299 AppendMSRData(r, MSR_PLATFORM_INFO, i);
300 AppendMSRData(r, IA32_PERF_STATUS, i);
301 AppendMSRData(r, IA32_THERM_STATUS_MSR, i);
302 AppendMSRData(r, IA32_TEMPERATURE_TARGET, i);
309 public void Update() {
311 for (int i = 0; i < coreTemperatures.Length; i++) {
313 if (WinRing0.RdmsrTx(
314 IA32_THERM_STATUS_MSR, out eax, out edx,
315 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i))))
317 // if reading is valid
318 if ((eax & 0x80000000) != 0) {
319 // get the dist from tjMax from bits 22:16
320 float deltaT = ((eax & 0x007F0000) >> 16);
321 float tjMax = coreTemperatures[i].Parameters[0].Value;
322 float tSlope = coreTemperatures[i].Parameters[1].Value;
323 coreTemperatures[i].Value = tjMax - tSlope * deltaT;
324 ActivateSensor(coreTemperatures[i]);
326 DeactivateSensor(coreTemperatures[i]);
331 if (cpuLoad.IsAvailable) {
333 for (int i = 0; i < coreLoads.Length; i++)
334 coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
335 if (totalLoad != null)
336 totalLoad.Value = cpuLoad.GetTotalLoad();
340 bool valid = WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
341 long time = Stopwatch.GetTimestamp();
342 ulong count = ((ulong)msb << 32) | lsb;
343 double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
344 if (valid && delta > 0.5) {
345 double maxClock = (count - lastCount) / (1e6 * delta);
348 for (int i = 0; i < coreClocks.Length; i++) {
349 System.Threading.Thread.Sleep(1);
350 if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
351 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
352 if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
353 uint nehalemMultiplier = eax & 0xff;
354 coreClocks[i].Value =
355 (float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
356 busClock = (float)(maxClock / maxNehalemMultiplier);
358 uint multiplier = (eax >> 8) & 0x1f;
359 uint maxMultiplier = (edx >> 8) & 0x1f;
360 // factor = multiplier * 2 to handle non integer multipliers
361 uint factor = (multiplier << 1) | ((eax >> 14) & 1);
362 uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
364 coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
365 busClock = (float)(2 * maxClock / maxFactor);
368 } else { // Intel Pentium 4
369 // if IA32_PERF_STATUS is not available, assume maxClock
370 coreClocks[i].Value = (float)maxClock;
374 this.busClock.Value = (float)busClock;
375 ActivateSensor(this.busClock);