Add support for Global\\Access_PCI mutex

Based on the work of @moellerm
This commit is contained in:
Phyxion
2020-05-25 12:04:28 +02:00
parent fe662558f4
commit b118b7a2f1
4 changed files with 307 additions and 188 deletions
@@ -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;
@@ -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;
+174 -147
View File
@@ -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
}
+60 -7
View File
@@ -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)