1.1 --- a/Hardware/CPU/IntelCPU.cs Sat Sep 18 19:56:39 2010 +0000
1.2 +++ b/Hardware/CPU/IntelCPU.cs Mon Sep 20 19:28:25 2010 +0000
1.3 @@ -37,52 +37,21 @@
1.4
1.5 using System;
1.6 using System.Collections.Generic;
1.7 -using System.Diagnostics;
1.8 -using System.Globalization;
1.9 -using System.Text;
1.10 -using System.Threading;
1.11
1.12 namespace OpenHardwareMonitor.Hardware.CPU {
1.13 - internal sealed class IntelCPU : Hardware, IHardware {
1.14 -
1.15 - private int processorIndex;
1.16 - private CPUID[][] cpuid;
1.17 - private int coreCount;
1.18 -
1.19 - private string name;
1.20 -
1.21 - private uint family;
1.22 - private uint model;
1.23 - private uint stepping;
1.24 + internal sealed class IntelCPU : GenericCPU {
1.25
1.26 private Sensor[] coreTemperatures;
1.27 + private Sensor[] coreClocks;
1.28 + private Sensor busClock;
1.29
1.30 - private Sensor totalLoad;
1.31 - private Sensor[] coreLoads;
1.32 - private Sensor[] coreClocks;
1.33 - private Sensor busClock;
1.34 - private bool hasTSC;
1.35 - private bool invariantTSC;
1.36 - private double estimatedMaxClock;
1.37 + private uint maxNehalemMultiplier = 0;
1.38
1.39 - private CPULoad cpuLoad;
1.40 -
1.41 - private ulong lastTimeStampCount;
1.42 - private long lastTime;
1.43 - private uint maxNehalemMultiplier = 0;
1.44 -
1.45 private const uint IA32_THERM_STATUS_MSR = 0x019C;
1.46 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
1.47 private const uint IA32_PERF_STATUS = 0x0198;
1.48 private const uint MSR_PLATFORM_INFO = 0xCE;
1.49
1.50 - private string CoreString(int i) {
1.51 - if (coreCount == 1)
1.52 - return "CPU Core";
1.53 - else
1.54 - return "CPU Core #" + (i + 1);
1.55 - }
1.56 -
1.57 private float[] Floats(float f) {
1.58 float[] result = new float[coreCount];
1.59 for (int i = 0; i < coreCount; i++)
1.60 @@ -90,17 +59,9 @@
1.61 return result;
1.62 }
1.63
1.64 - public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings) {
1.65 -
1.66 - this.processorIndex = processorIndex;
1.67 - this.cpuid = cpuid;
1.68 - this.coreCount = cpuid.Length;
1.69 - this.name = cpuid[0][0].Name;
1.70 -
1.71 - this.family = cpuid[0][0].Family;
1.72 - this.model = cpuid[0][0].Model;
1.73 - this.stepping = cpuid[0][0].Stepping;
1.74 -
1.75 + public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
1.76 + : base(processorIndex, cpuid, settings)
1.77 + {
1.78 float[] tjMax;
1.79 switch (family) {
1.80 case 0x06: {
1.81 @@ -134,7 +95,7 @@
1.82 tjMax = Floats(100); break;
1.83 default:
1.84 tjMax = Floats(90); break;
1.85 - } break;
1.86 + } break;
1.87 case 0x1A: // Intel Core i7 LGA1366 (45nm)
1.88 case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
1.89 case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
1.90 @@ -143,8 +104,7 @@
1.91 tjMax = new float[coreCount];
1.92 for (int i = 0; i < coreCount; i++) {
1.93 if (WinRing0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
1.94 - out edx, (UIntPtr)(1L << cpuid[i][0].Thread)))
1.95 - {
1.96 + out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) {
1.97 tjMax[i] = (eax >> 16) & 0xFF;
1.98 } else {
1.99 tjMax[i] = 100;
1.100 @@ -162,9 +122,8 @@
1.101 }
1.102
1.103 // check if processor supports a digital thermal sensor
1.104 - if (cpuid[0][0].Data.GetLength(0) > 6 &&
1.105 - (cpuid[0][0].Data[6, 0] & 1) != 0)
1.106 - {
1.107 + if (cpuid[0][0].Data.GetLength(0) > 6 &&
1.108 + (cpuid[0][0].Data[6, 0] & 1) != 0) {
1.109 coreTemperatures = new Sensor[coreCount];
1.110 for (int i = 0; i < coreTemperatures.Length; i++) {
1.111 coreTemperatures[i] = new Sensor(CoreString(i), i,
1.112 @@ -181,50 +140,7 @@
1.113 coreTemperatures = new Sensor[0];
1.114 }
1.115
1.116 - if (coreCount > 1)
1.117 - totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this, settings);
1.118 - else
1.119 - totalLoad = null;
1.120 - coreLoads = new Sensor[coreCount];
1.121 - for (int i = 0; i < coreLoads.Length; i++)
1.122 - coreLoads[i] = new Sensor(CoreString(i), i + 1,
1.123 - SensorType.Load, this, settings);
1.124 - cpuLoad = new CPULoad(cpuid);
1.125 - if (cpuLoad.IsAvailable) {
1.126 - foreach (Sensor sensor in coreLoads)
1.127 - ActivateSensor(sensor);
1.128 - if (totalLoad != null)
1.129 - ActivateSensor(totalLoad);
1.130 - }
1.131 -
1.132 - // check if processor has TSC
1.133 - if (cpuid[0][0].Data.GetLength(0) > 1
1.134 - && (cpuid[0][0].Data[1, 3] & 0x10) != 0)
1.135 - hasTSC = true;
1.136 - else
1.137 - hasTSC = false;
1.138 -
1.139 - // check if processor supports invariant TSC
1.140 - if (cpuid[0][0].ExtData.GetLength(0) > 7
1.141 - && (cpuid[0][0].ExtData[7, 3] & 0x100) != 0)
1.142 - invariantTSC = true;
1.143 - else
1.144 - invariantTSC = false;
1.145 -
1.146 - // preload the function
1.147 - EstimateMaxClock(0);
1.148 - EstimateMaxClock(0);
1.149 -
1.150 - // estimate the max clock in MHz
1.151 - List<double> estimatedMaxClocks = new List<double>(3);
1.152 - for (int i = 0; i < 3; i++)
1.153 - estimatedMaxClocks.Add(1e-6 * EstimateMaxClock(0.025));
1.154 - estimatedMaxClocks.Sort();
1.155 - estimatedMaxClock = estimatedMaxClocks[1];
1.156 -
1.157 - lastTimeStampCount = 0;
1.158 - lastTime = 0;
1.159 - busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
1.160 + busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
1.161 coreClocks = new Sensor[coreCount];
1.162 for (int i = 0; i < coreClocks.Length; i++) {
1.163 coreClocks[i] =
1.164 @@ -232,96 +148,26 @@
1.165 if (hasTSC)
1.166 ActivateSensor(coreClocks[i]);
1.167 }
1.168 -
1.169 - Update();
1.170 +
1.171 + Update();
1.172 }
1.173
1.174 - public override string Name {
1.175 - get { return name; }
1.176 + protected override uint[] GetMSRs() {
1.177 + return new uint[] {
1.178 + MSR_PLATFORM_INFO,
1.179 + IA32_PERF_STATUS ,
1.180 + IA32_THERM_STATUS_MSR,
1.181 + IA32_TEMPERATURE_TARGET
1.182 + };
1.183 }
1.184
1.185 - public override Identifier Identifier {
1.186 - get {
1.187 - return new Identifier("intelcpu",
1.188 - processorIndex.ToString(CultureInfo.InvariantCulture));
1.189 - }
1.190 - }
1.191 + public override void Update() {
1.192 + base.Update();
1.193
1.194 - public override HardwareType HardwareType {
1.195 - get { return HardwareType.CPU; }
1.196 - }
1.197 -
1.198 - private static void AppendMSRData(StringBuilder r, uint msr, int thread) {
1.199 - uint eax, edx;
1.200 - if (WinRing0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) {
1.201 - r.Append(" ");
1.202 - r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
1.203 - r.Append(" ");
1.204 - r.Append((edx).ToString("X8", CultureInfo.InvariantCulture));
1.205 - r.Append(" ");
1.206 - r.Append((eax).ToString("X8", CultureInfo.InvariantCulture));
1.207 - r.AppendLine();
1.208 - }
1.209 - }
1.210 -
1.211 - public override string GetReport() {
1.212 - StringBuilder r = new StringBuilder();
1.213 -
1.214 - r.AppendLine("Intel CPU");
1.215 - r.AppendLine();
1.216 - r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
1.217 - r.AppendFormat("Number of Cores: {0}{1}", coreCount,
1.218 - Environment.NewLine);
1.219 - r.AppendFormat("Threads per Core: {0}{1}", cpuid[0].Length,
1.220 - Environment.NewLine);
1.221 - r.AppendLine("TSC: " +
1.222 - (hasTSC ? (invariantTSC ? "Invariant" : "Not Invariant") : "None"));
1.223 - r.AppendLine(string.Format(CultureInfo.InvariantCulture,
1.224 - "Timer Frequency: {0} MHz", Stopwatch.Frequency * 1e-6));
1.225 - r.AppendLine(string.Format(CultureInfo.InvariantCulture,
1.226 - "Max Clock: {0} MHz", Math.Round(estimatedMaxClock * 100) * 0.01));
1.227 - r.AppendLine();
1.228 -
1.229 - for (int i = 0; i < cpuid.Length; i++) {
1.230 - r.AppendLine("MSR Core #" + (i + 1));
1.231 - r.AppendLine();
1.232 - r.AppendLine(" MSR EDX EAX");
1.233 - AppendMSRData(r, MSR_PLATFORM_INFO, cpuid[i][0].Thread);
1.234 - AppendMSRData(r, IA32_PERF_STATUS, cpuid[i][0].Thread);
1.235 - AppendMSRData(r, IA32_THERM_STATUS_MSR, cpuid[i][0].Thread);
1.236 - AppendMSRData(r, IA32_TEMPERATURE_TARGET, cpuid[i][0].Thread);
1.237 - r.AppendLine();
1.238 - }
1.239 -
1.240 - return r.ToString();
1.241 - }
1.242 -
1.243 - private static double EstimateMaxClock(double timeWindow) {
1.244 - long ticks = (long)(timeWindow * Stopwatch.Frequency);
1.245 - uint lsbBegin, msbBegin, lsbEnd, msbEnd;
1.246 -
1.247 - Thread.BeginThreadAffinity();
1.248 - long timeBegin = Stopwatch.GetTimestamp() +
1.249 - (long)Math.Ceiling(0.001 * ticks);
1.250 - long timeEnd = timeBegin + ticks;
1.251 - while (Stopwatch.GetTimestamp() < timeBegin) { }
1.252 - WinRing0.Rdtsc(out lsbBegin, out msbBegin);
1.253 - while (Stopwatch.GetTimestamp() < timeEnd) { }
1.254 - WinRing0.Rdtsc(out lsbEnd, out msbEnd);
1.255 - Thread.EndThreadAffinity();
1.256 -
1.257 - ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
1.258 - ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
1.259 -
1.260 - return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) /
1.261 - (timeEnd - timeBegin);
1.262 - }
1.263 -
1.264 - public override void Update() {
1.265 for (int i = 0; i < coreTemperatures.Length; i++) {
1.266 uint eax, edx;
1.267 if (WinRing0.RdmsrTx(
1.268 - IA32_THERM_STATUS_MSR, out eax, out edx,
1.269 + IA32_THERM_STATUS_MSR, out eax, out edx,
1.270 (UIntPtr)(1L << cpuid[i][0].Thread))) {
1.271 // if reading is valid
1.272 if ((eax & 0x80000000) != 0) {
1.273 @@ -336,62 +182,39 @@
1.274 }
1.275 }
1.276
1.277 - if (cpuLoad.IsAvailable) {
1.278 - cpuLoad.Update();
1.279 - for (int i = 0; i < coreLoads.Length; i++)
1.280 - coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
1.281 - if (totalLoad != null)
1.282 - totalLoad.Value = cpuLoad.GetTotalLoad();
1.283 - }
1.284 -
1.285 if (hasTSC) {
1.286 - uint lsb, msb;
1.287 - WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
1.288 - long time = Stopwatch.GetTimestamp();
1.289 - ulong timeStampCount = ((ulong)msb << 32) | lsb;
1.290 - double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
1.291 - if (delta > 0.5) {
1.292 - double maxClock;
1.293 - if (invariantTSC)
1.294 - maxClock = (timeStampCount - lastTimeStampCount) / (1e6 * delta);
1.295 - else
1.296 - maxClock = estimatedMaxClock;
1.297 -
1.298 - double newBusClock = 0;
1.299 - uint eax, edx;
1.300 - for (int i = 0; i < coreClocks.Length; i++) {
1.301 - System.Threading.Thread.Sleep(1);
1.302 - if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
1.303 - (UIntPtr)(1L << cpuid[i][0].Thread))) {
1.304 - if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
1.305 - uint nehalemMultiplier = eax & 0xff;
1.306 - coreClocks[i].Value =
1.307 - (float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
1.308 - newBusClock = (float)(maxClock / maxNehalemMultiplier);
1.309 - } else { // Core 2
1.310 - uint multiplier = (eax >> 8) & 0x1f;
1.311 - uint maxMultiplier = (edx >> 8) & 0x1f;
1.312 - // factor = multiplier * 2 to handle non integer multipliers
1.313 - uint factor = (multiplier << 1) | ((eax >> 14) & 1);
1.314 - uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
1.315 - if (maxFactor > 0) {
1.316 - coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
1.317 - newBusClock = (float)(2 * maxClock / maxFactor);
1.318 - }
1.319 + double newBusClock = 0;
1.320 + uint eax, edx;
1.321 + for (int i = 0; i < coreClocks.Length; i++) {
1.322 + System.Threading.Thread.Sleep(1);
1.323 + if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
1.324 + (UIntPtr)(1L << cpuid[i][0].Thread))) {
1.325 + if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
1.326 + uint nehalemMultiplier = eax & 0xff;
1.327 + coreClocks[i].Value =
1.328 + (float)(nehalemMultiplier * MaxClock / maxNehalemMultiplier);
1.329 + newBusClock = (float)(MaxClock / maxNehalemMultiplier);
1.330 + } else { // Core 2
1.331 + uint multiplier = (eax >> 8) & 0x1f;
1.332 + uint maxMultiplier = (edx >> 8) & 0x1f;
1.333 + // factor = multiplier * 2 to handle non integer multipliers
1.334 + uint factor = (multiplier << 1) | ((eax >> 14) & 1);
1.335 + uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
1.336 + if (maxFactor > 0) {
1.337 + coreClocks[i].Value = (float)(factor * MaxClock / maxFactor);
1.338 + newBusClock = (float)(2 * MaxClock / maxFactor);
1.339 }
1.340 - } else { // Intel Pentium 4
1.341 - // if IA32_PERF_STATUS is not available, assume maxClock
1.342 - coreClocks[i].Value = (float)maxClock;
1.343 }
1.344 - }
1.345 - if (newBusClock > 0) {
1.346 - this.busClock.Value = (float)newBusClock;
1.347 - ActivateSensor(this.busClock);
1.348 + } else { // Intel Pentium 4
1.349 + // if IA32_PERF_STATUS is not available, assume maxClock
1.350 + coreClocks[i].Value = (float)MaxClock;
1.351 }
1.352 }
1.353 - lastTimeStampCount = timeStampCount;
1.354 - lastTime = time;
1.355 + if (newBusClock > 0) {
1.356 + this.busClock.Value = (float)newBusClock;
1.357 + ActivateSensor(this.busClock);
1.358 + }
1.359 }
1.360 }
1.361 - }
1.362 + }
1.363 }