From 37ff883525db10fc08751cd276a0d214daf4a36b Mon Sep 17 00:00:00 2001 From: Johannes Krampf Date: Thu, 18 Apr 2013 15:35:59 +0200 Subject: [PATCH] Initial port of amdmsrtweaker to Linux. (CAUTION: Completely untested!) --- AmdMsrTweaker.cpp | 213 +++++----- AmdMsrTweaker.sln | 26 -- AmdMsrTweaker.vcxproj | 186 --------- AmdMsrTweaker.vcxproj.filters | 45 -- Info.cpp | 748 ++++++++++++++++------------------ Info.h | 134 +++--- Makefile | 7 + StringUtils.h | 85 ++-- WinRing0.cpp | 115 +++--- WinRing0.h | 58 +-- Worker.cpp | 379 ++++++++--------- Worker.h | 31 +- 12 files changed, 806 insertions(+), 1221 deletions(-) delete mode 100644 AmdMsrTweaker.sln delete mode 100644 AmdMsrTweaker.vcxproj delete mode 100644 AmdMsrTweaker.vcxproj.filters create mode 100644 Makefile diff --git a/AmdMsrTweaker.cpp b/AmdMsrTweaker.cpp index 84634bc..6361cdb 100644 --- a/AmdMsrTweaker.cpp +++ b/AmdMsrTweaker.cpp @@ -5,8 +5,8 @@ * about permitted and prohibited uses of this code. */ +#include #include -#include #include "Info.h" #include "Worker.h" #include "WinRing0.h" @@ -21,131 +21,100 @@ void WaitForKey(); /// Entry point for the program. -int main(int argc, const char* argv[]) -{ - // initialize WinRing0 - if (!InitializeOls() || GetDllStatus() != 0) - { - cerr << "ERROR: WinRing0 initialization failed" << endl; - DeinitializeOls(); - - return 1; - } - - try - { - Info info; - if (!info.Initialize()) - { - cout << "ERROR: unsupported CPU" << endl; - DeinitializeOls(); - WaitForKey(); - return 2; - } - - if (argc > 1) - { - Worker worker(info); - - if (!worker.ParseParams(argc, argv)) - { - DeinitializeOls(); - WaitForKey(); - return 3; - } - - worker.ApplyChanges(); - } - else - { - PrintInfo(info); - WaitForKey(); - } - } - catch (const std::exception& e) - { - cerr << "ERROR: " << e.what() << endl; - DeinitializeOls(); - WaitForKey(); - return 10; - } - - DeinitializeOls(); - - return 0; +int main(int argc, const char* argv[]) { + try { + Info info; + if (!info.Initialize()) { + cout << "ERROR: unsupported CPU" << endl; + WaitForKey(); + return 2; + } + + if (argc > 1) { + Worker worker(info); + + if (!worker.ParseParams(argc, argv)) { + WaitForKey(); + return 3; + } + + worker.ApplyChanges(); + } else { + PrintInfo(info); + WaitForKey(); + } + } catch (const std::exception& e) { + cerr << "ERROR: " << e.what() << endl; + WaitForKey(); + return 10; + } + + return 0; } -void PrintInfo(const Info& info) -{ - cout << endl; - cout << "AmdMsrTweaker v1.1" << endl; - cout << endl; - - cout << ".:. General" << endl << "---" << endl; - cout << " AMD family 0x" << std::hex << info.Family << ", model 0x" << info.Model << std::dec << " CPU, " << info.NumCores << " cores" << endl; - cout << " Default reference clock: " << info.multiScaleFactor * 100 << " MHz" << endl; - cout << " Available multipliers: " << (info.MinMulti / info.multiScaleFactor) << " .. " << (info.MaxSoftwareMulti / info.multiScaleFactor) << endl; - cout << " Available voltage IDs: " << info.MinVID << " .. " << info.MaxVID << " (" << info.VIDStep << " steps)" << endl; - cout << endl; - - cout << ".:. Turbo" << endl << "---" << endl; - if (!info.IsBoostSupported) - cout << " not supported" << endl; - else - { - cout << " " << (info.IsBoostEnabled ? "enabled" : "disabled") << endl; - cout << " " << (info.IsBoostLocked ? "locked" : "unlocked") << endl; - - if (info.MaxMulti != info.MaxSoftwareMulti) - cout << " Max multiplier: " << (info.MaxMulti / info.multiScaleFactor) << endl; - } - cout << endl; - - cout << ".:. P-states" << endl << "---" << endl; - cout << " " << info.NumPStates << " of " << (info.Family == 0x10 ? 5 : 8) << " enabled (P0 .. P" << (info.NumPStates - 1) << ")" << endl; - - if (info.IsBoostSupported && info.NumBoostStates > 0) - { - cout << " Turbo P-states:"; - for (int i = 0; i < info.NumBoostStates; i++) - cout << " P" << i; - cout << endl; - } - - cout << " ---" << endl; - - for (int i = 0; i < info.NumPStates; i++) - { - const PStateInfo pi = info.ReadPState(i); - - cout << " P" << i << ": " << (pi.Multi / info.multiScaleFactor) << "x at " << info.DecodeVID(pi.VID) << "V" << endl; - - if (pi.NBPState >= 0) - { - cout << " NorthBridge in NB_P" << pi.NBPState; - if (pi.NBVID >= 0) - cout << " at " << info.DecodeVID(pi.NBVID) << "V"; - cout << endl; - } - } - - if (info.Family == 0x15) - { - cout << " ---" << endl; - - for (int i = 0; i < info.NumNBPStates; i++) - { - const NBPStateInfo pi = info.ReadNBPState(i); - cout << " NB_P" << i << ": " << pi.Multi << "x at " << info.DecodeVID(pi.VID) << "V" << endl; - } - } +void PrintInfo(const Info& info) { + cout << endl; + cout << "AmdMsrTweaker v1.1" << endl; + cout << endl; + + cout << ".:. General" << endl << "---" << endl; + cout << " AMD family 0x" << std::hex << info.Family << ", model 0x" << info.Model << std::dec << " CPU, " << info.NumCores << " cores" << endl; + cout << " Default reference clock: " << info.multiScaleFactor * 100 << " MHz" << endl; + cout << " Available multipliers: " << (info.MinMulti / info.multiScaleFactor) << " .. " << (info.MaxSoftwareMulti / info.multiScaleFactor) << endl; + cout << " Available voltage IDs: " << info.MinVID << " .. " << info.MaxVID << " (" << info.VIDStep << " steps)" << endl; + cout << endl; + + cout << ".:. Turbo" << endl << "---" << endl; + if (!info.IsBoostSupported) + cout << " not supported" << endl; + else { + cout << " " << (info.IsBoostEnabled ? "enabled" : "disabled") << endl; + cout << " " << (info.IsBoostLocked ? "locked" : "unlocked") << endl; + + if (info.MaxMulti != info.MaxSoftwareMulti) + cout << " Max multiplier: " << (info.MaxMulti / info.multiScaleFactor) << endl; + } + cout << endl; + + cout << ".:. P-states" << endl << "---" << endl; + cout << " " << info.NumPStates << " of " << (info.Family == 0x10 ? 5 : 8) << " enabled (P0 .. P" << (info.NumPStates - 1) << ")" << endl; + + if (info.IsBoostSupported && info.NumBoostStates > 0) { + cout << " Turbo P-states:"; + for (int i = 0; i < info.NumBoostStates; i++) + cout << " P" << i; + cout << endl; + } + + cout << " ---" << endl; + + for (int i = 0; i < info.NumPStates; i++) { + const PStateInfo pi = info.ReadPState(i); + + cout << " P" << i << ": " << (pi.Multi / info.multiScaleFactor) << "x at " << info.DecodeVID(pi.VID) << "V" << endl; + + if (pi.NBPState >= 0) { + cout << " NorthBridge in NB_P" << pi.NBPState; + if (pi.NBVID >= 0) + cout << " at " << info.DecodeVID(pi.NBVID) << "V"; + cout << endl; + } + } + + if (info.Family == 0x15) { + cout << " ---" << endl; + + for (int i = 0; i < info.NumNBPStates; i++) { + const NBPStateInfo pi = info.ReadNBPState(i); + cout << " NB_P" << i << ": " << pi.Multi << "x at " << info.DecodeVID(pi.VID) << "V" << endl; + } + } } -void WaitForKey() -{ - cout << endl << "Press any key to exit... "; - _getch(); - cout << endl; +void WaitForKey() { + cout << endl << "Press any key to exit... "; + getchar(); + cout << endl; } diff --git a/AmdMsrTweaker.sln b/AmdMsrTweaker.sln deleted file mode 100644 index 15d1a84..0000000 --- a/AmdMsrTweaker.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmdMsrTweaker", "AmdMsrTweaker.vcxproj", "{CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Debug|Win32.ActiveCfg = Debug|Win32 - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Debug|Win32.Build.0 = Debug|Win32 - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Debug|x64.ActiveCfg = Debug|x64 - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Debug|x64.Build.0 = Debug|x64 - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Release|Win32.ActiveCfg = Release|Win32 - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Release|Win32.Build.0 = Release|Win32 - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Release|x64.ActiveCfg = Release|x64 - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/AmdMsrTweaker.vcxproj b/AmdMsrTweaker.vcxproj deleted file mode 100644 index 3d5d068..0000000 --- a/AmdMsrTweaker.vcxproj +++ /dev/null @@ -1,186 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {CA5B3392-C34E-4B5B-A8F7-7A7055A5BFFC} - AmdMsrTweaker - - - - Application - NotSet - true - - - Application - NotSet - - - Application - NotSet - true - - - Application - NotSet - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)\$(Configuration)\$(Platform)\ - $(Platform)\$(Configuration)\ - false - $(SolutionDir)\$(Configuration)\$(Platform)\ - $(Platform)\$(Configuration)\ - false - $(SolutionDir)\$(Configuration)\$(Platform)\ - $(Platform)\$(Configuration)\ - false - $(SolutionDir)\$(Configuration)\$(Platform)\ - $(Platform)\$(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - DEBUG;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - Level4 - ProgramDatabase - 4100;%(DisableSpecificWarnings) - - - RequireAdministrator - true - MachineX86 - - - - - X64 - - - Disabled - DEBUG;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - Level4 - ProgramDatabase - 4100;%(DisableSpecificWarnings) - - - RequireAdministrator - true - MachineX64 - - - - - MinSpace - true - MultiThreaded - false - true - Level4 - - - 4100;%(DisableSpecificWarnings) - - - RequireAdministrator - false - true - true - MachineX86 - - - - - X64 - - - MinSpace - true - MultiThreaded - false - true - Level4 - - - 4100;%(DisableSpecificWarnings) - - - RequireAdministrator - false - true - true - MachineX64 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/AmdMsrTweaker.vcxproj.filters b/AmdMsrTweaker.vcxproj.filters deleted file mode 100644 index ca6079e..0000000 --- a/AmdMsrTweaker.vcxproj.filters +++ /dev/null @@ -1,45 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Info.cpp b/Info.cpp index 1ddf809..99b7054 100644 --- a/Info.cpp +++ b/Info.cpp @@ -5,6 +5,7 @@ * about permitted and prohibited uses of this code. */ +#include #include // for min/max #include #include "Info.h" @@ -20,469 +21,418 @@ static const double DIVISORS_12[] = { 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, 1 void FindFraction(double value, const double* divisors, - int& numerator, int& divisorIndex, - int minNumerator, int maxNumerator); - - -bool Info::Initialize() -{ - CpuidRegs regs; - QWORD msr; - DWORD eax; - - // verify vendor = AMD ("AuthenticAMD") - regs = Cpuid(0x80000000); - if (regs.ecx != 0x444d4163) // "DMAc" - return false; - - // check family - regs = Cpuid(0x80000001); - Family = GetBits(regs.eax, 8, 4) + GetBits(regs.eax, 20, 8); - if (!(Family == 0x10 || Family == 0x12 || Family == 0x14 || Family == 0x15)) - return false; - - // read model - Model = GetBits(regs.eax, 4, 4) + (GetBits(regs.eax, 16, 4) << 4); - - //set VID step for SVI2 platforms (otherwise 0.0125 is assumed, see header) - // Family 0x15 Models 10-1F is Trinity/Richland - // Family 0x15 Models 30-3F is Kaveri - if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) - VIDStep = 0.00625; - - // scale factor from external multi to internal one (default 1, set for 200MHz REFCLK platforms) - // Family 0x10 includes all AM2+/AM3 K10 CPUs - // Family 0x15 Models 0-F is Bulldozer/Piledriver - if (Family == 0x10 || (Family == 0x15 && Model < 0x10)) - multiScaleFactor = 2.0; - - // number of physical cores - regs = Cpuid(0x80000008); - NumCores = GetBits(regs.ecx, 0, 8) + 1; - - // number of hardware P-states - eax = ReadPciConfig(AMD_CPU_DEVICE, 3, 0xdc); - NumPStates = GetBits(eax, 8, 3) + 1; - - if (Family == 0x15) - { - eax = ReadPciConfig(AMD_CPU_DEVICE, 0xf5, 0x170); - NumNBPStates = (eax & 0x3) + 1; - } - - // get limits - msr = Rdmsr(0xc0010071); - - const int maxMulti = GetBits(msr, 49, 6); - const int minVID = GetBits(msr, 42, 7); - const int maxVID = GetBits(msr, 35, 7); - - MinMulti = (Family == 0x14 ? (maxMulti == 0 ? 0 : (maxMulti + 16) / 26.5) - : 1.0); - MaxMulti = (maxMulti == 0 ? (Family == 0x14 ? 0 - : (Family == 0x12 ? 31 + 16 : 47 + 16)) - : (Family == 0x12 || Family == 0x14 ? maxMulti + 16 : maxMulti)); - MaxSoftwareMulti = MaxMulti; - - MinVID = (minVID == 0 ? 0.0 - : DecodeVID(minVID)); - MaxVID = (maxVID == 0 ? 1.55 - : DecodeVID(maxVID)); - - // is CBP (core performance boost) supported? - regs = Cpuid(0x80000007); - IsBoostSupported = (GetBits(regs.edx, 9, 1) == 1); - - if (IsBoostSupported) - { - // is CPB disabled for the current core? - msr = Rdmsr(0xc0010015); - const bool cpbDis = (GetBits(msr, 25, 1) == 1); - - // boost lock, number of boost P-states and boost source - eax = ReadPciConfig(AMD_CPU_DEVICE, 4, 0x15c); - IsBoostLocked = (Family == 0x12 ? true - : GetBits(eax, 31, 1) == 1); - NumBoostStates = (Family == 0x10 ? GetBits(eax, 2, 1) - : GetBits(eax, 2, 3)); - const int boostSrc = GetBits(eax, 0, 2); - const bool isBoostSrcEnabled = (Family == 0x10 ? (boostSrc == 3) - : (boostSrc == 1)); - - IsBoostEnabled = (isBoostSrcEnabled && !cpbDis); - - // max multi for software P-states (families 0x10 and 0x15) - if (Family == 0x10) - { - eax = ReadPciConfig(AMD_CPU_DEVICE, 3, 0x1f0); - const int maxSoftwareMulti = GetBits(eax, 20, 6); - MaxSoftwareMulti = (maxSoftwareMulti == 0 ? 63 - : maxSoftwareMulti); - } - else if (Family == 0x15) - { - eax = ReadPciConfig(AMD_CPU_DEVICE, 3, 0xd4); - const int maxSoftwareMulti = GetBits(eax, 0, 6); - MaxSoftwareMulti = (maxSoftwareMulti == 0 ? 63 - : maxSoftwareMulti); - } - } - - return true; + int& numerator, int& divisorIndex, + int minNumerator, int maxNumerator); + + +bool Info::Initialize() { + CpuidRegs regs; + uint64_t msr; + uint32_t eax; + + // verify vendor = AMD ("AuthenticAMD") + regs = Cpuid(0); + if (regs.ecx != 0x444d4163) // "DMAc" + return false; + + // check family + regs = Cpuid(1); + Family = GetBits(regs.eax, 8, 4) + GetBits(regs.eax, 20, 8); + if (!(Family == 0x10 || Family == 0x12 || Family == 0x14 || Family == 0x15)) + return false; + + // read model + Model = GetBits(regs.eax, 4, 4) + (GetBits(regs.eax, 16, 4) << 4); + + //set VID step for SVI2 platforms (otherwise 0.0125 is assumed, see header) + // Family 0x15 Models 10-1F is Trinity/Richland + // Family 0x15 Models 30-3F is Kaveri + if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) + VIDStep = 0.00625; + + // scale factor from external multi to internal one (default 1, set for 200MHz REFCLK platforms) + // Family 0x10 includes all AM2+/AM3 K10 CPUs + // Family 0x15 Models 0-F is Bulldozer/Piledriver + if (Family == 0x10 || (Family == 0x15 && Model < 0x10)) + multiScaleFactor = 2.0; + + // number of physical cores + regs = Cpuid(8); + NumCores = GetBits(regs.ecx, 0, 8) + 1; + + // number of hardware P-states + eax = ReadPciConfig(AMD_CPU_DEVICE, 3, 0xdc); + NumPStates = GetBits(eax, 8, 3) + 1; + + if (Family == 0x15) { + eax = ReadPciConfig(AMD_CPU_DEVICE, 0xf5, 0x170); + NumNBPStates = (eax & 0x3) + 1; + } + + // get limits + msr = Rdmsr(0xc0010071); + + const int maxMulti = GetBits(msr, 49, 6); + const int minVID = GetBits(msr, 42, 7); + const int maxVID = GetBits(msr, 35, 7); + + MinMulti = (Family == 0x14 ? (maxMulti == 0 ? 0 : (maxMulti + 16) / 26.5) + : 1.0); + MaxMulti = (maxMulti == 0 ? (Family == 0x14 ? 0 + : (Family == 0x12 ? 31 + 16 : 47 + 16)) + : (Family == 0x12 || Family == 0x14 ? maxMulti + 16 : maxMulti)); + MaxSoftwareMulti = MaxMulti; + + MinVID = (minVID == 0 ? 0.0 + : DecodeVID(minVID)); + MaxVID = (maxVID == 0 ? 1.55 + : DecodeVID(maxVID)); + + // is CBP (core performance boost) supported? + regs = Cpuid(7); + IsBoostSupported = (GetBits(regs.edx, 9, 1) == 1); + + if (IsBoostSupported) { + // is CPB disabled for the current core? + msr = Rdmsr(0xc0010015); + const bool cpbDis = (GetBits(msr, 25, 1) == 1); + + // boost lock, number of boost P-states and boost source + eax = ReadPciConfig(AMD_CPU_DEVICE, 4, 0x15c); + IsBoostLocked = (Family == 0x12 ? true + : GetBits(eax, 31, 1) == 1); + NumBoostStates = (Family == 0x10 ? GetBits(eax, 2, 1) + : GetBits(eax, 2, 3)); + const int boostSrc = GetBits(eax, 0, 2); + const bool isBoostSrcEnabled = (Family == 0x10 ? (boostSrc == 3) + : (boostSrc == 1)); + + IsBoostEnabled = (isBoostSrcEnabled && !cpbDis); + + // max multi for software P-states (families 0x10 and 0x15) + if (Family == 0x10) { + eax = ReadPciConfig(AMD_CPU_DEVICE, 3, 0x1f0); + const int maxSoftwareMulti = GetBits(eax, 20, 6); + MaxSoftwareMulti = (maxSoftwareMulti == 0 ? 63 + : maxSoftwareMulti); + } else if (Family == 0x15) { + eax = ReadPciConfig(AMD_CPU_DEVICE, 3, 0xd4); + const int maxSoftwareMulti = GetBits(eax, 0, 6); + MaxSoftwareMulti = (maxSoftwareMulti == 0 ? 63 + : maxSoftwareMulti); + } + } + + return true; } -PStateInfo Info::ReadPState(int index) const -{ - const QWORD msr = Rdmsr(0xc0010064 + index); - - PStateInfo result; - result.Index = index; - - int fid, did; - if (Family == 0x14) - { - fid = GetBits(msr, 4, 5); // DID MSD - did = GetBits(msr, 0, 4); // DID LSD - } - else if (Family == 0x12) - { - fid = GetBits(msr, 4, 5); - did = GetBits(msr, 0, 4); - } - else - { - fid = GetBits(msr, 0, 6); - did = GetBits(msr, 6, 3); - } - - result.Multi = DecodeMulti(fid, did); - - //on SVI2 platforms, VID is 8 bits - if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) - result.VID = GetBits(msr, 9, 8); - else - result.VID = GetBits(msr, 9, 7); - - if (!(Family == 0x12 || Family == 0x14)) - { - const int nbDid = GetBits(msr, 22, 1); - result.NBPState = nbDid; - } - else - result.NBPState = -1; - - if (Family == 0x10) - { - result.NBVID = GetBits(msr, 25, 7); - } - else - result.NBVID = -1; - - return result; +PStateInfo Info::ReadPState(int index) const { + const uint64_t msr = Rdmsr(0xc0010064 + index); + + PStateInfo result; + result.Index = index; + + int fid, did; + if (Family == 0x14) { + fid = GetBits(msr, 4, 5); // DID MSD + did = GetBits(msr, 0, 4); // DID LSD + } else if (Family == 0x12) { + fid = GetBits(msr, 4, 5); + did = GetBits(msr, 0, 4); + } else { + fid = GetBits(msr, 0, 6); + did = GetBits(msr, 6, 3); + } + + result.Multi = DecodeMulti(fid, did); + + //on SVI2 platforms, VID is 8 bits + if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) + result.VID = GetBits(msr, 9, 8); + else + result.VID = GetBits(msr, 9, 7); + + if (!(Family == 0x12 || Family == 0x14)) { + const int nbDid = GetBits(msr, 22, 1); + result.NBPState = nbDid; + } else + result.NBPState = -1; + + if (Family == 0x10) { + result.NBVID = GetBits(msr, 25, 7); + } else + result.NBVID = -1; + + return result; } -void Info::WritePState(const PStateInfo& info) const -{ - const DWORD regIndex = 0xc0010064 + info.Index; - QWORD msr = Rdmsr(regIndex); - - if (info.Multi >= 0) - { - int fid, did; - EncodeMulti(info.Multi, fid, did); - - if (Family == 0x14) - { - SetBits(msr, fid, 4, 5); // DID MSD - SetBits(msr, did, 0, 4); // DID LSD - } - else if (Family == 0x12) - { - SetBits(msr, fid, 4, 5); - SetBits(msr, did, 0, 4); - } - else - { - SetBits(msr, fid, 0, 6); - SetBits(msr, did, 6, 3); - } - } - - if (info.VID >= 0) - { - //on SVI2 platforms, VID is 8 bits - if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) - SetBits(msr, info.VID, 9, 8); - else - SetBits(msr, info.VID, 9, 7); - } - - if (info.NBPState >= 0) - { - if (!(Family == 0x12 || Family == 0x14)) - { - const int nbDid = max(0, min(1, info.NBPState)); - SetBits(msr, nbDid, 22, 1); - } - } - - if (info.NBVID >= 0) - { - if (Family == 0x10) - { - SetBits(msr, info.NBVID, 25, 7); - } - } - - Wrmsr(regIndex, msr); +void Info::WritePState(const PStateInfo& info) const { + const uint32_t regIndex = 0xc0010064 + info.Index; + uint64_t msr = Rdmsr(regIndex); + + if (info.Multi >= 0) { + int fid, did; + EncodeMulti(info.Multi, fid, did); + + if (Family == 0x14) { + SetBits(msr, fid, 4, 5); // DID MSD + SetBits(msr, did, 0, 4); // DID LSD + } else if (Family == 0x12) { + SetBits(msr, fid, 4, 5); + SetBits(msr, did, 0, 4); + } else { + SetBits(msr, fid, 0, 6); + SetBits(msr, did, 6, 3); + } + } + + if (info.VID >= 0) { + //on SVI2 platforms, VID is 8 bits + if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) + SetBits(msr, info.VID, 9, 8); + else + SetBits(msr, info.VID, 9, 7); + } + + if (info.NBPState >= 0) { + if (!(Family == 0x12 || Family == 0x14)) { + const int nbDid = max(0, min(1, info.NBPState)); + SetBits(msr, nbDid, 22, 1); + } + } + + if (info.NBVID >= 0) { + if (Family == 0x10) { + SetBits(msr, info.NBVID, 25, 7); + } + } + + Wrmsr(regIndex, msr); } -NBPStateInfo Info::ReadNBPState(int index) const -{ - if (Family != 0x15) - throw std::exception("NB P-states not supported"); +NBPStateInfo Info::ReadNBPState(int index) const { + if (Family != 0x15) + throw ExceptionWithMessage("NB P-states not supported"); - NBPStateInfo result; - result.Index = index; + NBPStateInfo result; + result.Index = index; - const DWORD eax = ReadPciConfig(AMD_CPU_DEVICE, 5, 0x160 + index * 4); + const uint32_t eax = ReadPciConfig(AMD_CPU_DEVICE, 5, 0x160 + index * 4); - const int fid = GetBits(eax, 1, 5); - const int did = GetBits(eax, 7, 1); - int vid = GetBits(eax, 10, 7); + const int fid = GetBits(eax, 1, 5); + const int did = GetBits(eax, 7, 1); + int vid = GetBits(eax, 10, 7); - //on SVI2 platforms, 8th bit for NB P-State is stored separately - if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) - vid += (GetBits(eax, 21, 1) << 7); + //on SVI2 platforms, 8th bit for NB P-State is stored separately + if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) + vid += (GetBits(eax, 21, 1) << 7); - result.Multi = (fid + 4) / pow(2.0, did); - result.VID = vid; + result.Multi = (fid + 4) / pow(2.0, did); + result.VID = vid; - return result; + return result; } -void Info::WriteNBPState(const NBPStateInfo& info) const -{ - if (Family != 0x15) - throw std::exception("NB P-states not supported"); +void Info::WriteNBPState(const NBPStateInfo& info) const { + if (Family != 0x15) + throw ExceptionWithMessage("NB P-states not supported"); - const DWORD regAddress = 0x160 + info.Index * 4; - DWORD eax = ReadPciConfig(AMD_CPU_DEVICE, 5, regAddress); + const uint32_t regAddress = 0x160 + info.Index * 4; + uint32_t eax = ReadPciConfig(AMD_CPU_DEVICE, 5, regAddress); - if (info.Multi >= 0) - { - static const double divisors[] = { 1.0, 2.0, 0.0 }; // 2^did + if (info.Multi >= 0) { + static const double divisors[] = { 1.0, 2.0, 0.0 }; // 2^did - int numerator, divisorIndex; - FindFraction(info.Multi, divisors, numerator, divisorIndex, 4, 31 + 4); + int numerator, divisorIndex; + FindFraction(info.Multi, divisors, numerator, divisorIndex, 4, 31 + 4); - const int fid = numerator - 4; - const int did = divisorIndex; + const int fid = numerator - 4; + const int did = divisorIndex; - SetBits(eax, fid, 1, 5); - SetBits(eax, did, 7, 1); - } + SetBits(eax, fid, 1, 5); + SetBits(eax, did, 7, 1); + } - if (info.VID >= 0) - { - SetBits(eax, info.VID, 10, 7); + if (info.VID >= 0) { + SetBits(eax, info.VID, 10, 7); - //on SVI2 platforms, 8th bit for NB P-State is stored separately - if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) - SetBits(eax, (info.VID >> 7), 21, 1); - } + //on SVI2 platforms, 8th bit for NB P-State is stored separately + if (Family == 0x15 && ((Model > 0xF && Model < 0x20) || (Model > 0x2F && Model < 0x40))) + SetBits(eax, (info.VID >> 7), 21, 1); + } - WritePciConfig(AMD_CPU_DEVICE, 5, regAddress, eax); + WritePciConfig(AMD_CPU_DEVICE, 5, regAddress, eax); } -void Info::SetCPBDis(bool enabled) const -{ - if (!IsBoostSupported) - throw std::exception("CPB not supported"); +void Info::SetCPBDis(bool enabled) const { + if (!IsBoostSupported) + throw ExceptionWithMessage("CPB not supported"); - const DWORD index = 0xc0010015; - QWORD msr = Rdmsr(index); - SetBits(msr, (enabled ? 0 : 1), 25, 1); - Wrmsr(index, msr); + const uint32_t index = 0xc0010015; + uint64_t msr = Rdmsr(index); + SetBits(msr, (enabled ? 0 : 1), 25, 1); + Wrmsr(index, msr); } -void Info::SetBoostSource(bool enabled) const -{ - if (!IsBoostSupported) - throw std::exception("CPB not supported"); +void Info::SetBoostSource(bool enabled) const { + if (!IsBoostSupported) + throw ExceptionWithMessage("CPB not supported"); - DWORD eax = ReadPciConfig(AMD_CPU_DEVICE, 4, 0x15c); - const int bits = (enabled ? (Family == 0x10 ? 3 : 1) - : 0); - SetBits(eax, bits, 0, 2); - WritePciConfig(AMD_CPU_DEVICE, 4, 0x15c, eax); + uint32_t eax = ReadPciConfig(AMD_CPU_DEVICE, 4, 0x15c); + const int bits = (enabled ? (Family == 0x10 ? 3 : 1) + : 0); + SetBits(eax, bits, 0, 2); + WritePciConfig(AMD_CPU_DEVICE, 4, 0x15c, eax); } -void Info::SetAPM(bool enabled) const -{ - if (Family != 0x15) - throw std::exception("APM not supported"); +void Info::SetAPM(bool enabled) const { + if (Family != 0x15) + throw ExceptionWithMessage("APM not supported"); - DWORD eax = ReadPciConfig(AMD_CPU_DEVICE, 4, 0x15c); - SetBits(eax, (enabled ? 1 : 0), 7, 1); - WritePciConfig(AMD_CPU_DEVICE, 4, 0x15c, eax); + uint32_t eax = ReadPciConfig(AMD_CPU_DEVICE, 4, 0x15c); + SetBits(eax, (enabled ? 1 : 0), 7, 1); + WritePciConfig(AMD_CPU_DEVICE, 4, 0x15c, eax); } -int Info::GetCurrentPState() const -{ - const QWORD msr = Rdmsr(0xc0010071); - const int i = GetBits(msr, 16, 3); - return i; +int Info::GetCurrentPState() const { + const uint64_t msr = Rdmsr(0xc0010071); + const int i = GetBits(msr, 16, 3); + return i; } -void Info::SetCurrentPState(int index) const -{ - if (index < 0 || index >= NumPStates) - throw std::exception("P-state index out of range"); +void Info::SetCurrentPState(int index) const { + if (index < 0 || index >= NumPStates) + throw ExceptionWithMessage("P-state index out of range"); - index -= NumBoostStates; - if (index < 0) - index = 0; + index -= NumBoostStates; + if (index < 0) + index = 0; - const DWORD regIndex = 0xc0010062; - QWORD msr = Rdmsr(regIndex); - SetBits(msr, index, 0, 3); - Wrmsr(regIndex, msr); + const uint32_t regIndex = 0xc0010062; + uint64_t msr = Rdmsr(regIndex); + SetBits(msr, index, 0, 3); + Wrmsr(regIndex, msr); } -double Info::DecodeMulti(int fid, int did) const -{ - if (Family == 0x14) - { - // fid => DID MSD (integral part of divisor - 1) - // did => DID LSD (fractional part of divisor, in quarters) +double Info::DecodeMulti(int fid, int did) const { + if (Family == 0x14) { + // fid => DID MSD (integral part of divisor - 1) + // did => DID LSD (fractional part of divisor, in quarters) - double divisor = fid + 1; + double divisor = fid + 1; - if (divisor >= 16) - did &= ~1; // ignore least significant bit of LSD - divisor += did * 0.25; + if (divisor >= 16) + did &= ~1; // ignore least significant bit of LSD + divisor += did * 0.25; - return MaxMulti / divisor; - } + return MaxMulti / divisor; + } - const double* divisors = (Family == 0x12 ? DIVISORS_12 - : DIVISORS_10_15); + const double* divisors = (Family == 0x12 ? DIVISORS_12 + : DIVISORS_10_15); - return (fid + 16) / divisors[did]; + return (fid + 16) / divisors[did]; } -void Info::EncodeMulti(double multi, int& fid, int& did) const -{ - if (Family == 0x14) - { - if (MaxMulti == 0) - throw std::exception("cannot encode multiplier (family 0x14) - unknown max multiplier"); - - const double exactDivisor = max(1.0, min(26.5, MaxMulti / multi)); - - double integer; - const double fractional = modf(exactDivisor, &integer); - - fid = (int)integer - 1; - - did = (int)ceil(fractional / 0.25); - - if (integer >= 16) - { - if (did == 1) - did = 2; - else if (did == 3) - did = 4; - } - - if (did == 4) - { - fid++; - did = 0; - } - - return; - } - - const int minNumerator = 16; // numerator: 0x10 = 16 as fixed offset - int maxNumerator; - const double* divisors; - - if (Family == 0x12) - { - maxNumerator = 31 + minNumerator; // 5 bits => max 2^5-1 = 31 - divisors = DIVISORS_12; - } - else - { - maxNumerator = 47 + minNumerator; // 6 bits, but max 0x2f = 47 - divisors = DIVISORS_10_15; - } - - int numerator, divisorIndex; - FindFraction(multi, divisors, numerator, divisorIndex, minNumerator, maxNumerator); - - fid = numerator - minNumerator; - did = divisorIndex; +void Info::EncodeMulti(double multi, int& fid, int& did) const { + if (Family == 0x14) { + if (MaxMulti == 0) + throw ExceptionWithMessage("cannot encode multiplier (family 0x14) - unknown max multiplier"); + + const double exactDivisor = max(1.0, min(26.5, MaxMulti / multi)); + + double integer; + const double fractional = modf(exactDivisor, &integer); + + fid = (int)integer - 1; + + did = (int)ceil(fractional / 0.25); + + if (integer >= 16) { + if (did == 1) + did = 2; + else if (did == 3) + did = 4; + } + + if (did == 4) { + fid++; + did = 0; + } + + return; + } + + const int minNumerator = 16; // numerator: 0x10 = 16 as fixed offset + int maxNumerator; + const double* divisors; + + if (Family == 0x12) { + maxNumerator = 31 + minNumerator; // 5 bits => max 2^5-1 = 31 + divisors = DIVISORS_12; + } else { + maxNumerator = 47 + minNumerator; // 6 bits, but max 0x2f = 47 + divisors = DIVISORS_10_15; + } + + int numerator, divisorIndex; + FindFraction(multi, divisors, numerator, divisorIndex, minNumerator, maxNumerator); + + fid = numerator - minNumerator; + did = divisorIndex; } -double Info::DecodeVID(int vid) const -{ - return 1.55 - vid * VIDStep; +double Info::DecodeVID(int vid) const { + return 1.55 - vid * VIDStep; } -int Info::EncodeVID(double vid) const -{ - vid = max(0.0, min(1.55, vid)); +int Info::EncodeVID(double vid) const { + vid = max(0.0, min(1.55, vid)); - // round to nearest step - int r = (int)(vid / VIDStep + 0.5); + // round to nearest step + int r = (int)(vid / VIDStep + 0.5); - //1.55 / VIDStep = highest VID (0 V) - return (int)(1.55 / VIDStep) - r; + //1.55 / VIDStep = highest VID (0 V) + return (int)(1.55 / VIDStep) - r; } void FindFraction(double value, const double* divisors, - int& numerator, int& divisorIndex, - int minNumerator, int maxNumerator) -{ - // limitations: non-negative value and divisors - - // count the null-terminated and ascendingly ordered divisors - int numDivisors = 0; - for (; divisors[numDivisors] > 0; numDivisors++) { } - - // make sure the value is in a valid range - value = max(minNumerator / divisors[numDivisors-1], min(maxNumerator / divisors[0], value)); - - // search the best-matching combo - double bestValue = -1.0; // numerator / divisors[divisorIndex] - for (int i = 0; i < numDivisors; i++) - { - const double d = divisors[i]; - const int n = max(minNumerator, min(maxNumerator, (int)(value * d))); - const double myValue = n / d; - - if (myValue <= value && myValue > bestValue) - { - numerator = n; - divisorIndex = i; - bestValue = myValue; - - if (bestValue == value) - break; - } - } + int& numerator, int& divisorIndex, + int minNumerator, int maxNumerator) { + // limitations: non-negative value and divisors + + // count the null-terminated and ascendingly ordered divisors + int numDivisors = 0; + for (; divisors[numDivisors] > 0; numDivisors++) { } + + // make sure the value is in a valid range + value = max(minNumerator / divisors[numDivisors-1], min(maxNumerator / divisors[0], value)); + + // search the best-matching combo + double bestValue = -1.0; // numerator / divisors[divisorIndex] + for (int i = 0; i < numDivisors; i++) { + const double d = divisors[i]; + const int n = max(minNumerator, min(maxNumerator, (int)(value * d))); + const double myValue = n / d; + + if (myValue <= value && myValue > bestValue) { + numerator = n; + divisorIndex = i; + bestValue = myValue; + + if (bestValue == value) + break; + } + } } diff --git a/Info.h b/Info.h index e1148ff..1f7bb68 100644 --- a/Info.h +++ b/Info.h @@ -8,84 +8,80 @@ #pragma once -struct PStateInfo -{ - int Index; // hardware index - double Multi; // internal one for 100 MHz reference - int VID; - int NBPState; - int NBVID; // family 0x10 only +struct PStateInfo { + int Index; // hardware index + double Multi; // internal one for 100 MHz reference + int VID; + int NBPState; + int NBVID; // family 0x10 only }; -struct NBPStateInfo -{ - int Index; - double Multi; // for 200 MHz reference - int VID; +struct NBPStateInfo { + int Index; + double Multi; // for 200 MHz reference + int VID; }; -class Info -{ +class Info { public: - int Family; - int Model; - int NumCores; - int NumPStates; - int NumNBPStates; - - double MinMulti, MaxMulti; // internal ones for 100 MHz reference - double MaxSoftwareMulti; // for software (i.e., non-boost) P-states - double MinVID, MaxVID; - double VIDStep; - double multiScaleFactor; - - bool IsBoostSupported; - bool IsBoostEnabled; - bool IsBoostLocked; - int NumBoostStates; - - - Info() - : Family(0) - , Model(0) - , NumCores(0) - , NumPStates(0) - , NumNBPStates(2) //except family 0x15, we have at least 2 NB P-States - , MinMulti(0.0), MaxMulti(0.0) - , MaxSoftwareMulti(0.0) - , MinVID(0.0), MaxVID(0.0) - , VIDStep(0.0125) //default step for pre SVI2 platforms - , multiScaleFactor(1.0) //default for 100MHz REFCLK - , IsBoostSupported(false) - , IsBoostEnabled(false) - , IsBoostLocked(false) - , NumBoostStates(0) - { - } - - bool Initialize(); - - PStateInfo ReadPState(int index) const; - void WritePState(const PStateInfo& info) const; - - NBPStateInfo ReadNBPState(int index) const; - void WriteNBPState(const NBPStateInfo& info) const; - - void SetCPBDis(bool enabled) const; - void SetBoostSource(bool enabled) const; - void SetAPM(bool enabled) const; - - int GetCurrentPState() const; - void SetCurrentPState(int index) const; - - double DecodeVID(int vid) const; - int EncodeVID(double vid) const; + int Family; + int Model; + int NumCores; + int NumPStates; + int NumNBPStates; + + double MinMulti, MaxMulti; // internal ones for 100 MHz reference + double MaxSoftwareMulti; // for software (i.e., non-boost) P-states + double MinVID, MaxVID; + double VIDStep; + double multiScaleFactor; + + bool IsBoostSupported; + bool IsBoostEnabled; + bool IsBoostLocked; + int NumBoostStates; + + + Info() + : Family(0) + , Model(0) + , NumCores(0) + , NumPStates(0) + , NumNBPStates(2) //except family 0x15, we have at least 2 NB P-States + , MinMulti(0.0), MaxMulti(0.0) + , MaxSoftwareMulti(0.0) + , MinVID(0.0), MaxVID(0.0) + , VIDStep(0.0125) //default step for pre SVI2 platforms + , multiScaleFactor(1.0) //default for 100MHz REFCLK + , IsBoostSupported(false) + , IsBoostEnabled(false) + , IsBoostLocked(false) + , NumBoostStates(0) { + } + + bool Initialize(); + + PStateInfo ReadPState(int index) const; + void WritePState(const PStateInfo& info) const; + + NBPStateInfo ReadNBPState(int index) const; + void WriteNBPState(const NBPStateInfo& info) const; + + void SetCPBDis(bool enabled) const; + void SetBoostSource(bool enabled) const; + void SetAPM(bool enabled) const; + + int GetCurrentPState() const; + void SetCurrentPState(int index) const; + + double DecodeVID(int vid) const; + int EncodeVID(double vid) const; private: - double DecodeMulti(int fid, int did) const; - void EncodeMulti(double multi, int& fid, int& did) const; + double DecodeMulti(int fid, int did) const; + void EncodeMulti(double multi, int& fid, int& did) const; }; diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..82caeab --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +CXX = g++ +CXXFLAGS=-Os -Wall -pedantic + +all: + ${CXX} AmdMsrTweaker.cpp Info.cpp WinRing0.cpp Worker.cpp ${CXXFLAGS} -o amdmsrt + + diff --git a/StringUtils.h b/StringUtils.h index a9b18dc..b8bb594 100644 --- a/StringUtils.h +++ b/StringUtils.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include @@ -14,57 +15,51 @@ /// /// Some helper functions when working with strings. /// -class StringUtils -{ +class StringUtils { public: - /// Returns the string representation (according to std::stringstream) of a variable. - template static std::string ToString(const T& t) - { - std::stringstream ss; - ss << t; - return ss.str(); - } + /// Returns the string representation (according to std::stringstream) of a variable. + template static std::string ToString(const T& t) { + std::stringstream ss; + ss << t; + return ss.str(); + } - /// Returns the hexadecimal string representation (according to std::stringstream) of a variable. - template static std::string ToHexString(const T& t) - { - std::stringstream ss; - ss << std::hex << t; - return ss.str(); - } + /// Returns the hexadecimal string representation (according to std::stringstream) of a variable. + template static std::string ToHexString(const T& t) { + std::stringstream ss; + ss << std::hex << t; + return ss.str(); + } - /// - /// Splits a string into tokens separated by one or more delimiter characters. - /// Empty tokens may be skipped. - /// - static void Tokenize(std::vector& result, const char* str, const char* delimiters, bool skipEmpty = false) - { - // check for NULL and empty strings - if (str == NULL || delimiters == NULL || str[0] == 0 || delimiters[0] == 0) - return; + /// + /// Splits a string into tokens separated by one or more delimiter characters. + /// Empty tokens may be skipped. + /// + static void Tokenize(std::vector& result, const char* str, const char* delimiters, bool skipEmpty = false) { + // check for NULL and empty strings + if (str == NULL || delimiters == NULL || str[0] == 0 || delimiters[0] == 0) + return; - // create a copy of the string as it will be modified during tokenization - // (every delimiter will be replaced by a NULL character) - const size_t stringSize = strlen(str) + 1; // include the terminating NULL character - char* copy = new char[stringSize]; - memcpy(copy, str, stringSize); + // create a copy of the string as it will be modified during tokenization + // (every delimiter will be replaced by a NULL character) + const size_t stringSize = strlen(str) + 1; // include the terminating NULL character + char* copy = new char[stringSize]; + memcpy(copy, str, stringSize); - char* remainder; - char* token = strtok_s(copy, delimiters, &remainder); - while (token != NULL) - { - // skip empty tokens? - if (!skipEmpty || token[0] != 0) - result.push_back(std::string(token)); + char* remainder; + char* token = strtok_r(copy, delimiters, &remainder); + while (token != NULL) { + // skip empty tokens? + if (!skipEmpty || token[0] != 0) + result.push_back(std::string(token)); - token = strtok_s(NULL, delimiters, &remainder); - } + token = strtok_r(NULL, delimiters, &remainder); + } - delete[] copy; - } - static void Tokenize(std::vector& result, const std::string& str, const char* delimiters, bool skipEmpty = false) - { - return Tokenize(result, str.c_str(), delimiters, skipEmpty); - } + delete[] copy; + } + static void Tokenize(std::vector& result, const std::string& str, const char* delimiters, bool skipEmpty = false) { + return Tokenize(result, str.c_str(), delimiters, skipEmpty); + } }; diff --git a/WinRing0.cpp b/WinRing0.cpp index 6ca4053..ff75f41 100644 --- a/WinRing0.cpp +++ b/WinRing0.cpp @@ -5,8 +5,7 @@ * about permitted and prohibited uses of this code. */ -#pragma comment(lib, "WinRing0/WinRing0.lib") -#pragma comment(lib, "WinRing0/WinRing0x64.lib") +#include #include "WinRing0.h" #include "StringUtils.h" @@ -14,88 +13,70 @@ using std::exception; using std::string; +uint32_t ReadPciConfig(uint32_t device, uint32_t function, uint32_t regAddress) { + uint32_t result; + char path[255]= "\0"; + sprintf(path, "/proc/bus/pci/00/%d.%d", device, function); -DWORD ReadPciConfig(DWORD device, DWORD function, DWORD regAddress) -{ - const DWORD pciAddress = ((device & 0x1f) << 3) | (function & 0x7); + FILE* pci = fopen(path, "r"); + fseek(pci, function, SEEK_SET); + fread(&result, sizeof(result), 1, pci); + fclose(pci); - DWORD result; - if (!ReadPciConfigDwordEx(pciAddress, regAddress, &result)) - { - string msg = "cannot read from PCI configuration space (F"; - msg += StringUtils::ToString(function); - msg += "x"; - msg += StringUtils::ToHexString(regAddress); - msg += ")"; - - throw exception(msg.c_str()); - } - - return result; + return result; } -void WritePciConfig(DWORD device, DWORD function, DWORD regAddress, DWORD value) -{ - const DWORD pciAddress = ((device & 0x1f) << 3) | (function & 0x7); - - if (!WritePciConfigDwordEx(pciAddress, regAddress, value)) - { - string msg = "cannot write to PCI configuration space (F"; - msg += StringUtils::ToString(function); - msg += "x"; - msg += StringUtils::ToHexString(regAddress); - msg += ")"; +void WritePciConfig(uint32_t device, uint32_t function, uint32_t regAddress, uint32_t value) { + char path[255]= "\0"; + sprintf(path, "/proc/bus/pci/00/%d.%d", device, function); - throw exception(msg.c_str()); - } + FILE* pci = fopen(path, "w"); + fseek(pci, function, SEEK_SET); + fwrite(&value, sizeof(value), 1, pci); + fclose(pci); } -QWORD Rdmsr(DWORD index) -{ - QWORD result; - PDWORD eax = (PDWORD)&result; - PDWORD edx = eax + 1; +uint64_t Rdmsr(uint32_t index) { + uint64_t result; - if (!Rdmsr(index, eax, edx)) - { - string msg = "cannot read from MSR (0x"; - msg += StringUtils::ToHexString(index); - msg += ")"; + FILE* msr = fopen("/dev/cpu/0/msr", "r"); + fseek(msr, index, SEEK_SET); + fread(&result, sizeof(result), 1, msr); + fclose(msr); - throw exception(msg.c_str()); - } - - return result; + return result; } -void Wrmsr(DWORD index, const QWORD& value) -{ - PDWORD eax = (PDWORD)&value; - PDWORD edx = eax + 1; +int get_num_cpu() { + CpuidRegs regs = Cpuid(4); + return 1 + ((regs.eax>>26)&0xff); +} - if (!Wrmsr(index, *eax, *edx)) - { - string msg = "cannot write to MSR (0x"; - msg += StringUtils::ToHexString(index); - msg += ")"; +void Wrmsr(uint32_t index, const uint64_t& value) { + char path[255]= "\0"; - throw exception(msg.c_str()); - } + for (int i = 0; i < get_num_cpu(); i++) { + sprintf(path, "/dev/cpu/%d/msr", i); + FILE* msr = fopen(path, "w"); + fseek(msr, index, SEEK_SET); + fwrite(&value, sizeof(value), 1, msr); + fclose(msr); + } } -CpuidRegs Cpuid(DWORD index) -{ - CpuidRegs result; - if (!Cpuid(index, &result.eax, &result.ebx, &result.ecx, &result.edx)) - { - string msg = "cannot execute CPUID instruction (0x"; - msg += StringUtils::ToHexString(index); - msg += ")"; +CpuidRegs Cpuid(uint32_t index) { + CpuidRegs result; - throw exception(msg.c_str()); - } + FILE* cpuid = fopen("/dev/cpu/0/cpuid", "r"); + fseek(cpuid, index, SEEK_SET); + fread(&(result.eax), sizeof(result.eax), 1, cpuid); + fread(&(result.ebx), sizeof(result.ebx), 1, cpuid); + fread(&(result.ecx), sizeof(result.ecx), 1, cpuid); + fread(&(result.edx), sizeof(result.edx), 1, cpuid); + fclose(cpuid); - return result; + return result; } + diff --git a/WinRing0.h b/WinRing0.h index d2adbb7..50114b1 100644 --- a/WinRing0.h +++ b/WinRing0.h @@ -7,43 +7,45 @@ #pragma once -#define WIN32_MEAN_AND_LEAN -#include -#undef min -#undef max +#include -#include "WinRing0/OlsApi.h" +#include +#include - -typedef unsigned long long QWORD; - -struct CpuidRegs -{ - DWORD eax; - DWORD ebx; - DWORD ecx; - DWORD edx; +struct CpuidRegs { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; }; -static const DWORD AMD_CPU_DEVICE = 0x18; // first AMD CPU +static const uint32_t AMD_CPU_DEVICE = 0x18; // first AMD CPU -DWORD ReadPciConfig(DWORD device, DWORD function, DWORD regAddress); -void WritePciConfig(DWORD device, DWORD function, DWORD regAddress, DWORD value); +uint32_t ReadPciConfig(uint32_t device, uint32_t function, uint32_t regAddress); +void WritePciConfig(uint32_t device, uint32_t function, uint32_t regAddress, uint32_t value); -QWORD Rdmsr(DWORD index); -void Wrmsr(DWORD index, const QWORD& value); +uint64_t Rdmsr(uint32_t index); +void Wrmsr(uint32_t index, const uint64_t& value); -CpuidRegs Cpuid(DWORD index); +CpuidRegs Cpuid(uint32_t index); -template DWORD GetBits(T value, unsigned char offset, unsigned char numBits) -{ - const T mask = (((T)1 << numBits) - (T)1); // 2^numBits - 1; after right-shift - return (DWORD)((value >> offset) & mask); +template uint32_t GetBits(T value, unsigned char offset, unsigned char numBits) { + const T mask = (((T)1 << numBits) - (T)1); // 2^numBits - 1; after right-shift + return (uint32_t)((value >> offset) & mask); } -template void SetBits(T& value, DWORD bits, unsigned char offset, unsigned char numBits) -{ - const T mask = (((T)1 << numBits) - (T)1) << offset; // 2^numBits - 1, shifted by offset to the left - value = (value & ~mask) | (((T)bits << offset) & mask); +template void SetBits(T& value, uint32_t bits, unsigned char offset, unsigned char numBits) { + const T mask = (((T)1 << numBits) - (T)1) << offset; // 2^numBits - 1, shifted by offset to the left + value = (value & ~mask) | (((T)bits << offset) & mask); } + +class ExceptionWithMessage: public std::exception { + const char* what; + +public: + + ExceptionWithMessage(std::string msg) { + this->what = msg.c_str(); + } +}; diff --git a/Worker.cpp b/Worker.cpp index 5e4729f..521019c 100644 --- a/Worker.cpp +++ b/Worker.cpp @@ -8,6 +8,9 @@ #include #include #include + +#include + #include "Worker.h" #include "StringUtils.h" #include "WinRing0.h" @@ -21,233 +24,173 @@ using std::tolower; using std::vector; -static void SplitPair(string& left, string& right, const string& str, char delimiter) -{ - const size_t i = str.find(delimiter); +static void SplitPair(string& left, string& right, const string& str, char delimiter) { + const size_t i = str.find(delimiter); - left = str.substr(0, i); + left = str.substr(0, i); - if (i == string::npos) - right.clear(); - else - right = str.substr(i + 1); + if (i == string::npos) + right.clear(); + else + right = str.substr(i + 1); } -bool Worker::ParseParams(int argc, const char* argv[]) -{ - const Info& info = *_info; - - PStateInfo psi; - psi.Multi = psi.VID = psi.NBVID = -1; - psi.NBPState = -1; - - NBPStateInfo nbpsi; - nbpsi.Multi = nbpsi.VID = -1.0; - - for (int i = 0; i < info.NumPStates; i++) - { - _pStates.push_back(psi); - _pStates.back().Index = i; - } - for (int i = 0; i < info.NumNBPStates; i++) - { - _nbPStates.push_back(nbpsi); - _nbPStates.back().Index = i; - } - - for (int i = 1; i < argc; i++) - { - const string param(argv[i]); - - string key, value; - SplitPair(key, value, param, '='); - - if (value.empty()) - { - if (param.length() >= 2 && tolower(param[0]) == 'p') - { - const int index = atoi(param.c_str() + 1); - if (index >= 0 && index < info.NumPStates) - { - _pState = index; - continue; - } - } - } - else - { - if (key.length() >= 2 && tolower(key[0]) == 'p') - { - const int index = atoi(key.c_str() + 1); - if (index >= 0 && index < info.NumPStates) - { - string multi, vid; - SplitPair(multi, vid, value, '@'); - - if (!multi.empty()) - _pStates[index].Multi = info.multiScaleFactor * atof(multi.c_str()); - if (!vid.empty()) - _pStates[index].VID = info.EncodeVID(atof(vid.c_str())); - - continue; - } - } - - if (key.length() >= 5 && _strnicmp(key.c_str(), "NB_P", 4) == 0) - { - const int index = atoi(key.c_str() + 4); - if (index >= 0 && index < info.NumNBPStates) - { - string multi, vid; - SplitPair(multi, vid, value, '@'); - - if (!multi.empty()) - _nbPStates[index].Multi = atof(multi.c_str()); - if (!vid.empty()) - _nbPStates[index].VID = info.EncodeVID(atof(vid.c_str())); - - continue; - } - } - - if (_stricmp(key.c_str(), "NB_low") == 0) - { - const int index = atoi(value.c_str()); - - int j = 0; - for (; j < min(index, info.NumPStates); j++) - _pStates[j].NBPState = 0; - for (; j < info.NumPStates; j++) - _pStates[j].NBPState = 1; - - continue; - } - - if (_stricmp(key.c_str(), "Turbo") == 0) - { - const int flag = atoi(value.c_str()); - if (flag == 0 || flag == 1) - { - _turbo = flag; - continue; - } - } - - if (_stricmp(key.c_str(), "APM") == 0) - { - const int flag = atoi(value.c_str()); - if (flag == 0 || flag == 1) - { - _apm = flag; - continue; - } - } - } - - cerr << "ERROR: invalid parameter " << param.c_str() << endl; - return false; - } - - return true; +bool Worker::ParseParams(int argc, const char* argv[]) { + const Info& info = *_info; + + PStateInfo psi; + psi.Multi = psi.VID = psi.NBVID = -1; + psi.NBPState = -1; + + NBPStateInfo nbpsi; + nbpsi.Multi = nbpsi.VID = -1.0; + + for (int i = 0; i < info.NumPStates; i++) { + _pStates.push_back(psi); + _pStates.back().Index = i; + } + for (int i = 0; i < info.NumNBPStates; i++) { + _nbPStates.push_back(nbpsi); + _nbPStates.back().Index = i; + } + + for (int i = 1; i < argc; i++) { + const string param(argv[i]); + + string key, value; + SplitPair(key, value, param, '='); + + if (value.empty()) { + if (param.length() >= 2 && tolower(param[0]) == 'p') { + const int index = atoi(param.c_str() + 1); + if (index >= 0 && index < info.NumPStates) { + _pState = index; + continue; + } + } + } else { + if (key.length() >= 2 && tolower(key[0]) == 'p') { + const int index = atoi(key.c_str() + 1); + if (index >= 0 && index < info.NumPStates) { + string multi, vid; + SplitPair(multi, vid, value, '@'); + + if (!multi.empty()) + _pStates[index].Multi = info.multiScaleFactor * atof(multi.c_str()); + if (!vid.empty()) + _pStates[index].VID = info.EncodeVID(atof(vid.c_str())); + + continue; + } + } + + if (key.length() >= 5 && strncasecmp(key.c_str(), "NB_P", 4) == 0) { + const int index = atoi(key.c_str() + 4); + if (index >= 0 && index < info.NumNBPStates) { + string multi, vid; + SplitPair(multi, vid, value, '@'); + + if (!multi.empty()) + _nbPStates[index].Multi = atof(multi.c_str()); + if (!vid.empty()) + _nbPStates[index].VID = info.EncodeVID(atof(vid.c_str())); + + continue; + } + } + + if (strcasecmp(key.c_str(), "NB_low") == 0) { + const int index = atoi(value.c_str()); + + int j = 0; + for (; j < min(index, info.NumPStates); j++) + _pStates[j].NBPState = 0; + for (; j < info.NumPStates; j++) + _pStates[j].NBPState = 1; + + continue; + } + + if (strcasecmp(key.c_str(), "Turbo") == 0) { + const int flag = atoi(value.c_str()); + if (flag == 0 || flag == 1) { + _turbo = flag; + continue; + } + } + + if (strcasecmp(key.c_str(), "APM") == 0) { + const int flag = atoi(value.c_str()); + if (flag == 0 || flag == 1) { + _apm = flag; + continue; + } + } + } + + cerr << "ERROR: invalid parameter " << param.c_str() << endl; + return false; + } + + return true; } -static bool ContainsChanges(const PStateInfo& info) -{ - return (info.Multi >= 0 || info.VID >= 0 || info.NBVID >= 0 || info.NBPState >= 0); +static bool ContainsChanges(const PStateInfo& info) { + return (info.Multi >= 0 || info.VID >= 0 || info.NBVID >= 0 || info.NBPState >= 0); } -static bool ContainsChanges(const NBPStateInfo& info) -{ - return (info.Multi >= 0 || info.VID >= 0); -} - -static void SwitchTo(int logicalCPUIndex) -{ - const HANDLE hThread = GetCurrentThread(); - SetThreadAffinityMask(hThread, (DWORD_PTR)1 << logicalCPUIndex); +static bool ContainsChanges(const NBPStateInfo& info) { + return (info.Multi >= 0 || info.VID >= 0); } -void Worker::ApplyChanges() -{ - const Info& info = *_info; - - if (info.Family == 0x15) - { - for (int i = 0; i < _nbPStates.size(); i++) - { - const NBPStateInfo& nbpsi = _nbPStates[i]; - if (ContainsChanges(nbpsi)) - info.WriteNBPState(nbpsi); - } - } - else if (info.Family == 0x10 && (_nbPStates[0].VID >= 0 || _nbPStates[1].VID >= 0)) - { - for (int i = 0; i < _pStates.size(); i++) - { - PStateInfo& psi = _pStates[i]; - - const int nbPState = (psi.NBPState >= 0 ? psi.NBPState : - info.ReadPState(i).NBPState); - const NBPStateInfo& nbpsi = _nbPStates[nbPState]; - - if (nbpsi.VID >= 0) - psi.NBVID = nbpsi.VID; - } - } - - if (_turbo >= 0 && info.IsBoostSupported) - info.SetBoostSource(_turbo == 1); - if (_apm >= 0 && info.Family == 0x15) - info.SetAPM(_apm == 1); - - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - const int numLogicalCPUs = sysInfo.dwNumberOfProcessors; - - // switch to the highest thread priority (we do not want to get interrupted often) - const HANDLE hProcess = GetCurrentProcess(); - const HANDLE hThread = GetCurrentThread(); - SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS); - SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); - - // perform one iteration in each logical core - for (int j = 0; j < numLogicalCPUs; j++) - { - SwitchTo(j); - - for (int i = 0; i < _pStates.size(); i++) - { - const PStateInfo& psi = _pStates[i]; - if (ContainsChanges(psi)) - info.WritePState(psi); - } - - if (_turbo >= 0 && info.IsBoostSupported) - info.SetCPBDis(_turbo == 1); - } - - for (int j = 0; j < numLogicalCPUs; j++) - { - SwitchTo(j); - - const int currentPState = info.GetCurrentPState(); - const int newPState = (_pState >= 0 ? _pState : currentPState); - - if (newPState != currentPState) - info.SetCurrentPState(newPState); - else - { - if (ContainsChanges(_pStates[currentPState])) - { - const int tempPState = (currentPState == info.NumPStates - 1 ? 0 : info.NumPStates - 1); - info.SetCurrentPState(tempPState); - Sleep(1); - info.SetCurrentPState(currentPState); - } - } - } - - SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL); - SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS); +void Worker::ApplyChanges() { + const Info& info = *_info; + + if (info.Family == 0x15) { + for (size_t i = 0; i < _nbPStates.size(); i++) { + const NBPStateInfo& nbpsi = _nbPStates[i]; + if (ContainsChanges(nbpsi)) + info.WriteNBPState(nbpsi); + } + } else if (info.Family == 0x10 && (_nbPStates[0].VID >= 0 || _nbPStates[1].VID >= 0)) { + for (size_t i = 0; i < _pStates.size(); i++) { + PStateInfo& psi = _pStates[i]; + + const int nbPState = (psi.NBPState >= 0 ? psi.NBPState : + info.ReadPState(i).NBPState); + const NBPStateInfo& nbpsi = _nbPStates[nbPState]; + + if (nbpsi.VID >= 0) + psi.NBVID = nbpsi.VID; + } + } + + if (_turbo >= 0 && info.IsBoostSupported) + info.SetBoostSource(_turbo == 1); + if (_apm >= 0 && info.Family == 0x15) + info.SetAPM(_apm == 1); + + for (size_t i = 0; i < _pStates.size(); i++) { + const PStateInfo& psi = _pStates[i]; + if (ContainsChanges(psi)) + info.WritePState(psi); + } + + if (_turbo >= 0 && info.IsBoostSupported) + info.SetCPBDis(_turbo == 1); + + const int currentPState = info.GetCurrentPState(); + const int newPState = (_pState >= 0 ? _pState : currentPState); + + if (newPState != currentPState) + info.SetCurrentPState(newPState); + else { + if (ContainsChanges(_pStates[currentPState])) { + const int tempPState = (currentPState == info.NumPStates - 1 ? 0 : info.NumPStates - 1); + info.SetCurrentPState(tempPState); + sleep(1); + info.SetCurrentPState(currentPState); + } + } } diff --git a/Worker.h b/Worker.h index 76c34c3..fd0d69c 100644 --- a/Worker.h +++ b/Worker.h @@ -11,28 +11,27 @@ #include "Info.h" -class Worker -{ +class Worker { public: - Worker(const Info& info) - : _info(&info) - , _turbo(-1) - , _apm(-1) - , _pState(-1) - { } + Worker(const Info& info) + : _info(&info) + , _turbo(-1) + , _apm(-1) + , _pState(-1) + { } - bool ParseParams(int argc, const char* argv[]); + bool ParseParams(int argc, const char* argv[]); - void ApplyChanges(); + void ApplyChanges(); private: - const Info* _info; - std::vector _pStates; - std::vector _nbPStates; - int _turbo; // enable (1)/disable (0) CPB - int _apm; // enable (1)/disable (0) APM - int _pState; // hardware index of the P-state to be activated + const Info* _info; + std::vector _pStates; + std::vector _nbPStates; + int _turbo; // enable (1)/disable (0) CPB + int _apm; // enable (1)/disable (0) APM + int _pState; // hardware index of the P-state to be activated };