From 65b0293b1c59cadd5112213e8882dcca746d2cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=B6ller?= Date: Sat, 24 Apr 2010 19:59:52 +0000 Subject: [PATCH] Implemented APIC based CPU enumeration (Issue 41). --- External/WinRing0.dll | Bin 55296 -> 55296 bytes External/WinRing0x64.dll | Bin 58368 -> 57856 bytes Hardware/CPU/AMD0FCPU.cs | 48 +++---- Hardware/CPU/AMD10CPU.cs | 15 +-- Hardware/CPU/CPUGroup.cs | 226 ++++++++++++++++----------------- Hardware/CPU/CPUID.cs | 252 +++++++++++++++++++++++++++++++++++++ Hardware/CPU/CPULoad.cs | 25 ++-- Hardware/CPU/IntelCPU.cs | 119 +++++------------- Hardware/WinRing0.cs | 11 +- OpenHardwareMonitor.csproj | 1 + 10 files changed, 445 insertions(+), 252 deletions(-) create mode 100644 Hardware/CPU/CPUID.cs diff --git a/External/WinRing0.dll b/External/WinRing0.dll index beaf2b0f38db28d20e4a3400f34832bf470429a0..e0ed0cbacd601695c2f7374a03ebb75fc4bf490a 100644 GIT binary patch delta 1413 zcmZ|Ne@v8h7y$6+`@-xjg4ei!$tj1h5H{v}@6XfmzIT(@%tpY?YvhKb8jM}#Dn))6 za>uXWUJg9JCf01RNF$kcc&Pnhbpl!u{aC|tYZfl1r&*mRF4s_cPDd+T&-S_d?s=Yj zzVG+GuR9Ru4#e$_#F4yD{5Oi@uKx_QkYtiDts*&$VJRJER?z^lk`j7_T2BK@X-kI$Vi*(M)Oh!6=>GwX4}1iM6p6 zqX{rMIqB4|xfov&TdEf);3F6uVb^_i@}K&~`|9zrdeVu70lEKf_-Fn?Jcr1ZTIGdPY zDS>XBhZVp|1hb(YoaXaqrcmx^eX|>@b_B?+a@4CA#FzcO=E1VO|zBQnrt1mKHG%tM;kQb4e!NEFmfw6p0jh$aof1JxkKDZ z?kDaKF58lCS#K$|ylQE+9I>3Rd}jIGGH(%im3Q!!d<#$ckNLCw5BwcINhlPy2rl6j z!7IEc1cZ~qUqZ5I5_3hD=n-{sSo}qt7ZapH=|!nQ`cAqiJs>|L`{ZRK$|+?``9gWv Tnr1aw&DQMTSKkN*KNtTu(wgkK delta 1537 zcmZwFe{2(F7zgm@y)8?D$~x(!!f>$hOAvGI{pe}z6@>yyhENy~$;b#Qvk8c}$pl8b zmEms3VDp_05wTI^R{~TDDn?@6AQ@-?4JP;pWI5NZdquB5KB{oj558$5)c|6WEc834L#xa#=39H$T zgdy~VCgqMGiXOLzSV_E{93{>KIZ}h}#;TKL!$ZQ|xNOC{`M%|Qgy(V+^H%iQgyL*I zYjsoDF?W8n!cL{bqZJM+&5l+$sWdZM;iA$3QD18ZIjAgMN?!FJB{VZ&t1Ii2PG){& zWEhLnjafEhzTFJi&4NzDW)?ckK#w7q1x~ZD*T^yhF0^kpxMkpox4I!x6pbOp_T6B!3KYe(NUJ2erbMhhBVAC^UE-Zqj z@H*7MHrNeEpasssdAJCd;YKrs=?`?Mg(w5;;Dj8=g9+dP4JN}3SO6tZ4z=(e?1Qi1 zEc^_;Fz`6hBk&mLFbj&|HP`@+u3gHB+VFcuz%q4Y36aj;qllqaUf z52PJBTr-TtxpCSZ7UX5}D*2TBy{st#rAFDJe6BPr7nOWfY(z?{0RVb>DEOc_w*O&vefUPuO$VbIkLDr_CcsLnNOxOXHV^qh(R{%4=jUZ_@TEy^|JmJ(E#sBfv+KdBFRW$h_#iuSBl Rr)|}?YcXwS;^Z00_7?@XBr5;_ diff --git a/External/WinRing0x64.dll b/External/WinRing0x64.dll index 27fd92a4a11deecf05bd26ffac32737653c5d687..e5b7e44130bab26741bc13bc06c94c854b5beb18 100644 GIT binary patch delta 12957 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 delta 13275 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 diff --git a/Hardware/CPU/AMD0FCPU.cs b/Hardware/CPU/AMD0FCPU.cs index 1605e5a..3683139 100644 --- a/Hardware/CPU/AMD0FCPU.cs +++ b/Hardware/CPU/AMD0FCPU.cs @@ -63,41 +63,46 @@ namespace OpenHardwareMonitor.Hardware.CPU { private const byte THERM_SENSE_CORE_SEL_CPU0 = 0x4; private const byte THERM_SENSE_CORE_SEL_CPU1 = 0x0; - public AMD0FCPU(string name, uint family, uint model, uint stepping, - uint[,] cpuidData, uint[,] cpuidExtData) { - - this.name = name; - this.icon = Utilities.EmbeddedResources.GetImage("cpu.png"); + public AMD0FCPU(CPUID[][] cpuid) { - uint coreCount = 1; - if (cpuidExtData.GetLength(0) > 8) - coreCount = (cpuidExtData[8, 2] & 0xFF) + 1; + this.name = cpuid[0][0].Name; + this.icon = Utilities.EmbeddedResources.GetImage("cpu.png"); - // max two cores - coreCount = coreCount > 2 ? 2 : coreCount; + int coreCount = cpuid.Length; totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); float offset = -49.0f; // AM2+ 65nm +21 offset + uint model = cpuid[0][0].Model; if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c) offset += 21; - coreTemperatures = new Sensor[coreCount]; - coreLoads = new Sensor[coreCount]; - for (int i = 0; i < coreCount; i++) { - coreTemperatures[i] = - new Sensor("Core #" + (i + 1), i, null, SensorType.Temperature, this, - new ParameterDescription[] { new ParameterDescription("Offset", - "Temperature offset of the thermal sensor.\n" + - "Temperature = Value + Offset.", offset) + // check if processor supports a digital thermal sensor + if (cpuid[0][0].ExtData.GetLength(0) > 7 && + (cpuid[0][0].ExtData[7, 3] & 1) != 0) + { + coreTemperatures = new Sensor[coreCount]; + for (int i = 0; i < coreCount; i++) { + coreTemperatures[i] = + new Sensor("Core #" + (i + 1), i, null, SensorType.Temperature, + this, new ParameterDescription[] { + new ParameterDescription("Offset", + "Temperature offset of the thermal sensor.\n" + + "Temperature = Value + Offset.", offset) }); - coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, - SensorType.Load, this); + } + } else { + coreTemperatures = new Sensor[0]; } - cpuLoad = new CPULoad(coreCount, 1); + coreLoads = new Sensor[coreCount]; + for (int i = 0; i < coreCount; i++) + coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, + SensorType.Load, this); + + cpuLoad = new CPULoad(cpuid); if (cpuLoad.IsAvailable) { foreach (Sensor sensor in coreLoads) ActivateSensor(sensor); @@ -128,7 +133,6 @@ namespace OpenHardwareMonitor.Hardware.CPU { public void Update() { if (pciAddress != 0xFFFFFFFF) { - for (uint i = 0; i < coreTemperatures.Length; i++) { if (WinRing0.WritePciConfigDwordEx( pciAddress, THERMTRIP_STATUS_REGISTER, diff --git a/Hardware/CPU/AMD10CPU.cs b/Hardware/CPU/AMD10CPU.cs index 96b8a0c..b9a16a2 100644 --- a/Hardware/CPU/AMD10CPU.cs +++ b/Hardware/CPU/AMD10CPU.cs @@ -60,15 +60,12 @@ namespace OpenHardwareMonitor.Hardware.CPU { private const ushort PCI_AMD_11H_MISCELLANEOUS_DEVICE_ID = 0x1303; private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4; - public AMD10CPU(string name, uint family, uint model, uint stepping, - uint[,] cpuidData, uint[,] cpuidExtData) { - - this.name = name; - this.icon = Utilities.EmbeddedResources.GetImage("cpu.png"); + public AMD10CPU(CPUID[][] cpuid) { - uint coreCount = 1; - if (cpuidExtData.GetLength(0) > 8) - coreCount = (cpuidExtData[8, 2] & 0xFF) + 1; + this.name = cpuid[0][0].Name; + this.icon = Utilities.EmbeddedResources.GetImage("cpu.png"); + + int coreCount = cpuid.Length; totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); @@ -77,7 +74,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, SensorType.Load, this); - cpuLoad = new CPULoad(coreCount, 1); + cpuLoad = new CPULoad(cpuid); if (cpuLoad.IsAvailable) { foreach (Sensor sensor in coreLoads) ActivateSensor(sensor); diff --git a/Hardware/CPU/CPUGroup.cs b/Hardware/CPU/CPUGroup.cs index ff39653..ee81551 100644 --- a/Hardware/CPU/CPUGroup.cs +++ b/Hardware/CPU/CPUGroup.cs @@ -37,6 +37,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text; namespace OpenHardwareMonitor.Hardware.CPU { @@ -44,119 +45,99 @@ namespace OpenHardwareMonitor.Hardware.CPU { public class CPUGroup : IGroup { private List hardware = new List(); - private string cpuBrandString; - private string cpuVendor; - private uint[,] cpuidData; - private uint[,] cpuidExtData; + private CPUID[][][] threads; - private uint family; - private uint model; - private uint stepping; + private CPUID[][] GetProcessorThreads() { - private static uint CPUID = 0; - private static uint CPUID_EXT = 0x80000000; + List threads = new List(); + for (int i = 0; i < 32; i++) { + try { + threads.Add(new CPUID(i)); + } catch (ArgumentException) { } + } - public static void AppendRegister(StringBuilder b, uint value) { - b.Append((char)((value) & 0xff)); - b.Append((char)((value >> 8) & 0xff)); - b.Append((char)((value >> 16) & 0xff)); - b.Append((char)((value >> 24) & 0xff)); + SortedDictionary> processors = + new SortedDictionary>(); + foreach (CPUID thread in threads) { + List list; + processors.TryGetValue(thread.ProcessorId, out list); + if (list == null) { + list = new List(); + processors.Add(thread.ProcessorId, list); + } + list.Add(thread); + } + + CPUID[][] processorThreads = new CPUID[processors.Count][]; + int index = 0; + foreach (List list in processors.Values) { + processorThreads[index] = list.ToArray(); + index++; + } + return processorThreads; + } + + private CPUID[][] GroupThreadsByCore(CPUID[] threads) { + + SortedDictionary> cores = + new SortedDictionary>(); + foreach (CPUID thread in threads) { + List coreList; + cores.TryGetValue(thread.CoreId, out coreList); + if (coreList == null) { + coreList = new List(); + cores.Add(thread.CoreId, coreList); + } + coreList.Add(thread); + } + + CPUID[][] coreThreads = new CPUID[cores.Count][]; + int index = 0; + foreach (List list in cores.Values) { + coreThreads[index] = list.ToArray(); + index++; + } + return coreThreads; } public CPUGroup() { - - if (!WinRing0.IsAvailable) + if (!WinRing0.IsCpuid()) return; - if (WinRing0.IsCpuid()) { - uint maxCPUID = 0; - uint maxCPUID_EXT = 0; - uint eax, ebx, ecx, edx; + CPUID[][] processorThreads = GetProcessorThreads(); + this.threads = new CPUID[processorThreads.Length][][]; - - if (WinRing0.Cpuid(CPUID, out eax, out ebx, out ecx, out edx)) { - maxCPUID = eax; - StringBuilder vendorBuilder = new StringBuilder(); - AppendRegister(vendorBuilder, ebx); - AppendRegister(vendorBuilder, edx); - AppendRegister(vendorBuilder, ecx); - cpuVendor = vendorBuilder.ToString(); + int index = 0; + foreach (CPUID[] threads in processorThreads) { + if (threads.Length == 0) + continue; + + CPUID[][] coreThreads = GroupThreadsByCore(threads); - eax = ebx = ecx = edx = 0; - if (WinRing0.Cpuid(CPUID_EXT, out eax, out ebx, out ecx, out edx)) { - maxCPUID_EXT = eax - CPUID_EXT; - } - } - if (maxCPUID == 0 || maxCPUID_EXT == 0) - return; + this.threads[index] = coreThreads; + index++; - cpuidData = new uint[maxCPUID + 1, 4]; - for (uint i = 0; i < (maxCPUID + 1); i++) - WinRing0.Cpuid(CPUID + i, out cpuidData[i, 0], out cpuidData[i, 1], - out cpuidData[i, 2], out cpuidData[i, 3]); - - cpuidExtData = new uint[maxCPUID_EXT + 1, 4]; - for (uint i = 0; i < (maxCPUID_EXT + 1); i++) - WinRing0.Cpuid(CPUID_EXT + i, out cpuidExtData[i, 0], - out cpuidExtData[i, 1], out cpuidExtData[i, 2], - out cpuidExtData[i, 3]); - - StringBuilder nameBuilder = new StringBuilder(); - for (uint i = 2; i <= 4; i++) { - if (WinRing0.Cpuid(CPUID_EXT + i, out eax, out ebx, out ecx, out edx)) - { - AppendRegister(nameBuilder, eax); - AppendRegister(nameBuilder, ebx); - AppendRegister(nameBuilder, ecx); - AppendRegister(nameBuilder, edx); - } - } - nameBuilder.Replace('\0', ' '); - cpuBrandString = nameBuilder.ToString().Trim(); - nameBuilder.Replace("(R)", " "); - nameBuilder.Replace("(TM)", " "); - nameBuilder.Replace("(tm)", " "); - nameBuilder.Replace("CPU", ""); - for (int i = 0; i < 10; i++) nameBuilder.Replace(" ", " "); - string name = nameBuilder.ToString(); - if (name.Contains("@")) - name = name.Remove(name.LastIndexOf('@')); - name = name.Trim(); - - this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) + - ((cpuidData[1, 0] & 0x0F00) >> 8); - this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) + - ((cpuidData[1, 0] & 0xF0) >> 4); - this.stepping = (cpuidData[1, 0] & 0x0F); - - switch (cpuVendor) { - case "GenuineIntel": - hardware.Add(new IntelCPU(name, family, model, stepping, - cpuidData, cpuidExtData)); - break; - case "AuthenticAMD": - // check if processor supports a digital thermal sensor - if (maxCPUID_EXT >= 7 && (cpuidExtData[7, 3] & 1) != 0) { - switch (family) { - case 0x0F: - hardware.Add(new AMD0FCPU(name, family, model, stepping, - cpuidData, cpuidExtData)); - break; - case 0x10: - hardware.Add(new AMD10CPU(name, family, model, stepping, - cpuidData, cpuidExtData)); - break; - default: - break; - } - } + switch (threads[0].Vendor) { + case Vendor.Intel: + hardware.Add(new IntelCPU(coreThreads)); break; + case Vendor.AMD: + switch (threads[0].Family) { + case 0x0F: + hardware.Add(new AMD0FCPU(coreThreads)); + break; + case 0x10: + hardware.Add(new AMD10CPU(coreThreads)); + break; + default: + break; + } break; default: break; - } + } } } - + public IHardware[] Hardware { get { return hardware.ToArray(); @@ -178,32 +159,43 @@ namespace OpenHardwareMonitor.Hardware.CPU { public string GetReport() { StringBuilder r = new StringBuilder(); - + r.AppendLine("CPUID"); r.AppendLine(); - r.AppendFormat("Processor Vendor: {0}{1}", cpuVendor, - Environment.NewLine); - r.AppendFormat("Processor Brand: {0}{1}", cpuBrandString, - Environment.NewLine); - r.AppendFormat("Family: 0x{0}{1}", family.ToString("X"), - Environment.NewLine); - r.AppendFormat("Model: 0x{0}{1}", model.ToString("X"), - Environment.NewLine); - r.AppendFormat("Stepping: 0x{0}{1}", stepping.ToString("X"), - Environment.NewLine); - r.AppendLine(); - r.AppendLine("CPUID Return Values"); - r.AppendLine(); + for (int i = 0; i < threads.Length; i++) { - if (cpuidData != null) { - r.AppendLine(" Function EAX EBX ECX EDX"); - AppendCpuidData(r, cpuidData, CPUID); - AppendCpuidData(r, cpuidExtData, CPUID_EXT); + r.AppendLine("Processor " + i); + r.AppendLine(); + r.AppendFormat("Processor Vendor: {0}{1}", threads[i][0][0].Vendor, + Environment.NewLine); + r.AppendFormat("Processor Brand: {0}{1}", threads[i][0][0].BrandString, + Environment.NewLine); + r.AppendFormat("Family: 0x{0}{1}", + threads[i][0][0].Family.ToString("X"), Environment.NewLine); + r.AppendFormat("Model: 0x{0}{1}", + threads[i][0][0].Model.ToString("X"), Environment.NewLine); + r.AppendFormat("Stepping: 0x{0}{1}", + threads[i][0][0].Stepping.ToString("X"), Environment.NewLine); r.AppendLine(); - } - return r.ToString(); + r.AppendLine("CPUID Return Values"); + r.AppendLine(); + for (int j = 0; j < threads[i].Length; j++) + for (int k = 0; k < threads[i][j].Length; k++) { + r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread); + r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId); + r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId); + r.AppendLine(" Core ID: " + threads[i][j][k].CoreId); + r.AppendLine(" Thread ID: " + threads[i][j][k].ThreadId); + r.AppendLine(); + r.AppendLine(" Function EAX EBX ECX EDX"); + AppendCpuidData(r, threads[i][j][k].Data, CPUID.CPUID_0); + AppendCpuidData(r, threads[i][j][k].ExtData, CPUID.CPUID_EXT); + r.AppendLine(); + } + } + return r.ToString(); } public void Close() { } diff --git a/Hardware/CPU/CPUID.cs b/Hardware/CPU/CPUID.cs new file mode 100644 index 0000000..0e380af --- /dev/null +++ b/Hardware/CPU/CPUID.cs @@ -0,0 +1,252 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2009-2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenHardwareMonitor.Hardware.CPU { + + public enum Vendor { + Unknown, + Intel, + AMD, + } + + public class CPUID { + + private int thread; + + private uint maxCpuid = 0; + private uint maxCpuidExt = 0; + + private Vendor vendor; + + private string cpuBrandString; + private string name; + + private uint[,] cpuidData; + private uint[,] cpuidExtData; + + private uint family; + private uint model; + private uint stepping; + + private uint apicId; + + private uint threadMaskWith; + private uint coreMaskWith; + + private uint processorId; + private uint coreId; + private uint threadId; + + public static uint CPUID_0 = 0; + public static uint CPUID_EXT = 0x80000000; + + private void AppendRegister(StringBuilder b, uint value) { + b.Append((char)((value) & 0xff)); + b.Append((char)((value >> 8) & 0xff)); + b.Append((char)((value >> 16) & 0xff)); + b.Append((char)((value >> 24) & 0xff)); + } + + public CPUID(int thread) { + this.thread = thread; + + uint eax, ebx, ecx, edx; + + UIntPtr mask = (UIntPtr)(1L << thread); + + if (WinRing0.CpuidTx(CPUID_0, 0, + out eax, out ebx, out ecx, out edx, mask)) { + maxCpuid = eax; + StringBuilder vendorBuilder = new StringBuilder(); + AppendRegister(vendorBuilder, ebx); + AppendRegister(vendorBuilder, edx); + AppendRegister(vendorBuilder, ecx); + string cpuVendor = vendorBuilder.ToString(); + switch (cpuVendor) { + case "GenuineIntel": + vendor = Vendor.Intel; + break; + case "AuthenticAMD": + vendor = Vendor.AMD; + break; + default: + vendor = Vendor.Unknown; + break; + } + eax = ebx = ecx = edx = 0; + if (WinRing0.CpuidTx(CPUID_EXT, 0, + out eax, out ebx, out ecx, out edx, mask)) + maxCpuidExt = eax - CPUID_EXT; + } else { + throw new ArgumentException(); + } + + if (maxCpuid == 0 || maxCpuidExt == 0) + return; + + cpuidData = new uint[maxCpuid + 1, 4]; + for (uint i = 0; i < (maxCpuid + 1); i++) + WinRing0.CpuidTx(CPUID_0 + i, 0, + out cpuidData[i, 0], out cpuidData[i, 1], + out cpuidData[i, 2], out cpuidData[i, 3], mask); + + cpuidExtData = new uint[MaxCpuidExt + 1, 4]; + for (uint i = 0; i < (MaxCpuidExt + 1); i++) + WinRing0.CpuidTx(CPUID_EXT + i, 0, + out cpuidExtData[i, 0], out cpuidExtData[i, 1], + out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask); + + StringBuilder nameBuilder = new StringBuilder(); + for (uint i = 2; i <= 4; i++) { + if (WinRing0.CpuidTx(CPUID_EXT + i, 0, + out eax, out ebx, out ecx, out edx, mask)) + { + AppendRegister(nameBuilder, eax); + AppendRegister(nameBuilder, ebx); + AppendRegister(nameBuilder, ecx); + AppendRegister(nameBuilder, edx); + } + } + nameBuilder.Replace('\0', ' '); + cpuBrandString = nameBuilder.ToString().Trim(); + nameBuilder.Replace("(R)", " "); + nameBuilder.Replace("(TM)", " "); + nameBuilder.Replace("(tm)", " "); + nameBuilder.Replace("CPU", ""); + for (int i = 0; i < 10; i++) nameBuilder.Replace(" ", " "); + name = nameBuilder.ToString(); + if (name.Contains("@")) + name = name.Remove(name.LastIndexOf('@')); + name = name.Trim(); + + this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) + + ((cpuidData[1, 0] & 0x0F00) >> 8); + this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) + + ((cpuidData[1, 0] & 0xF0) >> 4); + this.stepping = (cpuidData[1, 0] & 0x0F); + + this.apicId = (cpuidData[1, 1] >> 24) & 0xFF; + + switch (vendor) { + case Vendor.Intel: + uint maxCoreAndThreadIdPerPackage = (cpuidData[1, 1] >> 16) & 0xFF; + uint maxCoreIdPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1; + threadMaskWith = (uint)Math.Ceiling(Math.Log( + maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage, 2)); + coreMaskWith = (uint)Math.Ceiling(Math.Log(maxCoreIdPerPackage, 2)); + break; + case Vendor.AMD: + uint corePerPackage = (cpuidExtData[8, 2] & 0xFF) + 1; + threadMaskWith = 0; + coreMaskWith = (uint)Math.Ceiling(Math.Log(corePerPackage, 2)); + break; + default: + threadMaskWith = 0; + coreMaskWith = 0; + break; + } + + processorId = (uint)(apicId >> (int)(coreMaskWith + threadMaskWith)); + coreId = (uint)((apicId >> (int)(threadMaskWith)) - processorId); + threadId = apicId - processorId - coreId; + } + + public string Name { + get { return name; } + } + + public string BrandString { + get { return cpuBrandString; } + } + + public int Thread { + get { return thread; } + } + + public uint MaxCPUID { + get { return maxCpuid; } + } + + public uint MaxCpuidExt { + get { return maxCpuidExt; } + } + + public Vendor Vendor { + get { return vendor; } + } + + public uint Family { + get { return family; } + } + + public uint Model { + get { return model; } + } + + public uint Stepping { + get { return stepping; } + } + + public uint ApicId { + get { return apicId; } + } + + public uint ProcessorId { + get { return processorId; } + } + + public uint CoreId { + get { return coreId; } + } + + public uint ThreadId { + get { return threadId; } + } + + public uint[,] Data { + get { return cpuidData; } + } + + public uint[,] ExtData { + get { return cpuidExtData; } + } + } +} diff --git a/Hardware/CPU/CPULoad.cs b/Hardware/CPU/CPULoad.cs index c33c03f..803561d 100644 --- a/Hardware/CPU/CPULoad.cs +++ b/Hardware/CPU/CPULoad.cs @@ -68,8 +68,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { [Out] SystemProcessorPerformanceInformation[] informations, int structSize, out IntPtr returnLength); - private uint coreCount; - private uint logicalProcessorsPerCore; + private CPUID[][] cpuid; private long systemTime; private long[] idleTimes; @@ -80,7 +79,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { private bool available = false; private long[] GetIdleTimes() { - long[] result = new long[coreCount * logicalProcessorsPerCore]; + long[] result = new long[cpuid.Length * cpuid[0].Length]; SystemProcessorPerformanceInformation[] informations = new SystemProcessorPerformanceInformation[result.Length]; @@ -97,10 +96,9 @@ namespace OpenHardwareMonitor.Hardware.CPU { return result; } - public CPULoad(uint coreCount, uint logicalProcessorsPerCore) { - this.coreCount = coreCount; - this.logicalProcessorsPerCore = logicalProcessorsPerCore; - this.coreLoads = new float[coreCount]; + public CPULoad(CPUID[][] cpuid) { + this.cpuid = cpuid; + this.coreLoads = new float[cpuid.Length]; this.systemTime = DateTime.Now.Ticks; this.totalLoad = 0; try { @@ -135,21 +133,22 @@ namespace OpenHardwareMonitor.Hardware.CPU { return; float total = 0; - for (int i = 0; i < coreCount; i++) { + int count = 0; + for (int i = 0; i < cpuid.Length; i++) { float value = 0; - for (int j = 0; j < logicalProcessorsPerCore; j++) { - long index = i * logicalProcessorsPerCore + j; + for (int j = 0; j < cpuid[i].Length; j++) { + long index = cpuid[i][j].Thread; long delta = idleTimes[index] - this.idleTimes[index]; value += delta; total += delta; + count++; } - value = 1.0f - value / (logicalProcessorsPerCore * + value = 1.0f - value / (cpuid[i].Length * (systemTime - this.systemTime)); value = value < 0 ? 0 : value; coreLoads[i] = value * 100; } - total = 1.0f - total / (coreCount * logicalProcessorsPerCore * - (systemTime - this.systemTime)); + total = 1.0f - total / (count * (systemTime - this.systemTime)); total = total < 0 ? 0 : total; this.totalLoad = total * 100; diff --git a/Hardware/CPU/IntelCPU.cs b/Hardware/CPU/IntelCPU.cs index 143560d..058e627 100644 --- a/Hardware/CPU/IntelCPU.cs +++ b/Hardware/CPU/IntelCPU.cs @@ -48,6 +48,9 @@ using System.Text; namespace OpenHardwareMonitor.Hardware.CPU { public class IntelCPU : Hardware, IHardware { + private CPUID[][] cpuid; + private int coreCount; + private string name; private Image icon; @@ -60,15 +63,11 @@ namespace OpenHardwareMonitor.Hardware.CPU { private Sensor totalLoad; private Sensor[] coreLoads; private Sensor[] coreClocks; - private Sensor busClock; - private uint logicalProcessors; - private uint logicalProcessorsPerCore; - private uint coreCount; + private Sensor busClock; private bool hasTSC; private bool invariantTSC; private double estimatedMaxClock; - private ulong affinityMask; private CPULoad cpuLoad; private ulong lastTimeStampCount; @@ -87,10 +86,6 @@ namespace OpenHardwareMonitor.Hardware.CPU { return "CPU Core #" + (i + 1); } - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - private static extern bool GetProcessAffinityMask(IntPtr handle, - out IntPtr processMask, out IntPtr systemMask); - private float[] Floats(float f) { float[] result = new float[coreCount]; for (int i = 0; i < coreCount; i++) @@ -98,64 +93,16 @@ namespace OpenHardwareMonitor.Hardware.CPU { return result; } - public IntelCPU(string name, uint family, uint model, uint stepping, - uint[,] cpuidData, uint[,] cpuidExtData) { - - this.name = name; + public IntelCPU(CPUID[][] cpuid) { + + this.cpuid = cpuid; + this.coreCount = cpuid.Length; + this.name = cpuid[0][0].Name; this.icon = Utilities.EmbeddedResources.GetImage("cpu.png"); - this.family = family; - this.model = model; - this.stepping = stepping; - - logicalProcessors = 0; - if (cpuidData.GetLength(0) > 0x0B) { - uint eax, ebx, ecx, edx; - WinRing0.CpuidEx(0x0B, 0, out eax, out ebx, out ecx, out edx); - logicalProcessorsPerCore = ebx & 0xFF; - if (logicalProcessorsPerCore > 0) { - WinRing0.CpuidEx(0x0B, 1, out eax, out ebx, out ecx, out edx); - logicalProcessors = ebx & 0xFF; - } - } - if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x04) { - uint coresPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1; - uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF; - logicalProcessorsPerCore = logicalPerPackage / coresPerPackage; - logicalProcessors = logicalPerPackage; - } - if (logicalProcessors <= 0 && cpuidData.GetLength(0) > 0x01) { - uint logicalPerPackage = (cpuidData[1, 1] >> 16) & 0xFF; - logicalProcessorsPerCore = logicalPerPackage; - logicalProcessors = logicalPerPackage; - } - if (logicalProcessors <= 0) { - logicalProcessors = 1; - logicalProcessorsPerCore = 1; - } - - IntPtr processMask, systemMask; - GetProcessAffinityMask(Process.GetCurrentProcess().Handle, - out processMask, out systemMask); - affinityMask = (ulong)systemMask; - - // correct values in case HypeThreading is disabled - if (logicalProcessorsPerCore > 1) { - ulong affinity = affinityMask; - int availableLogicalProcessors = 0; - while (affinity != 0) { - if ((affinity & 0x1) > 0) - availableLogicalProcessors++; - affinity >>= 1; - } - while (logicalProcessorsPerCore > 1 && - availableLogicalProcessors < logicalProcessors) { - logicalProcessors >>= 1; - logicalProcessorsPerCore >>= 1; - } - } - - coreCount = logicalProcessors / logicalProcessorsPerCore; + this.family = cpuid[0][0].Family; + this.model = cpuid[0][0].Model; + this.stepping = cpuid[0][0].Stepping; float[] tjMax; switch (family) { @@ -191,8 +138,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { tjMax = new float[coreCount]; for (int i = 0; i < coreCount; i++) { if (WinRing0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax, - out edx, (UIntPtr)( - 1 << (int)(logicalProcessorsPerCore * i)))) + out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) { tjMax[i] = (eax >> 16) & 0xFF; } else { @@ -211,7 +157,9 @@ namespace OpenHardwareMonitor.Hardware.CPU { } // check if processor supports a digital thermal sensor - if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) { + if (cpuid[0][0].Data.GetLength(0) > 6 && + (cpuid[0][0].Data[6, 0] & 1) != 0) + { coreTemperatures = new Sensor[coreCount]; for (int i = 0; i < coreTemperatures.Length; i++) { coreTemperatures[i] = new Sensor(CoreString(i), i, tjMax[i], @@ -235,7 +183,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { for (int i = 0; i < coreLoads.Length; i++) coreLoads[i] = new Sensor(CoreString(i), i + 1, SensorType.Load, this); - cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore); + cpuLoad = new CPULoad(cpuid); if (cpuLoad.IsAvailable) { foreach (Sensor sensor in coreLoads) ActivateSensor(sensor); @@ -244,13 +192,15 @@ namespace OpenHardwareMonitor.Hardware.CPU { } // check if processor has TSC - if (cpuidData.GetLength(0) > 1 && (cpuidData[1, 3] & 0x10) != 0) + if (cpuid[0][0].Data.GetLength(0) > 1 + && (cpuid[0][0].Data[1, 3] & 0x10) != 0) hasTSC = true; else hasTSC = false; // check if processor supports invariant TSC - if (cpuidExtData.GetLength(0) > 7 && (cpuidExtData[7, 3] & 0x100) != 0) + if (cpuid[0][0].ExtData.GetLength(0) > 7 + && (cpuid[0][0].ExtData[7, 3] & 0x100) != 0) invariantTSC = true; else invariantTSC = false; @@ -288,10 +238,9 @@ namespace OpenHardwareMonitor.Hardware.CPU { get { return icon; } } - private void AppendMSRData(StringBuilder r, uint msr, int core) { + private void AppendMSRData(StringBuilder r, uint msr, int thread) { uint eax, edx; - if (WinRing0.RdmsrTx(msr, out eax, out edx, - (UIntPtr)(1 << (int)(logicalProcessorsPerCore * core)))) { + if (WinRing0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) { r.Append(" "); r.Append((msr).ToString("X8")); r.Append(" "); @@ -310,10 +259,8 @@ namespace OpenHardwareMonitor.Hardware.CPU { r.AppendFormat("Name: {0}{1}", name, Environment.NewLine); r.AppendFormat("Number of Cores: {0}{1}", coreCount, Environment.NewLine); - r.AppendFormat("Threads per Core: {0}{1}", logicalProcessorsPerCore, - Environment.NewLine); - r.AppendFormat("Affinity Mask: 0x{0}{1}", affinityMask.ToString("X"), - Environment.NewLine); + r.AppendFormat("Threads per Core: {0}{1}", cpuid[0].Length, + Environment.NewLine); r.AppendLine("TSC: " + (hasTSC ? (invariantTSC ? "Invariant" : "Not Invariant") : "None")); r.AppendLine(string.Format(CultureInfo.InvariantCulture, @@ -322,14 +269,14 @@ namespace OpenHardwareMonitor.Hardware.CPU { "Max Clock: {0} MHz", Math.Round(estimatedMaxClock * 100) * 0.01)); r.AppendLine(); - for (int i = 0; i < coreCount; i++) { + for (int i = 0; i < cpuid.Length; i++) { r.AppendLine("MSR Core #" + (i + 1)); r.AppendLine(); r.AppendLine(" MSR EDX EAX"); - AppendMSRData(r, MSR_PLATFORM_INFO, i); - AppendMSRData(r, IA32_PERF_STATUS, i); - AppendMSRData(r, IA32_THERM_STATUS_MSR, i); - AppendMSRData(r, IA32_TEMPERATURE_TARGET, i); + AppendMSRData(r, MSR_PLATFORM_INFO, cpuid[i][0].Thread); + AppendMSRData(r, IA32_PERF_STATUS, cpuid[i][0].Thread); + AppendMSRData(r, IA32_THERM_STATUS_MSR, cpuid[i][0].Thread); + AppendMSRData(r, IA32_TEMPERATURE_TARGET, cpuid[i][0].Thread); r.AppendLine(); } @@ -360,8 +307,8 @@ namespace OpenHardwareMonitor.Hardware.CPU { for (int i = 0; i < coreTemperatures.Length; i++) { uint eax, edx; if (WinRing0.RdmsrTx( - IA32_THERM_STATUS_MSR, out eax, out edx, - (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) { + IA32_THERM_STATUS_MSR, out eax, out edx, + (UIntPtr)(1L << cpuid[i][0].Thread))) { // if reading is valid if ((eax & 0x80000000) != 0) { // get the dist from tjMax from bits 22:16 @@ -402,7 +349,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { for (int i = 0; i < coreClocks.Length; i++) { System.Threading.Thread.Sleep(1); if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx, - (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) { + (UIntPtr)(1L << cpuid[i][0].Thread))) { if (maxNehalemMultiplier > 0) { // Core i3, i5, i7 uint nehalemMultiplier = eax & 0xff; coreClocks[i].Value = diff --git a/Hardware/WinRing0.cs b/Hardware/WinRing0.cs index 13d5009..8f57941 100644 --- a/Hardware/WinRing0.cs +++ b/Hardware/WinRing0.cs @@ -79,10 +79,11 @@ namespace OpenHardwareMonitor.Hardware { public delegate uint GetDllStatusDelegate(); public delegate bool IsCpuidDelegate(); - public delegate bool CpuidDelegate(uint index, - out uint eax, out uint ebx, out uint ecx, out uint edx); - public delegate bool CpuidExDelegate(uint index, uint ecxValue, + public delegate bool CpuidDelegate(uint index, uint ecxValue, out uint eax, out uint ebx, out uint ecx, out uint edx); + public delegate bool CpuidTxDelegate(uint index, uint ecxValue, + out uint eax, out uint ebx, out uint ecx, out uint edx, + UIntPtr threadAffinityMask); public delegate bool RdmsrDelegate(uint index, out uint eax, out uint edx); public delegate bool RdmsrTxDelegate(uint index, out uint eax, out uint edx, UIntPtr threadAffinityMask); @@ -105,7 +106,7 @@ namespace OpenHardwareMonitor.Hardware { public static GetDllStatusDelegate GetDllStatus; public static IsCpuidDelegate IsCpuid; public static CpuidDelegate Cpuid; - public static CpuidExDelegate CpuidEx; + public static CpuidTxDelegate CpuidTx; public static RdmsrDelegate Rdmsr; public static RdmsrTxDelegate RdmsrTx; public static ReadIoPortByteDelegate ReadIoPortByte; @@ -134,7 +135,7 @@ namespace OpenHardwareMonitor.Hardware { GetDelegate("GetDllStatus", out GetDllStatus); GetDelegate("IsCpuid", out IsCpuid); GetDelegate("Cpuid", out Cpuid); - GetDelegate("CpuidEx", out CpuidEx); + GetDelegate("CpuidTx", out CpuidTx); GetDelegate("Rdmsr", out Rdmsr); GetDelegate("RdmsrTx", out RdmsrTx); GetDelegate("ReadIoPortByte", out ReadIoPortByte); diff --git a/OpenHardwareMonitor.csproj b/OpenHardwareMonitor.csproj index e490bcf..188e918 100644 --- a/OpenHardwareMonitor.csproj +++ b/OpenHardwareMonitor.csproj @@ -78,6 +78,7 @@ +