Hardware/CPU/IntelCPU.cs
changeset 191 6545fa3ae298
parent 182 4801e9eaf979
child 195 0ee888c485d5
     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  }