mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-09-02 07:15:31 +00:00
Added additional Intel Sandy Bridge CPU power sensors.
This commit is contained in:
@@ -55,8 +55,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
private readonly Sensor packageTemperature;
|
private readonly Sensor packageTemperature;
|
||||||
private readonly Sensor[] coreClocks;
|
private readonly Sensor[] coreClocks;
|
||||||
private readonly Sensor busClock;
|
private readonly Sensor busClock;
|
||||||
private readonly Sensor packagePower;
|
private readonly Sensor[] powerSensors;
|
||||||
private readonly Sensor coresPower;
|
|
||||||
|
|
||||||
private readonly Microarchitecture microarchitecture;
|
private readonly Microarchitecture microarchitecture;
|
||||||
private readonly double timeStampCounterMultiplier;
|
private readonly double timeStampCounterMultiplier;
|
||||||
@@ -68,15 +67,17 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1;
|
private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1;
|
||||||
private const uint MSR_RAPL_POWER_UNIT = 0x606;
|
private const uint MSR_RAPL_POWER_UNIT = 0x606;
|
||||||
private const uint MSR_PKG_ENERY_STATUS = 0x611;
|
private const uint MSR_PKG_ENERY_STATUS = 0x611;
|
||||||
|
private const uint MSR_DRAM_ENERGY_STATUS = 0x619;
|
||||||
private const uint MSR_PP0_ENERY_STATUS = 0x639;
|
private const uint MSR_PP0_ENERY_STATUS = 0x639;
|
||||||
private const uint MSR_PP1_ENERY_STATUS = 0x641;
|
private const uint MSR_PP1_ENERY_STATUS = 0x641;
|
||||||
|
|
||||||
|
private readonly uint[] energyStatusMSRs = { MSR_PKG_ENERY_STATUS,
|
||||||
|
MSR_PP0_ENERY_STATUS, MSR_PP1_ENERY_STATUS, MSR_DRAM_ENERGY_STATUS };
|
||||||
|
private readonly string[] powerSensorLabels =
|
||||||
|
{ "CPU Package", "CPU Cores", "CPU Graphics", "CPU DRAM" };
|
||||||
private float energyUnitMultiplier = 0;
|
private float energyUnitMultiplier = 0;
|
||||||
private DateTime lastPackageTime;
|
private DateTime[] lastEnergyTime;
|
||||||
private uint lastPackageEnergyConsumed;
|
private uint[] lastEnergyConsumed;
|
||||||
private DateTime lastCoresTime;
|
|
||||||
private uint lastCoresEnergyConsumed;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private float[] Floats(float f) {
|
private float[] Floats(float f) {
|
||||||
@@ -101,8 +102,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
|
public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
|
||||||
: base(processorIndex, cpuid, settings)
|
: base(processorIndex, cpuid, settings) {
|
||||||
{
|
|
||||||
// set tjMax
|
// set tjMax
|
||||||
float[] tjMax;
|
float[] tjMax;
|
||||||
switch (family) {
|
switch (family) {
|
||||||
@@ -157,7 +157,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
microarchitecture = Microarchitecture.Unknown;
|
microarchitecture = Microarchitecture.Unknown;
|
||||||
tjMax = Floats(100);
|
tjMax = Floats(100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -170,7 +170,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
case 0x04: // Pentium 4, Pentium D, Celeron D (90nm)
|
case 0x04: // Pentium 4, Pentium D, Celeron D (90nm)
|
||||||
case 0x06: // Pentium 4, Pentium D, Celeron D (65nm)
|
case 0x06: // Pentium 4, Pentium D, Celeron D (65nm)
|
||||||
microarchitecture = Microarchitecture.NetBurst;
|
microarchitecture = Microarchitecture.NetBurst;
|
||||||
tjMax = Floats(100);
|
tjMax = Floats(100);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
microarchitecture = Microarchitecture.Unknown;
|
microarchitecture = Microarchitecture.Unknown;
|
||||||
@@ -180,7 +180,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
microarchitecture = Microarchitecture.Unknown;
|
microarchitecture = Microarchitecture.Unknown;
|
||||||
tjMax = Floats(100);
|
tjMax = Floats(100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,11 +191,11 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
case Microarchitecture.Core: {
|
case Microarchitecture.Core: {
|
||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
|
if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
|
||||||
timeStampCounterMultiplier =
|
timeStampCounterMultiplier =
|
||||||
((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
|
((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Microarchitecture.Nehalem:
|
case Microarchitecture.Nehalem:
|
||||||
case Microarchitecture.SandyBridge: {
|
case Microarchitecture.SandyBridge: {
|
||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
|
if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
|
||||||
@@ -214,12 +214,11 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
|
|
||||||
// check if processor supports a digital thermal sensor at core level
|
// check if processor supports a digital thermal sensor at core level
|
||||||
if (cpuid[0][0].Data.GetLength(0) > 6 &&
|
if (cpuid[0][0].Data.GetLength(0) > 6 &&
|
||||||
(cpuid[0][0].Data[6, 0] & 1) != 0)
|
(cpuid[0][0].Data[6, 0] & 1) != 0) {
|
||||||
{
|
|
||||||
coreTemperatures = new Sensor[coreCount];
|
coreTemperatures = new Sensor[coreCount];
|
||||||
for (int i = 0; i < coreTemperatures.Length; i++) {
|
for (int i = 0; i < coreTemperatures.Length; i++) {
|
||||||
coreTemperatures[i] = new Sensor(CoreString(i), i,
|
coreTemperatures[i] = new Sensor(CoreString(i), i,
|
||||||
SensorType.Temperature, this, new [] {
|
SensorType.Temperature, this, new[] {
|
||||||
new ParameterDescription(
|
new ParameterDescription(
|
||||||
"TjMax [°C]", "TjMax temperature of the core sensor.\n" +
|
"TjMax [°C]", "TjMax temperature of the core sensor.\n" +
|
||||||
"Temperature = TjMax - TSlope * Value.", tjMax[i]),
|
"Temperature = TjMax - TSlope * Value.", tjMax[i]),
|
||||||
@@ -234,10 +233,9 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
|
|
||||||
// check if processor supports a digital thermal sensor at package level
|
// check if processor supports a digital thermal sensor at package level
|
||||||
if (cpuid[0][0].Data.GetLength(0) > 6 &&
|
if (cpuid[0][0].Data.GetLength(0) > 6 &&
|
||||||
(cpuid[0][0].Data[6, 0] & 0x40) != 0)
|
(cpuid[0][0].Data[6, 0] & 0x40) != 0) {
|
||||||
{
|
packageTemperature = new Sensor("CPU Package",
|
||||||
packageTemperature = new Sensor("CPU Package",
|
coreTemperatures.Length, SensorType.Temperature, this, new[] {
|
||||||
coreTemperatures.Length, SensorType.Temperature, this, new[] {
|
|
||||||
new ParameterDescription(
|
new ParameterDescription(
|
||||||
"TjMax [°C]", "TjMax temperature of the package sensor.\n" +
|
"TjMax [°C]", "TjMax temperature of the package sensor.\n" +
|
||||||
"Temperature = TjMax - TSlope * Value.", tjMax[0]),
|
"Temperature = TjMax - TSlope * Value.", tjMax[0]),
|
||||||
@@ -245,7 +243,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
"Temperature slope of the digital thermal sensor.\n" +
|
"Temperature slope of the digital thermal sensor.\n" +
|
||||||
"Temperature = TjMax - TSlope * Value.", 1)}, settings);
|
"Temperature = TjMax - TSlope * Value.", 1)}, settings);
|
||||||
ActivateSensor(packageTemperature);
|
ActivateSensor(packageTemperature);
|
||||||
}
|
}
|
||||||
|
|
||||||
busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
|
busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
|
||||||
coreClocks = new Sensor[coreCount];
|
coreClocks = new Sensor[coreCount];
|
||||||
@@ -257,29 +255,26 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (microarchitecture == Microarchitecture.SandyBridge) {
|
if (microarchitecture == Microarchitecture.SandyBridge) {
|
||||||
|
|
||||||
|
powerSensors = new Sensor[energyStatusMSRs.Length];
|
||||||
|
lastEnergyTime = new DateTime[energyStatusMSRs.Length];
|
||||||
|
lastEnergyConsumed = new uint[energyStatusMSRs.Length];
|
||||||
|
|
||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
if (Ring0.Rdmsr(MSR_RAPL_POWER_UNIT, out eax, out edx))
|
if (Ring0.Rdmsr(MSR_RAPL_POWER_UNIT, out eax, out edx))
|
||||||
energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1FF));
|
energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1FF));
|
||||||
|
|
||||||
|
if (energyUnitMultiplier != 0) {
|
||||||
|
for (int i = 0; i < energyStatusMSRs.Length; i++) {
|
||||||
|
if (!Ring0.Rdmsr(energyStatusMSRs[i], out eax, out edx))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (energyUnitMultiplier != 0 &&
|
lastEnergyTime[i] = DateTime.UtcNow;
|
||||||
Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx))
|
lastEnergyConsumed[i] = eax;
|
||||||
{
|
powerSensors[i] = new Sensor(powerSensorLabels[i], i,
|
||||||
lastPackageTime = DateTime.UtcNow;
|
SensorType.Power, this, settings);
|
||||||
lastPackageEnergyConsumed = eax;
|
ActivateSensor(powerSensors[i]);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +282,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override uint[] GetMSRs() {
|
protected override uint[] GetMSRs() {
|
||||||
return new [] {
|
return new[] {
|
||||||
MSR_PLATFORM_INFO,
|
MSR_PLATFORM_INFO,
|
||||||
IA32_PERF_STATUS ,
|
IA32_PERF_STATUS ,
|
||||||
IA32_THERM_STATUS_MSR,
|
IA32_THERM_STATUS_MSR,
|
||||||
@@ -295,6 +290,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
IA32_PACKAGE_THERM_STATUS,
|
IA32_PACKAGE_THERM_STATUS,
|
||||||
MSR_RAPL_POWER_UNIT,
|
MSR_RAPL_POWER_UNIT,
|
||||||
MSR_PKG_ENERY_STATUS,
|
MSR_PKG_ENERY_STATUS,
|
||||||
|
MSR_DRAM_ENERGY_STATUS,
|
||||||
MSR_PP0_ENERY_STATUS,
|
MSR_PP0_ENERY_STATUS,
|
||||||
MSR_PP1_ENERY_STATUS
|
MSR_PP1_ENERY_STATUS
|
||||||
};
|
};
|
||||||
@@ -356,9 +352,8 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
for (int i = 0; i < coreClocks.Length; i++) {
|
for (int i = 0; i < coreClocks.Length; i++) {
|
||||||
System.Threading.Thread.Sleep(1);
|
System.Threading.Thread.Sleep(1);
|
||||||
if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
|
if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
|
||||||
1UL << cpuid[i][0].Thread))
|
1UL << cpuid[i][0].Thread)) {
|
||||||
{
|
newBusClock =
|
||||||
newBusClock =
|
|
||||||
TimeStampCounterFrequency / timeStampCounterMultiplier;
|
TimeStampCounterFrequency / timeStampCounterMultiplier;
|
||||||
switch (microarchitecture) {
|
switch (microarchitecture) {
|
||||||
case Microarchitecture.Nehalem: {
|
case Microarchitecture.Nehalem: {
|
||||||
@@ -370,12 +365,12 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
coreClocks[i].Value = (float)(multiplier * newBusClock);
|
coreClocks[i].Value = (float)(multiplier * newBusClock);
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
double multiplier =
|
double multiplier =
|
||||||
((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
|
((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
|
||||||
coreClocks[i].Value = (float)(multiplier * newBusClock);
|
coreClocks[i].Value = (float)(multiplier * newBusClock);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if IA32_PERF_STATUS is not available, assume TSC frequency
|
// if IA32_PERF_STATUS is not available, assume TSC frequency
|
||||||
coreClocks[i].Value = (float)TimeStampCounterFrequency;
|
coreClocks[i].Value = (float)TimeStampCounterFrequency;
|
||||||
}
|
}
|
||||||
@@ -386,34 +381,26 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (powerSensors != null) {
|
||||||
|
foreach (Sensor sensor in powerSensors) {
|
||||||
|
if (sensor == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (packagePower != null) {
|
uint eax, edx;
|
||||||
uint eax, edx;
|
if (!Ring0.Rdmsr(energyStatusMSRs[sensor.Index], out eax, out edx))
|
||||||
if (Ring0.Rdmsr(MSR_PKG_ENERY_STATUS, out eax, out edx)) {
|
continue;
|
||||||
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;
|
DateTime time = DateTime.UtcNow;
|
||||||
uint energyConsumed = eax;
|
uint energyConsumed = eax;
|
||||||
float deltaTime = (float)(time - lastCoresTime).TotalSeconds;
|
float deltaTime =
|
||||||
if (deltaTime > 0.01) {
|
(float)(time - lastEnergyTime[sensor.Index]).TotalSeconds;
|
||||||
coresPower.Value = energyUnitMultiplier *
|
if (deltaTime < 0.01)
|
||||||
unchecked(energyConsumed - lastCoresEnergyConsumed) / deltaTime;
|
continue;
|
||||||
lastCoresTime = time;
|
|
||||||
lastCoresEnergyConsumed = energyConsumed;
|
sensor.Value = energyUnitMultiplier * unchecked(
|
||||||
}
|
energyConsumed - lastEnergyConsumed[sensor.Index]) / deltaTime;
|
||||||
|
lastEnergyTime[sensor.Index] = time;
|
||||||
|
lastEnergyConsumed[sensor.Index] = energyConsumed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user