Added additional Intel Sandy Bridge CPU power sensors.
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 }