Add support for multiple processor groups.

Merge from upstream.
This commit is contained in:
Phyxion
2020-05-11 13:29:52 +02:00
parent a18136b55e
commit 3cc3d9139c
22 changed files with 390 additions and 135 deletions
@@ -120,7 +120,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
{
Thread.Sleep(1);
if (Ring0.ReadMsr(FIDVID_STATUS, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(FIDVID_STATUS, out uint eax, out uint _, _cpuId[i][0].Affinity))
{
// CurrFID can be found in eax bits 0-5, MaxFID in 16-21
// 8-13 hold StartFID, we don't use that here.
@@ -143,7 +143,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
bool corePerformanceBoostSupport = (cpuId[0][0].ExtData[7, 3] & (1 << 9)) > 0;
// set affinity to the first thread for all frequency estimations
ulong mask = ThreadAffinity.Set(1UL << cpuId[0][0].Thread);
var previousAffinity = ThreadAffinity.Set(cpuId[0][0].Affinity);
// disable core performance boost
Ring0.ReadMsr(HWCR, out uint hwcrEax, out uint hwcrEdx);
@@ -164,12 +164,12 @@ namespace LibreHardwareMonitor.Hardware.CPU
Ring0.WriteMsr(HWCR, hwcrEax, hwcrEdx);
// restore the thread affinity.
ThreadAffinity.Set(mask);
ThreadAffinity.Set(previousAffinity);
// the file reader for lm-sensors support on Linux
_temperatureStream = null;
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
{
string[] devicePaths = Directory.GetDirectories("/sys/class/hwmon/");
foreach (string path in devicePaths)
@@ -177,8 +177,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
string name = null;
try
{
using (StreamReader reader = new StreamReader(path + "/device/name"))
name = reader.ReadLine();
using StreamReader reader = new StreamReader(path + "/device/name");
name = reader.ReadLine();
}
catch (IOException)
{ }
@@ -450,7 +451,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
{
Thread.Sleep(1);
if (Ring0.ReadMsr(COFVID_STATUS, out uint curEax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(COFVID_STATUS, out uint curEax, out uint _, _cpuId[i][0].Affinity))
{
double multiplier = GetCoreMultiplier(curEax);
@@ -96,7 +96,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
private readonly Sensor _coreTemperatureTctlTdie;
private readonly Sensor[] _ccdTemperatures;
private readonly Sensor _coreVoltage;
private readonly Amd17Cpu _hw;
private readonly Amd17Cpu _hardware;
private readonly Sensor _packagePower;
private readonly Sensor _socVoltage;
private Sensor _ccdsMaxTemperature;
@@ -104,20 +104,20 @@ namespace LibreHardwareMonitor.Hardware.CPU
private DateTime _lastPwrTime = new DateTime(0);
private uint _lastPwrValue;
public Processor(Hardware hw)
public Processor(Hardware hardware)
{
_hw = (Amd17Cpu)hw;
_hardware = (Amd17Cpu)hardware;
Nodes = new List<NumaNode>();
_packagePower = new Sensor("Package Power", _hw._sensorPower++, SensorType.Power, _hw, _hw._settings);
_coreTemperatureTctl = new Sensor("Core (Tctl)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
_coreTemperatureTdie = new Sensor("Core (Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
_coreTemperatureTctlTdie = new Sensor("Core (Tctl/Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
_packagePower = new Sensor("Package Power", _hardware._sensorPower++, SensorType.Power, _hardware, _hardware._settings);
_coreTemperatureTctl = new Sensor("Core (Tctl)", _hardware._sensorTemperatures++, SensorType.Temperature, _hardware, _hardware._settings);
_coreTemperatureTdie = new Sensor("Core (Tdie)", _hardware._sensorTemperatures++, SensorType.Temperature, _hardware, _hardware._settings);
_coreTemperatureTctlTdie = new Sensor("Core (Tctl/Tdie)", _hardware._sensorTemperatures++, SensorType.Temperature, _hardware, _hardware._settings);
_ccdTemperatures = new Sensor[8]; // Hardcoded until there's a way to get max CCDs.
_coreVoltage = new Sensor("Core (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
_socVoltage = new Sensor("SoC (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
_coreVoltage = new Sensor("Core (SVI2 TFN)", _hardware._sensorVoltage++, SensorType.Voltage, _hardware, _hardware._settings);
_socVoltage = new Sensor("SoC (SVI2 TFN)", _hardware._sensorVoltage++, SensorType.Voltage, _hardware, _hardware._settings);
_hw.ActivateSensor(_packagePower);
_hardware.ActivateSensor(_packagePower);
}
public List<NumaNode> Nodes { get; }
@@ -131,7 +131,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
return;
ulong mask = Ring0.ThreadAffinitySet(1UL << cpu.Thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(cpu.Affinity);
// MSRC001_0299
// TU [19:16]
@@ -195,7 +195,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset);
Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1);
Ring0.ThreadAffinitySet(mask);
ThreadAffinity.Set(previousAffinity);
// power consumption
// power.Value = (float) ((double)pu * 0.125);
@@ -250,14 +250,14 @@ namespace LibreHardwareMonitor.Hardware.CPU
_coreTemperatureTctl.Value = t;
_coreTemperatureTdie.Value = t + offset;
_hw.ActivateSensor(_coreTemperatureTctl);
_hw.ActivateSensor(_coreTemperatureTdie);
_hardware.ActivateSensor(_coreTemperatureTctl);
_hardware.ActivateSensor(_coreTemperatureTdie);
}
else
{
// Zen 2 doesn't have an offset so Tdie and Tctl are the same.
_coreTemperatureTctlTdie.Value = t;
_hw.ActivateSensor(_coreTemperatureTctlTdie);
_hardware.ActivateSensor(_coreTemperatureTctlTdie);
}
// Tested only on R5 3600 & Threadripper 3960X.
@@ -279,11 +279,11 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (_ccdTemperatures[i] == null)
{
_hw.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)",
_hw._sensorTemperatures++,
_hardware.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)",
_hardware._sensorTemperatures++,
SensorType.Temperature,
_hw,
_hw._settings));
_hardware,
_hardware._settings));
}
_ccdTemperatures[i].Value = ccdTemp;
@@ -296,20 +296,20 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (_ccdsMaxTemperature == null)
{
_hw.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)",
_hw._sensorTemperatures++,
_hardware.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)",
_hardware._sensorTemperatures++,
SensorType.Temperature,
_hw,
_hw._settings));
_hardware,
_hardware._settings));
}
if (_ccdsAverageTemperature == null)
{
_hw.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)",
_hw._sensorTemperatures++,
_hardware.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)",
_hardware._sensorTemperatures++,
SensorType.Temperature,
_hw,
_hw._settings));
_hardware,
_hardware._settings));
}
_ccdsMaxTemperature.Value = activeCcds.Max(x => x.Value);
@@ -329,7 +329,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
vcc = 1.550 - vidStep * svi0PlaneXVddCor;
_coreVoltage.Value = (float)vcc;
_hw.ActivateSensor(_coreVoltage);
_hardware.ActivateSensor(_coreVoltage);
}
// SoC (0x02), not every Zen cpu has this voltage.
@@ -339,7 +339,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
vcc = 1.550 - vidStep * svi0PlaneXVddCor;
_socVoltage.Value = (float)vcc;
_hw.ActivateSensor(_socVoltage);
_hardware.ActivateSensor(_socVoltage);
}
}
@@ -357,7 +357,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (node == null)
{
node = new NumaNode(_hw, numaId);
node = new NumaNode(_hardware, numaId);
Nodes.Add(node);
}
@@ -441,7 +441,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
return;
ulong mask = Ring0.ThreadAffinitySet(1UL << cpu.Thread);
var previousAffinity = ThreadAffinity.Set(cpu.Affinity);
// MSRC001_0299
// TU [19:16]
@@ -476,7 +476,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
// int IddDiv = (int)((eax >> 30) & 0x03);
// int IddValue = (int)((eax >> 22) & 0xff);
// int CpuVid = (int)((eax >> 14) & 0xff);
Ring0.ThreadAffinitySet(mask);
ThreadAffinity.Set(previousAffinity);
// clock
// CoreCOF is (Core::X86::Msr::PStateDef[CpuFid[7:0]] / Core::X86::Msr::PStateDef[CpuDfsId]) * 200
@@ -96,6 +96,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
{
for (int k = 0; k < _threads[i][j].Length; k++)
{
r.AppendLine(" CPU Group: " + _threads[i][j][k].Group);
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);
@@ -124,19 +125,30 @@ namespace LibreHardwareMonitor.Hardware.CPU
private static CpuId[][] GetProcessorThreads()
{
List<CpuId> threads = new List<CpuId>();
for (int i = 0; i < 64; i++)
for (int i = 0; i < ThreadAffinity.ProcessorGroupCount; i++)
{
try
for (int j = 0; j < 64; j++)
{
threads.Add(new CpuId(i));
}
catch (ArgumentOutOfRangeException)
{
// All cores found.
break;
try
{
if (!ThreadAffinity.IsValid(GroupAffinity.Single((ushort)i, j)))
continue;
var cpuid = CpuId.Get(i, j);
if (cpuid != null)
threads.Add(cpuid);
}
catch (ArgumentOutOfRangeException)
{
// All cores found.
break;
}
}
}
SortedDictionary<uint, List<CpuId>> processors = new SortedDictionary<uint, List<CpuId>>();
foreach (CpuId thread in threads)
{
+67 -13
View File
@@ -18,25 +18,28 @@ namespace LibreHardwareMonitor.Hardware.CPU
public class CpuId
{
// ReSharper disable InconsistentNaming
public const uint CPUID_0 = 0;
public const uint CPUID_EXT = 0x80000000;
// ReSharper restore InconsistentNaming
public CpuId(int thread)
/// <summary>
/// Initializes a new instance of the <see cref="CpuId" /> class.
/// </summary>
/// <param name="group">The group.</param>
/// <param name="thread">The thread.</param>
/// <param name="affinity">The affinity.</param>
private CpuId(int group, int thread, GroupAffinity affinity)
{
Thread = thread;
Group = group;
Affinity = affinity;
uint threadMaskWith;
uint coreMaskWith;
Thread = thread;
uint maxCpuidExt;
if (thread >= 64)
throw new ArgumentOutOfRangeException(nameof(thread));
ulong mask = 1UL << thread;
uint maxCpuid;
if (OpCode.CpuidTx(CPUID_0, 0, out uint eax, out uint ebx, out uint ecx, out uint edx, mask))
if (OpCode.CpuId(CPUID_0, 0, out uint eax, out uint ebx, out uint ecx, out uint edx))
{
if (eax > 0)
maxCpuid = eax;
@@ -49,6 +52,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
AppendRegister(vendorBuilder, edx);
AppendRegister(vendorBuilder, ecx);
string cpuVendor = vendorBuilder.ToString();
switch (cpuVendor)
{
case "GenuineIntel":
@@ -62,7 +66,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
break;
}
if (OpCode.CpuidTx(CPUID_EXT, 0, out eax, out _, out _, out _, mask))
if (OpCode.CpuId(CPUID_EXT, 0, out eax, out _, out _, out _))
{
if (eax > CPUID_EXT)
maxCpuidExt = eax - CPUID_EXT;
@@ -85,19 +89,19 @@ namespace LibreHardwareMonitor.Hardware.CPU
Data = new uint[maxCpuid + 1, 4];
for (uint i = 0; i < maxCpuid + 1; i++)
{
OpCode.CpuidTx(CPUID_0 + i, 0, out Data[i, 0], out Data[i, 1], out Data[i, 2], out Data[i, 3], mask);
OpCode.CpuId(CPUID_0 + i, 0, out Data[i, 0], out Data[i, 1], out Data[i, 2], out Data[i, 3]);
}
ExtData = new uint[maxCpuidExt + 1, 4];
for (uint i = 0; i < maxCpuidExt + 1; i++)
{
OpCode.CpuidTx(CPUID_EXT + i, 0, out ExtData[i, 0], out ExtData[i, 1], out ExtData[i, 2], out ExtData[i, 3], mask);
OpCode.CpuId(CPUID_EXT + i, 0, out ExtData[i, 0], out ExtData[i, 1], out ExtData[i, 2], out ExtData[i, 3]);
}
StringBuilder nameBuilder = new StringBuilder();
for (uint i = 2; i <= 4; i++)
{
if (OpCode.CpuidTx(CPUID_EXT + i, 0, out eax, out ebx, out ecx, out edx, mask))
if (OpCode.CpuId(CPUID_EXT + i, 0, out eax, out ebx, out ecx, out edx))
{
AppendRegister(nameBuilder, eax);
AppendRegister(nameBuilder, ebx);
@@ -141,6 +145,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
switch (Vendor)
{
case Vendor.Intel:
{
uint maxCoreAndThreadIdPerPackage = (Data[1, 1] >> 16) & 0xFF;
uint maxCoreIdPerPackage;
if (maxCpuid >= 4)
@@ -151,7 +156,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
threadMaskWith = NextLog2(maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage);
coreMaskWith = NextLog2(maxCoreIdPerPackage);
break;
}
case Vendor.AMD:
{
uint corePerPackage;
if (maxCpuidExt >= 8)
corePerPackage = (ExtData[8, 2] & 0xFF) + 1;
@@ -171,22 +178,31 @@ namespace LibreHardwareMonitor.Hardware.CPU
switch (maxCoresPerDie)
{
case 0x04: // Ryzen
{
coreMaskWith = NextLog2(16);
break;
}
case 0x05: // Threadripper
{
coreMaskWith = NextLog2(32);
break;
}
case 0x06: // Epic
{
coreMaskWith = NextLog2(64);
break;
}
}
}
break;
}
default:
{
threadMaskWith = 0;
coreMaskWith = 0;
break;
}
}
ProcessorId = ApicId >> (int)(coreMaskWith + threadMaskWith);
@@ -194,6 +210,8 @@ namespace LibreHardwareMonitor.Hardware.CPU
ThreadId = ApicId - (ProcessorId << (int)(coreMaskWith + threadMaskWith)) - (CoreId << (int)threadMaskWith);
}
public GroupAffinity Affinity { get; }
public uint ApicId { get; }
public string BrandString { get; } = string.Empty;
@@ -206,6 +224,8 @@ namespace LibreHardwareMonitor.Hardware.CPU
public uint Family { get; }
public int Group { get; }
public uint Model { get; }
public string Name { get; } = string.Empty;
@@ -220,6 +240,35 @@ namespace LibreHardwareMonitor.Hardware.CPU
public Vendor Vendor { get; } = Vendor.Unknown;
/// <summary>
/// Gets the specified <see cref="CpuId" />.
/// </summary>
/// <param name="group">The group.</param>
/// <param name="thread">The thread.</param>
/// <returns><see cref="CpuId" />.</returns>
public static CpuId Get(int group, int thread)
{
if (thread >= 64)
return null;
var affinity = GroupAffinity.Single((ushort)group, thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(affinity);
if (previousAffinity == GroupAffinity.Undefined)
return null;
try
{
return new CpuId(group, thread, affinity);
}
finally
{
ThreadAffinity.Set(previousAffinity);
}
}
private static void AppendRegister(StringBuilder b, uint value)
{
b.Append((char)(value & 0xff));
@@ -244,5 +293,10 @@ namespace LibreHardwareMonitor.Hardware.CPU
return count;
}
// ReSharper disable InconsistentNaming
public const uint CPUID_0 = 0;
public const uint CPUID_EXT = 0x80000000;
// ReSharper restore InconsistentNaming
}
}
@@ -79,9 +79,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (HasTimeStampCounter)
{
ulong mask = ThreadAffinity.Set(1UL << cpuId[0][0].Thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(cpuId[0][0].Affinity);
EstimateTimeStampCounterFrequency(out _estimatedTimeStampCounterFrequency, out _estimatedTimeStampCounterFrequencyError);
ThreadAffinity.Set(mask);
ThreadAffinity.Set(previousAffinity);
}
else
{
@@ -182,9 +182,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
error = beginError + endError;
}
private static void AppendMsrData(StringBuilder r, uint msr, int thread)
private static void AppendMsrData(StringBuilder r, uint msr, GroupAffinity affinity)
{
if (Ring0.ReadMsr(msr, out uint eax, out uint edx, 1UL << thread))
if (Ring0.ReadMsr(msr, out uint eax, out uint edx, affinity))
{
r.Append(" ");
r.Append(msr.ToString("X8", CultureInfo.InvariantCulture));
@@ -241,7 +241,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
r.AppendLine();
r.AppendLine(" MSR EDX EAX");
foreach (uint msr in msrArray)
AppendMsrData(r, msr, _cpuId[i][0].Thread);
AppendMsrData(r, msr, _cpuId[i][0].Affinity);
r.AppendLine();
}
@@ -255,7 +255,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (HasTimeStampCounter && _isInvariantTimeStampCounter)
{
// make sure always the same thread is used
ulong mask = ThreadAffinity.Set(1UL << _cpuId[0][0].Thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(_cpuId[0][0].Affinity);
// read time before and after getting the TSC to estimate the error
long firstTime = Stopwatch.GetTimestamp();
@@ -263,7 +263,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
long time = Stopwatch.GetTimestamp();
// restore the thread affinity mask
ThreadAffinity.Set(mask);
ThreadAffinity.Set(previousAffinity);
double delta = (double)(time - _lastTime) / Stopwatch.Frequency;
double error = (double)(time - firstTime) / Stopwatch.Frequency;
@@ -413,7 +413,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
float[] result = new float[_coreCount];
for (int i = 0; i < _coreCount; i++)
{
if (Ring0.ReadMsr(IA32_TEMPERATURE_TARGET, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(IA32_TEMPERATURE_TARGET, out uint eax, out uint _, _cpuId[i][0].Affinity))
result[i] = (eax >> 16) & 0xFF;
else
result[i] = 100;
@@ -461,7 +461,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
for (int i = 0; i < _coreTemperatures.Length; i++)
{
// if reading is valid
if (Ring0.ReadMsr(IA32_THERM_STATUS_MSR, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread) && (eax & 0x80000000) != 0)
if (Ring0.ReadMsr(IA32_THERM_STATUS_MSR, out uint eax, out uint _, _cpuId[i][0].Affinity) && (eax & 0x80000000) != 0)
{
// get the dist from tjMax from bits 22:16
float deltaT = (eax & 0x007F0000) >> 16;
@@ -493,7 +493,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (_packageTemperature != null)
{
// if reading is valid
if (Ring0.ReadMsr(IA32_PACKAGE_THERM_STATUS, out uint eax, out uint _, 1UL << _cpuId[0][0].Thread) && (eax & 0x80000000) != 0)
if (Ring0.ReadMsr(IA32_PACKAGE_THERM_STATUS, out uint eax, out uint _, _cpuId[0][0].Affinity) && (eax & 0x80000000) != 0)
{
// get the dist from tjMax from bits 22:16
float deltaT = (eax & 0x007F0000) >> 16;
@@ -513,7 +513,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
for (int i = 0; i < _coreClocks.Length; i++)
{
System.Threading.Thread.Sleep(1);
if (Ring0.ReadMsr(IA32_PERF_STATUS, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(IA32_PERF_STATUS, out uint eax, out uint _, _cpuId[i][0].Affinity))
{
newBusClock = TimeStampCounterFrequency / _timeStampCounterMultiplier;
switch (_microArchitecture)