Hardware/CPU/IntelCPU.cs
changeset 44 c150de283ca0
parent 31 c4d1fb76a9e1
child 46 f847947b7f8e
     1.1 --- a/Hardware/CPU/IntelCPU.cs	Sat Feb 13 17:08:36 2010 +0000
     1.2 +++ b/Hardware/CPU/IntelCPU.cs	Sun Feb 14 20:16:30 2010 +0000
     1.3 @@ -51,6 +51,8 @@
     1.4      private Sensor[] coreTemperatures;
     1.5      private Sensor totalLoad;
     1.6      private Sensor[] coreLoads;
     1.7 +    private Sensor[] coreClocks;
     1.8 +    private Sensor busClock;
     1.9  
    1.10      private float tjMax = 0;
    1.11      private uint logicalProcessors;
    1.12 @@ -58,9 +60,13 @@
    1.13      private uint coreCount;
    1.14  
    1.15      private CPULoad cpuLoad;
    1.16 +
    1.17 +    private ulong lastCount;    
    1.18 +    private long lastTime;
    1.19      
    1.20      private const uint IA32_THERM_STATUS_MSR = 0x019C;
    1.21      private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
    1.22 +    private const uint IA32_PERF_STATUS = 0x0198;
    1.23  
    1.24      public IntelCPU(string name, uint family, uint model, uint stepping, 
    1.25        uint[,] cpuidData, uint[,] cpuidExtData) {
    1.26 @@ -89,58 +95,64 @@
    1.27  
    1.28        coreCount = logicalProcessors / logicalProcessorsPerCore;
    1.29  
    1.30 -      switch (family) {
    1.31 -        case 0x06: {
    1.32 -          switch (model) {
    1.33 -            case 0x0F: // Intel Core 65nm
    1.34 -              switch (stepping) {
    1.35 -                case 0x06: // B2
    1.36 -                  switch (coreCount) {
    1.37 -                    case 2:
    1.38 +      // check if processor supports a digital thermal sensor
    1.39 +      if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) {
    1.40 +
    1.41 +        switch (family) {
    1.42 +          case 0x06: {
    1.43 +              switch (model) {
    1.44 +                case 0x0F: // Intel Core 65nm
    1.45 +                  switch (stepping) {
    1.46 +                    case 0x06: // B2
    1.47 +                      switch (coreCount) {
    1.48 +                        case 2:
    1.49 +                          tjMax = 80; break;
    1.50 +                        case 4:
    1.51 +                          tjMax = 90; break;
    1.52 +                        default:
    1.53 +                          tjMax = 85; break;
    1.54 +                      }
    1.55                        tjMax = 80; break;
    1.56 -                    case 4:
    1.57 +                    case 0x0B: // G0
    1.58                        tjMax = 90; break;
    1.59 +                    case 0x0D: // M0
    1.60 +                      tjMax = 85; break;
    1.61                      default:
    1.62                        tjMax = 85; break;
    1.63 -                  }
    1.64 -                  tjMax = 80; break;
    1.65 -                case 0x0B: // G0
    1.66 +                  } break;
    1.67 +                case 0x17: // Intel Core 45nm
    1.68 +                  tjMax = 100; break;
    1.69 +                case 0x1C: // Intel Atom 
    1.70                    tjMax = 90; break;
    1.71 -                case 0x0D: // M0
    1.72 -                  tjMax = 85; break;
    1.73 +                case 0x1A:
    1.74 +                  uint eax = 0, edx = 0;
    1.75 +                  if (WinRing0.RdmsrPx(
    1.76 +                      IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) {
    1.77 +                    tjMax = (eax >> 16) & 0xFF;
    1.78 +                  } else
    1.79 +                    tjMax = 100;
    1.80 +                  break;
    1.81                  default:
    1.82 -                  tjMax = 85; break;
    1.83 -              } break;            
    1.84 -            case 0x17: // Intel Core 45nm
    1.85 -              tjMax = 100; break;
    1.86 -            case 0x1C: // Intel Atom 
    1.87 -              tjMax = 90; break;
    1.88 -            case 0x1A:
    1.89 -              uint eax = 0, edx = 0;
    1.90 -              if (WinRing0.RdmsrPx(
    1.91 -                  IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) {
    1.92 -                tjMax = (eax >> 16) & 0xFF;
    1.93 -              } else
    1.94 -                tjMax = 100;
    1.95 -              break;
    1.96 -            default:
    1.97 -              tjMax = 100; break;
    1.98 -          }
    1.99 -        } break;
   1.100 -        default: tjMax = 100; break;
   1.101 +                  tjMax = 100; break;
   1.102 +              }
   1.103 +            } break;
   1.104 +          default: tjMax = 100; break;
   1.105 +        }
   1.106 +
   1.107 +        coreTemperatures = new Sensor[coreCount];
   1.108 +        for (int i = 0; i < coreTemperatures.Length; i++) {
   1.109 +          coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
   1.110 +            SensorType.Temperature, this);
   1.111 +        }
   1.112 +      } else {
   1.113 +        coreTemperatures = new Sensor[0];
   1.114        }
   1.115 -
   1.116 -      totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);     
   1.117 -
   1.118 -      coreTemperatures = new Sensor[coreCount];
   1.119 +              
   1.120 +      totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);   
   1.121        coreLoads = new Sensor[coreCount];
   1.122 -      for (int i = 0; i < coreTemperatures.Length; i++) {
   1.123 -        coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
   1.124 -          SensorType.Temperature, this);
   1.125 -        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, 
   1.126 -          SensorType.Load, this);
   1.127 -      }
   1.128 -
   1.129 +      for (int i = 0; i < coreLoads.Length; i++) 
   1.130 +        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1,
   1.131 +          SensorType.Load, this);     
   1.132        cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore);
   1.133        if (cpuLoad.IsAvailable) {
   1.134          foreach (Sensor sensor in coreLoads)
   1.135 @@ -148,6 +160,16 @@
   1.136          ActivateSensor(totalLoad);
   1.137        }
   1.138  
   1.139 +      lastCount = 0;
   1.140 +      lastTime = 0;
   1.141 +      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this);      
   1.142 +      coreClocks = new Sensor[coreCount];
   1.143 +      for (int i = 0; i < coreClocks.Length; i++) {
   1.144 +        coreClocks[i] = 
   1.145 +          new Sensor("Core #" + (i + 1), i + 1, SensorType.Clock, this);
   1.146 +        ActivateSensor(coreClocks[i]);
   1.147 +      }
   1.148 +      
   1.149        Update();                   
   1.150      }
   1.151  
   1.152 @@ -180,9 +202,9 @@
   1.153      }
   1.154  
   1.155      public void Update() {
   1.156 -
   1.157 -      uint eax = 0, edx = 0;      
   1.158 +            
   1.159        for (int i = 0; i < coreTemperatures.Length; i++) {
   1.160 +        uint eax = 0, edx = 0;
   1.161          if (WinRing0.RdmsrPx(
   1.162            IA32_THERM_STATUS_MSR, ref eax, ref edx, 
   1.163              (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) 
   1.164 @@ -204,6 +226,42 @@
   1.165            coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
   1.166          totalLoad.Value = cpuLoad.GetTotalLoad();
   1.167        }
   1.168 +     
   1.169 +      uint lsb = 0, msb = 0;
   1.170 +      bool valid = WinRing0.RdtscPx(ref lsb, ref msb, (UIntPtr)1);
   1.171 +      long time = Stopwatch.GetTimestamp();
   1.172 +      ulong count = ((ulong)msb << 32) | lsb;
   1.173 +      double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
   1.174 +      if (valid && delta > 0.5) {
   1.175 +        double maxClock = (float)((count - lastCount) / (1e6 * delta));
   1.176 +        double busClock = 0;
   1.177 +        uint eax, edx;       
   1.178 +        for (int i = 0; i < coreClocks.Length; i++) {
   1.179 +          eax = 0; edx = 0;
   1.180 +          System.Threading.Thread.Sleep(1);
   1.181 +          if (WinRing0.RdmsrPx(IA32_PERF_STATUS, ref eax, ref edx,
   1.182 +            (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
   1.183 +            uint multiplier = (eax >> 8) & 0x1f;
   1.184 +            uint maxMultiplier = (edx >> 8) & 0x1f;
   1.185 +            // factor = multiplier * 2 to handle non integer multipliers 
   1.186 +            uint factor = (multiplier << 1) | ((eax >> 14) & 1);
   1.187 +            uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
   1.188 +            if (maxFactor > 0) {
   1.189 +              coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
   1.190 +              busClock = (float)(2 * maxClock / maxFactor);
   1.191 +            }
   1.192 +          } else {
   1.193 +            // if IA32_PERF_STATUS is not available, assume maxClock
   1.194 +            coreClocks[i].Value = (float)maxClock;
   1.195 +          }                  
   1.196 +        }
   1.197 +        if (busClock > 0) {
   1.198 +          this.busClock.Value = (float)busClock;
   1.199 +          ActivateSensor(this.busClock);
   1.200 +        }
   1.201 +      }
   1.202 +      lastCount = count;
   1.203 +      lastTime = time;
   1.204      }  
   1.205    }
   1.206  }