Better core and thread number identification. Fixed clock reading on Intel Atom CPUs. New reporting of MSR values for Intel CPUs.
authormoel.mich
Wed, 17 Feb 2010 20:22:21 +0000
changeset 49b418098ceca3
parent 48 eb04985b7b6a
child 50 7d83a09511f0
Better core and thread number identification. Fixed clock reading on Intel Atom CPUs. New reporting of MSR values for Intel CPUs.
Hardware/CPU/IntelCPU.cs
     1.1 --- a/Hardware/CPU/IntelCPU.cs	Wed Feb 17 18:48:27 2010 +0000
     1.2 +++ b/Hardware/CPU/IntelCPU.cs	Wed Feb 17 20:22:21 2010 +0000
     1.3 @@ -74,6 +74,13 @@
     1.4      private const uint IA32_PERF_STATUS = 0x0198;
     1.5      private const uint MSR_PLATFORM_INFO = 0xCE;
     1.6  
     1.7 +    private string CoreString(int i) {
     1.8 +      if (coreCount == 1)
     1.9 +        return "CPU Core";
    1.10 +      else
    1.11 +        return "CPU Core #" + (i + 1);
    1.12 +    }
    1.13 +
    1.14      public IntelCPU(string name, uint family, uint model, uint stepping, 
    1.15        uint[,] cpuidData, uint[,] cpuidExtData) {
    1.16        
    1.17 @@ -95,8 +102,15 @@
    1.18          }   
    1.19        }
    1.20        if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x04) {
    1.21 -        logicalProcessors = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
    1.22 -        logicalProcessorsPerCore = 1;
    1.23 +        uint coresPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
    1.24 +        uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;        
    1.25 +        logicalProcessorsPerCore = logicalPerPackage / coresPerPackage;
    1.26 +        logicalProcessors = logicalPerPackage;
    1.27 +      }
    1.28 +      if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x01) {
    1.29 +        uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
    1.30 +        logicalProcessorsPerCore = logicalPerPackage;
    1.31 +        logicalProcessors = logicalPerPackage;
    1.32        }
    1.33        if (logicalProcessors <= 0) {
    1.34          logicalProcessors = 1;
    1.35 @@ -104,78 +118,78 @@
    1.36        }
    1.37  
    1.38        coreCount = logicalProcessors / logicalProcessorsPerCore;
    1.39 +      
    1.40 +      switch (family) {
    1.41 +        case 0x06: {
    1.42 +            switch (model) {
    1.43 +              case 0x0F: // Intel Core (65nm)
    1.44 +                switch (stepping) {
    1.45 +                  case 0x06: // B2
    1.46 +                    switch (coreCount) {
    1.47 +                      case 2:
    1.48 +                        tjMax = 80; break;
    1.49 +                      case 4:
    1.50 +                        tjMax = 90; break;
    1.51 +                      default:
    1.52 +                        tjMax = 85; break;
    1.53 +                    }
    1.54 +                    tjMax = 80; break;
    1.55 +                  case 0x0B: // G0
    1.56 +                    tjMax = 90; break;
    1.57 +                  case 0x0D: // M0
    1.58 +                    tjMax = 85; break;
    1.59 +                  default:
    1.60 +                    tjMax = 85; break;
    1.61 +                } break;
    1.62 +              case 0x17: // Intel Core (45nm)
    1.63 +                tjMax = 100; break;
    1.64 +              case 0x1C: // Intel Atom 
    1.65 +                tjMax = 90; break;
    1.66 +              case 0x1A: // Intel Core i7 LGA1366 (45nm)
    1.67 +              case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
    1.68 +              case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
    1.69 +                uint eax, edx;
    1.70 +                if (WinRing0.Rdmsr(IA32_TEMPERATURE_TARGET, out eax, out edx)) {
    1.71 +                  tjMax = (eax >> 16) & 0xFF;
    1.72 +                } else {
    1.73 +                  tjMax = 100;
    1.74 +                }
    1.75 +                if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
    1.76 +                  maxNehalemMultiplier = (eax >> 8) & 0xff;
    1.77 +                }
    1.78 +                break;
    1.79 +              default:
    1.80 +                tjMax = 100; break;
    1.81 +            }
    1.82 +          } break;
    1.83 +        default: tjMax = 100; break;
    1.84 +      }
    1.85  
    1.86        // check if processor supports a digital thermal sensor
    1.87        if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) {
    1.88 -
    1.89 -        switch (family) {
    1.90 -          case 0x06: {
    1.91 -              switch (model) {
    1.92 -                case 0x0F: // Intel Core 65nm
    1.93 -                  switch (stepping) {
    1.94 -                    case 0x06: // B2
    1.95 -                      switch (coreCount) {
    1.96 -                        case 2:
    1.97 -                          tjMax = 80; break;
    1.98 -                        case 4:
    1.99 -                          tjMax = 90; break;
   1.100 -                        default:
   1.101 -                          tjMax = 85; break;
   1.102 -                      }
   1.103 -                      tjMax = 80; break;
   1.104 -                    case 0x0B: // G0
   1.105 -                      tjMax = 90; break;
   1.106 -                    case 0x0D: // M0
   1.107 -                      tjMax = 85; break;
   1.108 -                    default:
   1.109 -                      tjMax = 85; break;
   1.110 -                  } break;
   1.111 -                case 0x17: // Intel Core 45nm
   1.112 -                  tjMax = 100; break;
   1.113 -                case 0x1C: // Intel Atom 
   1.114 -                  tjMax = 90; break;
   1.115 -                case 0x1A: // Intel Core i7
   1.116 -                case 0x1E: // Intel Core i5
   1.117 -                  uint eax, edx;
   1.118 -                  if (WinRing0.Rdmsr(IA32_TEMPERATURE_TARGET, out eax, out edx)) 
   1.119 -                  {
   1.120 -                    tjMax = (eax >> 16) & 0xFF;
   1.121 -                  } else
   1.122 -                    tjMax = 100;
   1.123 -                  break;
   1.124 -                default:
   1.125 -                  tjMax = 100; break;
   1.126 -              }
   1.127 -            } break;
   1.128 -          default: tjMax = 100; break;
   1.129 -        }
   1.130 -
   1.131 -        if (family == 0x06 && model >= 0x1A) { // Core i5, i7
   1.132 -          uint eax, edx;
   1.133 -          if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
   1.134 -            maxNehalemMultiplier = (eax >> 8) & 0xff;
   1.135 -          }
   1.136 -        }
   1.137 -
   1.138          coreTemperatures = new Sensor[coreCount];
   1.139          for (int i = 0; i < coreTemperatures.Length; i++) {
   1.140 -          coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
   1.141 +          coreTemperatures[i] = new Sensor(CoreString(i), i, tjMax,
   1.142              SensorType.Temperature, this);
   1.143          }
   1.144        } else {
   1.145          coreTemperatures = new Sensor[0];
   1.146        }
   1.147 -              
   1.148 -      totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);   
   1.149 +
   1.150 +      if (coreCount > 1)
   1.151 +        totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);
   1.152 +      else
   1.153 +        totalLoad = null;
   1.154        coreLoads = new Sensor[coreCount];
   1.155 -      for (int i = 0; i < coreLoads.Length; i++) 
   1.156 -        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1,
   1.157 +      for (int i = 0; i < coreLoads.Length; i++)
   1.158 +        coreLoads[i] = new Sensor(CoreString(i), i + 1,
   1.159            SensorType.Load, this);     
   1.160        cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore);
   1.161        if (cpuLoad.IsAvailable) {
   1.162          foreach (Sensor sensor in coreLoads)
   1.163            ActivateSensor(sensor);
   1.164 -        ActivateSensor(totalLoad);
   1.165 +        if (totalLoad != null)
   1.166 +          ActivateSensor(totalLoad);
   1.167        }
   1.168  
   1.169        lastCount = 0;
   1.170 @@ -183,8 +197,8 @@
   1.171        busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this);      
   1.172        coreClocks = new Sensor[coreCount];
   1.173        for (int i = 0; i < coreClocks.Length; i++) {
   1.174 -        coreClocks[i] = 
   1.175 -          new Sensor("Core #" + (i + 1), i + 1, SensorType.Clock, this);
   1.176 +        coreClocks[i] =
   1.177 +          new Sensor(CoreString(i), i + 1, SensorType.Clock, this);
   1.178          ActivateSensor(coreClocks[i]);
   1.179        }
   1.180        
   1.181 @@ -203,6 +217,20 @@
   1.182        get { return icon; }
   1.183      }
   1.184  
   1.185 +    private void AppendMSRData(StringBuilder r, uint msr, int core) {
   1.186 +      uint eax, edx;
   1.187 +      if (WinRing0.RdmsrTx(msr, out eax, out edx,
   1.188 +         (UIntPtr)(1 << (int)(logicalProcessorsPerCore * core)))) {
   1.189 +        r.Append(" ");
   1.190 +        r.Append((msr).ToString("X8"));
   1.191 +        r.Append("  ");
   1.192 +        r.Append((edx).ToString("X8"));
   1.193 +        r.Append("  ");
   1.194 +        r.Append((eax).ToString("X8"));
   1.195 +        r.AppendLine();
   1.196 +      }
   1.197 +    }
   1.198 +
   1.199      public string GetReport() {
   1.200        StringBuilder r = new StringBuilder();
   1.201  
   1.202 @@ -216,6 +244,17 @@
   1.203        r.AppendFormat("TjMax: {0}{1}", tjMax, Environment.NewLine);
   1.204        r.AppendLine();
   1.205  
   1.206 +      for (int i = 0; i < coreCount; i++) {
   1.207 +        r.AppendLine("MSR Core #" + (i + 1));
   1.208 +        r.AppendLine();
   1.209 +        r.AppendLine(" MSR       EDX       EAX");
   1.210 +        AppendMSRData(r, MSR_PLATFORM_INFO, i);
   1.211 +        AppendMSRData(r, IA32_PERF_STATUS, i);
   1.212 +        AppendMSRData(r, IA32_THERM_STATUS_MSR, i);
   1.213 +        AppendMSRData(r, IA32_TEMPERATURE_TARGET, i);
   1.214 +        r.AppendLine();
   1.215 +      }
   1.216 +
   1.217        return r.ToString();
   1.218      }
   1.219  
   1.220 @@ -242,7 +281,8 @@
   1.221          cpuLoad.Update();
   1.222          for (int i = 0; i < coreLoads.Length; i++)
   1.223            coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
   1.224 -        totalLoad.Value = cpuLoad.GetTotalLoad();
   1.225 +        if (totalLoad != null)
   1.226 +          totalLoad.Value = cpuLoad.GetTotalLoad();
   1.227        }
   1.228       
   1.229        uint lsb, msb;
   1.230 @@ -258,7 +298,12 @@
   1.231            System.Threading.Thread.Sleep(1);
   1.232            if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
   1.233              (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
   1.234 -            if (model < 0x1A) { // Core 2
   1.235 +            if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
   1.236 +              uint nehalemMultiplier = eax & 0xff;
   1.237 +              coreClocks[i].Value =
   1.238 +                (float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
   1.239 +              busClock = (float)(maxClock / maxNehalemMultiplier);
   1.240 +            } else { // Core 2
   1.241                uint multiplier = (eax >> 8) & 0x1f;
   1.242                uint maxMultiplier = (edx >> 8) & 0x1f;
   1.243                // factor = multiplier * 2 to handle non integer multipliers 
   1.244 @@ -268,14 +313,7 @@
   1.245                  coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
   1.246                  busClock = (float)(2 * maxClock / maxFactor);
   1.247                }
   1.248 -            } else { // Core i5, i7
   1.249 -              uint nehalemMultiplier = eax & 0xff;
   1.250 -              if (maxNehalemMultiplier > 0) {
   1.251 -                coreClocks[i].Value =
   1.252 -                  (float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
   1.253 -                busClock = (float)(maxClock / maxNehalemMultiplier);
   1.254 -              }
   1.255 -            }
   1.256 +            }  
   1.257            } else { // Intel Pentium 4
   1.258              // if IA32_PERF_STATUS is not available, assume maxClock
   1.259              coreClocks[i].Value = (float)maxClock;