# HG changeset patch # User moel.mich # Date 1311791236 0 # Node ID 1ccf99e620a98fe4ac3d257e2e457876d590a446 # Parent 82bfd8af42a7628692f5957a97d719145d7ec660 Added support for Intel CPU power sensors (package and cores). diff -r 82bfd8af42a7 -r 1ccf99e620a9 GUI/HardwareNode.cs --- a/GUI/HardwareNode.cs Mon Jul 25 21:09:21 2011 +0000 +++ b/GUI/HardwareNode.cs Wed Jul 27 18:27:16 2011 +0000 @@ -65,7 +65,8 @@ typeNodes.Add(new TypeNode(SensorType.Flow)); typeNodes.Add(new TypeNode(SensorType.Control)); typeNodes.Add(new TypeNode(SensorType.Level)); - + typeNodes.Add(new TypeNode(SensorType.Power)); + foreach (ISensor sensor in hardware.Sensors) SensorAdded(sensor); diff -r 82bfd8af42a7 -r 1ccf99e620a9 GUI/SensorNode.cs --- a/GUI/SensorNode.cs Mon Jul 25 21:09:21 2011 +0000 +++ b/GUI/SensorNode.cs Wed Jul 27 18:27:16 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2010 + Portions created by the Initial Developer are Copyright (C) 2009-2011 the Initial Developer. All Rights Reserved. Contributor(s): @@ -75,6 +75,7 @@ case SensorType.Flow: format = "{0:F0} L/h"; break; case SensorType.Control: format = "{0:F1} %"; break; case SensorType.Level: format = "{0:F1} %"; break; + case SensorType.Power: format = "{0:F1} W"; break; } bool hidden = settings.GetValue(new Identifier(sensor.Identifier, diff -r 82bfd8af42a7 -r 1ccf99e620a9 GUI/SensorNotifyIcon.cs --- a/GUI/SensorNotifyIcon.cs Mon Jul 25 21:09:21 2011 +0000 +++ b/GUI/SensorNotifyIcon.cs Wed Jul 27 18:27:16 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2010 + Portions created by the Initial Developer are Copyright (C) 2009-2011 the Initial Developer. All Rights Reserved. Contributor(s): @@ -196,6 +196,8 @@ return string.Format("{0:F0}", sensor.Value); case SensorType.Level: return string.Format("{0:F0}", sensor.Value); + case SensorType.Power: + return string.Format("{0:F0}", sensor.Value); } return "-"; } @@ -283,6 +285,7 @@ case SensorType.Flow: format = "\n{0}: {1:F0} L/h"; break; case SensorType.Control: format = "\n{0}: {1:F1} %"; break; case SensorType.Level: format = "\n{0}: {1:F1} %"; break; + case SensorType.Power: format = "\n{0}: {1:F0} W"; break; } string formattedValue = string.Format(format, sensor.Name, sensor.Value); string hardwareName = sensor.Hardware.Name; diff -r 82bfd8af42a7 -r 1ccf99e620a9 GUI/TypeNode.cs --- a/GUI/TypeNode.cs Mon Jul 25 21:09:21 2011 +0000 +++ b/GUI/TypeNode.cs Wed Jul 27 18:27:16 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2010 + Portions created by the Initial Developer are Copyright (C) 2009-2011 the Initial Developer. All Rights Reserved. Contributor(s): @@ -80,6 +80,10 @@ this.Image = Utilities.EmbeddedResources.GetImage("level.png"); this.Text = "Levels"; break; + case SensorType.Power: + this.Image = Utilities.EmbeddedResources.GetImage("power.png"); + this.Text = "Powers"; + break; } NodeAdded += new NodeEventHandler(TypeNode_NodeAdded); 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; + } + } + } } } } diff -r 82bfd8af42a7 -r 1ccf99e620a9 Hardware/ISensor.cs --- a/Hardware/ISensor.cs Mon Jul 25 21:09:21 2011 +0000 +++ b/Hardware/ISensor.cs Wed Jul 27 18:27:16 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2010 + Portions created by the Initial Developer are Copyright (C) 2009-2011 the Initial Developer. All Rights Reserved. Contributor(s): @@ -49,7 +49,8 @@ Fan, Flow, Control, - Level + Level, + Power } public struct SensorValue { diff -r 82bfd8af42a7 -r 1ccf99e620a9 OpenHardwareMonitor.csproj --- a/OpenHardwareMonitor.csproj Mon Jul 25 21:09:21 2011 +0000 +++ b/OpenHardwareMonitor.csproj Wed Jul 27 18:27:16 2011 +0000 @@ -217,6 +217,9 @@ + + + diff -r 82bfd8af42a7 -r 1ccf99e620a9 Resources/power.png Binary file Resources/power.png has changed