Added core clock and bus speed support for Intel Core i5, i7 CPUs.

This commit is contained in:
Michael Möller
2010-02-15 22:58:29 +00:00
parent e3a64e9a06
commit dc9108ade1
3 changed files with 65 additions and 36 deletions

View File

@@ -48,6 +48,10 @@ namespace OpenHardwareMonitor.Hardware.CPU {
private string name; private string name;
private Image icon; private Image icon;
private uint family;
private uint model;
private uint stepping;
private Sensor[] coreTemperatures; private Sensor[] coreTemperatures;
private Sensor totalLoad; private Sensor totalLoad;
private Sensor[] coreLoads; private Sensor[] coreLoads;
@@ -63,17 +67,23 @@ namespace OpenHardwareMonitor.Hardware.CPU {
private ulong lastCount; private ulong lastCount;
private long lastTime; private long lastTime;
private uint maxNehalemMultiplier = 0;
private const uint IA32_THERM_STATUS_MSR = 0x019C; private const uint IA32_THERM_STATUS_MSR = 0x019C;
private const uint IA32_TEMPERATURE_TARGET = 0x01A2; private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
private const uint IA32_PERF_STATUS = 0x0198; private const uint IA32_PERF_STATUS = 0x0198;
private const uint MSR_PLATFORM_INFO = 0xCE;
public IntelCPU(string name, uint family, uint model, uint stepping, public IntelCPU(string name, uint family, uint model, uint stepping,
uint[,] cpuidData, uint[,] cpuidExtData) { uint[,] cpuidData, uint[,] cpuidExtData) {
this.name = name; this.name = name;
this.icon = Utilities.EmbeddedResources.GetImage("cpu.png"); this.icon = Utilities.EmbeddedResources.GetImage("cpu.png");
this.family = family;
this.model = model;
this.stepping = stepping;
logicalProcessors = 0; logicalProcessors = 0;
if (cpuidData.GetLength(0) > 0x0B) { if (cpuidData.GetLength(0) > 0x0B) {
uint eax, ebx, ecx, edx; uint eax, ebx, ecx, edx;
@@ -124,10 +134,11 @@ namespace OpenHardwareMonitor.Hardware.CPU {
tjMax = 100; break; tjMax = 100; break;
case 0x1C: // Intel Atom case 0x1C: // Intel Atom
tjMax = 90; break; tjMax = 90; break;
case 0x1A: case 0x1A: // Intel Core i7
uint eax = 0, edx = 0; case 0x1E: // Intel Core i5
if (WinRing0.RdmsrPx( uint eax, edx;
IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) { if (WinRing0.Rdmsr(IA32_TEMPERATURE_TARGET, out eax, out edx))
{
tjMax = (eax >> 16) & 0xFF; tjMax = (eax >> 16) & 0xFF;
} else } else
tjMax = 100; tjMax = 100;
@@ -139,6 +150,13 @@ namespace OpenHardwareMonitor.Hardware.CPU {
default: tjMax = 100; break; default: tjMax = 100; break;
} }
if (family == 0x06 && model >= 0x1A) { // Core i5, i7
uint eax, edx;
if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
maxNehalemMultiplier = (eax >> 8) & 0xff;
}
}
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("Core #" + (i + 1), i, tjMax, coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
@@ -204,9 +222,9 @@ namespace OpenHardwareMonitor.Hardware.CPU {
public void Update() { public void Update() {
for (int i = 0; i < coreTemperatures.Length; i++) { for (int i = 0; i < coreTemperatures.Length; i++) {
uint eax = 0, edx = 0; uint eax, edx;
if (WinRing0.RdmsrPx( if (WinRing0.RdmsrTx(
IA32_THERM_STATUS_MSR, ref eax, ref edx, IA32_THERM_STATUS_MSR, out eax, out edx,
(UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i))))
{ {
// if reading is valid // if reading is valid
@@ -227,33 +245,41 @@ namespace OpenHardwareMonitor.Hardware.CPU {
totalLoad.Value = cpuLoad.GetTotalLoad(); totalLoad.Value = cpuLoad.GetTotalLoad();
} }
uint lsb = 0, msb = 0; uint lsb, msb;
bool valid = WinRing0.RdtscPx(ref lsb, ref msb, (UIntPtr)1); bool valid = WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
long time = Stopwatch.GetTimestamp(); long time = Stopwatch.GetTimestamp();
ulong count = ((ulong)msb << 32) | lsb; ulong count = ((ulong)msb << 32) | lsb;
double delta = ((double)(time - lastTime)) / Stopwatch.Frequency; double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
if (valid && delta > 0.5) { if (valid && delta > 0.5) {
double maxClock = (float)((count - lastCount) / (1e6 * delta)); double maxClock = (count - lastCount) / (1e6 * delta);
double busClock = 0; double busClock = 0;
uint eax, edx; uint eax, edx;
for (int i = 0; i < coreClocks.Length; i++) { for (int i = 0; i < coreClocks.Length; i++) {
eax = 0; edx = 0;
System.Threading.Thread.Sleep(1); System.Threading.Thread.Sleep(1);
if (WinRing0.RdmsrPx(IA32_PERF_STATUS, ref eax, ref edx, if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
(UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) { (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
uint multiplier = (eax >> 8) & 0x1f; if (model < 0x1A) { // Core 2
uint maxMultiplier = (edx >> 8) & 0x1f; uint multiplier = (eax >> 8) & 0x1f;
// factor = multiplier * 2 to handle non integer multipliers uint maxMultiplier = (edx >> 8) & 0x1f;
uint factor = (multiplier << 1) | ((eax >> 14) & 1); // factor = multiplier * 2 to handle non integer multipliers
uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1); uint factor = (multiplier << 1) | ((eax >> 14) & 1);
if (maxFactor > 0) { uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
coreClocks[i].Value = (float)(factor * maxClock / maxFactor); if (maxFactor > 0) {
busClock = (float)(2 * maxClock / maxFactor); coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
busClock = (float)(2 * maxClock / maxFactor);
}
} else { // Core i5, i7
uint nehalemMultiplier = eax & 0xff;
if (maxNehalemMultiplier > 0) {
coreClocks[i].Value =
(float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
busClock = (float)(maxClock / maxNehalemMultiplier);
}
} }
} else { } else { // Intel Pentium 4
// if IA32_PERF_STATUS is not available, assume maxClock // if IA32_PERF_STATUS is not available, assume maxClock
coreClocks[i].Value = (float)maxClock; coreClocks[i].Value = (float)maxClock;
} }
} }
if (busClock > 0) { if (busClock > 0) {
this.busClock.Value = (float)busClock; this.busClock.Value = (float)busClock;
@@ -262,6 +288,6 @@ namespace OpenHardwareMonitor.Hardware.CPU {
} }
lastCount = count; lastCount = count;
lastTime = time; lastTime = time;
} }
} }
} }

View File

@@ -83,8 +83,9 @@ namespace OpenHardwareMonitor.Hardware {
out uint eax, out uint ebx, out uint ecx, out uint edx); out uint eax, out uint ebx, out uint ecx, out uint edx);
public delegate bool CpuidExDelegate(uint index, uint ecxValue, public delegate bool CpuidExDelegate(uint index, uint ecxValue,
out uint eax, out uint ebx, out uint ecx, out uint edx); out uint eax, out uint ebx, out uint ecx, out uint edx);
public delegate bool RdmsrPxDelegate(uint index, ref uint eax, ref uint edx, public delegate bool RdmsrDelegate(uint index, out uint eax, out uint edx);
UIntPtr processAffinityMask); public delegate bool RdmsrTxDelegate(uint index, out uint eax, out uint edx,
UIntPtr threadAffinityMask);
public delegate byte ReadIoPortByteDelegate(ushort port); public delegate byte ReadIoPortByteDelegate(ushort port);
public delegate void WriteIoPortByteDelegate(ushort port, byte value); public delegate void WriteIoPortByteDelegate(ushort port, byte value);
public delegate void SetPciMaxBusIndexDelegate(byte max); public delegate void SetPciMaxBusIndexDelegate(byte max);
@@ -94,8 +95,8 @@ namespace OpenHardwareMonitor.Hardware {
uint regAddress, out uint value); uint regAddress, out uint value);
public delegate bool WritePciConfigDwordExDelegate(uint pciAddress, public delegate bool WritePciConfigDwordExDelegate(uint pciAddress,
uint regAddress, uint value); uint regAddress, uint value);
public delegate bool RdtscPxDelegate(ref uint eax, ref uint edx, public delegate bool RdtscTxDelegate(out uint eax, out uint edx,
UIntPtr processAffinityMask); UIntPtr threadAffinityMask);
private static InitializeOlsDelegate InitializeOls; private static InitializeOlsDelegate InitializeOls;
private static DeinitializeOlsDelegate DeinitializeOls; private static DeinitializeOlsDelegate DeinitializeOls;
@@ -104,14 +105,15 @@ namespace OpenHardwareMonitor.Hardware {
public static IsCpuidDelegate IsCpuid; public static IsCpuidDelegate IsCpuid;
public static CpuidDelegate Cpuid; public static CpuidDelegate Cpuid;
public static CpuidExDelegate CpuidEx; public static CpuidExDelegate CpuidEx;
public static RdmsrPxDelegate RdmsrPx; public static RdmsrDelegate Rdmsr;
public static RdmsrTxDelegate RdmsrTx;
public static ReadIoPortByteDelegate ReadIoPortByte; public static ReadIoPortByteDelegate ReadIoPortByte;
public static WriteIoPortByteDelegate WriteIoPortByte; public static WriteIoPortByteDelegate WriteIoPortByte;
public static SetPciMaxBusIndexDelegate SetPciMaxBusIndex; public static SetPciMaxBusIndexDelegate SetPciMaxBusIndex;
public static FindPciDeviceByIdDelegate FindPciDeviceById; public static FindPciDeviceByIdDelegate FindPciDeviceById;
public static ReadPciConfigDwordExDelegate ReadPciConfigDwordEx; public static ReadPciConfigDwordExDelegate ReadPciConfigDwordEx;
public static WritePciConfigDwordExDelegate WritePciConfigDwordEx; public static WritePciConfigDwordExDelegate WritePciConfigDwordEx;
public static RdtscPxDelegate RdtscPx; public static RdtscTxDelegate RdtscTx;
private static void GetDelegate<T>(string entryPoint, out T newDelegate) private static void GetDelegate<T>(string entryPoint, out T newDelegate)
where T : class where T : class
@@ -131,14 +133,15 @@ namespace OpenHardwareMonitor.Hardware {
GetDelegate("IsCpuid", out IsCpuid); GetDelegate("IsCpuid", out IsCpuid);
GetDelegate("Cpuid", out Cpuid); GetDelegate("Cpuid", out Cpuid);
GetDelegate("CpuidEx", out CpuidEx); GetDelegate("CpuidEx", out CpuidEx);
GetDelegate("RdmsrPx", out RdmsrPx); GetDelegate("Rdmsr", out Rdmsr);
GetDelegate("RdmsrTx", out RdmsrTx);
GetDelegate("ReadIoPortByte", out ReadIoPortByte); GetDelegate("ReadIoPortByte", out ReadIoPortByte);
GetDelegate("WriteIoPortByte", out WriteIoPortByte); GetDelegate("WriteIoPortByte", out WriteIoPortByte);
GetDelegate("SetPciMaxBusIndex", out SetPciMaxBusIndex); GetDelegate("SetPciMaxBusIndex", out SetPciMaxBusIndex);
GetDelegate("FindPciDeviceById", out FindPciDeviceById); GetDelegate("FindPciDeviceById", out FindPciDeviceById);
GetDelegate("ReadPciConfigDwordEx", out ReadPciConfigDwordEx); GetDelegate("ReadPciConfigDwordEx", out ReadPciConfigDwordEx);
GetDelegate("WritePciConfigDwordEx", out WritePciConfigDwordEx); GetDelegate("WritePciConfigDwordEx", out WritePciConfigDwordEx);
GetDelegate("RdtscPx", out RdtscPx); GetDelegate("RdtscTx", out RdtscTx);
try { try {
if (InitializeOls != null && InitializeOls()) if (InitializeOls != null && InitializeOls())

View File

@@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.20.1")] [assembly: AssemblyVersion("0.1.21.0")]
[assembly: AssemblyFileVersion("0.1.20.1")] [assembly: AssemblyFileVersion("0.1.21.0")]