Added Added a mainboard specific configuration for the Shuttle SH67Hx barebones. Added the SMBIOS system information to the report.
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-2011
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.Globalization;
42 namespace OpenHardwareMonitor.Hardware.CPU {
43 internal sealed class IntelCPU : GenericCPU {
45 private enum Microarchitecture {
54 private readonly Sensor[] coreTemperatures;
55 private readonly Sensor packageTemperature;
56 private readonly Sensor[] coreClocks;
57 private readonly Sensor busClock;
58 private readonly Sensor packagePower;
59 private readonly Sensor coresPower;
61 private readonly Microarchitecture microarchitecture;
62 private readonly double timeStampCounterMultiplier;
64 private const uint IA32_THERM_STATUS_MSR = 0x019C;
65 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
66 private const uint IA32_PERF_STATUS = 0x0198;
67 private const uint MSR_PLATFORM_INFO = 0xCE;
68 private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1;
69 private const uint MSR_RAPL_POWER_UNIT = 0x606;
70 private const uint MSR_PKG_ENERY_STATUS = 0x611;
71 private const uint MSR_PP0_ENERY_STATUS = 0x639;
72 private const uint MSR_PP1_ENERY_STATUS = 0x641;
74 private float energyUnitMultiplier = 0;
75 private DateTime lastPackageTime;
76 private uint lastPackageEnergyConsumed;
77 private DateTime lastCoresTime;
78 private uint lastCoresEnergyConsumed;
82 private float[] Floats(float f) {
83 float[] result = new float[coreCount];
84 for (int i = 0; i < coreCount; i++)
89 private float[] GetTjMaxFromMSR() {
91 float[] result = new float[coreCount];
92 for (int i = 0; i < coreCount; i++) {
93 if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
94 out edx, 1UL << cpuid[i][0].Thread)) {
95 result[i] = (eax >> 16) & 0xFF;
103 public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
104 : base(processorIndex, cpuid, settings)
111 case 0x0F: // Intel Core 2 (65nm)
112 microarchitecture = Microarchitecture.Core;
117 tjMax = Floats(80 + 10); break;
119 tjMax = Floats(90 + 10); break;
121 tjMax = Floats(85 + 10); break;
123 tjMax = Floats(80 + 10); break;
125 tjMax = Floats(90 + 10); break;
127 tjMax = Floats(85 + 10); break;
129 tjMax = Floats(85 + 10); break;
131 case 0x17: // Intel Core 2 (45nm)
132 microarchitecture = Microarchitecture.Core;
133 tjMax = Floats(100); break;
134 case 0x1C: // Intel Atom (45nm)
135 microarchitecture = Microarchitecture.Atom;
138 tjMax = Floats(90); break;
140 tjMax = Floats(100); break;
142 tjMax = Floats(90); break;
144 case 0x1A: // Intel Core i7 LGA1366 (45nm)
145 case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
146 case 0x1F: // Intel Core i5, i7
147 case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
148 case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
149 case 0x2E: // Intel Xeon Processor 7500 series
150 microarchitecture = Microarchitecture.Nehalem;
151 tjMax = GetTjMaxFromMSR();
153 case 0x2A: // Intel Core i5, i7 2xxx LGA1155 (32nm)
154 case 0x2D: // Next Generation Intel Xeon Processor
155 microarchitecture = Microarchitecture.SandyBridge;
156 tjMax = GetTjMaxFromMSR();
159 microarchitecture = Microarchitecture.Unknown;
166 case 0x00: // Pentium 4 (180nm)
167 case 0x01: // Pentium 4 (130nm)
168 case 0x02: // Pentium 4 (130nm)
169 case 0x03: // Pentium 4, Celeron D (90nm)
170 case 0x04: // Pentium 4, Pentium D, Celeron D (90nm)
171 case 0x06: // Pentium 4, Pentium D, Celeron D (65nm)
172 microarchitecture = Microarchitecture.NetBurst;
176 microarchitecture = Microarchitecture.Unknown;
182 microarchitecture = Microarchitecture.Unknown;
187 // set timeStampCounterMultiplier
188 switch (microarchitecture) {
189 case Microarchitecture.NetBurst:
190 case Microarchitecture.Atom:
191 case Microarchitecture.Core: {
193 if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
194 timeStampCounterMultiplier =
195 ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
198 case Microarchitecture.Nehalem:
199 case Microarchitecture.SandyBridge: {
201 if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
202 timeStampCounterMultiplier = (eax >> 8) & 0xff;
206 timeStampCounterMultiplier = 1;
208 if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
209 timeStampCounterMultiplier =
210 ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
215 // check if processor supports a digital thermal sensor at core level
216 if (cpuid[0][0].Data.GetLength(0) > 6 &&
217 (cpuid[0][0].Data[6, 0] & 1) != 0)
219 coreTemperatures = new Sensor[coreCount];
220 for (int i = 0; i < coreTemperatures.Length; i++) {
221 coreTemperatures[i] = new Sensor(CoreString(i), i,
222 SensorType.Temperature, this, new [] {
223 new ParameterDescription(
224 "TjMax [°C]", "TjMax temperature of the core sensor.\n" +
225 "Temperature = TjMax - TSlope * Value.", tjMax[i]),
226 new ParameterDescription("TSlope [°C]",
227 "Temperature slope of the digital thermal sensor.\n" +
228 "Temperature = TjMax - TSlope * Value.", 1)}, settings);
229 ActivateSensor(coreTemperatures[i]);
232 coreTemperatures = new Sensor[0];
235 // check if processor supports a digital thermal sensor at package level
236 if (cpuid[0][0].Data.GetLength(0) > 6 &&
237 (cpuid[0][0].Data[6, 0] & 0x40) != 0)
239 packageTemperature = new Sensor("CPU Package",
240 coreTemperatures.Length, SensorType.Temperature, this, new[] {
241 new ParameterDescription(
242 "TjMax [°C]", "TjMax temperature of the package sensor.\n" +
243 "Temperature = TjMax - TSlope * Value.", tjMax[0]),
244 new ParameterDescription("TSlope [°C]",
245 "Temperature slope of the digital thermal sensor.\n" +
246 "Temperature = TjMax - TSlope * Value.", 1)}, settings);
247 ActivateSensor(packageTemperature);
250 busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
251 coreClocks = new Sensor[coreCount];
252 for (int i = 0; i < coreClocks.Length; i++) {
254 new Sensor(CoreString(i), i + 1, SensorType.Clock, this, settings);
255 if (HasTimeStampCounter)
256 ActivateSensor(coreClocks[i]);
259 if (microarchitecture == Microarchitecture.SandyBridge) {
261 if (Ring0.Rdmsr(MSR_RAPL_POWER_UNIT, out eax, out edx))
262 energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1FF));
265 if (energyUnitMultiplier != 0 &&
266 Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx))
268 lastPackageTime = DateTime.UtcNow;
269 lastPackageEnergyConsumed = eax;
270 packagePower = new Sensor("CPU Package", 0, SensorType.Power, this,
272 ActivateSensor(packagePower);
275 if (energyUnitMultiplier != 0 &&
276 Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx))
278 lastCoresTime = DateTime.UtcNow;
279 lastCoresEnergyConsumed = eax;
280 coresPower = new Sensor("CPU Cores", 1, SensorType.Power, this,
282 ActivateSensor(coresPower);
289 protected override uint[] GetMSRs() {
293 IA32_THERM_STATUS_MSR,
294 IA32_TEMPERATURE_TARGET,
295 IA32_PACKAGE_THERM_STATUS,
297 MSR_PKG_ENERY_STATUS,
298 MSR_PP0_ENERY_STATUS,
303 public override string GetReport() {
304 StringBuilder r = new StringBuilder();
305 r.Append(base.GetReport());
307 r.Append("Microarchitecture: ");
308 r.AppendLine(microarchitecture.ToString());
309 r.Append("Time Stamp Counter Multiplier: ");
310 r.AppendLine(timeStampCounterMultiplier.ToString(
311 CultureInfo.InvariantCulture));
317 public override void Update() {
320 for (int i = 0; i < coreTemperatures.Length; i++) {
323 IA32_THERM_STATUS_MSR, out eax, out edx,
324 1UL << cpuid[i][0].Thread)) {
325 // if reading is valid
326 if ((eax & 0x80000000) != 0) {
327 // get the dist from tjMax from bits 22:16
328 float deltaT = ((eax & 0x007F0000) >> 16);
329 float tjMax = coreTemperatures[i].Parameters[0].Value;
330 float tSlope = coreTemperatures[i].Parameters[1].Value;
331 coreTemperatures[i].Value = tjMax - tSlope * deltaT;
333 coreTemperatures[i].Value = null;
338 if (packageTemperature != null) {
341 IA32_PACKAGE_THERM_STATUS, out eax, out edx,
342 1UL << cpuid[0][0].Thread)) {
343 // get the dist from tjMax from bits 22:16
344 float deltaT = ((eax & 0x007F0000) >> 16);
345 float tjMax = packageTemperature.Parameters[0].Value;
346 float tSlope = packageTemperature.Parameters[1].Value;
347 packageTemperature.Value = tjMax - tSlope * deltaT;
349 packageTemperature.Value = null;
353 if (HasTimeStampCounter) {
354 double newBusClock = 0;
356 for (int i = 0; i < coreClocks.Length; i++) {
357 System.Threading.Thread.Sleep(1);
358 if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
359 1UL << cpuid[i][0].Thread))
362 TimeStampCounterFrequency / timeStampCounterMultiplier;
363 switch (microarchitecture) {
364 case Microarchitecture.Nehalem: {
365 uint multiplier = eax & 0xff;
366 coreClocks[i].Value = (float)(multiplier * newBusClock);
368 case Microarchitecture.SandyBridge: {
369 uint multiplier = (eax >> 8) & 0xff;
370 coreClocks[i].Value = (float)(multiplier * newBusClock);
374 ((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
375 coreClocks[i].Value = (float)(multiplier * newBusClock);
379 // if IA32_PERF_STATUS is not available, assume TSC frequency
380 coreClocks[i].Value = (float)TimeStampCounterFrequency;
383 if (newBusClock > 0) {
384 this.busClock.Value = (float)newBusClock;
385 ActivateSensor(this.busClock);
390 if (packagePower != null) {
392 if (Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) {
393 DateTime time = DateTime.UtcNow;
394 uint energyConsumed = eax;
395 float deltaTime = (float)(time - lastPackageTime).TotalSeconds;
396 if (deltaTime > 0.01) {
397 packagePower.Value = energyUnitMultiplier *
398 unchecked(energyConsumed - lastPackageEnergyConsumed) / deltaTime;
399 lastPackageTime = time;
400 lastPackageEnergyConsumed = energyConsumed;
405 if (coresPower != null) {
407 if (Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx)) {
408 DateTime time = DateTime.UtcNow;
409 uint energyConsumed = eax;
410 float deltaTime = (float)(time - lastCoresTime).TotalSeconds;
411 if (deltaTime > 0.01) {
412 coresPower.Value = energyUnitMultiplier *
413 unchecked(energyConsumed - lastCoresEnergyConsumed) / deltaTime;
414 lastCoresTime = time;
415 lastCoresEnergyConsumed = energyConsumed;