1.1 --- a/Hardware/CPU/IntelCPU.cs Fri Oct 08 12:18:32 2010 +0000
1.2 +++ b/Hardware/CPU/IntelCPU.cs Sun Oct 10 16:57:11 2010 +0000
1.3 @@ -36,16 +36,25 @@
1.4 */
1.5
1.6 using System;
1.7 -using System.Collections.Generic;
1.8 +using System.Globalization;
1.9 +using System.Text;
1.10
1.11 namespace OpenHardwareMonitor.Hardware.CPU {
1.12 internal sealed class IntelCPU : GenericCPU {
1.13
1.14 + private enum Microarchitecture {
1.15 + Unknown,
1.16 + Core,
1.17 + Atom,
1.18 + Nehalem
1.19 + }
1.20 +
1.21 private readonly Sensor[] coreTemperatures;
1.22 private readonly Sensor[] coreClocks;
1.23 private readonly Sensor busClock;
1.24
1.25 - private readonly uint maxNehalemMultiplier;
1.26 + private readonly Microarchitecture microarchitecture;
1.27 + private readonly double timeStampCounterMultiplier;
1.28
1.29 private const uint IA32_THERM_STATUS_MSR = 0x019C;
1.30 private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
1.31 @@ -62,11 +71,13 @@
1.32 public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
1.33 : base(processorIndex, cpuid, settings)
1.34 {
1.35 + // set tjMax
1.36 float[] tjMax;
1.37 switch (family) {
1.38 case 0x06: {
1.39 switch (model) {
1.40 - case 0x0F: // Intel Core (65nm)
1.41 + case 0x0F: // Intel Core 2 (65nm)
1.42 + microarchitecture = Microarchitecture.Core;
1.43 switch (stepping) {
1.44 case 0x06: // B2
1.45 switch (coreCount) {
1.46 @@ -85,9 +96,11 @@
1.47 default:
1.48 tjMax = Floats(85 + 10); break;
1.49 } break;
1.50 - case 0x17: // Intel Core (45nm)
1.51 + case 0x17: // Intel Core 2 (45nm)
1.52 + microarchitecture = Microarchitecture.Core;
1.53 tjMax = Floats(100); break;
1.54 case 0x1C: // Intel Atom (45nm)
1.55 + microarchitecture = Microarchitecture.Atom;
1.56 switch (stepping) {
1.57 case 0x02: // C0
1.58 tjMax = Floats(90); break;
1.59 @@ -100,6 +113,7 @@
1.60 case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
1.61 case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
1.62 case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
1.63 + microarchitecture = Microarchitecture.Nehalem;
1.64 uint eax, edx;
1.65 tjMax = new float[coreCount];
1.66 for (int i = 0; i < coreCount; i++) {
1.67 @@ -109,16 +123,39 @@
1.68 } else {
1.69 tjMax[i] = 100;
1.70 }
1.71 - }
1.72 - if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
1.73 - maxNehalemMultiplier = (eax >> 8) & 0xff;
1.74 - }
1.75 + }
1.76 break;
1.77 default:
1.78 - tjMax = Floats(100); break;
1.79 + microarchitecture = Microarchitecture.Unknown;
1.80 + tjMax = Floats(100);
1.81 + break;
1.82 }
1.83 } break;
1.84 - default: tjMax = Floats(100); break;
1.85 + default:
1.86 + microarchitecture = Microarchitecture.Unknown;
1.87 + tjMax = Floats(100);
1.88 + break;
1.89 + }
1.90 +
1.91 + // set timeStampCounterMultiplier
1.92 + switch (microarchitecture) {
1.93 + case Microarchitecture.Atom:
1.94 + case Microarchitecture.Core: {
1.95 + uint eax, edx;
1.96 + if (WinRing0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
1.97 + timeStampCounterMultiplier =
1.98 + ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
1.99 + }
1.100 + } break;
1.101 + case Microarchitecture.Nehalem: {
1.102 + uint eax, edx;
1.103 + if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
1.104 + timeStampCounterMultiplier = (eax >> 8) & 0xff;
1.105 + }
1.106 + } break;
1.107 + default:
1.108 + timeStampCounterMultiplier = 1;
1.109 + break;
1.110 }
1.111
1.112 // check if processor supports a digital thermal sensor
1.113 @@ -161,6 +198,18 @@
1.114 };
1.115 }
1.116
1.117 + public override string GetReport() {
1.118 + StringBuilder r = new StringBuilder();
1.119 + r.Append(base.GetReport());
1.120 +
1.121 + r.Append("Time Stamp Counter Multiplier: ");
1.122 + r.AppendLine(timeStampCounterMultiplier.ToString(
1.123 + CultureInfo.InvariantCulture));
1.124 + r.AppendLine();
1.125 +
1.126 + return r.ToString();
1.127 + }
1.128 +
1.129 public override void Update() {
1.130 base.Update();
1.131
1.132 @@ -188,27 +237,18 @@
1.133 for (int i = 0; i < coreClocks.Length; i++) {
1.134 System.Threading.Thread.Sleep(1);
1.135 if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
1.136 - (UIntPtr)(1L << cpuid[i][0].Thread))) {
1.137 - if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
1.138 - uint nehalemMultiplier = eax & 0xff;
1.139 - coreClocks[i].Value =(float)(nehalemMultiplier *
1.140 - TimeStampCounterFrequency / maxNehalemMultiplier);
1.141 - newBusClock =
1.142 - (float)(TimeStampCounterFrequency / maxNehalemMultiplier);
1.143 - } else { // Core 2
1.144 - uint multiplier = (eax >> 8) & 0x1f;
1.145 - uint maxMultiplier = (edx >> 8) & 0x1f;
1.146 - // factor = multiplier * 2 to handle non integer multipliers
1.147 - uint factor = (multiplier << 1) | ((eax >> 14) & 1);
1.148 - uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
1.149 - if (maxFactor > 0) {
1.150 - coreClocks[i].Value =
1.151 - (float)(factor * TimeStampCounterFrequency / maxFactor);
1.152 - newBusClock =
1.153 - (float)(2 * TimeStampCounterFrequency / maxFactor);
1.154 - }
1.155 - }
1.156 - } else { // Intel Pentium 4
1.157 + (UIntPtr)(1L << cpuid[i][0].Thread)))
1.158 + {
1.159 + newBusClock =
1.160 + TimeStampCounterFrequency / timeStampCounterMultiplier;
1.161 + if (microarchitecture == Microarchitecture.Nehalem) {
1.162 + uint multiplier = eax & 0xff;
1.163 + coreClocks[i].Value = (float)(multiplier * newBusClock);
1.164 + } else {
1.165 + double multiplier = ((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
1.166 + coreClocks[i].Value = (float)(multiplier * newBusClock);
1.167 + }
1.168 + } else {
1.169 // if IA32_PERF_STATUS is not available, assume TSC frequency
1.170 coreClocks[i].Value = (float)TimeStampCounterFrequency;
1.171 }