diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index 440c9a20..ca038a2c 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -80,7 +80,7 @@ volatile CustomizeTable C = { .marikoCpuUVLow = 0, // No undervolt .marikoCpuUVHigh = 0, // No undervolt -.tableConf = DEFAULT_TABLE, +.tableConf = TBREAK_1683, .marikoCpuLowVmin = 620, .marikoCpuHighVmin = 750, /* 1120mV is NVIDIA rating */ @@ -98,7 +98,7 @@ volatile CustomizeTable C = { .eristaCpuBoostClock = 1785000, // Default boost clock .marikoCpuBoostClock = 1963000, // Default boost clock -.eristaGpuUV = 0, +.eristaGpuUV = 2, .eristaGpuVmin = 810, .marikoGpuUV = 0, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp index 868717cc..97c5ea89 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp @@ -22,122 +22,140 @@ namespace ams::ldr::hoc::pcv { -Result MemFreqPllmLimit(u32* ptr) { - clk_pll_param* entry = reinterpret_cast(ptr); - R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry()); + Result MemFreqPllmLimit(u32* ptr) { + clk_pll_param* entry = reinterpret_cast(ptr); + R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry()); - // Double the max clk simply - u32 max_clk = entry->freq * 2; - entry->freq = max_clk; - entry->vco_max = max_clk; - R_SUCCEED(); -} - -Result MemVoltHandler(u32* ptr) { - // ptr value might be default_uv or max_uv - regulator* entries[2] = { - reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_1.default_uv)), - reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_1.max_uv)), - }; - - constexpr u32 uv_step = 12'500; - constexpr u32 uv_min = 600'000; - - auto validator = [](regulator* entry) { - R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); + // Double the max clk simply + u32 max_clk = entry->freq * 2; + entry->freq = max_clk; + entry->vco_max = max_clk; R_SUCCEED(); - }; - - regulator* entry = nullptr; - for (auto& i : entries) { - if (R_SUCCEEDED(validator(i))) - entry = i; } - R_UNLESS(entry, ldr::ResultInvalidRegulatorEntry()); + Result MemVoltHandler(u32* ptr) { + // ptr value might be default_uv or max_uv + regulator* entries[2] = { + reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_1.default_uv)), + reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_1.max_uv)), + }; - u32 emc_uv = C.commonEmcMemVolt; - if (!emc_uv) - R_SKIP(); - - if (emc_uv % uv_step) - emc_uv = emc_uv / uv_step * uv_step; // rounding - - PATCH_OFFSET(ptr, emc_uv); - - R_SUCCEED(); -} - -void SafetyCheck() { - // if (C.custRev != CUST_REV) - // CRASH("Triggered"); - - struct sValidator { - volatile u32 value; - u32 min; - u32 max; - bool value_required = false; - - Result check() { - if (!value_required && !value) - R_SUCCEED(); - - if (min && value < min) - R_THROW(ldr::ResultSafetyCheckFailure()); - if (max && value > max) - R_THROW(ldr::ResultSafetyCheckFailure()); + constexpr u32 uv_step = 12'500; + constexpr u32 uv_min = 600'000; + auto validator = [](regulator* entry) { + R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); R_SUCCEED(); + }; + + regulator* entry = nullptr; + for (auto& i : entries) { + if (R_SUCCEEDED(validator(i))) { + entry = i; + } } - }; - u32 eristaCpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq); - u32 marikoCpuDvfsMaxFreq; - if (C.marikoCpuUVHigh) { - marikoCpuDvfsMaxFreq = static_cast( - GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq - ); - } else { - marikoCpuDvfsMaxFreq = static_cast( - GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq - ); + + R_UNLESS(entry, ldr::ResultInvalidRegulatorEntry()); + + u32 emc_uv = C.commonEmcMemVolt; + if (!emc_uv) { + R_SKIP(); } - u32 eristaGpuDvfsMaxFreq; - switch (C.eristaGpuUV) - { - case 0: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); - break; - case 1: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq); - break; - case 2: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq); - break; - default: - eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); - break; + + if (emc_uv % uv_step) { + emc_uv = emc_uv / uv_step * uv_step; // rounding + } + + PATCH_OFFSET(ptr, emc_uv); + + R_SUCCEED(); } - u32 marikoGpuDvfsMaxFreq; - switch (C.marikoGpuUV) { + void SafetyCheck() { + // if (C.custRev != CUST_REV) + // CRASH("Triggered"); + + struct sValidator { + volatile u32 value; + u32 min; + u32 max; + bool value_required = false; + + Result check() { + if (!value_required && !value) + R_SUCCEED(); + + if (min && value < min) + R_THROW(ldr::ResultSafetyCheckFailure()); + if (max && value > max) + R_THROW(ldr::ResultSafetyCheckFailure()); + + R_SUCCEED(); + } + }; + + u32 eristaCpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq); + u32 marikoCpuDvfsMaxFreq; + if (C.marikoCpuUVHigh) { + marikoCpuDvfsMaxFreq = static_cast( + GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq + ); + } else { + marikoCpuDvfsMaxFreq = static_cast( + GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq + ); + } + u32 eristaGpuDvfsMaxFreq; + switch (C.eristaGpuUV) { case 0: - marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq); + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); break; case 1: - marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTableSLT)->freq); + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq); break; case 2: - marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTableHiOPT)->freq); + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq); break; default: - marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq); + eristaGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); break; - } + } + u32 marikoGpuDvfsMaxFreq; + switch (C.marikoGpuUV) { + case 0: + marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq); + break; + case 1: + marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTableSLT)->freq); + break; + case 2: + marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTableHiOPT)->freq); + break; + default: + marikoGpuDvfsMaxFreq = static_cast(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq); + break; + } + + using namespace ams::ldr::hoc::pcv; + sValidator validators[] = { + { C.eristaCpuBoostClock, 1020'000, 2295'000, true }, + { C.marikoCpuBoostClock, 1020'000, 2703'000, true }, + { C.commonEmcMemVolt, 912'500, 1350'000 }, // Official burst vmax for the RAMs is 1500mV + { C.eristaCpuMaxVolt, 1000, 1257 }, + { GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000 }, + { C.marikoCpuMaxVolt, 1000, 1235 }, + { C.marikoEmcMaxClock, 1600'000, 3500'000 }, + { C.marikoEmcVddqVolt, 250'000, 700'000 }, + { eristaCpuDvfsMaxFreq, 1785'000, 2295'000 }, + { marikoCpuDvfsMaxFreq, 1785'000, 2703'000 }, + { eristaGpuDvfsMaxFreq, 768'000, 1152'000 }, + { marikoGpuDvfsMaxFreq, 768'000, 1536'000 }, + }; using namespace ams::ldr::hoc::pcv; sValidator validators[] = { { C.eristaCpuBoostClock, 1020'000, 2295'000, true }, @@ -154,21 +172,22 @@ void SafetyCheck() { { marikoGpuDvfsMaxFreq, 768'000, 1536'000 }, }; - for (auto& i : validators) { - if (R_FAILED(i.check())) - CRASH("Validation FAIL"); + for (auto& i : validators) { + if (R_FAILED(i.check())) { + CRASH("Validation FAIL"); + } + } } -} -void Patch(uintptr_t mapped_nso, size_t nso_size) { - #ifdef ATMOSPHERE_IS_STRATOSPHERE - SafetyCheck(); - bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); - if (isMariko) - mariko::Patch(mapped_nso, nso_size); - else - erista::Patch(mapped_nso, nso_size); - #endif -} + void Patch(uintptr_t mapped_nso, size_t nso_size) { + #ifdef ATMOSPHERE_IS_STRATOSPHERE + SafetyCheck(); + bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); + if (isMariko) + mariko::Patch(mapped_nso, nso_size); + else + erista::Patch(mapped_nso, nso_size); + #endif + } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp index ea77bac2..caa5cd99 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp @@ -16,153 +16,154 @@ * along with this program. If not, see . */ - #pragma once +#pragma once - namespace ams::ldr::hoc::pcv { +namespace ams::ldr::hoc::pcv { - typedef struct cvb_coefficients { - s32 c0 = 0; - s32 c1 = 0; - s32 c2 = 0; - s32 c3 = 0; - s32 c4 = 0; - s32 c5 = 0; - } cvb_coefficients; + typedef struct cvb_coefficients { + s32 c0 = 0; + s32 c1 = 0; + s32 c2 = 0; + s32 c3 = 0; + s32 c4 = 0; + s32 c5 = 0; + } cvb_coefficients; - typedef struct cvb_entry_t { - u64 freq; - cvb_coefficients cvb_dfll_param; - cvb_coefficients cvb_pll_param; - } cvb_entry_t; - static_assert(sizeof(cvb_entry_t) == 0x38); + typedef struct cvb_entry_t { + u64 freq; + cvb_coefficients cvb_dfll_param; + cvb_coefficients cvb_pll_param; + } cvb_entry_t; + static_assert(sizeof(cvb_entry_t) == 0x38); - typedef struct cvb_cpu_dfll_data { - u32 tune0_low; - u32 tune0_high; - u32 tune1_low; - u32 tune1_high; - unsigned int tune_high_min_millivolts; - unsigned int tune_high_margin_millivolts; - unsigned long dvco_calibration_max; - } cvb_cpu_dfll_data; + typedef struct cvb_cpu_dfll_data { + u32 tune0_low; + u32 tune0_high; + u32 tune1_low; + u32 tune1_high; + unsigned int tune_high_min_millivolts; + unsigned int tune_high_margin_millivolts; + unsigned long dvco_calibration_max; + } cvb_cpu_dfll_data; - typedef struct emc_dvb_dvfs_table_t { - u64 freq; - s32 volt[4] = {0}; - } emc_dvb_dvfs_table_t; + typedef struct emc_dvb_dvfs_table_t { + u64 freq; + s32 volt[4] = {0}; + } emc_dvb_dvfs_table_t; - typedef struct __attribute__((packed)) div_nmp { - u8 divn_shift; - u8 divn_width; - u8 divm_shift; - u8 divm_width; - u8 divp_shift; - u8 divp_width; - u8 override_divn_shift; - u8 override_divm_shift; - u8 override_divp_shift; - } div_nmp; + typedef struct __attribute__((packed)) div_nmp { + u8 divn_shift; + u8 divn_width; + u8 divm_shift; + u8 divm_width; + u8 divp_shift; + u8 divp_width; + u8 override_divn_shift; + u8 override_divm_shift; + u8 override_divp_shift; + } div_nmp; - typedef struct __attribute__((packed)) clk_pll_param { - u32 freq; - u32 input_min; - u32 input_max; - u32 cf_min; - u32 cf_max; - u32 vco_min; - u32 vco_max; - s32 lock_delay; - u32 fixed_rate; - u32 unk_0; - struct div_nmp *div_nmp; - u32 unk_1[4]; - void (*unk_fn)(u64* unk_struct); // set_defaults? - } clk_pll_param; + typedef struct __attribute__((packed)) clk_pll_param { + u32 freq; + u32 input_min; + u32 input_max; + u32 cf_min; + u32 cf_max; + u32 vco_min; + u32 vco_max; + s32 lock_delay; + u32 fixed_rate; + u32 unk_0; + struct div_nmp *div_nmp; + u32 unk_1[4]; + void (*unk_fn)(u64* unk_struct); // set_defaults? + } clk_pll_param; - typedef struct __attribute__((packed)) dvfs_rail { - u32 id; - u32 unk_0[5]; - u32 freq; - u32 unk_1[8]; - u32 unk_flag; - u32 min_mv; - u32 step_mv; - u32 max_mv; - u32 unk_2[11]; - } dvfs_rail; + typedef struct __attribute__((packed)) dvfs_rail { + u32 id; + u32 unk_0[5]; + u32 freq; + u32 unk_1[8]; + u32 unk_flag; + u32 min_mv; + u32 step_mv; + u32 max_mv; + u32 unk_2[11]; + } dvfs_rail; - typedef struct __attribute__((packed)) regulator { - u64 id; - const char* name; - u32 type; - union { - struct { - u32 volt_reg; - u32 step_uv; - u32 min_uv; - u32 default_uv; - u32 max_uv; - u32 unk_0[2]; - } type_1; - struct { - u32 unk_0; - u32 step_uv; - u32 unk_1; - u32 min_uv; - u32 max_uv; - u32 unk_2; - u32 default_uv; - } type_2_3; - }; - u32 unk_x[60]; - } regulator; - static_assert(sizeof(regulator) == 0x120); + typedef struct __attribute__((packed)) regulator { + u64 id; + const char* name; + u32 type; + union { + struct { + u32 volt_reg; + u32 step_uv; + u32 min_uv; + u32 default_uv; + u32 max_uv; + u32 unk_0[2]; + } type_1; + struct { + u32 unk_0; + u32 step_uv; + u32 unk_1; + u32 min_uv; + u32 max_uv; + u32 unk_2; + u32 default_uv; + } type_2_3; + }; + u32 unk_x[60]; + } regulator; + static_assert(sizeof(regulator) == 0x120); - constexpr u32 CpuClkOSLimit = 1785'000; + constexpr u32 CpuClkOSLimit = 1785'000; - constexpr u32 EmcClkOSLimit = 1600'000; + constexpr u32 EmcClkOSLimit = 1600'000; - #define R_SKIP() R_SUCCEED() + #define R_SKIP() R_SUCCEED() - // Count 32 / Index 31 is reserved to be empty - constexpr size_t DvfsTableEntryCount = 32; - constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1; + // Count 32 / Index 31 is reserved to be empty + constexpr size_t DvfsTableEntryCount = 32; + constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1; - template - size_t GetDvfsTableEntryCount(T* table_head) { - using NT = std::remove_const_t>; + template + size_t GetDvfsTableEntryCount(T* table_head) { + using NT = std::remove_const_t>; - auto is_empty = [](NT* entry) { - uint8_t* m = reinterpret_cast(entry); - for (size_t i = 0; i < sizeof(NT); i++) { - if (*(m + i)) - return false; - } - return true; - }; + auto is_empty = [](NT* entry) { + uint8_t* m = reinterpret_cast(entry); + for (size_t i = 0; i < sizeof(NT); i++) { + if (*(m + i)) { + return false; + } + } + return true; + }; - NT* table = const_cast(table_head); - size_t count = 0; - while (count < DvfsTableEntryLimit) { - if (is_empty(table++)) { - return count; - } - count++; - } - return DvfsTableEntryLimit; - } + NT* table = const_cast(table_head); + size_t count = 0; + while (count < DvfsTableEntryLimit) { + if (is_empty(table++)) { + return count; + } + count++; + } + return DvfsTableEntryLimit; + } - template - T* GetDvfsTableLastEntry(T* table_head) { - using NT = std::remove_const_t>; + template + T* GetDvfsTableLastEntry(T* table_head) { + using NT = std::remove_const_t>; - NT* table = const_cast(table_head); - size_t count = GetDvfsTableEntryCount(table_head); - if (!count) { - return nullptr; - } - size_t index = count - 1; - return table + index; - } + NT* table = const_cast(table_head); + size_t count = GetDvfsTableEntryCount(table_head); + if (!count) { + return nullptr; + } + size_t index = count - 1; + return table + index; + } - } +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp index d2c6e5c9..649933de 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp @@ -80,12 +80,13 @@ namespace ams::ldr::hoc::pcv::erista { R_SUCCEED(); } + /* In theory this should work, but it doesn't, I have no idea why ¯\_(ツ)_/¯ */ Result CpuVoltDfll(u32* ptr) { cvb_cpu_dfll_data *entry = reinterpret_cast(ptr); - R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry()); - R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); - R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); - R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); + R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry()); + R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); + R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); + R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); if( !C.eristaCpuUV) { R_SKIP(); @@ -453,12 +454,11 @@ namespace ams::ldr::hoc::pcv::erista { void Patch(uintptr_t mapped_nso, size_t nso_size) { PatcherEntry patches[] = { {"CPU Freq Table", CpuFreqCvbTable, 1, nullptr, static_cast(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq)}, - {"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, 825}, - {"CPU Volt Limit", &CpuVoltRange, 0, &CpuMaxVoltPatternFn}, - {"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, 825}, - {"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF}, - {"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, 810}, - {"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, 810}, + {"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial}, + {"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial}, + {"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF}, + {"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial}, + {"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial}, {"GPU Freq Table", GpuFreqCvbTable, 1, nullptr, static_cast(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq)}, {"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn}, {"GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax}, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp index e7a8d66d..dbafea57 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp @@ -20,116 +20,111 @@ namespace ams::ldr::hoc::ptm { -Result CpuPtmBoost(perf_conf_entry* entry) { + Result CpuPtmBoost(perf_conf_entry* entry) { + #ifdef ATMOSPHERE_IS_STRATOSPHERE + bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); + #else + bool isMariko = true; + #endif - #ifdef ATMOSPHERE_IS_STRATOSPHERE - bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); - #else - bool isMariko = true; - #endif + if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) { + R_SUCCEED(); + } + + u32 cpuPtmBoostNew = isMariko ? C.marikoCpuBoostClock * 1000 : C.eristaCpuBoostClock * 1000; + + PATCH_OFFSET(&(entry->cpu_freq_1), cpuPtmBoostNew); + PATCH_OFFSET(&(entry->cpu_freq_2), cpuPtmBoostNew); - if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) R_SUCCEED(); - - u32 cpuPtmBoostNew = isMariko ? C.marikoCpuBoostClock * 1000 : C.eristaCpuBoostClock * 1000; - - PATCH_OFFSET(&(entry->cpu_freq_1), cpuPtmBoostNew); - PATCH_OFFSET(&(entry->cpu_freq_2), cpuPtmBoostNew); - - R_SUCCEED(); -} - -Result MemPtm(perf_conf_entry* entry) { - PATCH_OFFSET(&(entry->emc_freq_1), memPtmLimit); - PATCH_OFFSET(&(entry->emc_freq_2), memPtmLimit); - - R_SUCCEED(); -} - -bool PtmEntryIsValid(perf_conf_entry* entry) { - return (entry->cpu_freq_1 == entry->cpu_freq_2 && - entry->gpu_freq_1 == entry->gpu_freq_2 && - entry->emc_freq_1 == entry->emc_freq_2); -} - -bool PtmTablePatternFn(u32* ptr) { - perf_conf_entry* entry = reinterpret_cast(ptr); - if (!PtmEntryIsValid(entry)) - return false; - - return entry->cpu_freq_1 == cpuPtmDefault; -} - -void Patch(uintptr_t mapped_nso, size_t nso_size) { - perf_conf_entry* confTable = nullptr; - for (uintptr_t ptr = mapped_nso; - ptr <= mapped_nso + nso_size - sizeof(perf_conf_entry) * entryCnt; - ptr += sizeof(u32)) - { - u32* ptr32 = reinterpret_cast(ptr); - if (PtmTablePatternFn(ptr32)) { - confTable = reinterpret_cast(ptr); - break; - } } - if (!confTable) { - CRASH("confTable not found!"); + Result MemPtm(perf_conf_entry* entry) { + PATCH_OFFSET(&(entry->emc_freq_1), memPtmLimit); + PATCH_OFFSET(&(entry->emc_freq_2), memPtmLimit); + + R_SUCCEED(); } - PatcherEntry cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, }; - PatcherEntry memPtmPatch = { "MEM Ptm", &MemPtm, 16, }; - - #ifdef ATMOSPHERE_IS_STRATOSPHERE - bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); - #else - bool isMariko = true; - #endif - - - for (u32 i = 0; i < entryCnt; i++) { - perf_conf_entry* entry = confTable + i; + bool PtmEntryIsValid(perf_conf_entry* entry) { + return (entry->cpu_freq_1 == entry->cpu_freq_2 && entry->gpu_freq_1 == entry->gpu_freq_2 && entry->emc_freq_1 == entry->emc_freq_2); + } + bool PtmTablePatternFn(u32* ptr) { + perf_conf_entry* entry = reinterpret_cast(ptr); if (!PtmEntryIsValid(entry)) { - LOGGING("@%p", &entry); - CRASH("Invalid ptm confTable entry"); + return false; } - switch (entry->cpu_freq_1) { - case cpuPtmBoost: - cpuPtmBoostPatch.Apply(entry); + return entry->cpu_freq_1 == cpuPtmDefault; + } + + void Patch(uintptr_t mapped_nso, size_t nso_size) { + perf_conf_entry* confTable = nullptr; + for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(perf_conf_entry) * entryCnt; ptr += sizeof(u32)) { + u32* ptr32 = reinterpret_cast(ptr); + if (PtmTablePatternFn(ptr32)) { + confTable = reinterpret_cast(ptr); break; - case cpuPtmDefault: - case cpuPtmDevOC: - break; - default: - LOGGING("%u (0x%08x) @%p", entry->cpu_freq_1, entry->conf_id, &(entry->cpu_freq_1)); - CRASH("Unknown CPU Freq"); + } } - switch (entry->emc_freq_1) { - case memPtmLimit: - case memPtmAlt: - case memPtmClamp: - if (isMariko) { - memPtmPatch.Apply(entry); - } - break; - default: - LOGGING("%u (0x%08x) @%p", entry->emc_freq_1, entry->conf_id, &(entry->emc_freq_2)); - CRASH("Unknown MEM Freq"); + if (!confTable) { + CRASH("confTable not found!"); + } + + PatcherEntry cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, }; + PatcherEntry memPtmPatch = { "MEM Ptm", &MemPtm, 16, }; + + #ifdef ATMOSPHERE_IS_STRATOSPHERE + bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); + #else + bool isMariko = true; + #endif + + for (u32 i = 0; i < entryCnt; i++) { + perf_conf_entry *entry = confTable + i; + + if (!PtmEntryIsValid(entry)) { + LOGGING("@%p", &entry); + CRASH("Invalid ptm confTable entry"); + } + + switch (entry->cpu_freq_1) { + case cpuPtmBoost: + cpuPtmBoostPatch.Apply(entry); + break; + case cpuPtmDefault: + case cpuPtmDevOC: + break; + default: + LOGGING("%u (0x%08x) @%p", entry->cpu_freq_1, entry->conf_id, &(entry->cpu_freq_1)); + CRASH("Unknown CPU Freq"); + } + + switch (entry->emc_freq_1) { + case memPtmLimit: + case memPtmAlt: + case memPtmClamp: + if (isMariko) { + memPtmPatch.Apply(entry); + } + break; + default: + LOGGING("%u (0x%08x) @%p", entry->emc_freq_1, entry->conf_id, &(entry->emc_freq_2)); + CRASH("Unknown MEM Freq"); + } + } + + LOGGING("%s Count: %zu", cpuPtmBoostPatch.description, cpuPtmBoostPatch.patched_count); + if (R_FAILED(cpuPtmBoostPatch.CheckResult())) + CRASH(cpuPtmBoostPatch.description); + + if (isMariko) { + LOGGING("%s Count: %zu", memPtmPatch.description, memPtmPatch.patched_count); + if (R_FAILED(memPtmPatch.CheckResult())) + CRASH(memPtmPatch.description); } } - LOGGING("%s Count: %zu", cpuPtmBoostPatch.description, cpuPtmBoostPatch.patched_count); - if (R_FAILED(cpuPtmBoostPatch.CheckResult())) - CRASH(cpuPtmBoostPatch.description); - - if (isMariko) { - LOGGING("%s Count: %zu", memPtmPatch.description, memPtmPatch.patched_count); - if (R_FAILED(memPtmPatch.CheckResult())) - CRASH(memPtmPatch.description); - } -} - } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp index 9c82bc60..9928516a 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp @@ -22,26 +22,26 @@ namespace ams::ldr::hoc::ptm { -typedef struct { - u32 conf_id; - u32 cpu_freq_1; // min-max pair? - u32 cpu_freq_2; - u32 gpu_freq_1; - u32 gpu_freq_2; - u32 emc_freq_1; - u32 emc_freq_2; - u32 padding; -} perf_conf_entry; + typedef struct { + u32 conf_id; + u32 cpu_freq_1; // min-max pair? + u32 cpu_freq_2; + u32 gpu_freq_1; + u32 gpu_freq_2; + u32 emc_freq_1; + u32 emc_freq_2; + u32 padding; + } perf_conf_entry; -constexpr u32 entryCnt = 16; -constexpr u32 cpuPtmDefault = 1020'000'000; -constexpr u32 cpuPtmDevOC = 1224'000'000; -constexpr u32 cpuPtmBoost = 1785'000'000; + constexpr u32 entryCnt = 16; + constexpr u32 cpuPtmDefault = 1020'000'000; + constexpr u32 cpuPtmDevOC = 1224'000'000; + constexpr u32 cpuPtmBoost = 1785'000'000; -constexpr u32 memPtmLimit = 1600'000'000; -constexpr u32 memPtmAlt = 1331'200'000; -constexpr u32 memPtmClamp = 1065'600'000; + constexpr u32 memPtmLimit = 1600'000'000; + constexpr u32 memPtmAlt = 1331'200'000; + constexpr u32 memPtmClamp = 1065'600'000; -void Patch(uintptr_t mapped_nso, size_t nso_size); + void Patch(uintptr_t mapped_nso, size_t nso_size); } diff --git a/Source/sys-clk/sysmodule/src/board.cpp b/Source/sys-clk/sysmodule/src/board.cpp index ccee28a1..6be64c4b 100644 --- a/Source/sys-clk/sysmodule/src/board.cpp +++ b/Source/sys-clk/sysmodule/src/board.cpp @@ -1249,6 +1249,7 @@ MarikoCpuUvEntry marikoCpuUvHigh[12] = { {0x0, 0xdfff, 0, 0x27f07ff}, }; void Board::SetCpuUvLevel(u32 levelLow, u32 levelHigh, u32 tbreakPoint) { + return; u32* tune0_ptr = (u32*)(cldvfs + CL_DVFS_TUNE0_0); u32* tune1_ptr = (u32*)(cldvfs + CL_DVFS_TUNE1_0);