* Update PawnIO modules to 2.2 https://github.com/namazso/PawnIO.Modules/releases/tag/0.2.2 * Update RyzenSMU.cs From RyzenSMU module
440 lines
19 KiB
C#
440 lines
19 KiB
C#
// ported from: https://gitlab.com/leogx9r/ryzen_smu
|
|
// and: https://github.com/irusanov/SMUDebugTool
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using LibreHardwareMonitor.PawnIo;
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
|
|
namespace LibreHardwareMonitor.Hardware;
|
|
|
|
internal class RyzenSMU
|
|
{
|
|
private readonly CpuCodeName _cpuCodeName;
|
|
private readonly bool _supportedCPU;
|
|
private readonly Exception _unsupportedCPUException;
|
|
|
|
private readonly Dictionary<uint, Dictionary<uint, SmuSensorType>> _supportedPmTableVersions = new()
|
|
{
|
|
{
|
|
// Zen Raven Ridge APU.
|
|
0x001E0004, new Dictionary<uint, SmuSensorType>
|
|
{
|
|
{ 7, new SmuSensorType { Name = "TDC", Type = SensorType.Current, Scale = 1 } },
|
|
{ 11, new SmuSensorType { Name = "EDC", Type = SensorType.Current, Scale = 1 } },
|
|
//{ 61, new SmuSensorType { Name = "Core", Type = SensorType.Voltage } },
|
|
//{ 62, new SmuSensorType { Name = "Core", Type = SensorType.Current, Scale = 1} },
|
|
//{ 63, new SmuSensorType { Name = "Core", Type = SensorType.Power, Scale = 1 } },
|
|
//{ 65, new SmuSensorType { Name = "SoC", Type = SensorType.Voltage } },
|
|
{ 66, new SmuSensorType { Name = "SoC", Type = SensorType.Current, Scale = 1 } },
|
|
{ 67, new SmuSensorType { Name = "SoC", Type = SensorType.Power, Scale = 1 } },
|
|
//{ 96, new SmuSensorType { Name = "Core #1", Type = SensorType.Power } },
|
|
//{ 97, new SmuSensorType { Name = "Core #2", Type = SensorType.Power } },
|
|
//{ 98, new SmuSensorType { Name = "Core #3", Type = SensorType.Power } },
|
|
//{ 99, new SmuSensorType { Name = "Core #4", Type = SensorType.Power } },
|
|
{ 108, new SmuSensorType { Name = "Core #1", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 109, new SmuSensorType { Name = "Core #2", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 110, new SmuSensorType { Name = "Core #3", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 111, new SmuSensorType { Name = "Core #4", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 150, new SmuSensorType { Name = "GFX", Type = SensorType.Voltage, Scale = 1 } },
|
|
{ 151, new SmuSensorType { Name = "GFX", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 154, new SmuSensorType { Name = "GFX", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 156, new SmuSensorType { Name = "GFX", Type = SensorType.Load, Scale = 1 } },
|
|
{ 166, new SmuSensorType { Name = "Fabric", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 177, new SmuSensorType { Name = "Uncore", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 178, new SmuSensorType { Name = "Memory", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 342, new SmuSensorType { Name = "Displays", Type = SensorType.Factor, Scale = 1 } }
|
|
}
|
|
},
|
|
{
|
|
// Zen 2.
|
|
0x00240903, new Dictionary<uint, SmuSensorType>
|
|
{
|
|
{ 15, new SmuSensorType { Name = "TDC", Type = SensorType.Current, Scale = 1 } },
|
|
{ 21, new SmuSensorType { Name = "EDC", Type = SensorType.Current, Scale = 1 } },
|
|
{ 48, new SmuSensorType { Name = "Fabric", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 50, new SmuSensorType { Name = "Uncore", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 51, new SmuSensorType { Name = "Memory", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 115, new SmuSensorType { Name = "SoC", Type = SensorType.Temperature, Scale = 1 } }
|
|
//{ 66, new SmuSensorType { Name = "Bus Speed", Type = SensorType.Clock, Scale = 1 } },
|
|
//{ 188, new SmuSensorType { Name = "Core #1", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 189, new SmuSensorType { Name = "Core #2", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 190, new SmuSensorType { Name = "Core #3", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 191, new SmuSensorType { Name = "Core #4", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 192, new SmuSensorType { Name = "Core #5", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 193, new SmuSensorType { Name = "Core #6", Type = SensorType.Clock, Scale = 1000 } },
|
|
}
|
|
},
|
|
{
|
|
// Zen 3.
|
|
0x00380805, new Dictionary<uint, SmuSensorType>
|
|
{
|
|
{ 3, new SmuSensorType { Name = "TDC", Type = SensorType.Current, Scale = 1 } },
|
|
// TODO: requires some post-processing
|
|
// see: https://gitlab.com/leogx9r/ryzen_smu/-/blob/master/userspace/monitor_cpu.c#L577
|
|
// { 9, new SmuSensorType { Name = "EDC", Type = SensorType.Current, Scale = 1 } },
|
|
{ 48, new SmuSensorType { Name = "Fabric", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 50, new SmuSensorType { Name = "Uncore", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 51, new SmuSensorType { Name = "Memory", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 127, new SmuSensorType { Name = "SoC", Type = SensorType.Temperature, Scale = 1 } },
|
|
|
|
//Core effective clock is now calculated in Amd17Cpu/Core
|
|
//{ 268, new SmuSensorType { Name = "Core #1 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 269, new SmuSensorType { Name = "Core #2 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 270, new SmuSensorType { Name = "Core #3 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 271, new SmuSensorType { Name = "Core #4 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 272, new SmuSensorType { Name = "Core #5 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 273, new SmuSensorType { Name = "Core #6 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 274, new SmuSensorType { Name = "Core #7 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 275, new SmuSensorType { Name = "Core #8 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 276, new SmuSensorType { Name = "Core #9 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 277, new SmuSensorType { Name = "Core #10 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 278, new SmuSensorType { Name = "Core #11 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 279, new SmuSensorType { Name = "Core #12 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 280, new SmuSensorType { Name = "Core #13 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 281, new SmuSensorType { Name = "Core #14 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 282, new SmuSensorType { Name = "Core #15 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 283, new SmuSensorType { Name = "Core #16 (Effective)", Type = SensorType.Clock, Scale = 1000 } }
|
|
}
|
|
},
|
|
{
|
|
// Zen 4.
|
|
0x00540004, new Dictionary<uint, SmuSensorType>
|
|
{
|
|
{ 3, new SmuSensorType { Name = "CPU PPT", Type = SensorType.Power, Scale = 1 } },
|
|
{ 11, new SmuSensorType { Name = "Package", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 20, new SmuSensorType { Name = "Core Power", Type = SensorType.Power, Scale = 1 } },
|
|
{ 21, new SmuSensorType { Name = "SOC Power", Type = SensorType.Power, Scale = 1 } },
|
|
{ 22, new SmuSensorType { Name = "Misc Power", Type = SensorType.Power, Scale = 1 } },
|
|
{ 26, new SmuSensorType { Name = "Total Power", Type = SensorType.Power, Scale = 1 } },
|
|
{ 47, new SmuSensorType { Name = "VDDCR", Type = SensorType.Voltage, Scale = 1 } },
|
|
{ 48, new SmuSensorType { Name = "TDC", Type = SensorType.Current, Scale = 1 } },
|
|
{ 49, new SmuSensorType { Name = "EDC", Type = SensorType.Current, Scale = 1 } },
|
|
{ 52, new SmuSensorType { Name = "VDDCR SoC", Type = SensorType.Voltage, Scale = 1 } },
|
|
{ 57, new SmuSensorType { Name = "VDD Misc", Type = SensorType.Voltage, Scale = 1 } },
|
|
{ 70, new SmuSensorType { Name = "Fabric", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 74, new SmuSensorType { Name = "Uncore", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 78, new SmuSensorType { Name = "Memory", Type = SensorType.Clock, Scale = 1 } },
|
|
{ 211, new SmuSensorType { Name = "IOD Hotspot", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 539, new SmuSensorType { Name = "L3 (CCD1)", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 540, new SmuSensorType { Name = "L3 (CCD2)", Type = SensorType.Temperature, Scale = 1 } },
|
|
{ 268, new SmuSensorType { Name = "LDO VDD", Type = SensorType.Voltage, Scale = 1 } },
|
|
|
|
// This is not working, some cores can be deactivated with the core disabled map.
|
|
// When Core 2 is disabled and Core 3 is enabled, the name of Core 3 == "Core 2".
|
|
//{ 357, new SmuSensorType { Name = "Core #1 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 358, new SmuSensorType { Name = "Core #2 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 359, new SmuSensorType { Name = "Core #3 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 360, new SmuSensorType { Name = "Core #4 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 361, new SmuSensorType { Name = "Core #5 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 362, new SmuSensorType { Name = "Core #6 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 363, new SmuSensorType { Name = "Core #7 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 364, new SmuSensorType { Name = "Core #8 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 365, new SmuSensorType { Name = "Core #9 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 366, new SmuSensorType { Name = "Core #10 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 367, new SmuSensorType { Name = "Core #11 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 368, new SmuSensorType { Name = "Core #12 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 369, new SmuSensorType { Name = "Core #13 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 370, new SmuSensorType { Name = "Core #14 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 371, new SmuSensorType { Name = "Core #15 (Effective)", Type = SensorType.Clock, Scale = 1000 } },
|
|
//{ 372, new SmuSensorType { Name = "Core #16 (Effective)", Type = SensorType.Clock, Scale = 1000 } }
|
|
}
|
|
}
|
|
};
|
|
|
|
private uint _pmTableSize;
|
|
private uint _pmTableSizeAlt;
|
|
private uint _pmTableVersion;
|
|
private uint _dramBaseAddr;
|
|
|
|
private readonly RyzenSmu _ryzenSmu;
|
|
|
|
public RyzenSMU()
|
|
{
|
|
try
|
|
{
|
|
_ryzenSmu = new RyzenSmu();
|
|
|
|
_cpuCodeName = (CpuCodeName)_ryzenSmu.GetCodeName();
|
|
|
|
_ryzenSmu.ResolvePmTable(out _pmTableVersion, out _dramBaseAddr);
|
|
|
|
SetupPmTableSize();
|
|
|
|
_supportedCPU = true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_supportedCPU = false;
|
|
_unsupportedCPUException = e;
|
|
}
|
|
}
|
|
|
|
public void Close() => _ryzenSmu.Close();
|
|
|
|
public string GetReport()
|
|
{
|
|
StringBuilder r = new();
|
|
|
|
r.AppendLine("Ryzen SMU");
|
|
r.AppendLine();
|
|
r.AppendLine($" PM table version: 0x{_pmTableVersion:X8}");
|
|
r.AppendLine($" PM table supported: {_supportedCPU}");
|
|
r.AppendLine($" PM table layout defined: {IsPmTableLayoutDefined()}");
|
|
|
|
if (_supportedCPU)
|
|
{
|
|
r.AppendLine($" PM table size: 0x{_pmTableSize:X3}");
|
|
r.AppendLine($" PM table start address: 0x{_dramBaseAddr:X8}");
|
|
r.AppendLine();
|
|
r.AppendLine(" PM table dump:");
|
|
|
|
try
|
|
{
|
|
float[] pm_values = UpdateAndReadDram();
|
|
r.AppendLine(" Idx Offset Value");
|
|
r.AppendLine(" ------------------------");
|
|
for (int i = 0; i < pm_values.Length; i++)
|
|
{
|
|
r.AppendLine($" {i,4} 0x{i * 4:X3} {pm_values[i]}");
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
r.AppendLine($" Exception: {e.Message}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r.AppendLine($" Initialization exception: {_unsupportedCPUException.Message}");
|
|
}
|
|
|
|
return r.ToString();
|
|
}
|
|
|
|
public Dictionary<uint, SmuSensorType> GetPmTableStructure()
|
|
{
|
|
if (!IsPmTableLayoutDefined())
|
|
return new Dictionary<uint, SmuSensorType>();
|
|
|
|
return _supportedPmTableVersions[_pmTableVersion];
|
|
}
|
|
|
|
public bool IsPmTableLayoutDefined()
|
|
{
|
|
return _supportedPmTableVersions.ContainsKey(_pmTableVersion);
|
|
}
|
|
|
|
public float[] GetPmTable()
|
|
{
|
|
if (!_supportedCPU)
|
|
return [0];
|
|
|
|
float[] table = null;
|
|
for (int tries_left = 2; tries_left != 0; --tries_left)
|
|
{
|
|
table = null;
|
|
try
|
|
{
|
|
table = UpdateAndReadDram();
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
|
|
if (table is { Length: > 0 } && table[0] != 0)
|
|
{
|
|
return table;
|
|
}
|
|
}
|
|
|
|
return table is { Length: > 0 } ? table : [0];
|
|
}
|
|
|
|
private float[] UpdateAndReadDram()
|
|
{
|
|
float[] table = new float[_pmTableSize / 4];
|
|
|
|
_ryzenSmu.UpdatePmTable();
|
|
long[] read = _ryzenSmu.ReadPmTable((int)((_pmTableSize + 7) / 8));
|
|
Buffer.BlockCopy(read, 0, table, 0, (int)_pmTableSize);
|
|
|
|
return table;
|
|
}
|
|
|
|
private void SetupPmTableSize()
|
|
{
|
|
switch (_cpuCodeName)
|
|
{
|
|
case CpuCodeName.Matisse:
|
|
switch (_pmTableVersion)
|
|
{
|
|
case 0x240902:
|
|
_pmTableSize = 0x514;
|
|
break;
|
|
case 0x240903:
|
|
_pmTableSize = 0x518;
|
|
break;
|
|
case 0x240802:
|
|
_pmTableSize = 0x7E0;
|
|
break;
|
|
case 0x240803:
|
|
_pmTableSize = 0x7E4;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case CpuCodeName.Vermeer:
|
|
switch (_pmTableVersion)
|
|
{
|
|
case 0x2D0903:
|
|
_pmTableSize = 0x594;
|
|
break;
|
|
case 0x380904:
|
|
_pmTableSize = 0x5A4;
|
|
break;
|
|
case 0x380905:
|
|
_pmTableSize = 0x5D0;
|
|
break;
|
|
case 0x2D0803:
|
|
_pmTableSize = 0x894;
|
|
break;
|
|
case 0x380804:
|
|
_pmTableSize = 0x8A4;
|
|
break;
|
|
case 0x380805:
|
|
_pmTableSize = 0x8F0;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case CpuCodeName.Renoir:
|
|
switch (_pmTableVersion)
|
|
{
|
|
case 0x370000:
|
|
_pmTableSize = 0x794;
|
|
break;
|
|
case 0x370001:
|
|
_pmTableSize = 0x884;
|
|
break;
|
|
case 0x370002:
|
|
case 0x370003:
|
|
_pmTableSize = 0x88C;
|
|
break;
|
|
case 0x370004:
|
|
_pmTableSize = 0x8AC;
|
|
break;
|
|
case 0x370005:
|
|
_pmTableSize = 0x8C8;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case CpuCodeName.Cezanne:
|
|
switch (_pmTableVersion)
|
|
{
|
|
case 0x400005:
|
|
_pmTableSize = 0x944;
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case CpuCodeName.Picasso:
|
|
case CpuCodeName.RavenRidge:
|
|
case CpuCodeName.RavenRidge2:
|
|
_pmTableSizeAlt = 0xA4;
|
|
_pmTableSize = 0x608 + _pmTableSizeAlt;
|
|
break;
|
|
|
|
case CpuCodeName.Raphael:
|
|
case CpuCodeName.GraniteRidge:
|
|
switch (_pmTableVersion)
|
|
{
|
|
case 0x00540004:
|
|
_pmTableSize = 0x948;
|
|
break;
|
|
|
|
case 0x00540104:
|
|
_pmTableSize = 0x950;
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
public struct SmuSensorType
|
|
{
|
|
public string Name;
|
|
public SensorType Type;
|
|
public float Scale;
|
|
}
|
|
|
|
|
|
private enum CpuCodeName
|
|
{
|
|
Undefined = -1,
|
|
Colfax,
|
|
Renoir,
|
|
Picasso,
|
|
Matisse,
|
|
Threadripper,
|
|
CastlePeak,
|
|
RavenRidge,
|
|
RavenRidge2,
|
|
SummitRidge,
|
|
PinnacleRidge,
|
|
Rembrandt,
|
|
Vermeer,
|
|
Vangogh,
|
|
Cezanne,
|
|
Milan,
|
|
Dali,
|
|
Raphael,
|
|
GraniteRidge,
|
|
Naples,
|
|
FireFlight,
|
|
Rome,
|
|
Chagall,
|
|
Lucienne,
|
|
Phoenix,
|
|
Phoenix2,
|
|
Mendocino,
|
|
Genoa,
|
|
StormPeak,
|
|
DragonRange,
|
|
Mero,
|
|
HawkPoint,
|
|
StrixPoint,
|
|
StrixHalo,
|
|
KrackanPoint,
|
|
KrackanPoint2,
|
|
Turin,
|
|
TurinD,
|
|
Bergamo,
|
|
ShimadaPeak,
|
|
}
|
|
}
|