Fixed the Intel Sandy Bridge CPU core clock calculation.
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.Globalization;
42 namespace OpenHardwareMonitor.Hardware.CPU {
43 internal sealed class IntelCPU : GenericCPU {
45 private enum Microarchitecture {
53 private readonly Sensor[] coreTemperatures;
54 private readonly Sensor[] coreClocks;
55 private readonly Sensor busClock;
57 private readonly Microarchitecture microarchitecture;
58 private readonly double timeStampCounterMultiplier;
60 private const uint IA32_THERM_STATUS_MSR = 0x019C;
61 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
62 private const uint IA32_PERF_STATUS = 0x0198;
63 private const uint MSR_PLATFORM_INFO = 0xCE;
65 private float[] Floats(float f) {
66 float[] result = new float[coreCount];
67 for (int i = 0; i < coreCount; i++)
72 private float[] GetTjMaxFromMSR() {
74 float[] result = new float[coreCount];
75 for (int i = 0; i < coreCount; i++) {
76 if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
77 out edx, 1UL << cpuid[i][0].Thread)) {
78 result[i] = (eax >> 16) & 0xFF;
86 public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
87 : base(processorIndex, cpuid, settings)
94 case 0x0F: // Intel Core 2 (65nm)
95 microarchitecture = Microarchitecture.Core;
100 tjMax = Floats(80 + 10); break;
102 tjMax = Floats(90 + 10); break;
104 tjMax = Floats(85 + 10); break;
106 tjMax = Floats(80 + 10); break;
108 tjMax = Floats(90 + 10); break;
110 tjMax = Floats(85 + 10); break;
112 tjMax = Floats(85 + 10); break;
114 case 0x17: // Intel Core 2 (45nm)
115 microarchitecture = Microarchitecture.Core;
116 tjMax = Floats(100); break;
117 case 0x1C: // Intel Atom (45nm)
118 microarchitecture = Microarchitecture.Atom;
121 tjMax = Floats(90); break;
123 tjMax = Floats(100); break;
125 tjMax = Floats(90); break;
127 case 0x1A: // Intel Core i7 LGA1366 (45nm)
128 case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
129 case 0x1F: // Intel Core i5, i7
130 case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
131 case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
132 case 0x2E: // Intel Xeon Processor 7500 series
133 microarchitecture = Microarchitecture.Nehalem;
134 tjMax = GetTjMaxFromMSR();
136 case 0x2A: // Intel Core i5, i7 2xxx LGA1155 (32nm)
137 case 0x2D: // Next Generation Intel Xeon Processor
138 microarchitecture = Microarchitecture.SandyBridge;
139 tjMax = GetTjMaxFromMSR();
142 microarchitecture = Microarchitecture.Unknown;
148 microarchitecture = Microarchitecture.Unknown;
153 // set timeStampCounterMultiplier
154 switch (microarchitecture) {
155 case Microarchitecture.Atom:
156 case Microarchitecture.Core: {
158 if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
159 timeStampCounterMultiplier =
160 ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
163 case Microarchitecture.Nehalem:
164 case Microarchitecture.SandyBridge: {
166 if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
167 timeStampCounterMultiplier = (eax >> 8) & 0xff;
171 timeStampCounterMultiplier = 1;
175 // check if processor supports a digital thermal sensor
176 if (cpuid[0][0].Data.GetLength(0) > 6 &&
177 (cpuid[0][0].Data[6, 0] & 1) != 0) {
178 coreTemperatures = new Sensor[coreCount];
179 for (int i = 0; i < coreTemperatures.Length; i++) {
180 coreTemperatures[i] = new Sensor(CoreString(i), i,
181 SensorType.Temperature, this, new [] {
182 new ParameterDescription(
183 "TjMax [°C]", "TjMax temperature of the core.\n" +
184 "Temperature = TjMax - TSlope * Value.", tjMax[i]),
185 new ParameterDescription("TSlope [°C]",
186 "Temperature slope of the digital thermal sensor.\n" +
187 "Temperature = TjMax - TSlope * Value.", 1)}, settings);
188 ActivateSensor(coreTemperatures[i]);
191 coreTemperatures = new Sensor[0];
194 busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
195 coreClocks = new Sensor[coreCount];
196 for (int i = 0; i < coreClocks.Length; i++) {
198 new Sensor(CoreString(i), i + 1, SensorType.Clock, this, settings);
199 if (HasTimeStampCounter)
200 ActivateSensor(coreClocks[i]);
206 protected override uint[] GetMSRs() {
210 IA32_THERM_STATUS_MSR,
211 IA32_TEMPERATURE_TARGET
215 public override string GetReport() {
216 StringBuilder r = new StringBuilder();
217 r.Append(base.GetReport());
219 r.Append("Time Stamp Counter Multiplier: ");
220 r.AppendLine(timeStampCounterMultiplier.ToString(
221 CultureInfo.InvariantCulture));
227 public override void Update() {
230 for (int i = 0; i < coreTemperatures.Length; i++) {
233 IA32_THERM_STATUS_MSR, out eax, out edx,
234 1UL << cpuid[i][0].Thread)) {
235 // if reading is valid
236 if ((eax & 0x80000000) != 0) {
237 // get the dist from tjMax from bits 22:16
238 float deltaT = ((eax & 0x007F0000) >> 16);
239 float tjMax = coreTemperatures[i].Parameters[0].Value;
240 float tSlope = coreTemperatures[i].Parameters[1].Value;
241 coreTemperatures[i].Value = tjMax - tSlope * deltaT;
243 coreTemperatures[i].Value = null;
248 if (HasTimeStampCounter) {
249 double newBusClock = 0;
251 for (int i = 0; i < coreClocks.Length; i++) {
252 System.Threading.Thread.Sleep(1);
253 if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
254 1UL << cpuid[i][0].Thread))
257 TimeStampCounterFrequency / timeStampCounterMultiplier;
258 switch (microarchitecture) {
259 case Microarchitecture.Nehalem: {
260 uint multiplier = eax & 0xff;
261 coreClocks[i].Value = (float)(multiplier * newBusClock);
263 case Microarchitecture.SandyBridge: {
264 uint multiplier = (eax >> 8) & 0xff;
265 coreClocks[i].Value = (float)(multiplier * newBusClock);
269 ((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
270 coreClocks[i].Value = (float)(multiplier * newBusClock);
274 // if IA32_PERF_STATUS is not available, assume TSC frequency
275 coreClocks[i].Value = (float)TimeStampCounterFrequency;
278 if (newBusClock > 0) {
279 this.busClock.Value = (float)newBusClock;
280 ActivateSensor(this.busClock);