Skip to content

Commit 80e8de6

Browse files
committed
Merge remote-tracking branch 'libre/master' into dev
# Conflicts: # OpenHardwareMonitor/OpenHardwareMonitor.csproj # OpenHardwareMonitorLib/Hardware/Cpu/IntelCpu.cs # OpenHardwareMonitorLib/Hardware/Motherboard/Lpc/LpcIO.cs # OpenHardwareMonitorLib/OpenHardwareMonitorLib.csproj
2 parents b14fa19 + 8aff90c commit 80e8de6

15 files changed

Lines changed: 661 additions & 158 deletions

File tree

OpenHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs

Lines changed: 293 additions & 71 deletions
Large diffs are not rendered by default.

OpenHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ namespace OpenHardwareMonitor.Hardware.Cpu;
88

99
internal class CpuLoad
1010
{
11-
private readonly float[] _threadLoads;
11+
private static readonly bool _queryIdleTimeSeparated = QueryIdleTimeSeparated();
1212

13+
private readonly double[] _threadLoads;
14+
private double _totalLoad;
1315
private long[] _idleTimes;
14-
private float _totalLoad;
1516
private long[] _totalTimes;
1617

1718
public CpuLoad(CpuId[][] cpuid)
1819
{
19-
_threadLoads = new float[cpuid.Sum(x => x.Length)];
20+
_threadLoads = new double[cpuid.Sum(x => x.Length)];
2021
_totalLoad = 0;
2122

2223
try
@@ -45,30 +46,62 @@ private static bool GetWindowsTimes(out long[] idle, out long[] total)
4546
idle = null;
4647
total = null;
4748

48-
//Query processor idle information
49+
//use the idle time routine only with a few specific windows 11 versions
50+
if (_queryIdleTimeSeparated)
51+
return GetWindowsTimesFromIdleTimes(out idle, out total);
52+
53+
//Query processor performance information
54+
Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] perfInformation = new Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[64];
55+
int perfSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
56+
if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation, perfInformation, perfInformation.Length * perfSize, out int perfReturn) != 0)
57+
return false;
58+
59+
idle = new long[perfReturn / perfSize];
60+
total = new long[perfReturn / perfSize];
61+
for (int i = 0; i < total.Length; i++)
62+
{
63+
idle[i] = perfInformation[i].IdleTime;
64+
total[i] = perfInformation[i].KernelTime + perfInformation[i].UserTime;
65+
}
66+
67+
return true;
68+
}
69+
70+
private static bool GetWindowsTimesFromIdleTimes(out long[] idle, out long[] total)
71+
{
72+
idle = null;
73+
total = null;
74+
75+
Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] perfInformation = new Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[64];
76+
int perfSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
4977
Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION[] idleInformation = new Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION[64];
5078
int idleSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION));
79+
80+
//Query processor performance and idle information
81+
//these 2 methods must be called as directly as possible one after the other
82+
83+
//Query processor idle information
5184
if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorIdleInformation, idleInformation, idleInformation.Length * idleSize, out int idleReturn) != 0)
5285
return false;
5386

5487
//Query processor performance information
55-
Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] perfInformation = new Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[64];
56-
int perfSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
57-
if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation,
58-
perfInformation,
59-
perfInformation.Length * perfSize,
60-
out int perfReturn) != 0)
61-
{
88+
if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation, perfInformation, perfInformation.Length * perfSize, out int perfReturn) != 0)
6289
return false;
63-
}
6490

65-
idle = new long[idleReturn / idleSize];
66-
for (int i = 0; i < idle.Length; i++)
67-
idle[i] = idleInformation[i].IdleTime;
91+
int perfItemsCount = perfReturn / perfSize;
92+
int idleItemsCount = idleReturn / idleSize;
6893

69-
total = new long[perfReturn / perfSize];
70-
for (int i = 0; i < total.Length; i++)
94+
if (perfItemsCount != idleItemsCount)
95+
return false;
96+
97+
idle = new long[perfItemsCount];
98+
total = new long[perfItemsCount];
99+
100+
for (int i = 0; i < perfItemsCount; i++)
101+
{
102+
idle[i] = idleInformation[i].IdleTime;
71103
total[i] = perfInformation[i].KernelTime + perfInformation[i].UserTime;
104+
}
72105

