Added core and bus clock support for Intel CPUs (Core 2).
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 {
51 private Sensor[] coreTemperatures;
52 private Sensor totalLoad;
53 private Sensor[] coreLoads;
54 private Sensor[] coreClocks;
55 private Sensor busClock;
57 private float tjMax = 0;
58 private uint logicalProcessors;
59 private uint logicalProcessorsPerCore;
60 private uint coreCount;
62 private CPULoad cpuLoad;
64 private ulong lastCount;
65 private long lastTime;
67 private const uint IA32_THERM_STATUS_MSR = 0x019C;
68 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
69 private const uint IA32_PERF_STATUS = 0x0198;
71 public IntelCPU(string name, uint family, uint model, uint stepping,
72 uint[,] cpuidData, uint[,] cpuidExtData) {
75 this.icon = Utilities.EmbeddedResources.GetImage("cpu.png");
77 logicalProcessors = 0;
78 if (cpuidData.GetLength(0) > 0x0B) {
79 uint eax, ebx, ecx, edx;
80 WinRing0.CpuidEx(0x0B, 0, out eax, out ebx, out ecx, out edx);
81 logicalProcessorsPerCore = ebx & 0xFF;
82 if (logicalProcessorsPerCore > 0) {
83 WinRing0.CpuidEx(0x0B, 1, out eax, out ebx, out ecx, out edx);
84 logicalProcessors = ebx & 0xFF;
87 if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x04) {
88 logicalProcessors = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
89 logicalProcessorsPerCore = 1;
91 if (logicalProcessors <= 0) {
92 logicalProcessors = 1;
93 logicalProcessorsPerCore = 1;
96 coreCount = logicalProcessors / logicalProcessorsPerCore;
98 // check if processor supports a digital thermal sensor
99 if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) {
104 case 0x0F: // Intel Core 65nm
123 case 0x17: // Intel Core 45nm
125 case 0x1C: // Intel Atom
128 uint eax = 0, edx = 0;
129 if (WinRing0.RdmsrPx(
130 IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) {
131 tjMax = (eax >> 16) & 0xFF;
139 default: tjMax = 100; break;
142 coreTemperatures = new Sensor[coreCount];
143 for (int i = 0; i < coreTemperatures.Length; i++) {
144 coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
145 SensorType.Temperature, this);
148 coreTemperatures = new Sensor[0];
151 totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);
152 coreLoads = new Sensor[coreCount];
153 for (int i = 0; i < coreLoads.Length; i++)
154 coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1,
155 SensorType.Load, this);
156 cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore);
157 if (cpuLoad.IsAvailable) {
158 foreach (Sensor sensor in coreLoads)
159 ActivateSensor(sensor);
160 ActivateSensor(totalLoad);
165 busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this);
166 coreClocks = new Sensor[coreCount];
167 for (int i = 0; i < coreClocks.Length; i++) {
169 new Sensor("Core #" + (i + 1), i + 1, SensorType.Clock, this);
170 ActivateSensor(coreClocks[i]);
180 public string Identifier {
181 get { return "/intelcpu/0"; }
188 public string GetReport() {
189 StringBuilder r = new StringBuilder();
191 r.AppendLine("Intel CPU");
193 r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
194 r.AppendFormat("Number of cores: {0}{1}", coreCount,
195 Environment.NewLine);
196 r.AppendFormat("Threads per core: {0}{1}", logicalProcessorsPerCore,
197 Environment.NewLine);
198 r.AppendFormat("TjMax: {0}{1}", tjMax, Environment.NewLine);
204 public void Update() {
206 for (int i = 0; i < coreTemperatures.Length; i++) {
207 uint eax = 0, edx = 0;
208 if (WinRing0.RdmsrPx(
209 IA32_THERM_STATUS_MSR, ref eax, ref edx,
210 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i))))
212 // if reading is valid
213 if ((eax & 0x80000000) != 0) {
214 // get the dist from tjMax from bits 22:16
215 coreTemperatures[i].Value = tjMax - ((eax & 0x007F0000) >> 16);
216 ActivateSensor(coreTemperatures[i]);
218 DeactivateSensor(coreTemperatures[i]);
223 if (cpuLoad.IsAvailable) {
225 for (int i = 0; i < coreLoads.Length; i++)
226 coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
227 totalLoad.Value = cpuLoad.GetTotalLoad();
230 uint lsb = 0, msb = 0;
231 bool valid = WinRing0.RdtscPx(ref lsb, ref msb, (UIntPtr)1);
232 long time = Stopwatch.GetTimestamp();
233 ulong count = ((ulong)msb << 32) | lsb;
234 double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
235 if (valid && delta > 0.5) {
236 double maxClock = (float)((count - lastCount) / (1e6 * delta));
239 for (int i = 0; i < coreClocks.Length; i++) {
241 System.Threading.Thread.Sleep(1);
242 if (WinRing0.RdmsrPx(IA32_PERF_STATUS, ref eax, ref edx,
243 (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
244 uint multiplier = (eax >> 8) & 0x1f;
245 uint maxMultiplier = (edx >> 8) & 0x1f;
246 // factor = multiplier * 2 to handle non integer multipliers
247 uint factor = (multiplier << 1) | ((eax >> 14) & 1);
248 uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
250 coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
251 busClock = (float)(2 * maxClock / maxFactor);
254 // if IA32_PERF_STATUS is not available, assume maxClock
255 coreClocks[i].Value = (float)maxClock;
259 this.busClock.Value = (float)busClock;
260 ActivateSensor(this.busClock);