Add hijack dvfs from sys-clk-eos
This commit is contained in:
@@ -96,9 +96,23 @@ std::atomic<uint64_t> idletick2{systemtickfrequency};
|
|||||||
std::atomic<uint64_t> idletick3{systemtickfrequency};
|
std::atomic<uint64_t> idletick3{systemtickfrequency};
|
||||||
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
|
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
|
||||||
u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC
|
u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC
|
||||||
|
u32 speedoBracket;
|
||||||
u16 cpuIDDQ, gpuIDDQ, socIDDQ;
|
u16 cpuIDDQ, gpuIDDQ, socIDDQ;
|
||||||
u8 g_dramID = 0;
|
u8 g_dramID = 0;
|
||||||
|
|
||||||
|
static const u32 ramBrackets[][22] = {
|
||||||
|
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||||
|
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||||
|
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||||
|
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||||
|
|
||||||
|
u32 dvfsTable[6][32] = {};
|
||||||
|
u64 dvfsAddress;
|
||||||
|
u32 ramVmin;
|
||||||
|
|
||||||
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
||||||
{
|
{
|
||||||
ASSERT_ENUM_VALID(SysClkModule, module);
|
ASSERT_ENUM_VALID(SysClkModule, module);
|
||||||
@@ -792,6 +806,7 @@ u8 Board::GetDramID() {
|
|||||||
void Board::FetchHardwareInfos()
|
void Board::FetchHardwareInfos()
|
||||||
{
|
{
|
||||||
fuseReadSpeedos();
|
fuseReadSpeedos();
|
||||||
|
SetSpeedoBracket();
|
||||||
u64 sku = 0, dramID = 0;
|
u64 sku = 0, dramID = 0;
|
||||||
Result rc = splInitialize();
|
Result rc = splInitialize();
|
||||||
ASSERT_RESULT_OK(rc, "splInitialize");
|
ASSERT_RESULT_OK(rc, "splInitialize");
|
||||||
@@ -816,9 +831,12 @@ void Board::FetchHardwareInfos()
|
|||||||
g_socType = SysClkSocType_Erista;
|
g_socType = SysClkSocType_Erista;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_socType == SysClkSocType_Mariko) {
|
||||||
|
CacheDvfsTable();
|
||||||
|
}
|
||||||
|
|
||||||
g_consoleType = (HorizonOCConsoleType)sku;
|
g_consoleType = (HorizonOCConsoleType)sku;
|
||||||
g_dramID = (u8)dramID;
|
g_dramID = (u8)dramID;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -926,6 +944,168 @@ std::uint32_t Board::GetVoltage(HocClkVoltage voltage)
|
|||||||
return out > 0 ? out : 0;
|
return out > 0 ? out : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Board::SetSpeedoBracket() {
|
||||||
|
if (cpuSpeedo2 >= 1754) {
|
||||||
|
speedoBracket = 3;
|
||||||
|
} else if (cpuSpeedo2 >= 1690) {
|
||||||
|
speedoBracket = 2;
|
||||||
|
} else if (cpuSpeedo2 > 1625) {
|
||||||
|
speedoBracket = 1;
|
||||||
|
} else {
|
||||||
|
speedoBracket = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Board::GetMinimumGpuVoltage(u32 freqMhz) {
|
||||||
|
if (freqMhz <= 1600)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (u32 voltageIndex = 0; voltageIndex < 22; ++voltageIndex) {
|
||||||
|
if (freqMhz <= ramBrackets[speedoBracket][voltageIndex]) {
|
||||||
|
return gpuDvfsArray[voltageIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle Board::GetPcvHandle() {
|
||||||
|
constexpr u64 PcvID = 0x10000000000001a;
|
||||||
|
u64 processIDList[80]{};
|
||||||
|
s32 processCount = 0;
|
||||||
|
Handle handle = INVALID_HANDLE;
|
||||||
|
|
||||||
|
DebugEventInfo debugEvent{};
|
||||||
|
|
||||||
|
/* Get all running processes. */
|
||||||
|
Result resultGetProcessList = svcGetProcessList(&processCount, processIDList, std::size(processIDList));
|
||||||
|
if (R_FAILED(resultGetProcessList)) {
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to find pcv. */
|
||||||
|
for (int i = 0; i < processCount; ++i) {
|
||||||
|
if (handle != INVALID_HANDLE) {
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to debug process, if it fails, try next process. */
|
||||||
|
Result resultSvcDebugProcess = svcDebugActiveProcess(&handle, processIDList[i]);
|
||||||
|
if (R_FAILED(resultSvcDebugProcess)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get a debug event. */
|
||||||
|
Result resultDebugEvent = svcGetDebugEvent(&debugEvent, handle);
|
||||||
|
if (R_SUCCEEDED(resultDebugEvent)) {
|
||||||
|
if (debugEvent.info.create_process.program_id == PcvID) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failed to get handle. */
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::CacheDvfsTable() {
|
||||||
|
const u32 voltagePattern[] = { 600000, 12500, 1400000, };
|
||||||
|
|
||||||
|
Handle handle = GetPcvHandle();
|
||||||
|
if (handle == INVALID_HANDLE) {
|
||||||
|
FileUtils::LogLine("[Board] Invalid handle!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryInfo memoryInfo = {};
|
||||||
|
u64 address = 0;
|
||||||
|
u32 pageInfo = 0;
|
||||||
|
constexpr u32 PageSize = 0x1000;
|
||||||
|
u8 buffer[PageSize];
|
||||||
|
|
||||||
|
/* Loop until failure. */
|
||||||
|
while (true) {
|
||||||
|
/* Find pcv heap. */
|
||||||
|
while (true) {
|
||||||
|
Result resultProcessMemory = svcQueryDebugProcessMemory(&memoryInfo, &pageInfo, handle, address);
|
||||||
|
address = memoryInfo.addr + memoryInfo.size;
|
||||||
|
|
||||||
|
if (R_FAILED(resultProcessMemory) || !address) {
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
FileUtils::LogLine("[Board] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory));
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memoryInfo.size && (memoryInfo.perm & 3) == 3 && static_cast<char>(memoryInfo.type) == 0x04) {
|
||||||
|
/* Found valid memory. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 base = 0; base < memoryInfo.size; base += PageSize) {
|
||||||
|
u32 memorySize = std::min(memoryInfo.size, static_cast<u64>(PageSize));
|
||||||
|
if (R_FAILED(svcReadDebugProcessMemory(buffer, handle, base + memoryInfo.addr, memorySize))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *resultPattern = static_cast<u8 *>(memmem(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern)));
|
||||||
|
u32 index = resultPattern - buffer;
|
||||||
|
|
||||||
|
if (!resultPattern) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assuming mariko. */
|
||||||
|
const u32 vmax = 800;
|
||||||
|
constexpr u32 DvfsTableOffset = 312;
|
||||||
|
if (!std::memcmp(&buffer[index + DvfsTableOffset], &vmax, sizeof(vmax))) {
|
||||||
|
std::memcpy(dvfsTable, &buffer[index + DvfsTableOffset], sizeof(dvfsTable));
|
||||||
|
dvfsAddress = base + memoryInfo.addr + DvfsTableOffset + index;
|
||||||
|
}
|
||||||
|
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::PcvHijackDvfs(u32 vmin) {
|
||||||
|
u32 table[192];
|
||||||
|
static_assert(sizeof(table) == sizeof(dvfsTable));
|
||||||
|
std::memcpy(table, dvfsTable, sizeof(dvfsTable));
|
||||||
|
|
||||||
|
if (ramVmin == vmin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < std::size(table); ++i) {
|
||||||
|
if (table[i] && table[i] <= vmin) {
|
||||||
|
table[i] = vmin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle handle = GetPcvHandle();
|
||||||
|
if (handle == INVALID_HANDLE) {
|
||||||
|
FileUtils::LogLine("Invalid handle!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rc = svcWriteDebugProcessMemory(handle, table, dvfsAddress, sizeof(table));
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
ramVmin = vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
}
|
||||||
|
|
||||||
#define MC_REGISTER_BASE 0x70019000
|
#define MC_REGISTER_BASE 0x70019000
|
||||||
#define MC_REGISTER_REGION_SIZE 0x1000
|
#define MC_REGISTER_REGION_SIZE 0x1000
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
class Board
|
class Board
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static void PcvHijackDvfs(u32 vmin);
|
||||||
|
static u32 GetMinimumGpuVoltage(u32 freqMhz);
|
||||||
static void fuseReadSpeedos();
|
static void fuseReadSpeedos();
|
||||||
static u16 getSpeedo(HorizonOCSpeedo speedoType);
|
static u16 getSpeedo(HorizonOCSpeedo speedoType);
|
||||||
static u16 getIDDQ(HorizonOCSpeedo speedoType);
|
static u16 getIDDQ(HorizonOCSpeedo speedoType);
|
||||||
@@ -67,4 +69,8 @@ class Board
|
|||||||
static void FetchHardwareInfos();
|
static void FetchHardwareInfos();
|
||||||
static PcvModule GetPcvModule(SysClkModule sysclkModule);
|
static PcvModule GetPcvModule(SysClkModule sysclkModule);
|
||||||
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
|
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
|
||||||
|
private:
|
||||||
|
static void SetSpeedoBracket();
|
||||||
|
static void CacheDvfsTable();
|
||||||
|
static Handle GetPcvHandle();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -441,6 +441,7 @@ void ClockManager::GovernorThread(void* arg)
|
|||||||
|
|
||||||
bool prevBoostMode = true;
|
bool prevBoostMode = true;
|
||||||
|
|
||||||
|
|
||||||
void ClockManager::Tick()
|
void ClockManager::Tick()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{this->contextMutex};
|
std::scoped_lock lock{this->contextMutex};
|
||||||
@@ -559,9 +560,17 @@ void ClockManager::Tick()
|
|||||||
targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10
|
targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Dvfs here. */
|
||||||
|
Board::SetHz((SysClkModule)module, nearestHz);
|
||||||
|
this->context->freqs[module] = nearestHz;
|
||||||
|
RefreshContext();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Board::SetHz((SysClkModule)module, nearestHz);
|
Board::SetHz((SysClkModule)module, nearestHz);
|
||||||
this->context->freqs[module] = nearestHz;
|
this->context->freqs[module] = nearestHz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(module == SysClkModule_CPU && this->config->GetConfigValue(HocClkConfigValue_FixCpuVoltBug)) {
|
if(module == SysClkModule_CPU && this->config->GetConfigValue(HocClkConfigValue_FixCpuVoltBug)) {
|
||||||
FixCpuBug();
|
FixCpuBug();
|
||||||
}
|
}
|
||||||
@@ -648,6 +657,7 @@ bool ClockManager::RefreshContext()
|
|||||||
break;
|
break;
|
||||||
case SysClkModule_MEM:
|
case SysClkModule_MEM:
|
||||||
Board::ResetToStockMem();
|
Board::ResetToStockMem();
|
||||||
|
/* Dvfs with vmin = 0 here. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -705,7 +715,7 @@ bool ClockManager::RefreshContext()
|
|||||||
|
|
||||||
for (unsigned int voltageSource = 0; voltageSource < HocClkVoltage_EnumMax; voltageSource++)
|
for (unsigned int voltageSource = 0; voltageSource < HocClkVoltage_EnumMax; voltageSource++)
|
||||||
{
|
{
|
||||||
this->context->voltages[voltageSource] = Board::GetVoltage((HocClkVoltage)voltageSource);
|
this->context->voltages[voltageSource] = Board::GetVoltage(HocClkVoltage_GPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->ConfigIntervalTimeout(SysClkConfigValue_CsvWriteIntervalMs, ns, &this->lastCsvWriteNs))
|
if (this->ConfigIntervalTimeout(SysClkConfigValue_CsvWriteIntervalMs, ns, &this->lastCsvWriteNs))
|
||||||
@@ -1027,55 +1037,3 @@ void ClockManager::UpdateRamTimings() {
|
|||||||
|
|
||||||
Board::UpdateShadowRegs(t1_tRCD, t2_tRP, t3_tRAS, t4_tRRD, t5_tRFC, t6_tRTW, t7_tWTR, t8_tREFI, ramFreq, rlAdd, wlAdd, hpMode);
|
Board::UpdateShadowRegs(t1_tRCD, t2_tRP, t3_tRAS, t4_tRRD, t5_tRFC, t6_tRTW, t7_tWTR, t8_tREFI, ramFreq, rlAdd, wlAdd, hpMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ramBrackets[][22] =
|
|
||||||
{
|
|
||||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
|
||||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
|
||||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
|
||||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned int gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
|
||||||
|
|
||||||
int ClockManager::GetSpeedoBracket (int speedo)
|
|
||||||
{
|
|
||||||
int speedoBracket = 3;
|
|
||||||
if ((speedo < 1754) && (speedoBracket = 2, speedo < 1690)) {
|
|
||||||
speedoBracket = !!(1625 < speedo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return speedoBracket;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ClockManager::GetGpuVoltage (unsigned int freq, int speedo)
|
|
||||||
{
|
|
||||||
long int loop;
|
|
||||||
int bracket = GetSpeedoBracket(speedo);
|
|
||||||
|
|
||||||
if (freq < 1601)
|
|
||||||
return 610;
|
|
||||||
|
|
||||||
loop = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (freq <= ramBrackets[bracket][loop])
|
|
||||||
return gpuDvfsArray[loop];
|
|
||||||
|
|
||||||
loop++;
|
|
||||||
} while (loop != 22);
|
|
||||||
|
|
||||||
return 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClockManager::calculateGpuVmin (void)
|
|
||||||
{
|
|
||||||
if(this->config->Refresh()) {
|
|
||||||
SysClkConfigValueList configValues;
|
|
||||||
this->config->GetConfigValues(&configValues);
|
|
||||||
|
|
||||||
int speedo = Board::getSpeedo(HorizonOCSpeedo_CPU), freq = this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock);
|
|
||||||
configValues.values[KipConfigValue_marikoGpuVmin] = GetGpuVoltage(freq, speedo);
|
|
||||||
this->config->SetConfigValues(&configValues, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -214,11 +214,6 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8*
|
|||||||
return ipcSrv->UpdateEmcRegs();
|
return ipcSrv->UpdateEmcRegs();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HocClkIpcCmd_CalculateGpuVmin:
|
|
||||||
if (r->data.size >= 0) {
|
|
||||||
return ipcSrv->CalculateGPUVmin();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SYSCLK_ERROR(Generic);
|
return SYSCLK_ERROR(Generic);
|
||||||
@@ -392,8 +387,3 @@ Result IpcService::UpdateEmcRegs() {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IpcService::CalculateGPUVmin() {
|
|
||||||
this->clockMgr->calculateGpuVmin();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user