From 12aab58198347e08e083abbe203e6acf703ff7a7 Mon Sep 17 00:00:00 2001 From: KazushiM <85604869+KazushiMe@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:22:02 +0800 Subject: [PATCH] [Sys-clk-OC] improve Auto-Boost CPU (reuse some code from Governor_PoC) --- README.md | 6 +- .../contents/00FF0000636C6BFF/exefs.nsp | Bin 168586 -> 167634 bytes SdOut/config/sys-clk/boost_start.flag | 0 .../sys-clk-OC/common/include/sysclk/clocks.h | 11 + .../sysmodule/src/clock_manager.cpp | 317 +++++++++++------- .../sys-clk-OC/sysmodule/src/clock_manager.h | 40 ++- .../sys-clk-OC/sysmodule/src/file_utils.cpp | 13 - Source/sys-clk-OC/sysmodule/src/file_utils.h | 1 - 8 files changed, 237 insertions(+), 151 deletions(-) delete mode 100644 SdOut/config/sys-clk/boost_start.flag diff --git a/README.md b/README.md index 5e598fec..4aa7e9fd 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,9 @@ This project will not be actively maintained by me and I'm looking for collabora - Add `/config/sys-clk/downclock_dock.flag` to use handheld clocks in Docked mode when Handheld mode is set in ReverseNX. - To **disable this feature**, use original version of ReverseNX-RT and delete `/config/sys-clk/ReverseNX_sync.flag`. - **Auto-Boost CPU for faster game loading** - - When a game launches or is in loading screen, sys-clk will boost CPU to 1963.5 MHz for ~10 seconds or until the loading screen ends. - - Some games don't utilize `SetCpuBoostMode` at all, e.g. Overcooked 2, so Auto-Boost will be unavailable to these games. - - To **disable this feature**, simply remove `boost_start.flag` and `boost.flag` in `/config/sys-clk/ `. + - Enable CPU Boost (1963.5 MHz) if CPU Core#3 (System Core) is stressed, especially when the game is loading assets from eMMC/SD card. + - Auto-Boost will be enabled only when charger is connected. (>90% w/ PD charger or >95% w/ unsupported charger) + - To **disable this feature**, simply remove `boost.flag` in `/config/sys-clk/ `. - Profile-aware clock override for all games - Add `[A111111111111111]` title config in `/config/sys-clk/config.ini` to set frequency override globally: ```ini diff --git a/SdOut/atmosphere/contents/00FF0000636C6BFF/exefs.nsp b/SdOut/atmosphere/contents/00FF0000636C6BFF/exefs.nsp index 7fa9818e8e1722102bc6a970c9cbc1950217ee2b..dffbb43756095157d3604a7cdf6a6bc832a9445f 100644 GIT binary patch delta 48900 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 diff --git a/SdOut/config/sys-clk/boost_start.flag b/SdOut/config/sys-clk/boost_start.flag deleted file mode 100644 index e69de29b..00000000 diff --git a/Source/sys-clk-OC/common/include/sysclk/clocks.h b/Source/sys-clk-OC/common/include/sysclk/clocks.h index c80d615e..d1f17195 100644 --- a/Source/sys-clk-OC/common/include/sysclk/clocks.h +++ b/Source/sys-clk-OC/common/include/sysclk/clocks.h @@ -48,8 +48,19 @@ typedef struct uint32_t freqs[SysClkModule_EnumMax]; uint32_t overrideFreqs[SysClkModule_EnumMax]; uint32_t temps[SysClkThermalSensor_EnumMax]; + uint32_t perfConfId; } SysClkContext; +typedef struct +{ + bool systemCoreBoostCPU; + bool systemCoreBoostCPUReset; + bool systemCoreCheckStuck; + uint64_t tickWaitTimeMs; + uint8_t systemCoreBoostThreshold; + // int16_t systemCoreStuckCount; +} SysClkOcExtra; + typedef struct { union { diff --git a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp index 15deeede..7e2d83b3 100644 --- a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp +++ b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp @@ -52,23 +52,29 @@ ClockManager::ClockManager() this->context->freqs[i] = 0; this->context->overrideFreqs[i] = 0; } + this->context->perfConfId = 0; this->running = false; this->lastTempLogNs = 0; this->lastCsvWriteNs = 0; + + this->oc = new SysClkOcExtra; + this->oc->systemCoreBoostCPU = false; + this->oc->systemCoreCheckStuck = false; + this->oc->tickWaitTimeMs = 500; + this->oc->systemCoreBoostThreshold = 100; + // this->oc->systemCoreStuckCount = 0; } ClockManager::~ClockManager() { delete this->config; delete this->context; + delete this->oc; } bool ClockManager::IsCpuBoostMode() { - std::uint32_t confId = 0; - Result rc = 0; - rc = apmExtGetCurrentPerformanceConfiguration(&confId); - ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration"); + std::uint32_t confId = this->context->perfConfId; if(confId == 0x92220009 || confId == 0x9222000A) return true; else @@ -163,36 +169,6 @@ void ClockManager::checkReverseNXTool() } } -bool ClockManager::GameStartBoost() -{ - if (tickStartBoost && this->GetConfig()->Enabled()) - { - if (Clocks::GetCurrentHz(SysClkModule_CPU) != MAX_CPU) - { - Clocks::SetHz(SysClkModule_CPU, MAX_CPU); - this->context->freqs[SysClkModule_CPU] = MAX_CPU; - } - - std::uint64_t applicationId = ProcessManagement::GetCurrentApplicationId(); - // If user exit the game - if (applicationId != this->context->applicationId) - { - tickStartBoost = 0; - return false; - } - - if (tickStartBoost == 1) - { - FileUtils::LogLine("[mgr] Boost done, reset to stock"); - Clocks::ResetToStock(); - } - tickStartBoost--; - return true; - } - - return false; -} - void ClockManager::SetRunning(bool running) { this->running = running; @@ -203,81 +179,93 @@ bool ClockManager::Running() return this->running; } +uint32_t ClockManager::GetHz(SysClkModule module) +{ + uint32_t hz = 0; + + /* Temp override setting */ + hz = this->context->overrideFreqs[module]; + + /* Per-Game setting */ + if (!hz) + hz = this->config->GetAutoClockHz(this->context->applicationId, module, this->context->profile); + + /* Global setting */ + if (!hz) + hz = this->config->GetAutoClockHz(0xA111111111111111, module, this->context->profile); + + /* Adjust hz if ReverseNX is enabled */ + if (!hz && isEnabledReverseNX) + { + switch(module) + { + case SysClkModule_CPU: + hz = 1020'000'000; + break; + case SysClkModule_GPU: + if (!isDockedReverseNX && ((FileUtils::IsDownclockDockEnabled() && RealProfile == SysClkProfile_Docked) + || RealProfile != SysClkProfile_Docked)) + hz = 460'800'000; + else + hz = 768'000'000; + break; + case SysClkModule_MEM: + if (!isDockedReverseNX && ((FileUtils::IsDownclockDockEnabled() && RealProfile == SysClkProfile_Docked) + || RealProfile != SysClkProfile_Docked)) + hz = 1331'200'000; + else + hz = 1600'000'000; + break; + default: + break; + } + } + + if (hz) + { + hz = Clocks::GetNearestHz(module, isEnabledReverseNX ? RealProfile : this->context->profile, hz); + + /* Ignore if MEM Max Hz > 1600 MHz */ + if (module == SysClkModule_MEM && hz == 1600'000'000 && this->context->freqs[module] >= hz) + { + return 0; + } + } + + if (module == SysClkModule_CPU) + { + if (this->oc->systemCoreBoostCPU && hz < MAX_CPU) + return MAX_CPU; + else if (!hz) + return 1020'000'000; + } + + return hz; +} + void ClockManager::Tick() { std::scoped_lock lock{this->contextMutex}; - if(!GameStartBoost()) + if ((this->RefreshContext() || this->config->Refresh()) && this->context->enabled) { - bool cpuBoost = FileUtils::IsBoostEnabled() ? IsCpuBoostMode() : false; - if (this->RefreshContext() || this->config->Refresh()) + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { - std::uint32_t hz = 0; - std::uint32_t hzForceOverride = 0; - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) + uint32_t hz = GetHz((SysClkModule)module); + + if (hz && hz != this->context->freqs[module]) { - hz = this->context->overrideFreqs[module]; - - if(!hz) + if (IsCpuBoostMode()) { - hz = this->config->GetAutoClockHz(this->context->applicationId, (SysClkModule)module, this->context->profile); - hzForceOverride = this->config->GetAutoClockHz(0xA111111111111111, (SysClkModule)module, this->context->profile); - if (!hz && hzForceOverride) - hz = hzForceOverride; - - if(isEnabledReverseNX && !hz) - { - switch(module) - { - case SysClkModule_CPU: - hz = 1020'000'000; - break; - case SysClkModule_GPU: - if (!isDockedReverseNX && ((FileUtils::IsDownclockDockEnabled() && RealProfile == SysClkProfile_Docked) - || RealProfile != SysClkProfile_Docked)) - hz = 460'800'000; - else - hz = 768'000'000; - break; - case SysClkModule_MEM: - if (!isDockedReverseNX && ((FileUtils::IsDownclockDockEnabled() && RealProfile == SysClkProfile_Docked) - || RealProfile != SysClkProfile_Docked)) - hz = 1331'200'000; - else - hz = 1600'000'000; - break; - } - } - - } - - if (hz) - { - hz = Clocks::GetNearestHz((SysClkModule)module, isEnabledReverseNX ? RealProfile : this->context->profile, hz); - if (module == SysClkModule_MEM && hz == 1600'000'000 && this->context->freqs[module] >= hz) + // Skip setting CPU or GPU clocks in CpuBoostMode if CPU <= 1963.5MHz or GPU >= 76.8MHz + if ((module == SysClkModule_CPU && hz <= MAX_CPU) || module == SysClkModule_GPU) { continue; } - - if (hz != this->context->freqs[module] && this->context->enabled) - { - if (cpuBoost) - { - // Skip setting CPU or GPU clocks in CpuBoostMode if CPU < 1963.5MHz or GPU > 76.8MHz - if (module == SysClkModule_CPU && hz < MAX_CPU) - { - continue; - } - if (module == SysClkModule_GPU && hz > 76'800'000) - { - continue; - } - } - FileUtils::LogLine("[mgr] %s clock set : %u.%u Mhz", Clocks::GetModuleName((SysClkModule)module, true), hz/1000000, hz/100000 - hz/1000000*10); - Clocks::SetHz((SysClkModule)module, hz); - this->context->freqs[module] = hz; - } } + FileUtils::LogLine("[mgr] %s clock set : %u.%u Mhz", Clocks::GetModuleName((SysClkModule)module, true), hz/1000000, hz/100000 - hz/1000000*10); + Clocks::SetHz((SysClkModule)module, hz); + this->context->freqs[module] = hz; } } } @@ -285,17 +273,113 @@ void ClockManager::Tick() void ClockManager::WaitForNextTick() { - svcSleepThread(this->GetConfig()->GetConfigValue(SysClkConfigValue_PollingIntervalMs) * 1000000ULL); + /* Self-check system core (#3) usage via idleticks at intervals (Not enabled at higher CPU freq or without charger) */ + this->oc->tickWaitTimeMs = this->GetConfig()->GetConfigValue(SysClkConfigValue_PollingIntervalMs); + + if ( this->context->enabled + && this->context->profile != SysClkProfile_Handheld + && this->context->freqs[SysClkModule_CPU] <= MAX_CPU) + { + uint64_t systemCoreIdleTickPrev = 0, systemCoreIdleTickNext = 0; + svcGetInfo(&systemCoreIdleTickPrev, InfoType_IdleTickCount, INVALID_HANDLE, 3); + svcSleepThread(this->oc->tickWaitTimeMs * 1000000ULL); + svcGetInfo(&systemCoreIdleTickNext, InfoType_IdleTickCount, INVALID_HANDLE, 3); + + /* Convert idletick to load% */ + /* If CPU core usage is 0%, then idletick = 19'200'000 per sec */ + uint64_t systemCoreIdleTick = systemCoreIdleTickNext - systemCoreIdleTickPrev; + uint64_t freeIdleTick = 19'200 * this->oc->tickWaitTimeMs; + uint8_t freePerc = systemCoreIdleTick / (freeIdleTick / 100); + + bool systemCoreBoostCPU_PrevState = this->oc->systemCoreBoostCPU; + + switch (this->context->profile) + { + case SysClkProfile_HandheldChargingOfficial: + case SysClkProfile_Docked: + this->oc->systemCoreBoostThreshold = systemCoreBoostCPU_PrevState ? 6 : 10; + break; + default: // Unofficial charger + this->oc->systemCoreBoostThreshold = systemCoreBoostCPU_PrevState ? 3 : 5; + break; + } + + this->oc->systemCoreBoostCPU = (freePerc <= this->oc->systemCoreBoostThreshold); + + if (systemCoreBoostCPU_PrevState && !this->oc->systemCoreBoostCPU) + { + Clocks::SetHz(SysClkModule_CPU, GetHz(SysClkModule_CPU)); + } + else if (!systemCoreBoostCPU_PrevState && this->oc->systemCoreBoostCPU) + { + Clocks::SetHz(SysClkModule_CPU, MAX_CPU); + } + } + else + { + svcSleepThread(this->oc->tickWaitTimeMs * 1000000ULL); + } + + /* Signal that systemCore is not busy */ + // this->oc->systemCoreStuckCount = 0; } +/* Tricky part, see IpcService implementation of calling static member function */ +// I don't see any use of this @ 1020 MHz (only useful at lowest freq), +// and downclock below 1020 MHz won't save battery. (same volt @ 600mV) +/*void ClockManager::CheckSystemCoreStuck(void *arg) +{ + ClockManager* clkMgr = (ClockManager*)arg; + while (clkMgr->oc->systemCoreCheckStuck) + { + svcSleepThread(clkMgr->oc->tickWaitTimeMs * 1000000ULL); + + if (clkMgr->context->freqs[SysClkModule_CPU] >= clkMgr->MAX_CPU) + continue; + + // Core #0,1,2 will check if Core#3 is stuck (threshold count = 2*3 = 6) + // ! Add mutex ! + if (clkMgr->oc->systemCoreStuckCount++ > 6) + { + // Signal that current core will take over to boost CPU and wait some time to recheck + clkMgr->oc->systemCoreStuckCount = -6; + Clocks::SetHz(SysClkModule_CPU, clkMgr->MAX_CPU); + } + } +}*/ + +/*void ClockManager::StartCheckSystemCore() +{ + this->oc->systemCoreCheckStuck = true; + threadCreate(&this->t_CheckSystemCoreStuck_0, this->CheckSystemCoreStuck, NULL, NULL, 0x1000, 0x20, 0); + threadCreate(&this->t_CheckSystemCoreStuck_1, this->CheckSystemCoreStuck, NULL, NULL, 0x1000, 0x20, 1); + threadCreate(&this->t_CheckSystemCoreStuck_2, this->CheckSystemCoreStuck, NULL, NULL, 0x1000, 0x20, 2); + threadStart(&this->t_CheckSystemCoreStuck_0); + threadStart(&this->t_CheckSystemCoreStuck_1); + threadStart(&this->t_CheckSystemCoreStuck_2); +}*/ + +/*void ClockManager::StopCheckSystemCore() +{ + this->oc->systemCoreCheckStuck = false; + threadWaitForExit(&this->t_CheckSystemCoreStuck_0); + threadWaitForExit(&this->t_CheckSystemCoreStuck_1); + threadWaitForExit(&this->t_CheckSystemCoreStuck_2); + threadClose(&this->t_CheckSystemCoreStuck_0); + threadClose(&this->t_CheckSystemCoreStuck_1); + threadClose(&this->t_CheckSystemCoreStuck_2); +}*/ + void ClockManager::checkReverseNXToolAsm(FILE* readFile, uint8_t* flag) { - // Copied from ReverseNXTool + // Magic Value uint8_t Docked[0x10] = {0xE0, 0x03, 0x00, 0x32, 0xC0, 0x03, 0x5F, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t Handheld[0x10] = {0x00, 0x00, 0xA0, 0x52, 0xC0, 0x03, 0x5F, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t filebuffer[0x10] = {0}; - uint8_t cmpresult = 0; fread(&filebuffer, 1, 16, readFile); + + uint8_t cmpresult = 0; cmpresult = memcmp(filebuffer, Docked, sizeof(Docked)); if (cmpresult != 0) { @@ -367,18 +451,6 @@ bool ClockManager::RefreshContext() if (applicationId != PROCESS_MANAGEMENT_QLAUNCH_TID) this->checkReverseNXTool(); } - - if (FileUtils::IsBoostStartEnabled() && this->context->applicationId != PROCESS_MANAGEMENT_QLAUNCH_TID) - { - // If a game starts and overrides for CPU are not enabled, then set MAX_CPU for 10 sec - std::uint32_t overcpu = this->context->overrideFreqs[SysClkModule_CPU]; - if (!overcpu) - { - tickStartBoost = (std::uint32_t)( 10'000 / this->GetConfig()->GetConfigValue(SysClkConfigValue_PollingIntervalMs) ) + 1; - FileUtils::LogLine("[mgr] A game starts, bump CPU to max for 10 sec"); - return true; - } - } } if (FileUtils::IsReverseNXSyncEnabled() && (!tickCheckReverseNXRT || recheckReverseNX)) @@ -420,8 +492,7 @@ bool ClockManager::RefreshContext() this->checkReverseNXTool(); break; } - // Check once per sec - tickCheckReverseNXRT = (std::uint32_t)( 1'000 / this->GetConfig()->GetConfigValue(SysClkConfigValue_PollingIntervalMs) ) + 1; + tickCheckReverseNXRT = (std::uint32_t)( 1'000 / this->oc->tickWaitTimeMs ) + 1; } tickCheckReverseNXRT--; @@ -444,6 +515,19 @@ bool ClockManager::RefreshContext() recheckReverseNX = true; } + /* Update PerformanceConfigurationId */ + { + uint32_t confId = 0; + Result rc = 0; + rc = apmExtGetCurrentPerformanceConfiguration(&confId); + ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration"); + if (this->context->perfConfId != confId) + { + this->context->perfConfId = confId; + hasChanged = true; + } + } + // restore clocks to stock values on app or profile change if(hasChanged) Clocks::ResetToStock(); @@ -453,10 +537,7 @@ bool ClockManager::RefreshContext() { hz = Clocks::GetCurrentHz((SysClkModule)module); - // Round to MHz - uint32_t cur_mhz = hz/1000'000; - uint32_t be4_mhz = this->context->freqs[module]/1000'000; - if (hz != 0 && cur_mhz != be4_mhz) + if (hz != 0 && hz != this->context->freqs[module]) { FileUtils::LogLine("[mgr] %s clock change: %u.%u Mhz", Clocks::GetModuleName((SysClkModule)module, true), hz/1000000, hz/100000 - hz/1000000*10); this->context->freqs[module] = hz; diff --git a/Source/sys-clk-OC/sysmodule/src/clock_manager.h b/Source/sys-clk-OC/sysmodule/src/clock_manager.h index 2d38dd5a..9fee66e4 100644 --- a/Source/sys-clk-OC/sysmodule/src/clock_manager.h +++ b/Source/sys-clk-OC/sysmodule/src/clock_manager.h @@ -26,26 +26,10 @@ class ClockManager static void Initialize(); static void Exit(); - bool recheckReverseNX = false; - bool isEnabledReverseNX = false; - bool isEnabledReverseNXTool = false; - bool isDockedReverseNX = false; - std::uint16_t tickCheckReverseNXRT = 0; - std::uint16_t tickStartBoost = 0; - char prevReverseNXRT = 0; - SysClkProfile RealProfile; - - bool IsCpuBoostMode(); - SysClkProfile ReverseNXProfile(bool); - void checkReverseNXTool(); - bool GameStartBoost(); - void SetRunning(bool running); bool Running(); void Tick(); void WaitForNextTick(); - void checkReverseNXToolAsm(FILE*, uint8_t*); - void checkReverseNXRT(bool, uint8_t*); SysClkContext GetCurrentContext(); Config* GetConfig(); @@ -62,4 +46,28 @@ class ClockManager SysClkContext *context; std::uint64_t lastTempLogNs; std::uint64_t lastCsvWriteNs; + + bool recheckReverseNX = false; + bool isEnabledReverseNX = false; + bool isEnabledReverseNXTool = false; + bool isDockedReverseNX = false; + uint16_t tickCheckReverseNXRT = 0; + uint8_t prevReverseNXRT = 0; + SysClkProfile RealProfile; + + bool IsCpuBoostMode(); + SysClkProfile ReverseNXProfile(bool); + void checkReverseNXTool(); + + void checkReverseNXToolAsm(FILE*, uint8_t*); + void checkReverseNXRT(bool, uint8_t*); + + SysClkOcExtra *oc; + uint32_t GetHz(SysClkModule); + + // Thread t_CheckSystemCoreStuck_0, t_CheckSystemCoreStuck_1, t_CheckSystemCoreStuck_2; + + // static void CheckSystemCoreStuck(void *arg); + // void StartCheckSystemCore(); + // void StopCheckSystemCore(); }; diff --git a/Source/sys-clk-OC/sysmodule/src/file_utils.cpp b/Source/sys-clk-OC/sysmodule/src/file_utils.cpp index 257e2e26..51d5e4ba 100644 --- a/Source/sys-clk-OC/sysmodule/src/file_utils.cpp +++ b/Source/sys-clk-OC/sysmodule/src/file_utils.cpp @@ -19,7 +19,6 @@ static LockableMutex g_csv_mutex; static std::atomic_bool g_has_initialized = false; static bool g_log_enabled = false; static bool g_boost_enabled = false; -static bool g_boost_start_enabled = false; static bool g_downclock_dock_enabled = false; static bool g_reversenx_tool_exist = false; static bool g_reversenx_sync_enabled = false; @@ -167,13 +166,6 @@ void FileUtils::InitCheckFlags() g_boost_enabled = true; fclose(file); } - - file = fopen(FILE_BOOST_START_FLAG_PATH, "r"); - if (file) - { - g_boost_start_enabled = true; - fclose(file); - } } file = fopen(FILE_DOWNCLOCK_DOCK_FLAG_PATH, "r"); @@ -203,11 +195,6 @@ bool FileUtils::IsBoostEnabled() return g_boost_enabled; } -bool FileUtils::IsBoostStartEnabled() -{ - return g_boost_start_enabled; -} - bool FileUtils::IsDownclockDockEnabled() { return g_downclock_dock_enabled; diff --git a/Source/sys-clk-OC/sysmodule/src/file_utils.h b/Source/sys-clk-OC/sysmodule/src/file_utils.h index 7cc3cac0..54be528b 100644 --- a/Source/sys-clk-OC/sysmodule/src/file_utils.h +++ b/Source/sys-clk-OC/sysmodule/src/file_utils.h @@ -37,7 +37,6 @@ class FileUtils static bool IsInitialized(); static bool IsLogEnabled(); static bool IsBoostEnabled(); - static bool IsBoostStartEnabled(); static bool IsDownclockDockEnabled(); static bool IsReverseNXSyncEnabled(); static bool IsReverseNXToolExist();