Hardware/CPU/IntelCPU.cs
changeset 46 f847947b7f8e
parent 44 c150de283ca0
child 49 b418098ceca3
     1.1 --- a/Hardware/CPU/IntelCPU.cs	Sun Feb 14 21:09:08 2010 +0000
     1.2 +++ b/Hardware/CPU/IntelCPU.cs	Mon Feb 15 22:58:29 2010 +0000
     1.3 @@ -48,6 +48,10 @@
     1.4      private string name;
     1.5      private Image icon;
     1.6  
     1.7 +    private uint family;
     1.8 +    private uint model;
     1.9 +    private uint stepping;
    1.10 +
    1.11      private Sensor[] coreTemperatures;
    1.12      private Sensor totalLoad;
    1.13      private Sensor[] coreLoads;
    1.14 @@ -63,17 +67,23 @@
    1.15  
    1.16      private ulong lastCount;    
    1.17      private long lastTime;
    1.18 +    private uint maxNehalemMultiplier = 0;
    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 +    private const uint MSR_PLATFORM_INFO = 0xCE;
    1.24  
    1.25      public IntelCPU(string name, uint family, uint model, uint stepping, 
    1.26        uint[,] cpuidData, uint[,] cpuidExtData) {
    1.27        
    1.28        this.name = name;
    1.29        this.icon = Utilities.EmbeddedResources.GetImage("cpu.png");
    1.30 -            
    1.31 +
    1.32 +      this.family = family;
    1.33 +      this.model = model;
    1.34 +      this.stepping = stepping;
    1.35 +
    1.36        logicalProcessors = 0;
    1.37        if (cpuidData.GetLength(0) > 0x0B) {
    1.38          uint eax, ebx, ecx, edx;
    1.39 @@ -124,10 +134,11 @@
    1.40                    tjMax = 100; break;
    1.41                  case 0x1C: // Intel Atom 
    1.42                    tjMax = 90; break;
    1.43 -                case 0x1A:
    1.44 -                  uint eax = 0, edx = 0;
    1.45 -                  if (WinRing0.RdmsrPx(
    1.46 -                      IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) {
    1.47 +                case 0x1A: // Intel Core i7
    1.48 +                case 0x1E: // Intel Core i5
    1.49 +                  uint eax, edx;
    1.50 +                  if (WinRing0.Rdmsr(IA32_TEMPERATURE_TARGET, out eax, out edx)) 
    1.51 +                  {
    1.52                      tjMax = (eax >> 16) & 0xFF;
    1.53                    } else
    1.54                      tjMax = 100;
    1.55 @@ -139,6 +150,13 @@
    1.56            default: tjMax = 100; break;
    1.57          }
    1.58  
    1.59 +        if (family == 0x06 && model >= 0x1A) { // Core i5, i7
    1.60 +          uint eax, edx;
    1.61 +          if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
    1.62 +            maxNehalemMultiplier = (eax >> 8) & 0xff;
    1.63 +          }
    1.64 +        }
    1.65 +
    1.66          coreTemperatures = new Sensor[coreCount];
    1.67          for (int i = 0; i < coreTemperatures.Length; i++) {
    1.68            coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
    1.69 @@ -204,9 +222,9 @@
    1.70      public void Update() {
    1.71              
    1.72        for (int i = 0; i < coreTemperatures.Length; i++) {
    1.73 -        uint eax = 0, edx = 0;
    1.74 -        if (WinRing0.RdmsrPx(
    1.75 -          IA32_THERM_STATUS_MSR, ref eax, ref edx, 
    1.76 +        uint eax, edx;
    1.77 +        if (WinRing0.RdmsrTx(
    1.78 +          IA32_THERM_STATUS_MSR, out eax, out edx, 
    1.79              (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) 
    1.80          {
    1.81            // if reading is valid
    1.82 @@ -227,33 +245,41 @@
    1.83          totalLoad.Value = cpuLoad.GetTotalLoad();
    1.84        }
    1.85       
    1.86 -      uint lsb = 0, msb = 0;
    1.87 -      bool valid = WinRing0.RdtscPx(ref lsb, ref msb, (UIntPtr)1);
    1.88 +      uint lsb, msb;
    1.89 +      bool valid = WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
    1.90        long time = Stopwatch.GetTimestamp();
    1.91        ulong count = ((ulong)msb << 32) | lsb;
    1.92        double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
    1.93        if (valid && delta > 0.5) {
    1.94 -        double maxClock = (float)((count - lastCount) / (1e6 * delta));
    1.95 +        double maxClock = (count - lastCount) / (1e6 * delta);
    1.96          double busClock = 0;
    1.97 -        uint eax, edx;       
    1.98 +        uint eax, edx;
    1.99          for (int i = 0; i < coreClocks.Length; i++) {
   1.100 -          eax = 0; edx = 0;
   1.101            System.Threading.Thread.Sleep(1);
   1.102 -          if (WinRing0.RdmsrPx(IA32_PERF_STATUS, ref eax, ref edx,
   1.103 +          if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
   1.104              (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
   1.105 -            uint multiplier = (eax >> 8) & 0x1f;
   1.106 -            uint maxMultiplier = (edx >> 8) & 0x1f;
   1.107 -            // factor = multiplier * 2 to handle non integer multipliers 
   1.108 -            uint factor = (multiplier << 1) | ((eax >> 14) & 1);
   1.109 -            uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
   1.110 -            if (maxFactor > 0) {
   1.111 -              coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
   1.112 -              busClock = (float)(2 * maxClock / maxFactor);
   1.113 +            if (model < 0x1A) { // Core 2
   1.114 +              uint multiplier = (eax >> 8) & 0x1f;
   1.115 +              uint maxMultiplier = (edx >> 8) & 0x1f;
   1.116 +              // factor = multiplier * 2 to handle non integer multipliers 
   1.117 +              uint factor = (multiplier << 1) | ((eax >> 14) & 1);
   1.118 +              uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
   1.119 +              if (maxFactor > 0) {
   1.120 +                coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
   1.121 +                busClock = (float)(2 * maxClock / maxFactor);
   1.122 +              }
   1.123 +            } else { // Core i5, i7
   1.124 +              uint nehalemMultiplier = eax & 0xff;
   1.125 +              if (maxNehalemMultiplier > 0) {
   1.126 +                coreClocks[i].Value =
   1.127 +                  (float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
   1.128 +                busClock = (float)(maxClock / maxNehalemMultiplier);
   1.129 +              }
   1.130              }
   1.131 -          } else {
   1.132 +          } else { // Intel Pentium 4
   1.133              // if IA32_PERF_STATUS is not available, assume maxClock
   1.134              coreClocks[i].Value = (float)maxClock;
   1.135 -          }                  
   1.136 +          }
   1.137          }
   1.138          if (busClock > 0) {
   1.139            this.busClock.Value = (float)busClock;
   1.140 @@ -262,6 +288,6 @@
   1.141        }
   1.142        lastCount = count;
   1.143        lastTime = time;
   1.144 -    }  
   1.145 -  }
   1.146 +    }
   1.147 +  }  
   1.148  }