mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-28 21:07:47 +00:00
Added AMD family 17h (Ryzen) CPU support.
This commit is contained in:
parent
f659aa0f60
commit
5748e67bf4
342
Hardware/CPU/AMD17CPU.cs
Normal file
342
Hardware/CPU/AMD17CPU.cs
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
Copyright (C) 2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenHardwareMonitor.Hardware.CPU {
|
||||||
|
|
||||||
|
internal sealed class AMD17CPU : AMDCPU {
|
||||||
|
|
||||||
|
private readonly Core[] cores;
|
||||||
|
|
||||||
|
private readonly Sensor coreTemperature;
|
||||||
|
private readonly Sensor tctlTemperature;
|
||||||
|
private readonly Sensor ccdMaxTemperature;
|
||||||
|
private readonly Sensor ccdAvgTemperature;
|
||||||
|
private readonly Sensor[] ccdTemperatures;
|
||||||
|
private readonly Sensor packagePowerSensor;
|
||||||
|
private readonly Sensor coresPowerSensor;
|
||||||
|
private readonly Sensor busClock;
|
||||||
|
|
||||||
|
private const uint FAMILY_17H_M01H_THM_TCON_TEMP = 0x00059800;
|
||||||
|
private const uint FAMILY_17H_M01H_THM_TCON_TEMP_RANGE_SEL = 0x80000;
|
||||||
|
private uint FAMILY_17H_M70H_CCD_TEMP(uint i) { return 0x00059954 + i * 4; }
|
||||||
|
private const uint FAMILY_17H_M70H_CCD_TEMP_VALID = 0x800;
|
||||||
|
private const uint MAX_CCD_COUNT = 8;
|
||||||
|
|
||||||
|
private const uint MSR_RAPL_PWR_UNIT = 0xC0010299;
|
||||||
|
private const uint MSR_CORE_ENERGY_STAT = 0xC001029A;
|
||||||
|
private const uint MSR_PKG_ENERGY_STAT = 0xC001029B;
|
||||||
|
private const uint MSR_P_STATE_0 = 0xC0010064;
|
||||||
|
private const uint MSR_FAMILY_17H_P_STATE = 0xc0010293;
|
||||||
|
|
||||||
|
private float energyUnitMultiplier = 0;
|
||||||
|
private uint lastEnergyConsumed;
|
||||||
|
private DateTime lastEnergyTime;
|
||||||
|
|
||||||
|
private readonly double timeStampCounterMultiplier;
|
||||||
|
|
||||||
|
private struct TctlOffsetItem {
|
||||||
|
public string Name { get; set; }
|
||||||
|
public float Offset { get; set; }
|
||||||
|
}
|
||||||
|
private IEnumerable<TctlOffsetItem> tctlOffsetItems = new[] {
|
||||||
|
new TctlOffsetItem { Name = "AMD Ryzen 5 1600X", Offset = 20.0f },
|
||||||
|
new TctlOffsetItem { Name = "AMD Ryzen 7 1700X", Offset = 20.0f },
|
||||||
|
new TctlOffsetItem { Name = "AMD Ryzen 7 1800X", Offset = 20.0f },
|
||||||
|
new TctlOffsetItem { Name = "AMD Ryzen 7 2700X", Offset = 10.0f },
|
||||||
|
new TctlOffsetItem { Name = "AMD Ryzen Threadripper 19", Offset = 27.0f },
|
||||||
|
new TctlOffsetItem { Name = "AMD Ryzen Threadripper 29", Offset = 27.0f }
|
||||||
|
};
|
||||||
|
private readonly float tctlOffset = 0.0f;
|
||||||
|
|
||||||
|
public AMD17CPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
|
||||||
|
: base(processorIndex, cpuid, settings)
|
||||||
|
{
|
||||||
|
string cpuName = cpuid[0][0].BrandString;
|
||||||
|
if (!string.IsNullOrEmpty(cpuName)) {
|
||||||
|
foreach (var item in tctlOffsetItems) {
|
||||||
|
if (cpuName.StartsWith(item.Name)) {
|
||||||
|
tctlOffset = item.Offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coreTemperature = new Sensor(
|
||||||
|
"CPU Package", 0, SensorType.Temperature, this, new[] {
|
||||||
|
new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
|
||||||
|
}, this.settings);
|
||||||
|
|
||||||
|
if (tctlOffset != 0.0f)
|
||||||
|
tctlTemperature = new Sensor(
|
||||||
|
"CPU Tctl", 1, true, SensorType.Temperature, this, new[] {
|
||||||
|
new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
|
||||||
|
}, this.settings);
|
||||||
|
|
||||||
|
ccdMaxTemperature = new Sensor(
|
||||||
|
"CPU CCD Max", 2, SensorType.Temperature, this, this.settings);
|
||||||
|
|
||||||
|
ccdAvgTemperature = new Sensor(
|
||||||
|
"CPU CCD Average", 3, SensorType.Temperature, this, this.settings);
|
||||||
|
|
||||||
|
ccdTemperatures = new Sensor[MAX_CCD_COUNT];
|
||||||
|
for (int i = 0; i < MAX_CCD_COUNT; i++) {
|
||||||
|
ccdTemperatures[i] = new Sensor(
|
||||||
|
"CPU CCD #" + (i + 1), i + 4, SensorType.Temperature, this,
|
||||||
|
new[] {
|
||||||
|
new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
|
||||||
|
}, this.settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Ring0.Rdmsr(MSR_RAPL_PWR_UNIT, out uint eax, out _)) {
|
||||||
|
energyUnitMultiplier = 1.0f / (1 << (int)((eax >> 8) & 0x1F));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (energyUnitMultiplier != 0) {
|
||||||
|
if (Ring0.Rdmsr(MSR_PKG_ENERGY_STAT, out uint energyConsumed, out _)) {
|
||||||
|
lastEnergyTime = DateTime.UtcNow;
|
||||||
|
lastEnergyConsumed = energyConsumed;
|
||||||
|
packagePowerSensor = new Sensor(
|
||||||
|
"CPU Package", 0, SensorType.Power, this, settings);
|
||||||
|
ActivateSensor(packagePowerSensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
coresPowerSensor = new Sensor("CPU Cores", 1, SensorType.Power, this,
|
||||||
|
settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
|
||||||
|
timeStampCounterMultiplier = GetTimeStampCounterMultiplier();
|
||||||
|
if (timeStampCounterMultiplier > 0) {
|
||||||
|
busClock.Value = (float)(TimeStampCounterFrequency /
|
||||||
|
timeStampCounterMultiplier);
|
||||||
|
ActivateSensor(busClock);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cores = new Core[coreCount];
|
||||||
|
for (int i = 0; i < this.cores.Length; i++) {
|
||||||
|
this.cores[i] = new Core(i, cpuid[i], this, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override uint[] GetMSRs() {
|
||||||
|
return new uint[] { MSR_P_STATE_0, MSR_FAMILY_17H_P_STATE,
|
||||||
|
MSR_RAPL_PWR_UNIT, MSR_CORE_ENERGY_STAT, MSR_PKG_ENERGY_STAT };
|
||||||
|
}
|
||||||
|
|
||||||
|
private IList<uint> GetSmnRegisters() {
|
||||||
|
var registers = new List<uint>();
|
||||||
|
registers.Add(FAMILY_17H_M01H_THM_TCON_TEMP);
|
||||||
|
for (uint i = 0; i < MAX_CCD_COUNT; i++) {
|
||||||
|
registers.Add(FAMILY_17H_M70H_CCD_TEMP(i));
|
||||||
|
}
|
||||||
|
return registers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetReport() {
|
||||||
|
StringBuilder r = new StringBuilder();
|
||||||
|
r.Append(base.GetReport());
|
||||||
|
|
||||||
|
r.Append("Time Stamp Counter Multiplier: ");
|
||||||
|
r.AppendLine(timeStampCounterMultiplier.ToString(
|
||||||
|
CultureInfo.InvariantCulture));
|
||||||
|
r.AppendLine();
|
||||||
|
|
||||||
|
r.AppendLine("SMN Registers");
|
||||||
|
r.AppendLine();
|
||||||
|
r.AppendLine(" Register Value");
|
||||||
|
var registers = GetSmnRegisters();
|
||||||
|
for (int i = 0; i < registers.Count; i++)
|
||||||
|
if (ReadSmnRegister(registers[i], out uint value)) {
|
||||||
|
r.Append(" ");
|
||||||
|
r.Append(registers[i].ToString("X8", CultureInfo.InvariantCulture));
|
||||||
|
r.Append(" ");
|
||||||
|
r.Append(value.ToString("X8", CultureInfo.InvariantCulture));
|
||||||
|
r.AppendLine();
|
||||||
|
}
|
||||||
|
r.AppendLine();
|
||||||
|
|
||||||
|
return r.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private double GetTimeStampCounterMultiplier() {
|
||||||
|
Ring0.Rdmsr(MSR_P_STATE_0, out uint eax, out _);
|
||||||
|
uint cpuDfsId = (eax >> 8) & 0x3f;
|
||||||
|
uint cpuFid = eax & 0xff;
|
||||||
|
return 2.0 * cpuFid / cpuDfsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ReadSmnRegister(uint address, out uint value) {
|
||||||
|
if (!Ring0.WritePciConfig(0, 0x60, address)) {
|
||||||
|
value = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Ring0.ReadPciConfig(0, 0x64, out value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update() {
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
uint value;
|
||||||
|
if (ReadSmnRegister(FAMILY_17H_M01H_THM_TCON_TEMP, out value)) {
|
||||||
|
float temperature = ((value >> 21) & 0x7FF) / 8.0f;
|
||||||
|
if ((value & FAMILY_17H_M01H_THM_TCON_TEMP_RANGE_SEL) != 0)
|
||||||
|
temperature -= 49;
|
||||||
|
|
||||||
|
if (tctlTemperature != null) {
|
||||||
|
tctlTemperature.Value = temperature +
|
||||||
|
tctlTemperature.Parameters[0].Value;
|
||||||
|
ActivateSensor(tctlTemperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
temperature -= tctlOffset;
|
||||||
|
|
||||||
|
coreTemperature.Value = temperature +
|
||||||
|
coreTemperature.Parameters[0].Value;
|
||||||
|
ActivateSensor(coreTemperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
float maxTemperature = float.MinValue;
|
||||||
|
int ccdCount = 0;
|
||||||
|
float ccdTemperatureSum = 0;
|
||||||
|
for (uint i = 0; i < MAX_CCD_COUNT; i++) {
|
||||||
|
if (ReadSmnRegister(FAMILY_17H_M70H_CCD_TEMP(i), out value)) {
|
||||||
|
if ((value & FAMILY_17H_M70H_CCD_TEMP_VALID) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float temperature = (value & 0x7FF) / 8.0f - 49;
|
||||||
|
temperature += ccdTemperatures[i].Parameters[0].Value;
|
||||||
|
|
||||||
|
if (temperature > maxTemperature)
|
||||||
|
maxTemperature = temperature;
|
||||||
|
ccdCount++;
|
||||||
|
ccdTemperatureSum += temperature;
|
||||||
|
|
||||||
|
ccdTemperatures[i].Value = temperature;
|
||||||
|
ActivateSensor(ccdTemperatures[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ccdCount > 1) {
|
||||||
|
ccdMaxTemperature.Value = maxTemperature;
|
||||||
|
ActivateSensor(ccdMaxTemperature);
|
||||||
|
|
||||||
|
ccdAvgTemperature.Value = ccdTemperatureSum / ccdCount;
|
||||||
|
ActivateSensor(ccdAvgTemperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Ring0.Rdmsr(MSR_PKG_ENERGY_STAT, out uint energyConsumed, out _)) {
|
||||||
|
|
||||||
|
DateTime time = DateTime.UtcNow;
|
||||||
|
float deltaTime = (float)(time - lastEnergyTime).TotalSeconds;
|
||||||
|
if (deltaTime > 0.01) {
|
||||||
|
|
||||||
|
packagePowerSensor.Value = energyUnitMultiplier * unchecked(
|
||||||
|
energyConsumed - lastEnergyConsumed) / deltaTime;
|
||||||
|
lastEnergyTime = time;
|
||||||
|
lastEnergyConsumed = energyConsumed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float? coresPower = 0f;
|
||||||
|
for (int i = 0; i < cores.Length; i++) {
|
||||||
|
cores[i].Update();
|
||||||
|
coresPower += cores[i].Power;
|
||||||
|
}
|
||||||
|
coresPowerSensor.Value = coresPower;
|
||||||
|
|
||||||
|
if (coresPower.HasValue) {
|
||||||
|
ActivateSensor(coresPowerSensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Core {
|
||||||
|
|
||||||
|
private readonly AMD17CPU cpu;
|
||||||
|
private readonly ulong threadAffinityMask;
|
||||||
|
|
||||||
|
private readonly Sensor powerSensor;
|
||||||
|
private readonly Sensor clockSensor;
|
||||||
|
|
||||||
|
private DateTime lastEnergyTime;
|
||||||
|
private uint lastEnergyConsumed;
|
||||||
|
private float? power = null;
|
||||||
|
|
||||||
|
public Core(int index, CPUID[] threads, AMD17CPU cpu, ISettings settings)
|
||||||
|
{
|
||||||
|
this.cpu = cpu;
|
||||||
|
this.threadAffinityMask = 1UL << threads[0].Thread;
|
||||||
|
|
||||||
|
string coreString = cpu.CoreString(index);
|
||||||
|
this.powerSensor =
|
||||||
|
new Sensor(coreString, index + 2, SensorType.Power, cpu, settings);
|
||||||
|
this.clockSensor =
|
||||||
|
new Sensor(coreString, index + 1, SensorType.Clock, cpu, settings);
|
||||||
|
|
||||||
|
if (cpu.energyUnitMultiplier != 0) {
|
||||||
|
if (Ring0.RdmsrTx(MSR_CORE_ENERGY_STAT, out uint energyConsumed,
|
||||||
|
out _, threadAffinityMask))
|
||||||
|
{
|
||||||
|
lastEnergyTime = DateTime.UtcNow;
|
||||||
|
lastEnergyConsumed = energyConsumed;
|
||||||
|
cpu.ActivateSensor(powerSensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double? GetMultiplier() {
|
||||||
|
if (Ring0.Rdmsr(MSR_FAMILY_17H_P_STATE, out uint eax, out _)) {
|
||||||
|
uint cpuDfsId = (eax >> 8) & 0x3f;
|
||||||
|
uint cpuFid = eax & 0xff;
|
||||||
|
return 2.0 * cpuFid / cpuDfsId;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float? Power { get { return power; } }
|
||||||
|
|
||||||
|
public void Update() {
|
||||||
|
DateTime energyTime = DateTime.MinValue;
|
||||||
|
double? multiplier = null;
|
||||||
|
|
||||||
|
ulong mask = ThreadAffinity.Set(threadAffinityMask);
|
||||||
|
if (Ring0.Rdmsr(MSR_CORE_ENERGY_STAT, out uint energyConsumed, out _)) {
|
||||||
|
energyTime = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiplier = GetMultiplier();
|
||||||
|
ThreadAffinity.Set(mask);
|
||||||
|
|
||||||
|
float deltaTime = (float)(energyTime - lastEnergyTime).TotalSeconds;
|
||||||
|
if (deltaTime > 0.01) {
|
||||||
|
power = cpu.energyUnitMultiplier *
|
||||||
|
unchecked(energyConsumed - lastEnergyConsumed) / deltaTime;
|
||||||
|
powerSensor.Value = power;
|
||||||
|
lastEnergyTime = energyTime;
|
||||||
|
lastEnergyConsumed = energyConsumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiplier.HasValue) {
|
||||||
|
float? clock = (float?)(multiplier * cpu.busClock.Value);
|
||||||
|
clockSensor.Value = clock;
|
||||||
|
if (clock.HasValue)
|
||||||
|
cpu.ActivateSensor(clockSensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,7 +4,7 @@
|
|||||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
Copyright (C) 2009-2014 Michael Möller <mmoeller@openhardwaremonitor.org>
|
Copyright (C) 2009-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -104,6 +104,9 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
case 0x16:
|
case 0x16:
|
||||||
hardware.Add(new AMD10CPU(index, coreThreads, settings));
|
hardware.Add(new AMD10CPU(index, coreThreads, settings));
|
||||||
break;
|
break;
|
||||||
|
case 0x17:
|
||||||
|
hardware.Add(new AMD17CPU(index, coreThreads, settings));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
hardware.Add(new GenericCPU(index, coreThreads, settings));
|
hardware.Add(new GenericCPU(index, coreThreads, settings));
|
||||||
break;
|
break;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
Copyright (C) 2009-2014 Michael Möller <mmoeller@openhardwaremonitor.org>
|
Copyright (C) 2009-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -179,13 +179,19 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
coreMaskWith = NextLog2(maxCoreIdPerPackage);
|
coreMaskWith = NextLog2(maxCoreIdPerPackage);
|
||||||
break;
|
break;
|
||||||
case Vendor.AMD:
|
case Vendor.AMD:
|
||||||
|
if (this.family == 0x17) {
|
||||||
|
coreMaskWith = (cpuidExtData[8, 2] >> 12) & 0xF;
|
||||||
|
threadMaskWith =
|
||||||
|
NextLog2(((cpuidExtData[0x1E, 1] >> 8) & 0xFF) + 1);
|
||||||
|
} else {
|
||||||
uint corePerPackage;
|
uint corePerPackage;
|
||||||
if (maxCpuidExt >= 8)
|
if (maxCpuidExt >= 8)
|
||||||
corePerPackage = (cpuidExtData[8, 2] & 0xFF) + 1;
|
corePerPackage = (cpuidExtData[8, 2] & 0xFF) + 1;
|
||||||
else
|
else
|
||||||
corePerPackage = 1;
|
corePerPackage = 1;
|
||||||
threadMaskWith = 0;
|
|
||||||
coreMaskWith = NextLog2(corePerPackage);
|
coreMaskWith = NextLog2(corePerPackage);
|
||||||
|
threadMaskWith = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
threadMaskWith = 0;
|
threadMaskWith = 0;
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
<Compile Include="Hardware\ATI\ATIGPU.cs" />
|
<Compile Include="Hardware\ATI\ATIGPU.cs" />
|
||||||
<Compile Include="Hardware\ATI\ATIGroup.cs" />
|
<Compile Include="Hardware\ATI\ATIGroup.cs" />
|
||||||
<Compile Include="Hardware\Control.cs" />
|
<Compile Include="Hardware\Control.cs" />
|
||||||
|
<Compile Include="Hardware\CPU\AMD17CPU.cs" />
|
||||||
<Compile Include="Hardware\FirmwareTable.cs" />
|
<Compile Include="Hardware\FirmwareTable.cs" />
|
||||||
<Compile Include="Hardware\HDD\DebugSmart.cs" />
|
<Compile Include="Hardware\HDD\DebugSmart.cs" />
|
||||||
<Compile Include="Hardware\HDD\DriveAttributeValue.cs" />
|
<Compile Include="Hardware\HDD\DriveAttributeValue.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user