From b118b7a2f1a299c8a527c71c4e31d1307331e505 Mon Sep 17 00:00:00 2001 From: Phyxion <7643972+Phyxion@users.noreply.github.com> Date: Mon, 25 May 2020 12:04:28 +0200 Subject: [PATCH] Add support for Global\\Access_PCI mutex Based on the work of @moellerm --- .../Hardware/Cpu/Amd0FCpu.cs | 30 +- .../Hardware/Cpu/Amd10Cpu.cs | 77 +++-- .../Hardware/Cpu/Amd17Cpu.cs | 321 ++++++++++-------- LibreHardwareMonitorLib/Hardware/Ring0.cs | 67 +++- 4 files changed, 307 insertions(+), 188 deletions(-) diff --git a/LibreHardwareMonitorLib/Hardware/Cpu/Amd0FCpu.cs b/LibreHardwareMonitorLib/Hardware/Cpu/Amd0FCpu.cs index 7eb67c4..718f6af 100644 --- a/LibreHardwareMonitorLib/Hardware/Cpu/Amd0FCpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Cpu/Amd0FCpu.cs @@ -92,26 +92,34 @@ namespace LibreHardwareMonitor.Hardware.CPU public override void Update() { base.Update(); - - if (_miscellaneousControlAddress != Interop.Ring0.INVALID_PCI_ADDRESS) + + if (Ring0.WaitPciBusMutex(10)) { - for (uint i = 0; i < _coreTemperatures.Length; i++) + if (_miscellaneousControlAddress != Interop.Ring0.INVALID_PCI_ADDRESS) { - if (Ring0.WritePciConfig(_miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, i > 0 ? _thermSenseCoreSelCPU1 : _thermSenseCoreSelCPU0)) + for (uint i = 0; i < _coreTemperatures.Length; i++) { - if (Ring0.ReadPciConfig(_miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, out uint value)) + if (Ring0.WritePciConfig(_miscellaneousControlAddress, + THERMTRIP_STATUS_REGISTER, + i > 0 ? _thermSenseCoreSelCPU1 : _thermSenseCoreSelCPU0)) { - _coreTemperatures[i].Value = ((value >> 16) & 0xFF) + _coreTemperatures[i].Parameters[0].Value; - ActivateSensor(_coreTemperatures[i]); - } - else - { - DeactivateSensor(_coreTemperatures[i]); + if (Ring0.ReadPciConfig(_miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, out uint value)) + { + _coreTemperatures[i].Value = ((value >> 16) & 0xFF) + _coreTemperatures[i].Parameters[0].Value; + ActivateSensor(_coreTemperatures[i]); + } + else + { + DeactivateSensor(_coreTemperatures[i]); + } } } } + + Ring0.ReleasePciBusMutex(); } + if (HasTimeStampCounter) { double newBusClock = 0; diff --git a/LibreHardwareMonitorLib/Hardware/Cpu/Amd10Cpu.cs b/LibreHardwareMonitorLib/Hardware/Cpu/Amd10Cpu.cs index c82495d..5d847b5 100644 --- a/LibreHardwareMonitorLib/Hardware/Cpu/Amd10Cpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Cpu/Amd10Cpu.cs @@ -22,13 +22,14 @@ namespace LibreHardwareMonitor.Hardware.CPU private readonly Sensor _coreVoltage; private readonly byte _cStatesIoOffset; private readonly Sensor[] _cStatesResidency; - private readonly bool _isSVI2; - + private readonly bool _isSvi2; + private readonly bool _hasSmuTemperatureRegister; private readonly uint _miscellaneousControlAddress; private readonly Sensor _northbridgeVoltage; private readonly FileStream _temperatureStream; private readonly double _timeStampCounterMultiplier; + public Amd10Cpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(processorIndex, cpuId, settings) { // AMD family 1Xh processors support only one temperature sensor @@ -38,7 +39,8 @@ namespace LibreHardwareMonitor.Hardware.CPU ActivateSensor(_coreVoltage); _northbridgeVoltage = new Sensor("Northbridge", 0, SensorType.Voltage, this, settings); ActivateSensor(_northbridgeVoltage); - _isSVI2 = (_family == 0x15 && _model >= 0x10) || _family == 0x16; + + _isSvi2 = (_family == 0x15 && _model >= 0x10) || _family == 0x16; switch (_family) { @@ -82,9 +84,15 @@ namespace LibreHardwareMonitor.Hardware.CPU break; } case 0x70: - case 0x60: + { + miscellaneousControlDeviceId = FAMILY_15H_MODEL_70_MISC_CONTROL_DEVICE_ID; + _hasSmuTemperatureRegister = true; + break; + } + case 0x60: { miscellaneousControlDeviceId = FAMILY_15H_MODEL_60_MISC_CONTROL_DEVICE_ID; + _hasSmuTemperatureRegister = true; break; } default: @@ -394,34 +402,34 @@ namespace LibreHardwareMonitor.Hardware.CPU { if (_miscellaneousControlAddress != Interop.Ring0.INVALID_PCI_ADDRESS) { - uint value; - if (_miscellaneousControlAddress == FAMILY_15H_MODEL_60_MISC_CONTROL_DEVICE_ID) - { - Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), 0xB8, F15H_M60H_REPORTED_TEMP_CTRL_OFFSET); - Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), 0xBC, out value); - } - else - { - Ring0.ReadPciConfig(_miscellaneousControlAddress, REPORTED_TEMPERATURE_CONTROL_REGISTER, out value); - } + bool isValueValid = _hasSmuTemperatureRegister + ? ReadSmuRegister(SMU_REPORTED_TEMP_CTRL_OFFSET, out uint value) + : Ring0.ReadPciConfig(_miscellaneousControlAddress, REPORTED_TEMPERATURE_CONTROL_REGISTER, out value); - if ((_family == 0x15 || _family == 0x16) && (value & 0x30000) == 0x3000) + if (isValueValid) { - if (_family == 0x15 && (_model & 0xF0) == 0x00) + if ((_family == 0x15 || _family == 0x16) && (value & 0x30000) == 0x3000) { - _coreTemperature.Value = ((value >> 21) & 0x7FC) / 8.0f + _coreTemperature.Parameters[0].Value - 49; + if (_family == 0x15 && (_model & 0xF0) == 0x00) + { + _coreTemperature.Value = ((value >> 21) & 0x7FC) / 8.0f + _coreTemperature.Parameters[0].Value - 49; + } + else + { + _coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f + _coreTemperature.Parameters[0].Value - 49; + } } else { - _coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f + _coreTemperature.Parameters[0].Value - 49; + _coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f + _coreTemperature.Parameters[0].Value; } + + ActivateSensor(_coreTemperature); } else { - _coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f + _coreTemperature.Parameters[0].Value; + DeactivateSensor(_coreTemperature); } - - ActivateSensor(_coreTemperature); } else { @@ -468,7 +476,7 @@ namespace LibreHardwareMonitor.Hardware.CPU float newCoreVoltage, newNbVoltage; uint coreVid60 = (curEax >> 9) & 0x7F; - if (_isSVI2) + if (_isSvi2) { newCoreVoltage = SVI2Volt(curEax >> 13 & 0x80 | coreVid60); newNbVoltage = SVI2Volt(curEax >> 24); @@ -506,6 +514,28 @@ namespace LibreHardwareMonitor.Hardware.CPU } } + private bool ReadSmuRegister(uint address, out uint value) + { + if (Ring0.WaitPciBusMutex(10)) + { + if (!Ring0.WritePciConfig(0, 0xB8, address)) + { + value = 0; + + Ring0.ReleasePciBusMutex(); + return false; + } + + bool result = Ring0.ReadPciConfig(0, 0xBC, out value); + + Ring0.ReleasePciBusMutex(); + return result; + } + + value = 0; + return false; + } + public override void Close() { _temperatureStream?.Close(); @@ -516,7 +546,7 @@ namespace LibreHardwareMonitor.Hardware.CPU private const uint CLOCK_POWER_TIMING_CONTROL_0_REGISTER = 0xD4; private const uint COFVID_STATUS = 0xC0010071; private const uint CSTATES_IO_PORT = 0xCD6; - private const uint F15H_M60H_REPORTED_TEMP_CTRL_OFFSET = 0xD8200CA4; + private const uint SMU_REPORTED_TEMP_CTRL_OFFSET = 0xD8200CA4; private const uint HWCR = 0xC0010015; private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3; private const uint P_STATE_0 = 0xC0010064; @@ -532,6 +562,7 @@ namespace LibreHardwareMonitor.Hardware.CPU private const ushort FAMILY_15H_MODEL_10_MISC_CONTROL_DEVICE_ID = 0x1403; private const ushort FAMILY_15H_MODEL_30_MISC_CONTROL_DEVICE_ID = 0x141D; private const ushort FAMILY_15H_MODEL_60_MISC_CONTROL_DEVICE_ID = 0x1573; + private const ushort FAMILY_15H_MODEL_70_MISC_CONTROL_DEVICE_ID = 0x15B3; private const ushort FAMILY_16H_MODEL_00_MISC_CONTROL_DEVICE_ID = 0x1533; private const ushort FAMILY_16H_MODEL_30_MISC_CONTROL_DEVICE_ID = 0x1583; private const ushort FAMILY_17H_MODEL_00_MISC_CONTROL_DEVICE_ID = 0x1577; diff --git a/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs b/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs index de3d6f1..74c27f1 100644 --- a/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Cpu/Amd17Cpu.cs @@ -91,18 +91,19 @@ namespace LibreHardwareMonitor.Hardware.CPU private class Processor { - private readonly Sensor _coreTemperatureTctl; - private readonly Sensor _coreTemperatureTdie; - private readonly Sensor _coreTemperatureTctlTdie; private readonly Sensor[] _ccdTemperatures; + private readonly Sensor _coreTemperatureTctl; + private readonly Sensor _coreTemperatureTctlTdie; + private readonly Sensor _coreTemperatureTdie; private readonly Sensor _coreVoltage; private readonly Amd17Cpu _hardware; private readonly Sensor _packagePower; private readonly Sensor _socVoltage; - private Sensor _ccdsMaxTemperature; private Sensor _ccdsAverageTemperature; + private Sensor _ccdsMaxTemperature; private DateTime _lastPwrTime = new DateTime(0); private uint _lastPwrValue; + private Sensor _busClock; public Processor(Hardware hardware) { @@ -116,7 +117,8 @@ namespace LibreHardwareMonitor.Hardware.CPU _ccdTemperatures = new Sensor[8]; // Hardcoded until there's a way to get max CCDs. _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); - + _busClock = new Sensor("Bus Speed", 0, SensorType.Clock, _hardware, _hardware._settings); + _hardware.ActivateSensor(_packagePower); } @@ -143,177 +145,186 @@ namespace LibreHardwareMonitor.Hardware.CPU // total_energy [31:0] DateTime sampleTime = DateTime.Now; Ring0.ReadMsr(MSR_PKG_ENERGY_STAT, out uint eax, out _); + uint totalEnergy = eax; - // THM_TCON_CUR_TMP - // CUR_TEMP [31:21] - 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); + uint smuSvi0Tfn = 0; + uint smuSvi0TelPlane0 = 0; + uint smuSvi0TelPlane1 = 0; - // SVI0_TFN_PLANE0 [0] - // SVI0_TFN_PLANE1 [1] - 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; - - bool isZen2 = false; - - // TODO: find a better way because these will probably keep changing in the future. - switch (cpu.Model) + if (Ring0.WaitPciBusMutex(10)) { - case 0x31: // Threadripper 3000. + // THM_TCON_CUR_TMP + // CUR_TEMP [31:21] + 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(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0Tfn); + + bool isZen2 = false; + + // TODO: find a better way because these will probably keep changing in the future. + + uint sviPlane0Offset; + uint sviPlane1Offset; + switch (cpu.Model) { - sviPlane0Offset = F17H_M01H_SVI + 0x14; - sviPlane1Offset = F17H_M01H_SVI + 0x10; - isZen2 = true; - break; + case 0x31: // Threadripper 3000. + { + sviPlane0Offset = F17H_M01H_SVI + 0x14; + sviPlane1Offset = F17H_M01H_SVI + 0x10; + isZen2 = true; + break; + } + case 0x71: // Zen 2. + { + sviPlane0Offset = F17H_M01H_SVI + 0x10; + sviPlane1Offset = F17H_M01H_SVI + 0xC; + isZen2 = true; + break; + } + default: // Zen and Zen+. + { + sviPlane0Offset = F17H_M01H_SVI + 0xC; + sviPlane1Offset = F17H_M01H_SVI + 0x10; + break; + } } - case 0x71: // Zen 2. + + // SVI0_PLANE0_VDDCOR [24:16] + // SVI0_PLANE0_IDDCOR [7:0] + Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane0Offset); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0TelPlane0); + + // SVI0_PLANE1_VDDCOR [24:16] + // SVI0_PLANE1_IDDCOR [7:0] + Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset); + Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0TelPlane1); + + ThreadAffinity.Set(previousAffinity); + + // power consumption + // power.Value = (float) ((double)pu * 0.125); + // esu = 15.3 micro Joule per increment + if (_lastPwrTime.Ticks == 0) { - sviPlane0Offset = F17H_M01H_SVI + 0x10; - sviPlane1Offset = F17H_M01H_SVI + 0xC; - isZen2 = true; - break; + _lastPwrTime = sampleTime; + _lastPwrValue = totalEnergy; } - 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(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane0Offset); - Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane0); + // ticks diff + TimeSpan time = sampleTime - _lastPwrTime; + long pwr; + if (_lastPwrValue <= totalEnergy) + pwr = totalEnergy - _lastPwrValue; + else + pwr = (0xffffffff - _lastPwrValue) + totalEnergy; - // SVI0_PLANE1_VDDCOR [24:16] - // SVI0_PLANE1_IDDCOR [7:0] - Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset); - Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1); - - ThreadAffinity.Set(previousAffinity); - - // power consumption - // power.Value = (float) ((double)pu * 0.125); - // esu = 15.3 micro Joule per increment - if (_lastPwrTime.Ticks == 0) - { + // update for next sample _lastPwrTime = sampleTime; _lastPwrValue = totalEnergy; - } - // ticks diff - TimeSpan time = sampleTime - _lastPwrTime; - long pwr; - if (_lastPwrValue <= totalEnergy) - pwr = totalEnergy - _lastPwrValue; - else - pwr = (0xffffffff - _lastPwrValue) + totalEnergy; + double energy = 15.3e-6 * pwr; + energy /= time.TotalSeconds; - // update for next sample - _lastPwrTime = sampleTime; - _lastPwrValue = totalEnergy; + if (!double.IsNaN(energy)) + _packagePower.Value = (float)energy; - double energy = 15.3e-6 * pwr; - energy /= time.TotalSeconds; + // current temp Bit [31:21] + // If bit 19 of the Temperature Control register is set, there is an additional offset of 49 degrees C. + bool tempOffsetFlag = (temperature & F17H_TEMP_OFFSET_FLAG) != 0; + temperature = (temperature >> 21) * 125; - if (!double.IsNaN(energy)) - _packagePower.Value = (float)energy; + float offset = 0.0f; - // current temp Bit [31:21] - //If bit 19 of the Temperature Control register is set, there is an additional offset of 49 degrees C. - bool tempOffsetFlag = (temperature & F17H_TEMP_OFFSET_FLAG) != 0; - temperature = (temperature >> 21) * 125; + // Offset table: https://github.com/torvalds/linux/blob/master/drivers/hwmon/k10temp.c#L78 + if (string.IsNullOrWhiteSpace(cpu.Name)) + offset = 0; + else if (cpu.Name.Contains("1600X") || cpu.Name.Contains("1700X") || cpu.Name.Contains("1800X")) + offset = -20.0f; + else if (cpu.Name.Contains("Threadripper 19") || cpu.Name.Contains("Threadripper 29")) + offset = -27.0f; + else if (cpu.Name.Contains("2700X")) + offset = -10.0f; - float offset = 0.0f; + float t = temperature * 0.001f; + if (tempOffsetFlag) + t += -49.0f; - // Offset table: https://github.com/torvalds/linux/blob/master/drivers/hwmon/k10temp.c#L78 - if (string.IsNullOrWhiteSpace(cpu.Name)) - offset = 0; - else if (cpu.Name.Contains("1600X") || cpu.Name.Contains("1700X") || cpu.Name.Contains("1800X")) - offset = -20.0f; - else if (cpu.Name.Contains("Threadripper 19") || cpu.Name.Contains("Threadripper 29")) - offset = -27.0f; - else if (cpu.Name.Contains("2700X")) - offset = -10.0f; - - float t = temperature * 0.001f; - if (tempOffsetFlag) - t += -49.0f; - - if (offset < 0) - { - _coreTemperatureTctl.Value = t; - _coreTemperatureTdie.Value = t + offset; - - _hardware.ActivateSensor(_coreTemperatureTctl); - _hardware.ActivateSensor(_coreTemperatureTdie); - } - else - { - // Zen 2 doesn't have an offset so Tdie and Tctl are the same. - _coreTemperatureTctlTdie.Value = t; - _hardware.ActivateSensor(_coreTemperatureTctlTdie); - } - - // Tested only on R5 3600 & Threadripper 3960X. - if (isZen2) - { - for (uint i = 0; i < _ccdTemperatures.Length; i++) + if (offset < 0) { - 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 ccdRawTemp); + _coreTemperatureTctl.Value = t; + _coreTemperatureTdie.Value = t + offset; - ccdRawTemp &= 0xFFF; - if (ccdRawTemp == 0) - break; - - - float ccdTemp = ((ccdRawTemp * 125) - 305000) * 0.001f; - if (ccdTemp > 125) // Zen 2 reports 95 degrees C max, but it might exceed that. - break; - - if (_ccdTemperatures[i] == null) - { - _hardware.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)", - _hardware._sensorTemperatures++, - SensorType.Temperature, - _hardware, - _hardware._settings)); - } - - _ccdTemperatures[i].Value = ccdTemp; + _hardware.ActivateSensor(_coreTemperatureTctl); + _hardware.ActivateSensor(_coreTemperatureTdie); + } + else + { + // Zen 2 doesn't have an offset so Tdie and Tctl are the same. + _coreTemperatureTctlTdie.Value = t; + _hardware.ActivateSensor(_coreTemperatureTctlTdie); } - Sensor[] activeCcds = _ccdTemperatures.Where(x => x != null).ToArray(); - if (activeCcds.Length > 1) + // Tested only on R5 3600 & Threadripper 3960X. + if (isZen2) { - // No need to get the max / average ccds temp if there is only one CCD. - - if (_ccdsMaxTemperature == null) + for (uint i = 0; i < _ccdTemperatures.Length; i++) { - _hardware.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)", - _hardware._sensorTemperatures++, - SensorType.Temperature, - _hardware, - _hardware._settings)); + 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 ccdRawTemp); + + ccdRawTemp &= 0xFFF; + if (ccdRawTemp == 0) + break; + + + float ccdTemp = ((ccdRawTemp * 125) - 305000) * 0.001f; + if (ccdTemp > 125) // Zen 2 reports 95 degrees C max, but it might exceed that. + break; + + + if (_ccdTemperatures[i] == null) + { + _hardware.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)", + _hardware._sensorTemperatures++, + SensorType.Temperature, + _hardware, + _hardware._settings)); + } + + _ccdTemperatures[i].Value = ccdTemp; } - if (_ccdsAverageTemperature == null) + Sensor[] activeCcds = _ccdTemperatures.Where(x => x != null).ToArray(); + if (activeCcds.Length > 1) { - _hardware.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)", - _hardware._sensorTemperatures++, - SensorType.Temperature, - _hardware, - _hardware._settings)); - } + // No need to get the max / average ccds temp if there is only one CCD. - _ccdsMaxTemperature.Value = activeCcds.Max(x => x.Value); - _ccdsAverageTemperature.Value = activeCcds.Average(x => x.Value); + if (_ccdsMaxTemperature == null) + { + _hardware.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)", + _hardware._sensorTemperatures++, + SensorType.Temperature, + _hardware, + _hardware._settings)); + } + + if (_ccdsAverageTemperature == null) + { + _hardware.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)", + _hardware._sensorTemperatures++, + SensorType.Temperature, + _hardware, + _hardware._settings)); + } + + _ccdsMaxTemperature.Value = activeCcds.Max(x => x.Value); + _ccdsAverageTemperature.Value = activeCcds.Average(x => x.Value); + } } } @@ -341,6 +352,21 @@ namespace LibreHardwareMonitor.Hardware.CPU _hardware.ActivateSensor(_socVoltage); } + + double timeStampCounterMultiplier = GetTimeStampCounterMultiplier(); + if (timeStampCounterMultiplier > 0) + { + _busClock.Value = (float)(_hardware.TimeStampCounterFrequency / timeStampCounterMultiplier); + _hardware.ActivateSensor(_busClock); + } + } + + private double GetTimeStampCounterMultiplier() + { + Ring0.ReadMsr(MSR_PSTATE_0, out uint eax, out _); + uint cpuDfsId = (eax >> 8) & 0x3f; + uint cpuFid = eax & 0xff; + return 2.0 * cpuFid / cpuDfsId; } public void AppendThread(CpuId thread, int numaId, int coreId) @@ -533,6 +559,7 @@ namespace LibreHardwareMonitor.Hardware.CPU private const uint MSR_PSTATE_0 = 0xC0010064; private const uint MSR_PWR_UNIT = 0xC0010299; private const uint PERF_CTL_0 = 0xC0010000; + private const uint PERF_CTR_0 = 0xC0010004; // ReSharper restore InconsistentNaming } diff --git a/LibreHardwareMonitorLib/Hardware/Ring0.cs b/LibreHardwareMonitorLib/Hardware/Ring0.cs index e620973..01952b6 100644 --- a/LibreHardwareMonitorLib/Hardware/Ring0.cs +++ b/LibreHardwareMonitorLib/Hardware/Ring0.cs @@ -22,9 +22,10 @@ namespace LibreHardwareMonitor.Hardware private static KernelDriver _driver; private static string _fileName; private static Mutex _isaBusMutex; + private static Mutex _pciBusMutex; private static readonly StringBuilder _report = new StringBuilder(); - + public static bool IsOpen { get { return _driver != null; } @@ -217,18 +218,19 @@ namespace LibreHardwareMonitor.Hardware if (!_driver.IsOpen) _driver = null; - string mutexName = "Global\\Access_ISABUS.HTP.Method"; + const string isaMutexName = "Global\\Access_ISABUS.HTP.Method"; + try { #if NETSTANDARD2_0 - _isaBusMutex = new Mutex(false, mutexName); + _isaBusMutex = new Mutex(false, isaMutexName); #else //mutex permissions set to everyone to allow other software to access the hardware //otherwise other monitoring software cant access var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); var securitySettings = new MutexSecurity(); securitySettings.AddAccessRule(allowEveryoneRule); - _isaBusMutex = new Mutex(false, mutexName, out _, securitySettings); + _isaBusMutex = new Mutex(false, isaMutexName, out _, securitySettings); #endif } catch (UnauthorizedAccessException) @@ -236,9 +238,29 @@ namespace LibreHardwareMonitor.Hardware try { #if NETSTANDARD2_0 - _isaBusMutex = Mutex.OpenExisting(mutexName); + _isaBusMutex = Mutex.OpenExisting(isaMutexName); #else - _isaBusMutex = Mutex.OpenExisting(mutexName, MutexRights.Synchronize); + _isaBusMutex = Mutex.OpenExisting(isaMutexName, MutexRights.Synchronize); +#endif + } + catch + { } + } + + const string pciMutexName = "Global\\Access_PCI"; + + try + { + _pciBusMutex = new Mutex(false, pciMutexName); + } + catch (UnauthorizedAccessException) + { + try + { +#if NETSTANDARD2_0 + _pciBusMutex = Mutex.OpenExisting(pciMutexName); +#else + _pciBusMutex = Mutex.OpenExisting(pciMutexName, MutexRights.Synchronize); #endif } catch @@ -266,6 +288,12 @@ namespace LibreHardwareMonitor.Hardware _isaBusMutex = null; } + if (_pciBusMutex != null) + { + _pciBusMutex.Close(); + _pciBusMutex = null; + } + // try to delete temporary driver file again if failed during open if (_fileName != null && File.Exists(_fileName)) { @@ -280,7 +308,7 @@ namespace LibreHardwareMonitor.Hardware { } } } - + public static string GetReport() { if (_report.Length > 0) @@ -321,6 +349,31 @@ namespace LibreHardwareMonitor.Hardware _isaBusMutex?.ReleaseMutex(); } + public static bool WaitPciBusMutex(int millisecondsTimeout) + { + if (_pciBusMutex == null) + return true; + + + try + { + return _pciBusMutex.WaitOne(millisecondsTimeout, false); + } + catch (AbandonedMutexException) + { + return true; + } + catch (InvalidOperationException) + { + return false; + } + } + + public static void ReleasePciBusMutex() + { + _pciBusMutex?.ReleaseMutex(); + } + public static bool ReadMsr(uint index, out uint eax, out uint edx) { if (_driver == null)