mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-30 13:57:38 +00:00
Implemented APIC based CPU enumeration (Issue 41).
This commit is contained in:
BIN
External/WinRing0.dll
vendored
BIN
External/WinRing0.dll
vendored
Binary file not shown.
BIN
External/WinRing0x64.dll
vendored
BIN
External/WinRing0x64.dll
vendored
Binary file not shown.
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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<IHardware> hardware = new List<IHardware>();
|
||||
|
||||
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<CPUID> threads = new List<CPUID>();
|
||||
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<uint, List<CPUID>> processors =
|
||||
new SortedDictionary<uint, List<CPUID>>();
|
||||
foreach (CPUID thread in threads) {
|
||||
List<CPUID> list;
|
||||
processors.TryGetValue(thread.ProcessorId, out list);
|
||||
if (list == null) {
|
||||
list = new List<CPUID>();
|
||||
processors.Add(thread.ProcessorId, list);
|
||||
}
|
||||
list.Add(thread);
|
||||
}
|
||||
|
||||
CPUID[][] processorThreads = new CPUID[processors.Count][];
|
||||
int index = 0;
|
||||
foreach (List<CPUID> list in processors.Values) {
|
||||
processorThreads[index] = list.ToArray();
|
||||
index++;
|
||||
}
|
||||
return processorThreads;
|
||||
}
|
||||
|
||||
private CPUID[][] GroupThreadsByCore(CPUID[] threads) {
|
||||
|
||||
SortedDictionary<uint, List<CPUID>> cores =
|
||||
new SortedDictionary<uint, List<CPUID>>();
|
||||
foreach (CPUID thread in threads) {
|
||||
List<CPUID> coreList;
|
||||
cores.TryGetValue(thread.CoreId, out coreList);
|
||||
if (coreList == null) {
|
||||
coreList = new List<CPUID>();
|
||||
cores.Add(thread.CoreId, coreList);
|
||||
}
|
||||
coreList.Add(thread);
|
||||
}
|
||||
|
||||
CPUID[][] coreThreads = new CPUID[cores.Count][];
|
||||
int index = 0;
|
||||
foreach (List<CPUID> 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() { }
|
||||
|
252
Hardware/CPU/CPUID.cs
Normal file
252
Hardware/CPU/CPUID.cs
Normal file
@@ -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 <m.moeller@gmx.ch>.
|
||||
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; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
|
@@ -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 =
|
||||
|
@@ -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);
|
||||
|
@@ -78,6 +78,7 @@
|
||||
<Compile Include="GUI\TypeNode.cs" />
|
||||
<Compile Include="Hardware\CPU\AMD10CPU.cs" />
|
||||
<Compile Include="Hardware\CPU\AMD0FCPU.cs" />
|
||||
<Compile Include="Hardware\CPU\CPUID.cs" />
|
||||
<Compile Include="Hardware\CPU\CPULoad.cs" />
|
||||
<Compile Include="Hardware\Hardware.cs" />
|
||||
<Compile Include="Hardware\HDD\HDD.cs" />
|
||||
|
Reference in New Issue
Block a user