Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Globalization;
15 namespace OpenHardwareMonitor.Hardware.CPU {
16 internal sealed class IntelCPU : GenericCPU {
18 private enum Microarchitecture {
28 private readonly Sensor[] coreTemperatures;
29 private readonly Sensor packageTemperature;
30 private readonly Sensor[] coreClocks;
31 private readonly Sensor busClock;
32 private readonly Sensor[] powerSensors;
34 private readonly Microarchitecture microarchitecture;
35 private readonly double timeStampCounterMultiplier;
37 private const uint IA32_THERM_STATUS_MSR = 0x019C;
38 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
39 private const uint IA32_PERF_STATUS = 0x0198;
40 private const uint MSR_PLATFORM_INFO = 0xCE;
41 private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1;
42 private const uint MSR_RAPL_POWER_UNIT = 0x606;
43 private const uint MSR_PKG_ENERY_STATUS = 0x611;
44 private const uint MSR_DRAM_ENERGY_STATUS = 0x619;
45 private const uint MSR_PP0_ENERY_STATUS = 0x639;
46 private const uint MSR_PP1_ENERY_STATUS = 0x641;
48 private readonly uint[] energyStatusMSRs = { MSR_PKG_ENERY_STATUS,
49 MSR_PP0_ENERY_STATUS, MSR_PP1_ENERY_STATUS, MSR_DRAM_ENERGY_STATUS };
50 private readonly string[] powerSensorLabels =
51 { "CPU Package", "CPU Cores", "CPU Graphics", "CPU DRAM" };
52 private float energyUnitMultiplier = 0;
53 private DateTime[] lastEnergyTime;
54 private uint[] lastEnergyConsumed;
57 private float[] Floats(float f) {
58 float[] result = new float[coreCount];
59 for (int i = 0; i < coreCount; i++)
64 private float[] GetTjMaxFromMSR() {
66 float[] result = new float[coreCount];
67 for (int i = 0; i < coreCount; i++) {
68 if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
69 out edx, 1UL << cpuid[i][0].Thread)) {
70 result[i] = (eax >> 16) & 0xFF;
78 public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
79 : base(processorIndex, cpuid, settings) {
85 case 0x0F: // Intel Core 2 (65nm)
86 microarchitecture = Microarchitecture.Core;
91 tjMax = Floats(80 + 10); break;
93 tjMax = Floats(90 + 10); break;
95 tjMax = Floats(85 + 10); break;
97 tjMax = Floats(80 + 10); break;
99 tjMax = Floats(90 + 10); break;
101 tjMax = Floats(85 + 10); break;
103 tjMax = Floats(85 + 10); break;
105 case 0x17: // Intel Core 2 (45nm)
106 microarchitecture = Microarchitecture.Core;
107 tjMax = Floats(100); break;
108 case 0x1C: // Intel Atom (45nm)
109 microarchitecture = Microarchitecture.Atom;
112 tjMax = Floats(90); break;
114 tjMax = Floats(100); break;
116 tjMax = Floats(90); break;
118 case 0x1A: // Intel Core i7 LGA1366 (45nm)
119 case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
120 case 0x1F: // Intel Core i5, i7
121 case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
122 case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
123 case 0x2E: // Intel Xeon Processor 7500 series (45nm)
124 case 0x2F: // Intel Xeon Processor (32nm)
125 microarchitecture = Microarchitecture.Nehalem;
126 tjMax = GetTjMaxFromMSR();
128 case 0x2A: // Intel Core i5, i7 2xxx LGA1155 (32nm)
129 case 0x2D: // Next Generation Intel Xeon, i7 3xxx LGA2011 (32nm)
130 microarchitecture = Microarchitecture.SandyBridge;
131 tjMax = GetTjMaxFromMSR();
133 case 0x3A: // Intel Core i5, i7 3xxx LGA1155 (22nm)
134 microarchitecture = Microarchitecture.IvyBridge;
135 tjMax = GetTjMaxFromMSR();
138 microarchitecture = Microarchitecture.Unknown;
145 case 0x00: // Pentium 4 (180nm)
146 case 0x01: // Pentium 4 (130nm)
147 case 0x02: // Pentium 4 (130nm)
148 case 0x03: // Pentium 4, Celeron D (90nm)
149 case 0x04: // Pentium 4, Pentium D, Celeron D (90nm)
150 case 0x06: // Pentium 4, Pentium D, Celeron D (65nm)
151 microarchitecture = Microarchitecture.NetBurst;
155 microarchitecture = Microarchitecture.Unknown;
161 microarchitecture = Microarchitecture.Unknown;
166 // set timeStampCounterMultiplier
167 switch (microarchitecture) {
168 case Microarchitecture.NetBurst:
169 case Microarchitecture.Atom:
170 case Microarchitecture.Core: {
172 if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
173 timeStampCounterMultiplier =
174 ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
177 case Microarchitecture.Nehalem:
178 case Microarchitecture.SandyBridge:
179 case Microarchitecture.IvyBridge: {
181 if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
182 timeStampCounterMultiplier = (eax >> 8) & 0xff;
186 timeStampCounterMultiplier = 0;
190 // check if processor supports a digital thermal sensor at core level
191 if (cpuid[0][0].Data.GetLength(0) > 6 &&
192 (cpuid[0][0].Data[6, 0] & 1) != 0 &&
193 microarchitecture != Microarchitecture.Unknown)
195 coreTemperatures = new Sensor[coreCount];
196 for (int i = 0; i < coreTemperatures.Length; i++) {
197 coreTemperatures[i] = new Sensor(CoreString(i), i,
198 SensorType.Temperature, this, new[] {
199 new ParameterDescription(
200 "TjMax [°C]", "TjMax temperature of the core sensor.\n" +
201 "Temperature = TjMax - TSlope * Value.", tjMax[i]),
202 new ParameterDescription("TSlope [°C]",
203 "Temperature slope of the digital thermal sensor.\n" +
204 "Temperature = TjMax - TSlope * Value.", 1)}, settings);
205 ActivateSensor(coreTemperatures[i]);
208 coreTemperatures = new Sensor[0];
211 // check if processor supports a digital thermal sensor at package level
212 if (cpuid[0][0].Data.GetLength(0) > 6 &&
213 (cpuid[0][0].Data[6, 0] & 0x40) != 0 &&
214 microarchitecture != Microarchitecture.Unknown)
216 packageTemperature = new Sensor("CPU Package",
217 coreTemperatures.Length, SensorType.Temperature, this, new[] {
218 new ParameterDescription(
219 "TjMax [°C]", "TjMax temperature of the package sensor.\n" +
220 "Temperature = TjMax - TSlope * Value.", tjMax[0]),
221 new ParameterDescription("TSlope [°C]",
222 "Temperature slope of the digital thermal sensor.\n" +
223 "Temperature = TjMax - TSlope * Value.", 1)}, settings);
224 ActivateSensor(packageTemperature);
227 busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
228 coreClocks = new Sensor[coreCount];
229 for (int i = 0; i < coreClocks.Length; i++) {
231 new Sensor(CoreString(i), i + 1, SensorType.Clock, this, settings);
232 if (HasTimeStampCounter && microarchitecture != Microarchitecture.Unknown)
233 ActivateSensor(coreClocks[i]);
236 if (microarchitecture == Microarchitecture.SandyBridge ||
237 microarchitecture == Microarchitecture.IvyBridge)
239 powerSensors = new Sensor[energyStatusMSRs.Length];
240 lastEnergyTime = new DateTime[energyStatusMSRs.Length];
241 lastEnergyConsumed = new uint[energyStatusMSRs.Length];
244 if (Ring0.Rdmsr(MSR_RAPL_POWER_UNIT, out eax, out edx))
245 energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1FF));
247 if (energyUnitMultiplier != 0) {
248 for (int i = 0; i < energyStatusMSRs.Length; i++) {
249 if (!Ring0.Rdmsr(energyStatusMSRs[i], out eax, out edx))
252 lastEnergyTime[i] = DateTime.UtcNow;
253 lastEnergyConsumed[i] = eax;
254 powerSensors[i] = new Sensor(powerSensorLabels[i], i,
255 SensorType.Power, this, settings);
256 ActivateSensor(powerSensors[i]);
264 protected override uint[] GetMSRs() {
268 IA32_THERM_STATUS_MSR,
269 IA32_TEMPERATURE_TARGET,
270 IA32_PACKAGE_THERM_STATUS,
272 MSR_PKG_ENERY_STATUS,
273 MSR_DRAM_ENERGY_STATUS,
274 MSR_PP0_ENERY_STATUS,
279 public override string GetReport() {
280 StringBuilder r = new StringBuilder();
281 r.Append(base.GetReport());
283 r.Append("Microarchitecture: ");
284 r.AppendLine(microarchitecture.ToString());
285 r.Append("Time Stamp Counter Multiplier: ");
286 r.AppendLine(timeStampCounterMultiplier.ToString(
287 CultureInfo.InvariantCulture));
293 public override void Update() {
296 for (int i = 0; i < coreTemperatures.Length; i++) {
299 IA32_THERM_STATUS_MSR, out eax, out edx,
300 1UL << cpuid[i][0].Thread)) {
301 // if reading is valid
302 if ((eax & 0x80000000) != 0) {
303 // get the dist from tjMax from bits 22:16
304 float deltaT = ((eax & 0x007F0000) >> 16);
305 float tjMax = coreTemperatures[i].Parameters[0].Value;
306 float tSlope = coreTemperatures[i].Parameters[1].Value;
307 coreTemperatures[i].Value = tjMax - tSlope * deltaT;
309 coreTemperatures[i].Value = null;
314 if (packageTemperature != null) {
317 IA32_PACKAGE_THERM_STATUS, out eax, out edx,
318 1UL << cpuid[0][0].Thread)) {
319 // get the dist from tjMax from bits 22:16
320 float deltaT = ((eax & 0x007F0000) >> 16);
321 float tjMax = packageTemperature.Parameters[0].Value;
322 float tSlope = packageTemperature.Parameters[1].Value;
323 packageTemperature.Value = tjMax - tSlope * deltaT;
325 packageTemperature.Value = null;
329 if (HasTimeStampCounter && timeStampCounterMultiplier > 0) {
330 double newBusClock = 0;
332 for (int i = 0; i < coreClocks.Length; i++) {
333 System.Threading.Thread.Sleep(1);
334 if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
335 1UL << cpuid[i][0].Thread)) {
337 TimeStampCounterFrequency / timeStampCounterMultiplier;
338 switch (microarchitecture) {
339 case Microarchitecture.Nehalem: {
340 uint multiplier = eax & 0xff;
341 coreClocks[i].Value = (float)(multiplier * newBusClock);
343 case Microarchitecture.SandyBridge:
344 case Microarchitecture.IvyBridge: {
345 uint multiplier = (eax >> 8) & 0xff;
346 coreClocks[i].Value = (float)(multiplier * newBusClock);
350 ((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
351 coreClocks[i].Value = (float)(multiplier * newBusClock);
355 // if IA32_PERF_STATUS is not available, assume TSC frequency
356 coreClocks[i].Value = (float)TimeStampCounterFrequency;
359 if (newBusClock > 0) {
360 this.busClock.Value = (float)newBusClock;
361 ActivateSensor(this.busClock);
365 if (powerSensors != null) {
366 foreach (Sensor sensor in powerSensors) {
371 if (!Ring0.Rdmsr(energyStatusMSRs[sensor.Index], out eax, out edx))
374 DateTime time = DateTime.UtcNow;
375 uint energyConsumed = eax;
377 (float)(time - lastEnergyTime[sensor.Index]).TotalSeconds;
378 if (deltaTime < 0.01)
381 sensor.Value = energyUnitMultiplier * unchecked(
382 energyConsumed - lastEnergyConsumed[sensor.Index]) / deltaTime;
383 lastEnergyTime[sensor.Index] = time;
384 lastEnergyConsumed[sensor.Index] = energyConsumed;