diff --git a/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs b/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs index 132f6ac..b8d20bf 100644 --- a/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs @@ -93,10 +93,14 @@ namespace LibreHardwareMonitor.Hardware.CPU { private readonly Sensor _coreTemperatureTctl; private readonly Sensor _coreTemperatureTdie; + private readonly Sensor _coreTemperatureTctlTdie; + private readonly Sensor[] _ccdTemperatures; private readonly Sensor _coreVoltage; private readonly Amd17Cpu _hw; private readonly Sensor _packagePower; private readonly Sensor _socVoltage; + private Sensor _ccdsMaxTemperature; + private Sensor _ccdsAverageTemperature; private DateTime _lastPwrTime = new DateTime(0); private uint _lastPwrValue; @@ -108,20 +112,19 @@ namespace LibreHardwareMonitor.Hardware.CPU _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); + _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); _hw.ActivateSensor(_packagePower); - _hw.ActivateSensor(_coreTemperatureTctl); - _hw.ActivateSensor(_coreTemperatureTdie); - _hw.ActivateSensor(_coreVoltage); } public List Nodes { get; } public void UpdateSensors() { - var node = Nodes[0]; + NumaNode node = Nodes[0]; Core core = node?.Cores[0]; CpuId cpu = core?.Threads[0]; if (cpu == null) @@ -144,23 +147,49 @@ namespace LibreHardwareMonitor.Hardware.CPU // THM_TCON_CUR_TMP // CUR_TEMP [31:21] - Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP); - Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint temperature); + Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint temperature); // SVI0_TFN_PLANE0 [0] // SVI0_TFN_PLANE1 [1] - Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8); - Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0Tfn); + Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0Tfn); + + uint sviPlane0Offset; + uint sviPlane1Offset; + + // TODO: find a better way because these will probably keep changing in the future. + switch (cpu.Model) + { + case 0x31: // Threadripper 3000. + { + sviPlane0Offset = F17H_M01H_SVI + 0x14; + sviPlane1Offset = F17H_M01H_SVI + 0x10; + break; + } + case 0x71: // Zen 2. + { + sviPlane0Offset = F17H_M01H_SVI + 0x10; + sviPlane1Offset = F17H_M01H_SVI + 0xC; + break; + } + default: // Zen and Zen+. + { + sviPlane0Offset = F17H_M01H_SVI + 0xC; + sviPlane1Offset = F17H_M01H_SVI + 0x10; + break; + } + } // SVI0_PLANE0_VDDCOR [24:16] // SVI0_PLANE0_IDDCOR [7:0] - Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0xc); - Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane0); + Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane0Offset); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane0); // SVI0_PLANE1_VDDCOR [24:16] // SVI0_PLANE1_IDDCOR [7:0] - Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x10); - Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1); + Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1); Ring0.ThreadAffinitySet(mask); @@ -212,27 +241,92 @@ namespace LibreHardwareMonitor.Hardware.CPU if (tempOffsetFlag) t += -49.0f; - _coreTemperatureTctl.Value = t; - _coreTemperatureTdie.Value = t + offset; + if (offset < 0) + { + _coreTemperatureTctl.Value = t; + _coreTemperatureTdie.Value = t + offset; + + _hw.ActivateSensor(_coreTemperatureTctl); + _hw.ActivateSensor(_coreTemperatureTdie); + } + else + { + // Zen 2 doesn't have an offset so Tdie and Tctl are the same. + _coreTemperatureTctlTdie.Value = t; + _hw.ActivateSensor(_coreTemperatureTctlTdie); + } + + // Tested only on R5 3600 & Threadripper 3960X. + for (uint i = 0; i < _ccdTemperatures.Length; i++) + { + Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M70H_CCD1_TEMP + (i * 0x4)); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint ccdTempData); + + uint ccdTemp = ccdTempData & 0xFFF; + if (ccdTemp == 0) + continue; + + if (_ccdTemperatures[i] == null) + { + _hw.ActivateSensor(_ccdTemperatures[i] = new Sensor( + $"Core CCD{i + 1} (Tdie)", + _hw._sensorTemperatures++, + SensorType.Temperature, + _hw, + _hw._settings)); + } + + _ccdTemperatures[i].Value = ((ccdTemp * 125) - 305000) * 0.001f; + } + + Sensor[] activeCcds = _ccdTemperatures.Where(x => x != null).ToArray(); + if (activeCcds.Length > 1) + { + // No need to get the max / average ccds temp if there is only one CCD. + + if (_ccdsMaxTemperature == null) + { + _hw.ActivateSensor(_ccdsMaxTemperature = new Sensor( + "Core CCDs Max (Tdie)", + _hw._sensorTemperatures++, + SensorType.Temperature, + _hw, + _hw._settings)); + } + + if (_ccdsAverageTemperature == null) + { + _hw.ActivateSensor(_ccdsAverageTemperature = new Sensor( + "Core CCDs Average (Tdie)", + _hw._sensorTemperatures++, + SensorType.Temperature, + _hw, + _hw._settings)); + } + + _ccdsMaxTemperature.Value = activeCcds.Max(x => x.Value); + _ccdsAverageTemperature.Value = activeCcds.Average(x => x.Value); + } // voltage - double vidStep = 0.00625; + const double vidStep = 0.00625; double vcc; uint svi0PlaneXVddCor; - // Core + // Core (0x01). if ((smuSvi0Tfn & 0x01) == 0) { - svi0PlaneXVddCor = ((cpu.Model == 0x71 ? smuSvi0TelPlane1 : smuSvi0TelPlane0) >> 16) & 0xff; + svi0PlaneXVddCor = (smuSvi0TelPlane0 >> 16) & 0xff; vcc = 1.550 - vidStep * svi0PlaneXVddCor; _coreVoltage.Value = (float)vcc; + + _hw.ActivateSensor(_coreVoltage); } - // SoC - // not every zen cpu has this voltage - if (cpu.Model == 0x71 || (smuSvi0Tfn & 0x02) == 0) + // SoC (0x02), not every Zen cpu has this voltage. + if (cpu.Model == 0x71 || cpu.Model == 0x31 || (smuSvi0Tfn & 0x02) == 0) { - svi0PlaneXVddCor = ((cpu.Model == 0x71 ? smuSvi0TelPlane0 : smuSvi0TelPlane1) >> 16) & 0xff; + svi0PlaneXVddCor = (smuSvi0TelPlane1 >> 16) & 0xff; vcc = 1.550 - vidStep * svi0PlaneXVddCor; _socVoltage.Value = (float)vcc; @@ -243,7 +337,7 @@ namespace LibreHardwareMonitor.Hardware.CPU public void AppendThread(CpuId thread, int numaId, int coreId) { NumaNode node = null; - foreach (var n in Nodes) + foreach (NumaNode n in Nodes) { if (n.NodeId == numaId) { @@ -281,7 +375,7 @@ namespace LibreHardwareMonitor.Hardware.CPU public void AppendThread(CpuId thread, int coreId) { Core core = null; - foreach (var c in Cores) + foreach (Core c in Cores) { if (c.CoreId == coreId) core = c; @@ -420,6 +514,7 @@ namespace LibreHardwareMonitor.Hardware.CPU private const uint COFVID_STATUS = 0xC0010071; private const uint F17H_M01H_SVI = 0x0005A000; private const uint F17H_M01H_THM_TCON_CUR_TMP = 0x00059800; + private const uint F17H_M70H_CCD1_TEMP = 0x00059954; private const uint F17H_TEMP_OFFSET_FLAG = 0x80000; private const uint FAMILY_17H_PCI_CONTROL_REGISTER = 0x60; private const uint HWCR = 0xC0010015; diff --git a/LibreHardwareMonitorLib/Hardware/Sensor.cs b/LibreHardwareMonitorLib/Hardware/Sensor.cs index d2e75b5..86ec6e2 100644 --- a/LibreHardwareMonitorLib/Hardware/Sensor.cs +++ b/LibreHardwareMonitorLib/Hardware/Sensor.cs @@ -37,6 +37,7 @@ namespace LibreHardwareMonitor.Hardware IsDefaultHidden = defaultHidden; SensorType = sensorType; _hardware = hardware; + Parameter[] parameters = new Parameter[parameterDescriptions?.Length ?? 0]; for (int i = 0; i < parameters.Length; i++) { @@ -166,29 +167,30 @@ namespace LibreHardwareMonitor.Hardware private void SetSensorValuesToSettings() { - using (MemoryStream m = new MemoryStream()) + using (MemoryStream memoryStream = new MemoryStream()) { - using (GZipStream c = new GZipStream(m, CompressionMode.Compress)) + using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Compress)) { - using (BufferedStream b = new BufferedStream(c, 65536)) + using (BufferedStream outputStream = new BufferedStream(gZipStream, 65536)) { - using (BinaryWriter writer = new BinaryWriter(b)) + using (BinaryWriter binaryWriter = new BinaryWriter(outputStream)) { long t = 0; + foreach (SensorValue sensorValue in _values) { long v = sensorValue.Time.ToBinary(); - writer.Write(v - t); + binaryWriter.Write(v - t); t = v; - writer.Write(sensorValue.Value); + binaryWriter.Write(sensorValue.Value); } - writer.Flush(); + binaryWriter.Flush(); } } } - _settings.SetValue(new Identifier(Identifier, "values").ToString(), Convert.ToBase64String(m.ToArray())); + _settings.SetValue(new Identifier(Identifier, "values").ToString(), Convert.ToBase64String(memoryStream.ToArray())); } } @@ -203,20 +205,23 @@ namespace LibreHardwareMonitor.Hardware { byte[] array = Convert.FromBase64String(s); DateTime now = DateTime.UtcNow; - using (MemoryStream m = new MemoryStream(array)) - using (GZipStream c = new GZipStream(m, CompressionMode.Decompress)) + + using (MemoryStream memoryStream = new MemoryStream(array)) + { + using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) { - using (MemoryStream unzip = new MemoryStream()) + using (MemoryStream destination = new MemoryStream()) { - c.CopyTo(unzip); - unzip.Seek(0, SeekOrigin.Begin); - using (BinaryReader reader = new BinaryReader(unzip)) + gZipStream.CopyTo(destination); + destination.Seek(0, SeekOrigin.Begin); + + using (BinaryReader reader = new BinaryReader(destination)) { try { long t = 0; long readLen = reader.BaseStream.Length - reader.BaseStream.Position; - while (true && readLen > 0) + while (readLen > 0) { t += reader.ReadInt64(); DateTime time = DateTime.FromBinary(t); @@ -234,9 +239,12 @@ namespace LibreHardwareMonitor.Hardware } } } + } } catch - { } + { + // Ignored. + } } if (_values.Count > 0)