73106
return true;
74107
}
@@ -126,12 +159,12 @@ private static bool GetUnixTimes(out long[] idle, out long[] total)
126159
return true;
127160
}
128161

129-
public float GetTotalLoad()
162+
public double GetTotalLoad()
130163
{
131164
return _totalLoad;
132165
}
133166

134-
public float GetThreadLoad(int thread)
167+
public double GetThreadLoad(int thread)
135168
{
136169
return _threadLoads[thread];
137170
}
@@ -151,28 +184,45 @@ public void Update()
151184
if (newIdleTimes == null)
152185
return;
153186

154-
float total = 0;
187+
double total = 0;
155188
int count = 0;
156189
for (int i = 0; i < _threadLoads.Length && i < _idleTimes.Length && i < newIdleTimes.Length; i++)
157190
{
158-
float idle = (newIdleTimes[i] - _idleTimes[i]) / (float)(newTotalTimes[i] - _totalTimes[i]);
159-
_threadLoads[i] = 100f * (1.0f - Math.Min(idle, 1.0f));
191+
double idle = (newIdleTimes[i] - _idleTimes[i]) / (double)(newTotalTimes[i] - _totalTimes[i]);
192+
idle = idle < 0.0 ? 0.0 : idle;
193+
idle = idle > 1.0 ? 1.0 : idle;
194+
195+
double load = 100.0 * (1.0 - Math.Min(idle, 1.0));
196+
_threadLoads[i] = Math.Round(load, 2);
160197
total += idle;
161198
count++;
162199
}
163200

164201
if (count > 0)
165202
{
166-
total = 1.0f - (total / count);
167-
total = total < 0 ? 0 : total;
203+
total = 1.0 - (total / count);
204+
total = total < 0.0 ? 0.0 : total;
205+
total = total > 1.0 ? 1.0 : total;
168206
}
169207
else
170208
{
171209
total = 0;
172210
}
173-
174-
_totalLoad = total * 100;
211+
212+
_totalLoad = Math.Round(total * 100.0, 2);
175213
_totalTimes = newTotalTimes;
176214
_idleTimes = newIdleTimes;
177215
}
216+
217+
private static bool QueryIdleTimeSeparated()
218+
{
219+
if (Software.OperatingSystem.IsUnix)
220+
return false;
221+
222+
// From Windows 11 22H2 the CPU idle time returned by SystemProcessorPerformanceInformation is invalid, this issue has been fixed with 24H2.
223+
OperatingSystem os = Environment.OSVersion;
224+
Version win1122H2 = new Version(10, 0, 22621, 0);
225+
Version win1124H2 = new Version(10, 0, 26100, 0);
226+
return os.Version >= win1122H2 && os.Version < win1124H2;
227+
}
178228
}

OpenHardwareMonitorLib/Hardware/Cpu/GenericCpu.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,14 +299,14 @@ public override void Update()
299299
{
300300
if (_threadLoads[i] != null)
301301
{
302-
_threadLoads[i].Value = _cpuLoad.GetThreadLoad(i);
302+
_threadLoads[i].Value = (float)_cpuLoad.GetThreadLoad(i);
303303
maxLoad = Math.Max(maxLoad, _threadLoads[i].Value ?? 0);
304304
}
305305
}
306306
}
307307

308308
if (_totalLoad != null)
309-
_totalLoad.Value = _cpuLoad.GetTotalLoad();
309+
_totalLoad.Value = (float)_cpuLoad.GetTotalLoad();
310310

311311
if (_maxLoad != null)
312312
_maxLoad.Value = maxLoad;

