Hardware/CPU/IntelCPU.cs
author moel.mich
Sat, 06 Aug 2011 17:27:55 +0000
changeset 320 df3493f75225
parent 317 1ccf99e620a9
child 321 1da7448c8e10
permissions -rw-r--r--
Added Added a mainboard specific configuration for the Shuttle SH67Hx barebones. Added the SMBIOS system information to the report.
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@264
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
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@219
    39
using System.Globalization;
moel@219
    40
using System.Text;
moel@1
    41
moel@1
    42
namespace OpenHardwareMonitor.Hardware.CPU {
moel@191
    43
  internal sealed class IntelCPU : GenericCPU {
moel@46
    44
moel@219
    45
    private enum Microarchitecture {
moel@219
    46
      Unknown,
moel@264
    47
      NetBurst,
moel@219
    48
      Core,
moel@219
    49
      Atom,
moel@249
    50
      Nehalem,
moel@249
    51
      SandyBridge
moel@219
    52
    }
moel@219
    53
moel@195
    54
    private readonly Sensor[] coreTemperatures;
moel@306
    55
    private readonly Sensor packageTemperature;
moel@195
    56
    private readonly Sensor[] coreClocks;
moel@195
    57
    private readonly Sensor busClock;
moel@317
    58
    private readonly Sensor packagePower;
moel@317
    59
    private readonly Sensor coresPower;
moel@63
    60
moel@219
    61
    private readonly Microarchitecture microarchitecture;
moel@219
    62
    private readonly double timeStampCounterMultiplier;
moel@79
    63
moel@1
    64
    private const uint IA32_THERM_STATUS_MSR = 0x019C;
moel@4
    65
    private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
moel@44
    66
    private const uint IA32_PERF_STATUS = 0x0198;
moel@46
    67
    private const uint MSR_PLATFORM_INFO = 0xCE;
moel@306
    68
    private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1;
moel@317
    69
    private const uint MSR_RAPL_POWER_UNIT = 0x606;
moel@317
    70
    private const uint MSR_PKG_ENERY_STATUS = 0x611;
moel@317
    71
    private const uint MSR_PP0_ENERY_STATUS = 0x639;
moel@320
    72
    private const uint MSR_PP1_ENERY_STATUS = 0x641;
moel@317
    73
moel@317
    74
    private float energyUnitMultiplier = 0;
moel@317
    75
    private DateTime lastPackageTime;
moel@317
    76
    private uint lastPackageEnergyConsumed;
moel@317
    77
    private DateTime lastCoresTime;
moel@317
    78
    private uint lastCoresEnergyConsumed;
moel@317
    79
moel@317
    80
moel@1
    81
moel@69
    82
    private float[] Floats(float f) {
moel@69
    83
      float[] result = new float[coreCount];
moel@69
    84
      for (int i = 0; i < coreCount; i++)
moel@69
    85
        result[i] = f;
moel@69
    86
      return result;
moel@69
    87
    }
moel@69
    88
moel@249
    89
    private float[] GetTjMaxFromMSR() {
moel@249
    90
      uint eax, edx;
moel@249
    91
      float[] result = new float[coreCount];
moel@249
    92
      for (int i = 0; i < coreCount; i++) {
moel@249
    93
        if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
moel@249
    94
          out edx, 1UL << cpuid[i][0].Thread)) {
moel@249
    95
          result[i] = (eax >> 16) & 0xFF;
moel@249
    96
        } else {
moel@249
    97
          result[i] = 100;
moel@249
    98
        }
moel@249
    99
      }
moel@249
   100
      return result;
moel@249
   101
    }
moel@249
   102
moel@191
   103
    public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
moel@191
   104
      : base(processorIndex, cpuid, settings) 
