Implemented APIC based CPU enumeration (Issue 41).

This commit is contained in:
Michael Möller
2010-04-24 19:59:52 +00:00
parent 1f2f9d6843
commit 65b0293b1c
10 changed files with 445 additions and 252 deletions

BIN
External/WinRing0.dll vendored

Binary file not shown.

Binary file not shown.

View File

@@ -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,

View File

@@ -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);

View File

@@ -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
View 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; }
}
}
}

View File

@@ -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;

View File

@@ -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 =

View File

@@ -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);

View File

@@ -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" />