# HG changeset patch # User moel.mich # Date 1266178590 0 # Node ID c150de283ca029a9d08c8a715cdb9ac94e7136b6 # Parent 5b7398d061b74ecae65210e86f08ffce42d6071d Added core and bus clock support for Intel CPUs (Core 2). diff -r 5b7398d061b7 -r c150de283ca0 GUI/SensorNotifyIcon.cs --- a/GUI/SensorNotifyIcon.cs Sat Feb 13 17:08:36 2010 +0000 +++ b/GUI/SensorNotifyIcon.cs Sun Feb 14 20:16:30 2010 +0000 @@ -107,9 +107,9 @@ set { this.color = value; this.darkColor = Color.FromArgb(255, - Math.Max(this.color.R - 100, 0), - Math.Max(this.color.G - 100, 0), - Math.Max(this.color.B - 100, 0)); + this.color.R / 3, + this.color.G / 3, + this.color.B / 3); Brush brush = this.brush; this.brush = new SolidBrush(this.color); if (brush != null) diff -r 5b7398d061b7 -r c150de283ca0 Hardware/CPU/CPUGroup.cs --- a/Hardware/CPU/CPUGroup.cs Sat Feb 13 17:08:36 2010 +0000 +++ b/Hardware/CPU/CPUGroup.cs Sun Feb 14 20:16:30 2010 +0000 @@ -131,10 +131,8 @@ switch (cpuVendor) { case "GenuineIntel": - // check if processor supports a digital thermal sensor - if (maxCPUID >= 6 && (cpuidData[6, 0] & 1) != 0) - hardware.Add(new IntelCPU(name, family, model, stepping, - cpuidData, cpuidExtData)); + hardware.Add(new IntelCPU(name, family, model, stepping, + cpuidData, cpuidExtData)); break; case "AuthenticAMD": // check if processor supports a digital thermal sensor diff -r 5b7398d061b7 -r c150de283ca0 Hardware/CPU/IntelCPU.cs --- a/Hardware/CPU/IntelCPU.cs Sat Feb 13 17:08:36 2010 +0000 +++ b/Hardware/CPU/IntelCPU.cs Sun Feb 14 20:16:30 2010 +0000 @@ -51,6 +51,8 @@ private Sensor[] coreTemperatures; private Sensor totalLoad; private Sensor[] coreLoads; + private Sensor[] coreClocks; + private Sensor busClock; private float tjMax = 0; private uint logicalProcessors; @@ -58,9 +60,13 @@ private uint coreCount; private CPULoad cpuLoad; + + private ulong lastCount; + private long lastTime; private const uint IA32_THERM_STATUS_MSR = 0x019C; private const uint IA32_TEMPERATURE_TARGET = 0x01A2; + private const uint IA32_PERF_STATUS = 0x0198; public IntelCPU(string name, uint family, uint model, uint stepping, uint[,] cpuidData, uint[,] cpuidExtData) { @@ -89,58 +95,64 @@ coreCount = logicalProcessors / logicalProcessorsPerCore; - switch (family) { - case 0x06: { - switch (model) { - case 0x0F: // Intel Core 65nm - switch (stepping) { - case 0x06: // B2 - switch (coreCount) { - case 2: + // check if processor supports a digital thermal sensor + if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) { + + switch (family) { + case 0x06: { + switch (model) { + case 0x0F: // Intel Core 65nm + switch (stepping) { + case 0x06: // B2 + switch (coreCount) { + case 2: + tjMax = 80; break; + case 4: + tjMax = 90; break; + default: + tjMax = 85; break; + } tjMax = 80; break; - case 4: + case 0x0B: // G0 tjMax = 90; break; + case 0x0D: // M0 + tjMax = 85; break; default: tjMax = 85; break; - } - tjMax = 80; break; - case 0x0B: // G0 + } break; + case 0x17: // Intel Core 45nm + tjMax = 100; break; + case 0x1C: // Intel Atom tjMax = 90; break; - case 0x0D: // M0 - tjMax = 85; break; + case 0x1A: + uint eax = 0, edx = 0; + if (WinRing0.RdmsrPx( + IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) { + tjMax = (eax >> 16) & 0xFF; + } else + tjMax = 100; + break; default: - tjMax = 85; break; - } break; - case 0x17: // Intel Core 45nm - tjMax = 100; break; - case 0x1C: // Intel Atom - tjMax = 90; break; - case 0x1A: - uint eax = 0, edx = 0; - if (WinRing0.RdmsrPx( - IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) { - tjMax = (eax >> 16) & 0xFF; - } else - tjMax = 100; - break; - default: - tjMax = 100; break; - } - } break; - default: tjMax = 100; break; + tjMax = 100; break; + } + } break; + default: tjMax = 100; break; + } + + coreTemperatures = new Sensor[coreCount]; + for (int i = 0; i < coreTemperatures.Length; i++) { + coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax, + SensorType.Temperature, this); + } + } else { + coreTemperatures = new Sensor[0]; } - - totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); - - coreTemperatures = new Sensor[coreCount]; + + totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); coreLoads = new Sensor[coreCount]; - for (int i = 0; i < coreTemperatures.Length; i++) { - coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax, - SensorType.Temperature, this); - coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, - SensorType.Load, this); - } - + for (int i = 0; i < coreLoads.Length; i++) + coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, + SensorType.Load, this); cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore); if (cpuLoad.IsAvailable) { foreach (Sensor sensor in coreLoads) @@ -148,6 +160,16 @@ ActivateSensor(totalLoad); } + lastCount = 0; + lastTime = 0; + busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this); + coreClocks = new Sensor[coreCount]; + for (int i = 0; i < coreClocks.Length; i++) { + coreClocks[i] = + new Sensor("Core #" + (i + 1), i + 1, SensorType.Clock, this); + ActivateSensor(coreClocks[i]); + } + Update(); } @@ -180,9 +202,9 @@ } public void Update() { - - uint eax = 0, edx = 0; + for (int i = 0; i < coreTemperatures.Length; i++) { + uint eax = 0, edx = 0; if (WinRing0.RdmsrPx( IA32_THERM_STATUS_MSR, ref eax, ref edx, (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) @@ -204,6 +226,42 @@ coreLoads[i].Value = cpuLoad.GetCoreLoad(i); totalLoad.Value = cpuLoad.GetTotalLoad(); } + + uint lsb = 0, msb = 0; + bool valid = WinRing0.RdtscPx(ref lsb, ref msb, (UIntPtr)1); + long time = Stopwatch.GetTimestamp(); + ulong count = ((ulong)msb << 32) | lsb; + double delta = ((double)(time - lastTime)) / Stopwatch.Frequency; + if (valid && delta > 0.5) { + double maxClock = (float)((count - lastCount) / (1e6 * delta)); + double busClock = 0; + uint eax, edx; + for (int i = 0; i < coreClocks.Length; i++) { + eax = 0; edx = 0; + System.Threading.Thread.Sleep(1); + if (WinRing0.RdmsrPx(IA32_PERF_STATUS, ref eax, ref edx, + (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) { + uint multiplier = (eax >> 8) & 0x1f; + uint maxMultiplier = (edx >> 8) & 0x1f; + // factor = multiplier * 2 to handle non integer multipliers + uint factor = (multiplier << 1) | ((eax >> 14) & 1); + uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1); + if (maxFactor > 0) { + coreClocks[i].Value = (float)(factor * maxClock / maxFactor); + busClock = (float)(2 * maxClock / maxFactor); + } + } else { + // if IA32_PERF_STATUS is not available, assume maxClock + coreClocks[i].Value = (float)maxClock; + } + } + if (busClock > 0) { + this.busClock.Value = (float)busClock; + ActivateSensor(this.busClock); + } + } + lastCount = count; + lastTime = time; } } } diff -r 5b7398d061b7 -r c150de283ca0 Hardware/WinRing0.cs --- a/Hardware/WinRing0.cs Sat Feb 13 17:08:36 2010 +0000 +++ b/Hardware/WinRing0.cs Sun Feb 14 20:16:30 2010 +0000 @@ -94,6 +94,8 @@ uint regAddress, out uint value); public delegate bool WritePciConfigDwordExDelegate(uint pciAddress, uint regAddress, uint value); + public delegate bool RdtscPxDelegate(ref uint eax, ref uint edx, + UIntPtr processAffinityMask); private static InitializeOlsDelegate InitializeOls; private static DeinitializeOlsDelegate DeinitializeOls; @@ -108,7 +110,8 @@ public static SetPciMaxBusIndexDelegate SetPciMaxBusIndex; public static FindPciDeviceByIdDelegate FindPciDeviceById; public static ReadPciConfigDwordExDelegate ReadPciConfigDwordEx; - public static WritePciConfigDwordExDelegate WritePciConfigDwordEx; + public static WritePciConfigDwordExDelegate WritePciConfigDwordEx; + public static RdtscPxDelegate RdtscPx; private static void GetDelegate(string entryPoint, out T newDelegate) where T : class @@ -135,6 +138,7 @@ GetDelegate("FindPciDeviceById", out FindPciDeviceById); GetDelegate("ReadPciConfigDwordEx", out ReadPciConfigDwordEx); GetDelegate("WritePciConfigDwordEx", out WritePciConfigDwordEx); + GetDelegate("RdtscPx", out RdtscPx); try { if (InitializeOls != null && InitializeOls()) diff -r 5b7398d061b7 -r c150de283ca0 Properties/AssemblyInfo.cs --- a/Properties/AssemblyInfo.cs Sat Feb 13 17:08:36 2010 +0000 +++ b/Properties/AssemblyInfo.cs Sun Feb 14 20:16:30 2010 +0000 @@ -69,5 +69,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.1.19.0")] -[assembly: AssemblyFileVersion("0.1.19.0")] +[assembly: AssemblyVersion("0.1.20.0")] +[assembly: AssemblyFileVersion("0.1.20.0")]