moel@191
   105
    {
moel@219
   106
      // set tjMax
moel@69
   107
      float[] tjMax;
moel@49
   108
      switch (family) {
moel@49
   109
        case 0x06: {
moel@49
   110
            switch (model) {
moel@219
   111
              case 0x0F: // Intel Core 2 (65nm)
moel@219
   112
                microarchitecture = Microarchitecture.Core;
moel@49
   113
                switch (stepping) {
moel@49
   114
                  case 0x06: // B2
moel@49
   115
                    switch (coreCount) {
moel@49
   116
                      case 2:
moel@69
   117
                        tjMax = Floats(80 + 10); break;
moel@49
   118
                      case 4:
moel@69
   119
                        tjMax = Floats(90 + 10); break;
moel@49
   120
                      default:
moel@69
   121
                        tjMax = Floats(85 + 10); break;
moel@49
   122
                    }
moel@69
   123
                    tjMax = Floats(80 + 10); break;
moel@49
   124
                  case 0x0B: // G0
moel@69
   125
                    tjMax = Floats(90 + 10); break;
moel@49
   126
                  case 0x0D: // M0
moel@69
   127
                    tjMax = Floats(85 + 10); break;
moel@49
   128
                  default:
moel@69
   129
                    tjMax = Floats(85 + 10); break;
moel@49
   130
                } break;
moel@219
   131
              case 0x17: // Intel Core 2 (45nm)
moel@219
   132
                microarchitecture = Microarchitecture.Core;
moel@69
   133
                tjMax = Floats(100); break;
moel@114
   134
              case 0x1C: // Intel Atom (45nm)
moel@219
   135
                microarchitecture = Microarchitecture.Atom;
moel@114
   136
                switch (stepping) {
moel@114
   137
                  case 0x02: // C0
moel@114
   138
                    tjMax = Floats(90); break;
moel@114
   139
                  case 0x0A: // A0, B0
moel@114
   140
                    tjMax = Floats(100); break;
moel@114
   141
                  default:
moel@114
   142
                    tjMax = Floats(90); break;
moel@191
   143
                } break;
moel@49
   144
              case 0x1A: // Intel Core i7 LGA1366 (45nm)
moel@49
   145
              case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
moel@249
   146
              case 0x1F: // Intel Core i5, i7 
moel@49
   147
              case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
moel@91
   148
              case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
moel@249
   149
              case 0x2E: // Intel Xeon Processor 7500 series
moel@219
   150
                microarchitecture = Microarchitecture.Nehalem;
moel@249
   151
                tjMax = GetTjMaxFromMSR();
moel@249
   152
                break;
moel@249
   153
              case 0x2A: // Intel Core i5, i7 2xxx LGA1155 (32nm)
moel@249
   154
              case 0x2D: // Next Generation Intel Xeon Processor
moel@249
   155
                microarchitecture = Microarchitecture.SandyBridge;
moel@249
   156
                tjMax = GetTjMaxFromMSR();
moel@49
   157
                break;
moel@49
   158
              default:
moel@219
   159
                microarchitecture = Microarchitecture.Unknown;
moel@219
   160
                tjMax = Floats(100); 
moel@219
   161
                break;
moel@49
   162
            }
moel@49
   163
          } break;
moel@264
   164
        case 0x0F: {
moel@264
   165
            switch (model) {
moel@264
   166
              case 0x00: // Pentium 4 (180nm)
moel@264
   167
              case 0x01: // Pentium 4 (130nm)
moel@264
   168
              case 0x02: // Pentium 4 (130nm)
moel@264
   169
              case 0x03: // Pentium 4, Celeron D (90nm)
moel@264
   170
              case 0x04: // Pentium 4, Pentium D, Celeron D (90nm)
moel@264
   171
              case 0x06: // Pentium 4, Pentium D, Celeron D (65nm)
moel@264
   172
                microarchitecture = Microarchitecture.NetBurst;
moel@264
   173
                tjMax = Floats(100); 
moel@264
   174
                break;
moel@264
   175
              default:
moel@264
   176
                microarchitecture = Microarchitecture.Unknown;
moel@264
   177
                tjMax = Floats(100);
moel@264
   178
                break;
moel@264
   179
            }
moel@264
   180
          } break;
moel@219
   181
        default:
moel@219
   182
          microarchitecture = Microarchitecture.Unknown;
moel@219
   183
          tjMax = Floats(100); 
moel@219
   184
          break;
moel@219
   185
      }
moel@219
   186
moel@219
   187
      // set timeStampCounterMultiplier
moel@219
   188
      switch (microarchitecture) {
moel@264
   189
        case Microarchitecture.NetBurst:
moel@219
   190
        case Microarchitecture.Atom:
moel@219
   191
        case Microarchitecture.Core: {
moel@219
   192
            uint eax, edx;
moel@236
   193
            if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
moel@219
   194
              timeStampCounterMultiplier = 
moel@219
   195
                ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
moel@219
   196
            }
moel@219
   197
          } break;
moel@249
   198
        case Microarchitecture.Nehalem: 
moel@249
   199
        case Microarchitecture.SandyBridge: {
moel@219
   200
            uint eax, edx;
moel@236
   201
            if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
moel@219
   202
              timeStampCounterMultiplier = (eax >> 8) & 0xff;
moel@219
   203
            }
moel@219
   204
          } break;