OpenHardwareMonitorLib/Hardware/Cpu/IntelCpu.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ public IntelCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(
216216
tjMax = GetTjMaxFromMsr();
217217
break;
218218

219+
case 0xC5: // Intel Core Ultra 9 200 Series ArrowLake
219220
case 0xC6: // Intel Core Ultra 7 200 Series ArrowLake
220221
_microArchitecture = MicroArchitecture.ArrowLake;
221222
tjMax = GetTjMaxFromMsr();
@@ -225,6 +226,14 @@ public IntelCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(
225226
_microArchitecture = MicroArchitecture.LunarLake;
226227
tjMax = GetTjMaxFromMsr();
227228
break;
229+
case 0x8F: // Intel Xeon W5-3435X // SapphireRapids
230+
_microArchitecture = MicroArchitecture.SapphireRapids;
231+
tjMax = GetTjMaxFromMsr();
232+
break;
233+
case 0x96: // Intel Celeron ElkhartLake
234+
_microArchitecture = MicroArchitecture.ElkhartLake;
235+
tjMax = GetTjMaxFromMsr();
236+
break;
228237

229238
default:
230239
_microArchitecture = MicroArchitecture.Unknown;
@@ -292,6 +301,8 @@ public IntelCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(
292301
case MicroArchitecture.Silvermont:
293302
case MicroArchitecture.Skylake:
294303
case MicroArchitecture.TigerLake:
304+
case MicroArchitecture.SapphireRapids:
305+
case MicroArchitecture.ElkhartLake:
295306
case MicroArchitecture.Tremont:
296307
if (Ring0.ReadMsr(MSR_PLATFORM_INFO, out eax, out uint _))
297308
_timeStampCounterMultiplier = (eax >> 8) & 0xff;
@@ -408,6 +419,8 @@ MicroArchitecture.SandyBridge or
408419
MicroArchitecture.Silvermont or
409420
MicroArchitecture.Skylake or
410421
MicroArchitecture.TigerLake or
422+
MicroArchitecture.SapphireRapids or
423+
MicroArchitecture.ElkhartLake or
411424
MicroArchitecture.Tremont)
412425
{
413426
_powerSensors = new Sensor[_energyStatusMsrs.Length];
@@ -612,6 +625,8 @@ public override void Update()
612625
case MicroArchitecture.Silvermont:
613626
case MicroArchitecture.Skylake:
614627
case MicroArchitecture.TigerLake:
628+
case MicroArchitecture.SapphireRapids:
629+
case MicroArchitecture.ElkhartLake:
615630
case MicroArchitecture.Tremont:
616631
_coreClocks[i].Value = (float)(((eax >> 8) & 0xff) * newBusClock);
617632
break;
@@ -704,6 +719,8 @@ private enum MicroArchitecture
704719
TigerLake,
705720
Tremont,
706721
RaptorLake,
722+
SapphireRapids,
723+
ElkhartLake,
707724
Unknown
708725
}
709726

OpenHardwareMonitorLib/Hardware/Motherboard/Identification.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,8 @@ public static Model GetModel(string name)
548548
return Model.ROG_STRIX_X670E_E_GAMING_WIFI;
549549
case var _ when name.Equals("ROG STRIX X670E-F GAMING WIFI", StringComparison.OrdinalIgnoreCase):
550550
return Model.ROG_STRIX_X670E_F_GAMING_WIFI;
551+
case var _ when name.Equals("ROG STRIX X870E-E GAMING WIFI", StringComparison.OrdinalIgnoreCase):
552+
return Model.ROG_STRIX_X870E_E_GAMING_WIFI;
551553
case var _ when name.Equals("B660GTN", StringComparison.OrdinalIgnoreCase):
552554
return Model.B660GTN;
553555
case var _ when name.Equals("X670E VALKYRIE", StringComparison.OrdinalIgnoreCase):
@@ -601,6 +603,14 @@ public static Model GetModel(string name)
601603
return Model.X870E_AORUS_PRO;
602604
case var _ when name.Equals("X870E AORUS PRO ICE", StringComparison.OrdinalIgnoreCase):
603605
return Model.X870E_AORUS_PRO_ICE;
606+
case var _ when name.Equals("PROART X870E-CREATOR WIFI", StringComparison.OrdinalIgnoreCase):
607+
return Model.PROART_X870E_CREATOR_WIFI;
608+
case var _ when name.Equals("PRIME X870-P", StringComparison.OrdinalIgnoreCase):
609+
return Model.PRIME_X870_P;
610+
case var _ when name.Equals("ROG CROSSHAIR X870E HERO", StringComparison.OrdinalIgnoreCase):
611+
return Model.ROG_CROSSHAIR_X870E_HERO;
612+
case var _ when name.Equals("X11SWN-E", StringComparison.OrdinalIgnoreCase):
613+
return Model.X11SWN_E;
604614
case var _ when name.Equals("Base Board Product Name", StringComparison.OrdinalIgnoreCase):
605615
case var _ when name.Equals("To be filled by O.E.M.", StringComparison.OrdinalIgnoreCase):
606616
return Model.Unknown;

OpenHardwareMonitorLib/Hardware/Motherboard/Lpc/Chip.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ internal enum Chip : ushort
6363
NCT6687D = 0xD592,
6464
NCT6683D = 0xC732,
6565
NCT6799D = 0xD802,
66+
NCT6701D = 0xD806,
6667

6768
W83627DHG = 0xA020,
6869
W83627DHGP = 0xB070,
@@ -136,6 +137,7 @@ public static string GetName(Chip chip)
136137
case Chip.NCT6686D: return "Nuvoton NCT6686D";
137138
case Chip.NCT6687D: return "Nuvoton NCT6687D";
138139
case Chip.NCT6683D: return "Nuvoton NCT6683D";
140+
case Chip.NCT6701D: return "Nuvoton NCT6701D";
139141

140142
case Chip.W83627DHG: return "Winbond W83627DHG";
141143
case Chip.W83627DHGP: return "Winbond W83627DHG-P";

OpenHardwareMonitorLib/Hardware/Motherboard/Lpc/IT87XX.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Globalization;
33
using System.Linq;
44
using System.Text;
5-
using System.Threading;
65

76
// ReSharper disable once InconsistentNaming
87

@@ -161,7 +160,7 @@ Chip.IT8631E or
161160
break;
162161

163162
case Chip.IT87952E:
164-
Voltages = new float?[10];
163+
Voltages = new float?[9];
165164
Temperatures = new float?[3];
166165
Fans = new float?[3];
167166
Controls = new float?[3];
@@ -188,7 +187,7 @@ Chip.IT8631E or
188187
Fans = new float?[3];
189188
Controls = new float?[3];
190189
break;
191-
190+
192191
case Chip.IT8620E:
193192
Voltages = new float?[9];
194193
Temperatures = new float?[3];
@@ -422,7 +421,7 @@ public void Update()
422421

423422
for (int i = 0; i < Voltages.Length; i++)
424423
{
425-
float value = _voltageGain * ReadByte((byte)(VOLTAGE_BASE_REG + i), out bool valid);
424+
float value = _voltageGain * ReadByte(IT87_REG_VIN[i], out bool valid);
426425

427426
if (!valid)
428427
continue;
@@ -596,7 +595,9 @@ private void RestoreDefaultFanPwmControl(int index)
596595

597596
private const byte TEMPERATURE_BASE_REG = 0x29;
598597
private const byte VENDOR_ID_REGISTER = 0x58;
599-
private const byte VOLTAGE_BASE_REG = 0x20;
598+
599+
// https://github.com/torvalds/linux/blob/master/drivers/hwmon/it87.c
600+
private readonly byte[] IT87_REG_VIN = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x2f, 0x2c, 0x2d, 0x2e };
600601

601602
private readonly byte[] FAN_PWM_CTRL_REG;
602603
private readonly byte[] FAN_PWM_CTRL_EXT_REG = { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab };

OpenHardwareMonitorLib/Hardware/Motherboard/Lpc/LpcIO.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,10 @@ private bool DetectWinbondFintek(LpcPort port)
397397
chip = Chip.NCT6799D;
398398
logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
399399
break;
400+
case 0x06:
401+
chip = Chip.NCT6701D;
402+
logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
403+
break;
400404
}
401405

402406
break;
@@ -487,6 +491,7 @@ private bool DetectWinbondFintek(LpcPort port)
487491
case Chip.NCT6686D:
488492
case Chip.NCT6687D:
489493
case Chip.NCT6683D:
494+
case Chip.NCT6701D:
490495
_superIOs.Add(new Nct677X(chip, revision, address, port));
491496
break;
492497

@@ -538,7 +543,7 @@ private bool DetectIT87(LpcPort port, Motherboard motherboard)
538543
port.IT87Enter();
539544
chipId = port.ReadWord(CHIP_ID_REGISTER);
540545
}
541-
546+
542547
Chip chip = chipId switch
543548
{
544549
0x8613 => Chip.IT8613E,

0 commit comments

Comments
 (0)