Added additional Intel Sandy Bridge CPU power sensors.
authormoel.mich
Thu, 11 Aug 2011 22:18:53 +0000
changeset 3211da7448c8e10
parent 320 df3493f75225
child 322 523c19d10a86
Added additional Intel Sandy Bridge CPU power sensors.
Hardware/CPU/IntelCPU.cs
     1.1 --- a/Hardware/CPU/IntelCPU.cs	Sat Aug 06 17:27:55 2011 +0000
     1.2 +++ b/Hardware/CPU/IntelCPU.cs	Thu Aug 11 22:18:53 2011 +0000
     1.3 @@ -55,8 +55,7 @@
     1.4      private readonly Sensor packageTemperature;
     1.5      private readonly Sensor[] coreClocks;
     1.6      private readonly Sensor busClock;
     1.7 -    private readonly Sensor packagePower;
     1.8 -    private readonly Sensor coresPower;
     1.9 +    private readonly Sensor[] powerSensors;
    1.10  
    1.11      private readonly Microarchitecture microarchitecture;
    1.12      private readonly double timeStampCounterMultiplier;
    1.13 @@ -68,15 +67,17 @@
    1.14      private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1;
    1.15      private const uint MSR_RAPL_POWER_UNIT = 0x606;
    1.16      private const uint MSR_PKG_ENERY_STATUS = 0x611;
    1.17 +    private const uint MSR_DRAM_ENERGY_STATUS = 0x619;
    1.18      private const uint MSR_PP0_ENERY_STATUS = 0x639;
    1.19      private const uint MSR_PP1_ENERY_STATUS = 0x641;
    1.20  
    1.21 +    private readonly uint[] energyStatusMSRs = { MSR_PKG_ENERY_STATUS, 
    1.22 +      MSR_PP0_ENERY_STATUS, MSR_PP1_ENERY_STATUS, MSR_DRAM_ENERGY_STATUS };
    1.23 +    private readonly string[] powerSensorLabels = 
    1.24 +      { "CPU Package", "CPU Cores", "CPU Graphics", "CPU DRAM" };
    1.25      private float energyUnitMultiplier = 0;
    1.26 -    private DateTime lastPackageTime;
    1.27 -    private uint lastPackageEnergyConsumed;
    1.28 -    private DateTime lastCoresTime;
    1.29 -    private uint lastCoresEnergyConsumed;
    1.30 -
    1.31 +    private DateTime[] lastEnergyTime;
    1.32 +    private uint[] lastEnergyConsumed;
    1.33  
    1.34  
    1.35      private float[] Floats(float f) {
    1.36 @@ -101,8 +102,7 @@
    1.37      }
    1.38  
    1.39      public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    1.40 -      : base(processorIndex, cpuid, settings) 
    1.41 -    {
    1.42 +      : base(processorIndex, cpuid, settings) {
    1.43        // set tjMax
    1.44        float[] tjMax;
    1.45        switch (family) {
    1.46 @@ -157,7 +157,7 @@
    1.47                  break;
    1.48                default:
    1.49                  microarchitecture = Microarchitecture.Unknown;
    1.50 -                tjMax = Floats(100); 
    1.51 +                tjMax = Floats(100);
    1.52                  break;
    1.53              }
    1.54            } break;
    1.55 @@ -170,7 +170,7 @@
    1.56                case 0x04: // Pentium 4, Pentium D, Celeron D (90nm)
    1.57                case 0x06: // Pentium 4, Pentium D, Celeron D (65nm)
    1.58                  microarchitecture = Microarchitecture.NetBurst;
    1.59 -                tjMax = Floats(100); 
    1.60 +                tjMax = Floats(100);
    1.61                  break;
    1.62                default:
    1.63                  microarchitecture = Microarchitecture.Unknown;
    1.64 @@ -180,7 +180,7 @@
    1.65            } break;
    1.66          default:
    1.67            microarchitecture = Microarchitecture.Unknown;
    1.68 -          tjMax = Floats(100); 
    1.69 +          tjMax = Floats(100);
    1.70            break;
    1.71        }
    1.72  
    1.73 @@ -191,11 +191,11 @@
    1.74          case Microarchitecture.Core: {
    1.75              uint eax, edx;
    1.76              if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
    1.77 -              timeStampCounterMultiplier = 
    1.78 +              timeStampCounterMultiplier =
    1.79                  ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
    1.80              }
    1.81            } break;
    1.82 -        case Microarchitecture.Nehalem: 
    1.83 +        case Microarchitecture.Nehalem:
    1.84          case Microarchitecture.SandyBridge: {
    1.85              uint eax, edx;
    1.86              if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
    1.87 @@ -214,12 +214,11 @@
    1.88  
    1.89        // check if processor supports a digital thermal sensor at core level
    1.90        if (cpuid[0][0].Data.GetLength(0) > 6 &&
    1.91 -        (cpuid[0][0].Data[6, 0] & 1) != 0) 
    1.92 -      {
    1.93 +        (cpuid[0][0].Data[6, 0] & 1) != 0) {
    1.94          coreTemperatures = new Sensor[coreCount];
    1.95          for (int i = 0; i < coreTemperatures.Length; i++) {
    1.96            coreTemperatures[i] = new Sensor(CoreString(i), i,
    1.97 -            SensorType.Temperature, this, new [] { 
    1.98 +            SensorType.Temperature, this, new[] { 
    1.99                new ParameterDescription(
   1.100                  "TjMax [°C]", "TjMax temperature of the core sensor.\n" + 
   1.101                  "Temperature = TjMax - TSlope * Value.", tjMax[i]), 
   1.102 @@ -234,10 +233,9 @@
   1.103  
   1.104        // check if processor supports a digital thermal sensor at package level
   1.105        if (cpuid[0][0].Data.GetLength(0) > 6 &&
   1.106 -        (cpuid[0][0].Data[6, 0] & 0x40) != 0) 
   1.107 -      {
   1.108 -          packageTemperature = new Sensor("CPU Package", 
   1.109 -            coreTemperatures.Length, SensorType.Temperature, this, new[] { 
   1.110 +        (cpuid[0][0].Data[6, 0] & 0x40) != 0) {
   1.111 +        packageTemperature = new Sensor("CPU Package",
   1.112 +          coreTemperatures.Length, SensorType.Temperature, this, new[] { 
   1.113                new ParameterDescription(
   1.114                  "TjMax [°C]", "TjMax temperature of the package sensor.\n" + 
   1.115                  "Temperature = TjMax - TSlope * Value.", tjMax[0]), 
   1.116 @@ -245,7 +243,7 @@
   1.117                  "Temperature slope of the digital thermal sensor.\n" + 
   1.118                  "Temperature = TjMax - TSlope * Value.", 1)}, settings);
   1.119          ActivateSensor(packageTemperature);
   1.120 -      } 
   1.121 +      }
   1.122  
   1.123        busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
   1.124        coreClocks = new Sensor[coreCount];
   1.125 @@ -257,29 +255,26 @@
   1.126        }
   1.127  
   1.128        if (microarchitecture == Microarchitecture.SandyBridge) {
   1.129 +
   1.130 +        powerSensors = new Sensor[energyStatusMSRs.Length];
   1.131 +        lastEnergyTime = new DateTime[energyStatusMSRs.Length];
   1.132 +        lastEnergyConsumed = new uint[energyStatusMSRs.Length];
   1.133 +
   1.134          uint eax, edx;
   1.135          if (Ring0.Rdmsr(MSR_RAPL_POWER_UNIT, out eax, out edx))
   1.136            energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1FF));
   1.137  
   1.138 +        if (energyUnitMultiplier != 0) {
   1.139 +          for (int i = 0; i < energyStatusMSRs.Length; i++) {
   1.140 +            if (!Ring0.Rdmsr(energyStatusMSRs[i], out eax, out edx))
   1.141 +              continue;
   1.142  
   1.143 -        if (energyUnitMultiplier != 0 && 
   1.144 -          Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) 
   1.145 -        {
   1.146 -          lastPackageTime = DateTime.UtcNow;
   1.147 -          lastPackageEnergyConsumed = eax;
   1.148 -          packagePower = new Sensor("CPU Package", 0, SensorType.Power, this, 
   1.149 -            settings);          
   1.150 -          ActivateSensor(packagePower);
   1.151 -        }
   1.152 -
   1.153 -        if (energyUnitMultiplier != 0 &&
   1.154 -          Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx)) 
   1.155 -        {
   1.156 -          lastCoresTime = DateTime.UtcNow;
   1.157 -          lastCoresEnergyConsumed = eax;
   1.158 -          coresPower = new Sensor("CPU Cores", 1, SensorType.Power, this,
   1.159 -            settings);
   1.160 -          ActivateSensor(coresPower);
   1.161 +            lastEnergyTime[i] = DateTime.UtcNow;
   1.162 +            lastEnergyConsumed[i] = eax;
   1.163 +            powerSensors[i] = new Sensor(powerSensorLabels[i], i,
   1.164 +              SensorType.Power, this, settings);
   1.165 +            ActivateSensor(powerSensors[i]);
   1.166 +          }
   1.167          }
   1.168        }
   1.169  
   1.170 @@ -287,7 +282,7 @@
   1.171      }
   1.172  
   1.173      protected override uint[] GetMSRs() {
   1.174 -      return new [] {
   1.175 +      return new[] {
   1.176          MSR_PLATFORM_INFO,
   1.177          IA32_PERF_STATUS ,
   1.178          IA32_THERM_STATUS_MSR,
   1.179 @@ -295,6 +290,7 @@
   1.180          IA32_PACKAGE_THERM_STATUS,
   1.181          MSR_RAPL_POWER_UNIT,
   1.182          MSR_PKG_ENERY_STATUS,
   1.183 +        MSR_DRAM_ENERGY_STATUS,
   1.184          MSR_PP0_ENERY_STATUS,
   1.185          MSR_PP1_ENERY_STATUS
   1.186        };
   1.187 @@ -356,9 +352,8 @@
   1.188          for (int i = 0; i < coreClocks.Length; i++) {
   1.189            System.Threading.Thread.Sleep(1);
   1.190            if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
   1.191 -            1UL << cpuid[i][0].Thread)) 
   1.192 -          {
   1.193 -            newBusClock = 
   1.194 +            1UL << cpuid[i][0].Thread)) {
   1.195 +            newBusClock =
   1.196                TimeStampCounterFrequency / timeStampCounterMultiplier;
   1.197              switch (microarchitecture) {
   1.198                case Microarchitecture.Nehalem: {
   1.199 @@ -370,12 +365,12 @@
   1.200                    coreClocks[i].Value = (float)(multiplier * newBusClock);
   1.201                  } break;
   1.202                default: {
   1.203 -                  double multiplier = 
   1.204 +                  double multiplier =
   1.205                      ((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
   1.206                    coreClocks[i].Value = (float)(multiplier * newBusClock);
   1.207                  } break;
   1.208 -            }         
   1.209 -          } else { 
   1.210 +            }
   1.211 +          } else {
   1.212              // if IA32_PERF_STATUS is not available, assume TSC frequency
   1.213              coreClocks[i].Value = (float)TimeStampCounterFrequency;
   1.214            }
   1.215 @@ -386,34 +381,26 @@
   1.216          }
   1.217        }
   1.218  
   1.219 +      if (powerSensors != null) {
   1.220 +        foreach (Sensor sensor in powerSensors) {
   1.221 +          if (sensor == null)
   1.222 +            continue;
   1.223  
   1.224 -      if (packagePower != null) {
   1.225 -        uint eax, edx;
   1.226 -        if (Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) {
   1.227 -          DateTime time = DateTime.UtcNow;    
   1.228 -          uint energyConsumed = eax;
   1.229 -          float deltaTime = (float)(time - lastPackageTime).TotalSeconds;
   1.230 -          if (deltaTime > 0.01) {
   1.231 -            packagePower.Value = energyUnitMultiplier * 
   1.232 -              unchecked(energyConsumed - lastPackageEnergyConsumed) / deltaTime;
   1.233 -            lastPackageTime = time;
   1.234 -            lastPackageEnergyConsumed = energyConsumed;
   1.235 -          }
   1.236 -        }         
   1.237 -      }
   1.238 +          uint eax, edx;
   1.239 +          if (!Ring0.Rdmsr(energyStatusMSRs[sensor.Index], out eax, out edx))
   1.240 +            continue;
   1.241  
   1.242 -      if (coresPower != null) {
   1.243 -        uint eax, edx;
   1.244 -        if (Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx)) {
   1.245            DateTime time = DateTime.UtcNow;
   1.246            uint energyConsumed = eax;
   1.247 -          float deltaTime = (float)(time - lastCoresTime).TotalSeconds;
   1.248 -          if (deltaTime > 0.01) {
   1.249 -            coresPower.Value = energyUnitMultiplier *
   1.250 -              unchecked(energyConsumed - lastCoresEnergyConsumed) / deltaTime;
   1.251 -            lastCoresTime = time;
   1.252 -            lastCoresEnergyConsumed = energyConsumed;
   1.253 -          }
   1.254 +          float deltaTime =
   1.255 +            (float)(time - lastEnergyTime[sensor.Index]).TotalSeconds;
   1.256 +          if (deltaTime < 0.01)
   1.257 +            continue;
   1.258 +
   1.259 +          sensor.Value = energyUnitMultiplier * unchecked(
   1.260 +            energyConsumed - lastEnergyConsumed[sensor.Index]) / deltaTime;
   1.261 +          lastEnergyTime[sensor.Index] = time;
   1.262 +          lastEnergyConsumed[sensor.Index] = energyConsumed;
   1.263          }
   1.264        }
   1.265      }