moel@264
   205
        default: {
moel@264
   206
            timeStampCounterMultiplier = 1;
moel@264
   207
            uint eax, edx;
moel@264
   208
            if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
moel@264
   209
              timeStampCounterMultiplier =
moel@264
   210
                ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
moel@264
   211
            }
moel@264
   212
          } break;
moel@49
   213
      }
moel@1
   214
moel@306
   215
      // check if processor supports a digital thermal sensor at core level
moel@191
   216
      if (cpuid[0][0].Data.GetLength(0) > 6 &&
moel@306
   217
        (cpuid[0][0].Data[6, 0] & 1) != 0) 
moel@306
   218
      {
moel@44
   219
        coreTemperatures = new Sensor[coreCount];
moel@44
   220
        for (int i = 0; i < coreTemperatures.Length; i++) {
moel@134
   221
          coreTemperatures[i] = new Sensor(CoreString(i), i,
moel@195
   222
            SensorType.Temperature, this, new [] { 
moel@63
   223
              new ParameterDescription(
moel@306
   224
                "TjMax [°C]", "TjMax temperature of the core sensor.\n" + 
moel@69
   225
                "Temperature = TjMax - TSlope * Value.", tjMax[i]), 
moel@122
   226
              new ParameterDescription("TSlope [°C]", 
moel@122
   227
                "Temperature slope of the digital thermal sensor.\n" + 
moel@165
   228
                "Temperature = TjMax - TSlope * Value.", 1)}, settings);
moel@155
   229
          ActivateSensor(coreTemperatures[i]);
moel@44
   230
        }
moel@44
   231
      } else {
moel@44
   232
        coreTemperatures = new Sensor[0];
moel@1
   233
      }
moel@49
   234
moel@306
   235
      // check if processor supports a digital thermal sensor at package level
moel@306
   236
      if (cpuid[0][0].Data.GetLength(0) > 6 &&
moel@306
   237
        (cpuid[0][0].Data[6, 0] & 0x40) != 0) 
moel@306
   238
      {
moel@306
   239
          packageTemperature = new Sensor("CPU Package", 
moel@306
   240
            coreTemperatures.Length, SensorType.Temperature, this, new[] { 
moel@306
   241
              new ParameterDescription(
moel@306
   242
                "TjMax [°C]", "TjMax temperature of the package sensor.\n" + 
moel@306
   243
                "Temperature = TjMax - TSlope * Value.", tjMax[0]), 
moel@306
   244
              new ParameterDescription("TSlope [°C]", 
moel@306
   245
                "Temperature slope of the digital thermal sensor.\n" + 
moel@306
   246
                "Temperature = TjMax - TSlope * Value.", 1)}, settings);
moel@306
   247
        ActivateSensor(packageTemperature);
moel@306
   248
      } 
moel@306
   249
moel@191
   250
      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
moel@44
   251
      coreClocks = new Sensor[coreCount];
moel@44
   252
      for (int i = 0; i < coreClocks.Length; i++) {
moel@49
   253
        coreClocks[i] =
moel@165
   254
          new Sensor(CoreString(i), i + 1, SensorType.Clock, this, settings);
moel@201
   255
        if (HasTimeStampCounter)
moel@79
   256
          ActivateSensor(coreClocks[i]);
moel@44
   257
      }
moel@191
   258
moel@317
   259
      if (microarchitecture == Microarchitecture.SandyBridge) {
moel@317
   260
        uint eax, edx;
moel@317
   261
        if (Ring0.Rdmsr(MSR_RAPL_POWER_UNIT, out eax, out edx))
moel@317
   262
          energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1FF));
moel@317
   263
moel@317
   264
