diff -r 82bfd8af42a7 -r 1ccf99e620a9 Hardware/CPU/IntelCPU.cs --- a/Hardware/CPU/IntelCPU.cs Mon Jul 25 21:09:21 2011 +0000 +++ b/Hardware/CPU/IntelCPU.cs Wed Jul 27 18:27:16 2011 +0000 @@ -55,6 +55,8 @@ private readonly Sensor packageTemperature; private readonly Sensor[] coreClocks; private readonly Sensor busClock; + private readonly Sensor packagePower; + private readonly Sensor coresPower; private readonly Microarchitecture microarchitecture; private readonly double timeStampCounterMultiplier; @@ -64,6 +66,17 @@ private const uint IA32_PERF_STATUS = 0x0198; private const uint MSR_PLATFORM_INFO = 0xCE; private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1; + private const uint MSR_RAPL_POWER_UNIT = 0x606; + private const uint MSR_PKG_ENERY_STATUS = 0x611; + private const uint MSR_PP0_ENERY_STATUS = 0x639; + + private float energyUnitMultiplier = 0; + private DateTime lastPackageTime; + private uint lastPackageEnergyConsumed; + private DateTime lastCoresTime; + private uint lastCoresEnergyConsumed; + + private float[] Floats(float f) { float[] result = new float[coreCount]; @@ -242,6 +255,33 @@ ActivateSensor(coreClocks[i]); } + if (microarchitecture == Microarchitecture.SandyBridge) { + uint eax, edx; + if (Ring0.Rdmsr(MSR_RAPL_POWER_UNIT, out eax, out edx)) + energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1FF)); + + + if (energyUnitMultiplier != 0 && + Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) + { + lastPackageTime = DateTime.UtcNow; + lastPackageEnergyConsumed = eax; + packagePower = new Sensor("CPU Package", 0, SensorType.Power, this, + settings); + ActivateSensor(packagePower); + } + + if (energyUnitMultiplier != 0 && + Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx)) + { + lastCoresTime = DateTime.UtcNow; + lastCoresEnergyConsumed = eax; + coresPower = new Sensor("CPU Cores", 1, SensorType.Power, this, + settings); + ActivateSensor(coresPower); + } + } + Update(); } @@ -251,7 +291,10 @@ IA32_PERF_STATUS , IA32_THERM_STATUS_MSR, IA32_TEMPERATURE_TARGET, - IA32_PACKAGE_THERM_STATUS + IA32_PACKAGE_THERM_STATUS, + MSR_RAPL_POWER_UNIT, + MSR_PKG_ENERY_STATUS, + MSR_PP0_ENERY_STATUS }; } @@ -340,6 +383,37 @@ ActivateSensor(this.busClock); } } + + + if (packagePower != null) { + uint eax, edx; + if (Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) { + DateTime time = DateTime.UtcNow; + uint energyConsumed = eax; + float deltaTime = (float)(time - lastPackageTime).TotalSeconds; + if (deltaTime > 0.01) { + packagePower.Value = energyUnitMultiplier * + unchecked(energyConsumed - lastPackageEnergyConsumed) / deltaTime; + lastPackageTime = time; + lastPackageEnergyConsumed = energyConsumed; + } + } + } + + if (coresPower != null) { + uint eax, edx; + if (Ring0.Rdmsr(MSR_PP0_ENERY_STATUS, out eax, out edx)) { + DateTime time = DateTime.UtcNow; + uint energyConsumed = eax; + float deltaTime = (float)(time - lastCoresTime).TotalSeconds; + if (deltaTime > 0.01) { + coresPower.Value = energyUnitMultiplier * + unchecked(energyConsumed - lastCoresEnergyConsumed) / deltaTime; + lastCoresTime = time; + lastCoresEnergyConsumed = energyConsumed; + } + } + } } } }