Hardware/CPU/IntelCPU.cs
author moel.mich
Sat, 02 Oct 2010 18:15:46 +0000
changeset 206 1fa8eddc24a7
parent 195 0ee888c485d5
child 219 ce04404774d6
permissions -rw-r--r--
Replaced HttpUtility.UrlEncode with Uri.EscapeDataString and deleted the reference to the System.Web assembly. The System.Web assembly seems to be missing on some .NET 4.0 installations (and the overhead of using it is a bit large, just for the UrlEncode method).
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@1
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@1
    40
moel@1
    41
namespace OpenHardwareMonitor.Hardware.CPU {
moel@191
    42
  internal sealed class IntelCPU : GenericCPU {
moel@46
    43
moel@195
    44
    private readonly Sensor[] coreTemperatures;
moel@195
    45
    private readonly Sensor[] coreClocks;
moel@195
    46
    private readonly Sensor busClock;
moel@63
    47
moel@195
    48
    private readonly uint maxNehalemMultiplier;
moel@79
    49
moel@1
    50
    private const uint IA32_THERM_STATUS_MSR = 0x019C;
moel@4
    51
    private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
moel@44
    52
    private const uint IA32_PERF_STATUS = 0x0198;
moel@46
    53
    private const uint MSR_PLATFORM_INFO = 0xCE;
moel@1
    54
moel@69
    55
    private float[] Floats(float f) {
moel@69
    56
      float[] result = new float[coreCount];
moel@69
    57
      for (int i = 0; i < coreCount; i++)
moel@69
    58
        result[i] = f;
moel@69
    59
      return result;
moel@69
    60
    }
moel@69
    61
moel@191
    62
    public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
moel@191
    63
      : base(processorIndex, cpuid, settings) 
moel@191
    64
    {
moel@69
    65
      float[] tjMax;
moel@49
    66
      switch (family) {
moel@49
    67
        case 0x06: {
moel@49
    68
            switch (model) {
moel@49
    69
              case 0x0F: // Intel Core (65nm)
moel@49
    70
                switch (stepping) {
moel@49
    71
                  case 0x06: // B2
moel@49
    72
                    switch (coreCount) {
moel@49
    73
                      case 2:
moel@69
    74
                        tjMax = Floats(80 + 10); break;
moel@49
    75
                      case 4:
moel@69
    76
                        tjMax = Floats(90 + 10); break;
moel@49
    77
                      default:
moel@69
    78
                        tjMax = Floats(85 + 10); break;
moel@49
    79
                    }
moel@69
    80
                    tjMax = Floats(80 + 10); break;
moel@49
    81
                  case 0x0B: // G0
moel@69
    82
                    tjMax = Floats(90 + 10); break;
moel@49
    83
                  case 0x0D: // M0
moel@69
    84
                    tjMax = Floats(85 + 10); break;
moel@49
    85
                  default:
moel@69
    86
                    tjMax = Floats(85 + 10); break;
moel@49
    87
                } break;
moel@49
    88
              case 0x17: // Intel Core (45nm)
moel@69
    89
                tjMax = Floats(100); break;
moel@114
    90
              case 0x1C: // Intel Atom (45nm)
moel@114
    91
                switch (stepping) {
moel@114
    92
                  case 0x02: // C0
moel@114
    93
                    tjMax = Floats(90); break;
moel@114
    94
                  case 0x0A: // A0, B0
moel@114
    95
                    tjMax = Floats(100); break;
moel@114
    96
                  default:
moel@114
    97
                    tjMax = Floats(90); break;
moel@191
    98
                } break;
moel@49
    99
              case 0x1A: // Intel Core i7 LGA1366 (45nm)
moel@49
   100
              case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
moel@49
   101
              case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
moel@91
   102
              case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
moel@49
   103
                uint eax, edx;
moel@69
   104
                tjMax = new float[coreCount];
moel@69
   105
                for (int i = 0; i < coreCount; i++) {
moel@69
   106
                  if (WinRing0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
moel@191
   107
                    out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) {
moel@69
   108
                    tjMax[i] = (eax >> 16) & 0xFF;
moel@69
   109
                  } else {
moel@69
   110
                    tjMax[i] = 100;
moel@69
   111
                  }
moel@49
   112
                }
moel@49
   113
                if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
moel@49
   114
                  maxNehalemMultiplier = (eax >> 8) & 0xff;
moel@49
   115
                }
moel@49
   116
                break;
moel@49
   117
              default:
moel@69
   118
                tjMax = Floats(100); break;
moel@49
   119
            }
moel@49
   120
          } break;
moel@69
   121
        default: tjMax = Floats(100); break;
moel@49
   122
      }
moel@1
   123
moel@44
   124
      // check if processor supports a digital thermal sensor
moel@191
   125
      if (cpuid[0][0].Data.GetLength(0) > 6 &&
moel@191
   126
        (cpuid[0][0].Data[6, 0] & 1) != 0) {
moel@44
   127
        coreTemperatures = new Sensor[coreCount];
moel@44
   128
        for (int i = 0; i < coreTemperatures.Length; i++) {
moel@134
   129
          coreTemperatures[i] = new Sensor(CoreString(i), i,
moel@195
   130
            SensorType.Temperature, this, new [] { 
moel@63
   131
              new ParameterDescription(
moel@122
   132
                "TjMax [°C]", "TjMax temperature of the core.\n" + 
moel@69
   133
                "Temperature = TjMax - TSlope * Value.", tjMax[i]), 
moel@122
   134
              new ParameterDescription("TSlope [°C]", 
moel@122
   135
                "Temperature slope of the digital thermal sensor.\n" + 
moel@165
   136
                "Temperature = TjMax - TSlope * Value.", 1)}, settings);
moel@155
   137
          ActivateSensor(coreTemperatures[i]);
moel@44
   138
        }
moel@44
   139
      } else {
moel@44
   140
        coreTemperatures = new Sensor[0];
moel@1
   141
      }
moel@49
   142
moel@191
   143
      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
moel@44
   144
      coreClocks = new Sensor[coreCount];
moel@44
   145
      for (int i = 0; i < coreClocks.Length; i++) {
moel@49
   146
        coreClocks[i] =
moel@165
   147
          new Sensor(CoreString(i), i + 1, SensorType.Clock, this, settings);
moel@201
   148
        if (HasTimeStampCounter)
moel@79
   149
          ActivateSensor(coreClocks[i]);
moel@44
   150
      }
moel@191
   151
moel@191
   152
      Update();
moel@1
   153
    }
moel@1
   154
moel@191
   155
    protected override uint[] GetMSRs() {
moel@195
   156
      return new [] {
moel@191
   157
        MSR_PLATFORM_INFO,
moel@191
   158
        IA32_PERF_STATUS ,
moel@191
   159
        IA32_THERM_STATUS_MSR,
moel@191
   160
        IA32_TEMPERATURE_TARGET
moel@191
   161
      };
moel@1
   162
    }
moel@1
   163
moel@191
   164
    public override void Update() {
moel@191
   165
      base.Update();
moel@1
   166
moel@1
   167
      for (int i = 0; i < coreTemperatures.Length; i++) {
moel@46
   168
        uint eax, edx;
moel@46
   169
        if (WinRing0.RdmsrTx(
moel@191
   170
          IA32_THERM_STATUS_MSR, out eax, out edx,
moel@90
   171
            (UIntPtr)(1L << cpuid[i][0].Thread))) {
moel@1
   172
          // if reading is valid
moel@1
   173
          if ((eax & 0x80000000) != 0) {
moel@1
   174
            // get the dist from tjMax from bits 22:16
moel@63
   175
            float deltaT = ((eax & 0x007F0000) >> 16);
moel@63
   176
            float tjMax = coreTemperatures[i].Parameters[0].Value;
moel@63
   177
            float tSlope = coreTemperatures[i].Parameters[1].Value;
moel@63
   178
            coreTemperatures[i].Value = tjMax - tSlope * deltaT;
moel@24
   179
          } else {
moel@155
   180
            coreTemperatures[i].Value = null;
moel@1
   181
          }
moel@79
   182
        }
moel@24
   183
      }
moel@24
   184
moel@201
   185
      if (HasTimeStampCounter) {
moel@191
   186
        double newBusClock = 0;
moel@191
   187
        uint eax, edx;
moel@191
   188
        for (int i = 0; i < coreClocks.Length; i++) {
moel@191
   189
          System.Threading.Thread.Sleep(1);
moel@191
   190
          if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
moel@191
   191
            (UIntPtr)(1L << cpuid[i][0].Thread))) {
moel@191
   192
            if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
moel@191
   193
              uint nehalemMultiplier = eax & 0xff;
moel@201
   194
              coreClocks[i].Value =(float)(nehalemMultiplier * 
moel@201
   195
                TimeStampCounterFrequency / maxNehalemMultiplier);
moel@201
   196
              newBusClock = 
moel@201
   197
                (float)(TimeStampCounterFrequency / maxNehalemMultiplier);
moel@191
   198
            } else { // Core 2
moel@191
   199
              uint multiplier = (eax >> 8) & 0x1f;
moel@191
   200
              uint maxMultiplier = (edx >> 8) & 0x1f;
moel@191
   201
              // factor = multiplier * 2 to handle non integer multipliers 
moel@191
   202
              uint factor = (multiplier << 1) | ((eax >> 14) & 1);
moel@191
   203
              uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
moel@191
   204
              if (maxFactor > 0) {
moel@201
   205
                coreClocks[i].Value = 
moel@201
   206
                  (float)(factor * TimeStampCounterFrequency / maxFactor);
moel@201
   207
                newBusClock = 
moel@201
   208
                  (float)(2 * TimeStampCounterFrequency / maxFactor);
moel@46
   209
              }
moel@79
   210
            }
moel@191
   211
          } else { // Intel Pentium 4
moel@201
   212
            // if IA32_PERF_STATUS is not available, assume TSC frequency
moel@201
   213
            coreClocks[i].Value = (float)TimeStampCounterFrequency;
moel@46
   214
          }
moel@44
   215
        }
moel@191
   216
        if (newBusClock > 0) {
moel@191
   217
          this.busClock.Value = (float)newBusClock;
moel@191
   218
          ActivateSensor(this.busClock);
moel@191
   219
        }
moel@44
   220
      }
moel@46
   221
    }
moel@191
   222
  }
moel@1
   223
}