moel@317
   265
        if (energyUnitMultiplier != 0 && 
moel@317
   266
          Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) 
moel@317
   267
        {
moel@317
   268
          lastPackageTime = DateTime.UtcNow;
moel@317
   269
          lastPackageEnergyConsumed = eax;
moel@317
   270
          packagePower = new Sensor("CPU Package", 0, SensorType.Power, this, 
moel@317
   271
            settings);          
moel@317
   272
          ActivateSensor(packagePower);
moel@317
   273
        }
moel@317
   274
moel@317
   275
        if (energyUnitMultiplier != 0 &&
moel@317
   276
          Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx)) 
moel@317
   277
        {
moel@317
   278
          lastCoresTime = DateTime.UtcNow;
moel@317
   279
          lastCoresEnergyConsumed = eax;
moel@317
   280
          coresPower = new Sensor("CPU Cores", 1, SensorType.Power, this,
moel@317
   281
            settings);
moel@317
   282
          ActivateSensor(coresPower);
moel@317
   283
        }
moel@317
   284
      }
moel@317
   285
moel@191
   286
      Update();
moel@1
   287
    }
moel@1
   288
moel@191
   289
    protected override uint[] GetMSRs() {
moel@195
   290
      return new [] {
moel@191
   291
        MSR_PLATFORM_INFO,
moel@191
   292
        IA32_PERF_STATUS ,
moel@191
   293
        IA32_THERM_STATUS_MSR,
moel@306
   294
        IA32_TEMPERATURE_TARGET,
moel@317
   295
        IA32_PACKAGE_THERM_STATUS,
moel@317
   296
        MSR_RAPL_POWER_UNIT,
moel@317
   297
        MSR_PKG_ENERY_STATUS,
moel@320
   298
        MSR_PP0_ENERY_STATUS,
moel@320
   299
        MSR_PP1_ENERY_STATUS
moel@191
   300
      };
moel@1
   301
    }
moel@1
   302
moel@219
   303
    public override string GetReport() {
moel@219
   304
      StringBuilder r = new StringBuilder();
moel@219
   305
      r.Append(base.GetReport());
moel@219
   306
moel@264
   307
      r.Append("Microarchitecture: ");
moel@264
   308
      r.AppendLine(microarchitecture.ToString());
moel@219
   309
      r.Append("Time Stamp Counter Multiplier: ");
moel@219
   310
      r.AppendLine(timeStampCounterMultiplier.ToString(
moel@219
   311
        CultureInfo.InvariantCulture));
moel@219
   312
      r.AppendLine();
moel@219
   313
moel@219
   314
      return r.ToString();
moel@219
   315
    }
moel@219
   316
