Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
fe26e9dc75 | |||
9ebbdfc47f | |||
f177ffda80 | |||
b2bf2571c6 | |||
ddcdd4f9b5 |
27
README.md
27
README.md
@ -1,3 +1,28 @@
|
||||
# ryzen-smu-cli
|
||||
|
||||
A CLI tool for the ZenStates SMU library.
|
||||
A CLI tool for the ZenStates SMU library. See [ZenStates-Core](https://github.com/irusanov/ZenStates-Core) for compatibility.
|
||||
|
||||
Requires [.NET Framework 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0).
|
||||
|
||||
All credit to irusanov, who wrote [ZenStates-Core](https://github.com/irusanov/ZenStates-Core) on which this depends for all meaningful functionality, and [SMUDebugTool](https://github.com/irusanov/SMUDebugTool) for usage examples.
|
||||
|
||||
Usage:
|
||||
```
|
||||
.\ryzen-smu-cli.exe --help
|
||||
Description:
|
||||
A CLI for the Ryzen SMU.
|
||||
|
||||
Usage:
|
||||
ryzen-smu-cli [options]
|
||||
|
||||
Options:
|
||||
--offset <offset> Specify a zero-indexed logical core, or list of logical cores, and their PBO offset(s), in a fashion similar to taskset. e.g. 0:-10,1:5,2:-20,14:-25. These are the logical core IDs as they appear in your system, not the true IDs according to fused hardware disabled cores.
|
||||
--disable-cores <disable-cores> Specify a zero-indexed list of logical cores to disable. e.g. 0,1,4,7,12,15. This setting does not take into account any current core disablement. All cores you wish to disable must be specified. Any that are unspecified will be enabled. This option requires a reboot.
|
||||
--enable-all-cores Enable all cores.
|
||||
--get-offsets-terse Print a list of all PBO offsets on logical cores in a simple, comma-separated format, without core identifiers. e.g. -15,0,2,-20.
|
||||
--get-physical-cores Print a list of physical cores, to find out which ones are disabled in <8-core-per-CCD SKUs.
|
||||
--set-pbo-scalar <set-pbo-scalar> Sets the PBO scalar. This is a whole number between 1 and 10.
|
||||
--get-pbo-scalar Get the current PBO scalar.
|
||||
--version Show version information
|
||||
-?, -h, --help Show help and usage information
|
||||
```
|
||||
|
@ -1,21 +0,0 @@
|
||||
Copyright (c) 2007-2009 OpenLibSys.org. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,12 +1,36 @@
|
||||
using System.CommandLine;
|
||||
using System.Management;
|
||||
using ZenStates.Core;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ryzen_smu_cli
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private static readonly Cpu ryzen = new();
|
||||
private static readonly Cpu ryzen;
|
||||
private static readonly Dictionary<int, int> mappedCores;
|
||||
static Program()
|
||||
{
|
||||
if (!IsAdministrator())
|
||||
{
|
||||
Console.WriteLine("This application must be run as an administrator.");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ryzen = new Cpu();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error: {ex.Message}");
|
||||
Console.WriteLine("If the previous message was unclear, for some reason, ZenStates-Core failed to initialize an instance of the CPU control object.");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
mappedCores = MapLogicalCoresToPhysical();
|
||||
}
|
||||
|
||||
private static readonly string wmiAMDACPI = "AMD_ACPI";
|
||||
private static readonly string wmiScope = "root\\wmi";
|
||||
@ -21,17 +45,35 @@ namespace ryzen_smu_cli
|
||||
|
||||
static int Main(string[] args)
|
||||
{
|
||||
if (!IsAdministrator())
|
||||
{
|
||||
Console.WriteLine("This application must be run as an administrator.");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
var rootCommand = new RootCommand("A CLI for the Ryzen SMU.");
|
||||
|
||||
var pboOffset = new Option<string>("--offset", "Specify a zero-indexed core, or list of cores, and their PBO offset(s), in a fashion similar to taskset. e.g. 0:-10,1:5,2:-20,14:-25");
|
||||
var disableCores = new Option<string>("--disable-cores", "Specify a zero-indexed list of cores to disable. e.g. 0,1,4,7,12,15. This setting does not take into account any current core disablement. All cores you wish to disable must be specified. Any that are unspecified will be enabled. This option requires a reboot.");
|
||||
var pboOffset = new Option<string>("--offset", "Specify a zero-indexed logical core, or list of logical cores, and their PBO offset(s), in a fashion similar to taskset. e.g. 0:-10,1:5,2:-20,14:-25. These are the logical core IDs as they appear in your system, not the true IDs according to fused hardware disabled cores. Alternatively, you may supply a simpler comma-separated list of offset values - e.g. 0,-14,-30,5,-10,-22 - but, obviously, this can only set the value on up to X core that you define.");
|
||||
var disableCores = new Option<string>("--disable-cores", "Specify a zero-indexed list of logical cores to disable. e.g. 0,1,4,7,12,15. This setting does not take into account any current core disablement. All cores you wish to disable must be specified. Any that are unspecified will be enabled. This option requires a reboot.");
|
||||
var enableCores = new Option<bool>("--enable-all-cores", "Enable all cores.");
|
||||
//var toggleJson = new Option<bool>("--json", "Enable json format for informational outputs.");
|
||||
var getCurrentPBOTerse = new Option<bool>("--get-offsets-terse", "Print a list of all PBO offsets on logical cores in a simple, comma-separated format, without core identifiers. e.g. -15,0,2,-20. Note that you cannot retrieve the offsets from disabled cores.");
|
||||
var getPhysicalCores = new Option<bool>("--get-physical-cores", "Print a list of physical cores, to find out which ones are disabled in <8-core-per-CCD SKUs.");
|
||||
var getEnabledCores = new Option<bool>("--get-enabled-cores", "Print a list of logically enabled/disabled cores, and their relationship to the physical cores, inclusive of factory-fused disabled cores.");
|
||||
var setPBOScalar = new Option<string>("--set-pbo-scalar", "Sets the PBO scalar. This is a whole number between 1 and 10.");
|
||||
var getPBOScalar = new Option<bool>("--get-pbo-scalar", "Get the current PBO scalar.");
|
||||
|
||||
rootCommand.AddOption(pboOffset);
|
||||
rootCommand.AddOption(disableCores);
|
||||
rootCommand.AddOption(enableCores);
|
||||
rootCommand.AddOption(getCurrentPBOTerse);
|
||||
rootCommand.AddOption(getPhysicalCores);
|
||||
rootCommand.AddOption(getEnabledCores);
|
||||
rootCommand.AddOption(setPBOScalar);
|
||||
rootCommand.AddOption(getPBOScalar);
|
||||
|
||||
rootCommand.SetHandler((offsetArgs, coreDisableArgs, enableAll) =>
|
||||
rootCommand.SetHandler((offsetArgs, coreDisableArgs, enableAll, getCurrentPBOTerse, getEnabledCores, getPhysicalCores,
|
||||
setPBOScalar, getPBOScalar) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(offsetArgs)) ApplyPBOOffset(offsetArgs);
|
||||
|
||||
@ -39,8 +81,56 @@ namespace ryzen_smu_cli
|
||||
|
||||
if (enableAll) ApplyDisableCores();
|
||||
|
||||
|
||||
}, pboOffset, disableCores, enableCores);
|
||||
if (getCurrentPBOTerse)
|
||||
{
|
||||
Console.WriteLine("Current PBO offsets:");
|
||||
string offsetLine = "";
|
||||
bool flagNotifyDisabledCCD = false;
|
||||
for (int i = 0; i < mappedCores.Count; i++)
|
||||
{
|
||||
int mapIndex = i < 8 ? 0 : 1;
|
||||
try
|
||||
{
|
||||
offsetLine += Convert.ToDecimal((int)ryzen.GetPsmMarginSingleCore((uint)(((mapIndex << 8) | ((mappedCores[i] % 8) & 0xF)) << 20)));
|
||||
offsetLine += ",";
|
||||
}
|
||||
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// This will occur if a CCD is disabled through BIOS e.g. with TURBO GAMER MODE.
|
||||
// But it's not a real problem.
|
||||
flagNotifyDisabledCCD = true;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine(offsetLine.TrimEnd(','));
|
||||
|
||||
if (flagNotifyDisabledCCD) Console.WriteLine("You have manually disabled cores. It is not possible to retrieve offset values while they are disabled.");
|
||||
}
|
||||
|
||||
if (getPhysicalCores)
|
||||
{
|
||||
Console.WriteLine("Fused status of physical cores:");
|
||||
for (var i = 0; i < ryzen.info.topology.physicalCores; i++)
|
||||
{
|
||||
int mapIndex = i < 8 ? 0 : 1;
|
||||
if ((~ryzen.info.topology.coreDisableMap[mapIndex] >> i % 8 & 1) == 0) Console.WriteLine($"Core {i}: Disabled");
|
||||
else Console.WriteLine($"Core {i}: Enabled");
|
||||
}
|
||||
}
|
||||
|
||||
if (getEnabledCores)
|
||||
{
|
||||
for (var i = 0; i < ryzen.info.topology.physicalCores; i++)
|
||||
{
|
||||
if (mappedCores.ContainsValue(i)) Console.WriteLine($"Core {i}: Enabled");
|
||||
else Console.WriteLine($"Core {i}: Disabled");
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(setPBOScalar)) ryzen.SetPBOScalar(Convert.ToUInt32(setPBOScalar));
|
||||
if (getPBOScalar) Console.WriteLine($"Current PBO scalar: {ryzen.GetPBOScalar()}");
|
||||
}, pboOffset, disableCores, enableCores, getCurrentPBOTerse, getEnabledCores, getPhysicalCores, setPBOScalar, getPBOScalar);
|
||||
|
||||
if (args.Length == 0)
|
||||
{
|
||||
@ -59,6 +149,25 @@ namespace ryzen_smu_cli
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static Dictionary<int, int> MapLogicalCoresToPhysical()
|
||||
{
|
||||
Dictionary<int, int> mappedCores = [];
|
||||
|
||||
int logicalCoreIter = 0;
|
||||
|
||||
for (var i = 0; i < ryzen.info.topology.physicalCores; i++)
|
||||
{
|
||||
int mapIndex = i < 8 ? 0 : 1;
|
||||
if (ryzen.GetPsmMarginSingleCore((uint)(((mapIndex << 8) | ((i % 8) & 0xF)) << 20)) != null)
|
||||
{
|
||||
mappedCores.Add(logicalCoreIter, i);
|
||||
logicalCoreIter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return mappedCores;
|
||||
}
|
||||
|
||||
private static string GetWmiInstanceName()
|
||||
{
|
||||
try
|
||||
@ -127,28 +236,55 @@ namespace ryzen_smu_cli
|
||||
|
||||
private static void ApplyPBOOffset(string offsetArgs)
|
||||
{
|
||||
string[] arg = offsetArgs.Split(',');
|
||||
|
||||
for (int i = 0; i < arg.Length; i++)
|
||||
// This checks if the current SKU has a known register for writing PBO offsets
|
||||
if (ryzen.smu.Rsmu.SMU_MSG_SetDldoPsmMargin != 0)
|
||||
{
|
||||
int core = Convert.ToInt32(arg[i].Split(':')[0]);
|
||||
int offset = Convert.ToInt32(arg[i].Split(':')[1]);
|
||||
string validArgFormat = @"^(-?\d{1,2}(,-?\d{1,2})*|\d{1,2}:-?\d{1,2}(,\d{1,2}:-?\d{1,2})*)$";
|
||||
|
||||
// Magic numbers from SMUDebugTool
|
||||
// This does some bitshifting calculations to get the mask for individual cores for chips with up to two CCDs
|
||||
// I'm not sure if it would work with more, in theory. It's unclear to me based on the github issues.
|
||||
int mapIndex = core < 8 ? 0 : 1;
|
||||
if ((~ryzen.info.topology.coreDisableMap[mapIndex] >> core % 8 & 1) == 1)
|
||||
if (Regex.IsMatch(offsetArgs, validArgFormat))
|
||||
{
|
||||
ryzen.SetPsmMarginSingleCore((uint)(((mapIndex << 8) | core % 8 & 0xF) << 20), offset);
|
||||
Console.WriteLine($"Set core {core} offset to {offset}!");
|
||||
string[] arg = offsetArgs.Split(',');
|
||||
|
||||
if (arg.Length <= mappedCores.Count)
|
||||
{
|
||||
for (int i = 0; i < arg.Length; i++)
|
||||
{
|
||||
// Magic numbers from SMUDebugTool
|
||||
// This does some bitshifting calculations to get the mask for individual cores for chips with up to two CCDs
|
||||
// Support for threadrippers/epyc is theoretically available, if the calculations were expanded, but are untested
|
||||
try
|
||||
{
|
||||
int mapIndex = mappedCores[i] < 8 ? 0 : 1;
|
||||
|
||||
if (arg[i].Contains(':'))
|
||||
{
|
||||
int core = Convert.ToInt32(arg[i].Split(':')[0]);
|
||||
int offset = Convert.ToInt32(arg[i].Split(':')[1]);
|
||||
ryzen.SetPsmMarginSingleCore((uint)(((mapIndex << 8) | mappedCores[core] % 8 & 0xF) << 20), offset);
|
||||
Console.WriteLine($"Set logical core {core}, physical core {mappedCores[core]} offset to {offset}!");
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ryzen.SetPsmMarginSingleCore((uint)(((mapIndex << 8) | mappedCores[i] % 8 & 0xF) << 20), Convert.ToInt32(arg[i]));
|
||||
Console.WriteLine($"Set logical core {i}, physical core {mappedCores[i]} offset to {arg[i]}!");
|
||||
}
|
||||
}
|
||||
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
Console.WriteLine($"Tried to set an offset on logical core {Convert.ToInt32(arg[i].Split(':')[0])}, but there are only {mappedCores.Count} (zero-indexed, as a reminder) logical cores active in the system.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else Console.WriteLine("Specified a greater number of offsets than logical cores active in the system. Please check and try again.");
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Unable to set offset on disabled core {core}.");
|
||||
}
|
||||
else Console.WriteLine("Malformed input format for offsets. Please check and try again.");
|
||||
}
|
||||
|
||||
else Console.WriteLine("You have attempted to enable PBO offsets on a CPU that does not support them.");
|
||||
}
|
||||
|
||||
private static void ApplyDisableCores(string coreArgs = "Enable")
|
||||
@ -191,5 +327,14 @@ namespace ryzen_smu_cli
|
||||
Console.WriteLine("Something has gone terribly wrong, the downcore config option is not present.");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAdministrator()
|
||||
{
|
||||
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
|
||||
{
|
||||
WindowsPrincipal principal = new WindowsPrincipal(identity);
|
||||
return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
END USER LICENSE AGREEMENT
|
||||
|
||||
Software License Agreement for WinIo
|
||||
The following terms apply to all files associated with the software unless
|
||||
explicitly disclaimed in individual files.
|
||||
|
||||
IMPORTANT- PLEASE READ CAREFULLY: BY INSTALLING THE SOFTWARE (AS DEFINED BELOW),
|
||||
OR COPYING THE SOFTWARE, YOU (EITHER ON BEHALF OF YOURSELF AS AN INDIVIDUAL OR
|
||||
ON BEHALF OF AN ENTITY AS ITS AUTHORIZED REPRESENTATIVE) AGREE TO ALL OF THE
|
||||
TERMS OF THIS END USER LICENSE AGREEMENT ("AGREEMENT") REGARDING YOUR USE OF
|
||||
THE SOFTWARE. IF YOU DO NOT AGREE WITH ALL OF THE TERMS OF THIS AGREEMENT, DO
|
||||
NOT INSTALL, COPY OR OTHERWISE USE THE SOFTWARE.
|
||||
|
||||
1. GRANT OF LICENSE: Subject to the terms below, Yariv Kaplan ("AUTHOR") hereby
|
||||
grants you a non-exclusive, non-transferable, non-assignable license to install
|
||||
and to use the downloadable version of WinIo ("SOFTWARE").
|
||||
|
||||
a. Redistributable Code. You may reproduce and distribute the object code form
|
||||
of the SOFTWARE solely in conjunction with, and as part of, your application
|
||||
("Permitted Application"); provided that you comply with the following:
|
||||
|
||||
If you redistribute any portion of the Redistributable Code, you agree that:
|
||||
|
||||
(i) you will only distribute the Redistributable Code in conjunction with, and
|
||||
as part of, your Permitted Application which adds significant functionality to
|
||||
the Redistributable Code and that distribution of the Permitted Application does
|
||||
not compete with the AUTHOR's distribution of the SOFTWARE;
|
||||
|
||||
(ii) you will include a valid copyright notice on your Permitted Application;
|
||||
|
||||
(iii) you will not permit further redistribution of the Redistributable Code;
|
||||
|
||||
(iv) you will indemnify, hold harmless, and defend the AUTHOR from and against
|
||||
any claims or lawsuits, including attorneys' fees, that arise or result from
|
||||
the use or distribution of your Permitted Application.
|
||||
|
||||
b. License to use Source Code. You may not sell, lease, rent, transfer or
|
||||
sublicense the source code of this SOFTWARE.
|
||||
|
||||
2. MODIFICATION: SOFTWARE Source Code may be modified without the prior written
|
||||
permission of the AUTHOR. Any modifications made to the SOFTWARE will continue
|
||||
to be subject to the terms and conditions of this AGREEMENT.
|
||||
|
||||
3. COPYRIGHT: All rights, title, and copyrights in and to the SOFTWARE and any
|
||||
copies of the SOFTWARE are owned by the AUTHOR. The SOFTWARE is protected by
|
||||
copyright laws and international treaty provisions. Therefore, you must treat
|
||||
the SOFTWARE like any other copyrighted material.
|
||||
|
||||
4. TITLE: You acknowledge that no title to the intellectual property in the
|
||||
SOFTWARE is transferred to you. Title, ownership, rights, and intellectual
|
||||
property rights in and to the SOFTWARE shall remain the exclusive property of
|
||||
the AUTHOR. The SOFTWARE is protected by copyright laws of the United States
|
||||
and international treaties.
|
||||
|
||||
5. LIMITATION OF LIABILITY: You must assume the entire risk of using the
|
||||
SOFTWARE.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
|
||||
SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHOR
|
||||
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
|
||||
AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||
ENHANCEMENTS, OR MODIFICATIONS.
|
@ -6,7 +6,7 @@
|
||||
<RootNamespace>ryzen_smu_cli</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>0.0.2</Version>
|
||||
<Version>0.1.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
Loading…
x
Reference in New Issue
Block a user