moel@191
   317
    public override void Update() {
moel@191
   318
      base.Update();
moel@1
   319
moel@1
   320
      for (int i = 0; i < coreTemperatures.Length; i++) {
moel@46
   321
        uint eax, edx;
moel@236
   322
        if (Ring0.RdmsrTx(
moel@191
   323
          IA32_THERM_STATUS_MSR, out eax, out edx,
moel@238
   324
            1UL << cpuid[i][0].Thread)) {
moel@1
   325
          // if reading is valid
moel@1
   326
          if ((eax & 0x80000000) != 0) {
moel@1
   327
            // get the dist from tjMax from bits 22:16
moel@63
   328
            float deltaT = ((eax & 0x007F0000) >> 16);
moel@63
   329
            float tjMax = coreTemperatures[i].Parameters[0].Value;
moel@63
   330
            float tSlope = coreTemperatures[i].Parameters[1].Value;
moel@63
   331
            coreTemperatures[i].Value = tjMax - tSlope * deltaT;
moel@24
   332
          } else {
moel@155
   333
            coreTemperatures[i].Value = null;
moel@1
   334
          }
moel@79
   335
        }
moel@24
   336
      }
moel@24
   337
moel@306
   338
      if (packageTemperature != null) {
moel@306
   339
        uint eax, edx;
moel@306
   340
        if (Ring0.RdmsrTx(
moel@315
   341
          IA32_PACKAGE_THERM_STATUS, out eax, out edx,
moel@306
   342
            1UL << cpuid[0][0].Thread)) {
moel@306
   343
          // get the dist from tjMax from bits 22:16
moel@306
   344
          float deltaT = ((eax & 0x007F0000) >> 16);
moel@306
   345
          float tjMax = packageTemperature.Parameters[0].Value;
moel@306
   346
          float tSlope = packageTemperature.Parameters[1].Value;
moel@306
   347
          packageTemperature.Value = tjMax - tSlope * deltaT;
moel@306
   348
        } else {
moel@306
   349
          packageTemperature.Value = null;
moel@306
   350
        }
moel@306
   351
      }
moel@306
   352
moel@201
   353
      if (HasTimeStampCounter) {
moel@191
   354
        double newBusClock = 0;
moel@191
   355
        uint eax, edx;
moel@191
   356
        for (int i = 0; i < coreClocks.Length; i++) {
moel@191
   357
          System.Threading.Thread.Sleep(1);
moel@236
   358
          if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
moel@238
   359
            1UL << cpuid[i][0].Thread)) 
moel@219
   360
          {
moel@219
   361
            newBusClock = 
moel@219
   362
              TimeStampCounterFrequency / timeStampCounterMultiplier;
moel@250
   363
            switch (microarchitecture) {
moel@250
   364
              case Microarchitecture.Nehalem: {
moel@250
   365
                  uint multiplier = eax & 0xff;
moel@250
   366
                  coreClocks[i].Value = (float)(multiplier * newBusClock);
moel@250
   367
                } break;
moel@250
   368
              case Microarchitecture.SandyBridge: {
moel@250
   369
                  uint multiplier = (eax >> 8) & 0xff;
moel@250
   370
                  coreClocks[i].Value = (float)(multiplier * newBusClock);
moel@250
   371
                } break;
moel@250
   372
              default: {
moel@250
   373
                  double multiplier = 
moel@250
   374
                    ((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
moel@250
   375
                  coreClocks[i].Value = (float)(multiplier * newBusClock);
moel@250
   376
                } break;
moel@250
   377
            }         
moel@219
   378
          } else { 
moel@201
   379
            // if IA32_PERF_STATUS is not available, assume TSC frequency
moel@201
   380
            coreClocks[i].Value = (float)TimeStampCounterFrequency;
moel@46
   381
          }
moel@44
   382
        }
moel@191
   383
        if (newBusClock > 0) {
moel@191
   384
          this.busClock.Value = (float)newBusClock;
moel@191
   385
          ActivateSensor(this.busClock);
moel@191
   386
        }
moel@44
   387
      }
moel@317
   388
moel@317
   389
moel@317
   390
      if (packagePower != null) {
moel@317
   391
        uint eax, edx;
moel@317
   392
        if (Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) {
moel@317
   393
          DateTime time = DateTime.UtcNow;    
moel@317
   394
          uint energyConsumed = eax;
moel@317
   395
          float deltaTime = (float)(time - lastPackageTime).TotalSeconds;
moel@317
   396
          if (deltaTime > 0.01) {
moel@317
   397
            packagePower.Value = energyUnitMultiplier * 
moel@317
   398
              unchecked(energyConsumed - lastPackageEnergyConsumed) / deltaTime;
moel@317
   399
            lastPackageTime = time;
moel@317
   400
            lastPackageEnergyConsumed = energyConsumed;
moel@317
   401
          }
moel@317
   402
        }         
moel@317
   403
      }
moel@317
   404
moel@317
   405
      if (coresPower != null) {
moel@317
   406
        uint eax, edx;
moel@317
   407
        if (Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx)) {
moel@317
   408
          DateTime time = DateTime.UtcNow;
moel@317
   409
          uint energyConsumed = eax;
moel@317
   410
          float deltaTime = (float)(time - lastCoresTime).TotalSeconds;
moel@317
   411
          if (deltaTime > 0.01) {
moel@317
   412
            coresPower.Value = energyUnitMultiplier *
moel@317
   413
              unchecked(energyConsumed - lastCoresEnergyConsumed) / deltaTime;
moel@317
   414
            lastCoresTime = time;
moel@317
   415
            lastCoresEnergyConsumed = energyConsumed;
moel@317
   416
          }
moel@317
   417
        }
moel@317
   418
      }
moel@46
   419
    }
moel@191
   420
  }
moel@1
   421
}