This commit is contained in:
souldbminersmwc
2026-05-19 16:22:06 -04:00
8 changed files with 166 additions and 186 deletions

View File

@@ -98,6 +98,7 @@ volatile CustomizeTable C = {
* 1331WL = 12
*/
/* Erista only. */
.mem_burst_read_latency = RL_1600,
.mem_burst_write_latency = WL_1600,
@@ -113,6 +114,7 @@ volatile CustomizeTable C = {
.tableConf = TBREAK_1683,
.marikoCpuLowVmin = 620,
.marikoCpuHighVmin = 750,
/* 1120mV is NVIDIA rating */
.marikoCpuMaxVolt = 1120,
@@ -125,17 +127,15 @@ volatile CustomizeTable C = {
/* 2703000 is potentially dangerous and not advised. */
.marikoCpuMaxClock = 1963500,
.eristaCpuBoostClock = 1785000, // Default boost clock
.marikoCpuBoostClock = 1963500, // Default boost clock
.eristaCpuBoostClock = 1785000, /* Default boost clock */
.marikoCpuBoostClock = 1963500, /* Default boost clock */
.eristaGpuUV = 0,
.eristaGpuVmin = 810,
.marikoGpuUV = 0,
/* Vmin past 795mV won't work due boot voltage being 800mV. */
.marikoGpuVmin = 610,
.marikoGpuVmax = 800,
.commonGpuVoltOffset = 0,
@@ -147,7 +147,6 @@ volatile CustomizeTable C = {
/* AUTO: Voltage is optimally chosen; with commonGpuVoltOffset applied. */
/* AUTO only works up to 1305 GPU on Mariko and 998 GPU on Erista (it is reccomended to manually set your 998MHz voltage though) */
/* You can overwrite auto with any voltage (in mv) of your choice - offset will not be applied. */
.eristaGpuVoltArray = {
AUTO /* 76 */,
AUTO /* 115 */,

View File

@@ -42,19 +42,6 @@ enum StepMode: u32 {
StepMode_133MHz = 3,
};
/*
* Read:
* 2133RL = 40
* 1866RL = 36
* 1600RL = 32
* 1331RL = 28
* Write:
* 2133WL = 18
* 1866WL = 16
* 1600WL = 14
* 1331WL = 12
*/
enum ReadLatency: u32 {
RL_2133 = 40,
RL_1866 = 36,
@@ -74,9 +61,6 @@ using CustomizeGpuDvfsTable = pcv::cvb_entry_t[pcv::DvfsTableEntryLimit];
static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(CustomizeGpuDvfsTable));
static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(pcv::cvb_entry_t) * pcv::DvfsTableEntryLimit);
constexpr uint32_t ERISTA_MTC_MAGIC = 0x43544D45; // EMTC
constexpr uint32_t MARIKO_MTC_MAGIC = 0x43544D4D; // MMTC
struct CustomizeTable {
u8 cust[4] = {'C', 'U', 'S', 'T'};
u32 custRev = CUST_REV;

View File

@@ -66,13 +66,13 @@ namespace ams::ldr::hoc {
size_t maximum_patched_count = 0;
patternFn pattern_search_fn = nullptr;
Pointer value_search;
size_t patched_count = 0;
Result Apply(Pointer *ptr) {
Result res = patcher_fn(ptr);
if (R_SUCCEEDED(res))
if (R_SUCCEEDED(res)) {
patched_count++;
}
return res;
}
@@ -80,13 +80,18 @@ namespace ams::ldr::hoc {
Result SearchAndApply(Pointer *ptr) {
bool searchOk = false;
if (pattern_search_fn) {
if (pattern_search_fn(ptr)) searchOk = true;
if (pattern_search_fn(ptr)) {
searchOk = true;
}
} else {
if (value_search == *(ptr)) searchOk = true;
if (value_search == *(ptr)) {
searchOk = true;
}
}
if (searchOk)
if (searchOk) {
return Apply(ptr);
}
R_THROW(ldr::ResultUnsuccessfulPatcher());
}
@@ -94,8 +99,9 @@ namespace ams::ldr::hoc {
Result CheckResult() {
R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher());
if (maximum_patched_count)
if (maximum_patched_count) {
R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher());
}
R_SUCCEED();
}

View File

@@ -76,24 +76,25 @@ namespace ams::ldr::hoc::pcv {
}
void SafetyCheck() {
// if (C.custRev != CUST_REV)
// CRASH("Triggered");
struct sValidator {
volatile u32 value;
u32 min;
u32 max;
bool value_required = false;
u32 panic;
bool value_required = false;
Result check() {
if (!value_required && !value)
if (!value_required && !value) {
R_SUCCEED();
}
if (min && value < min)
if (min && value < min) {
R_THROW(ldr::ResultSafetyCheckFailure());
if (max && value > max)
}
if (max && value > max) {
R_THROW(ldr::ResultSafetyCheckFailure());
}
R_SUCCEED();
}
@@ -102,13 +103,9 @@ namespace ams::ldr::hoc::pcv {
u32 eristaCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq);
u32 marikoCpuDvfsMaxFreq;
if (C.marikoCpuUVHigh) {
marikoCpuDvfsMaxFreq = static_cast<u32>(
GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq
);
marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq);
} else {
marikoCpuDvfsMaxFreq = static_cast<u32>(
GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq
);
marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq);
}
u32 eristaGpuDvfsMaxFreq;
switch (C.eristaGpuUV) {
@@ -142,22 +139,21 @@ namespace ams::ldr::hoc::pcv {
break;
}
using namespace ams::ldr::hoc::pcv;
sValidator validators[] = {
{ C.eristaCpuBoostClock, 1020'000, 2397'000, true, panic::Cpu },
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true, panic::Cpu },
{ C.eristaCpuMaxVolt, 1000, 1260, false, panic::Cpu },
{ C.marikoCpuMaxVolt, 1000, 1200, false, panic::Cpu },
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, false, panic::Cpu },
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu },
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc },
{ C.marikoEmcVddqVolt, 400'000, 750'000, false, panic::Emc },
{ C.marikoSocVmax, 1000, 1200, false, panic::Emc },
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu },
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu },
{ C.eristaCpuBoostClock, 1020'000, 2397'000, panic::Cpu, true },
{ C.marikoCpuBoostClock, 1020'000, 2703'000, panic::Cpu, true },
{ C.eristaCpuMaxVolt, 1000, 1260, panic::Cpu, },
{ C.marikoCpuMaxVolt, 1000, 1200, panic::Cpu, },
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, },
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, panic::Cpu, },
{ C.commonEmcMemVolt, 912'500, 1350'000, panic::Emc, }, /* Official vmax for the RAMs is 1400-1500mV */
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, panic::Emc, },
{ C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, },
{ C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, },
{ C.marikoSocVmax, 1000, 1200, panic::Emc, },
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, panic::Gpu, },
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, panic::Gpu, },
{ C.marikoGpuVmax, 800, 960, panic::Gpu, },
};
for (auto &v : validators) {

View File

@@ -195,26 +195,6 @@ namespace ams::ldr::hoc::pcv {
Result MemFreqPllmLimit(u32 *ptr);
Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2
template <typename T>
Result MemMtcCustomizeTable(T *dst, T *src) {
constexpr u32 mtc_magic = std::is_same_v<T, MarikoMtcTable> ? MARIKO_MTC_MAGIC : ERISTA_MTC_MAGIC;
R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic());
constexpr u32 ZERO_VAL = UINT32_MAX;
// Skip params from dvfs_ver to clock_src;
for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32)) {
u32 *src_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(src) + offset);
u32 *dst_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(dst) + offset);
u32 src_val = *src_ent;
if (src_val){
PATCH_OFFSET(dst_ent, src_val == ZERO_VAL ? 0 : src_val);
}
}
R_SUCCEED();
};
void SafetyCheck();
void Patch(uintptr_t mapped_nso, size_t nso_size);

View File

@@ -149,7 +149,7 @@ namespace ams::ldr::hoc::pcv {
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
auto is_empty = [](NT* entry) {
uint8_t* m = reinterpret_cast<uint8_t *>(entry);
u8 *m = reinterpret_cast<u8 *>(entry);
for (size_t i = 0; i < sizeof(NT); i++) {
if (*(m + i)) {
return false;

View File

@@ -136,17 +136,13 @@ namespace ams::ldr::hoc::pcv::erista {
Result GpuFreqMaxAsm(u32 *ptr32) {
// Check if both two instructions match the pattern
u32 ins1 = *ptr32, ins2 = *(ptr32 + 1);
if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1])))
if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1]))) {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
// Both instructions should operate on the same register
u8 rd = asm_get_rd(ins1);
if (rd != asm_get_rd(ins2))
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
/* Verify the limit. */
/* TODO: Make this a little bit cleaner at some point. */
if (AsmGetImm16(ins1) != (GpuClkOsLimit & 0xFFFF) || AsmGetImm16(ins2) != (GpuClkOsLimit >> 16)) {
if (rd != asm_get_rd(ins2)) {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
@@ -165,6 +161,7 @@ namespace ams::ldr::hoc::pcv::erista {
max_clock = GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq;
break;
}
u32 asm_patch[2] = {
asm_set_rd(asm_set_imm16(GpuAsmPattern[0], max_clock), rd),
asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd)
@@ -279,11 +276,9 @@ namespace ams::ldr::hoc::pcv::erista {
// WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv);
// WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2);
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
// ams::ldr::hoc::pcv::mariko::CalculateMrw2();
// table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
// table->dram_timings.rl = RL;
/* This needs some clean up. */
constexpr double MC_ARB_DIV = 4.0;
constexpr u32 MC_ARB_SFA = 2;

View File

@@ -837,10 +837,30 @@ namespace ams::ldr::hoc::pcv::mariko {
{ 1600000, { 675, 650, 637, }, },
{ 1866000, { DVB(DvbVolt( 700, 675, 650)) }, },
{ 2133000, { DVB(DvbVolt( 725, 700, 675)) }, },
{ 2400000, { DVB(DvbVolt( 750, 725, 700)) }, },
{ 2246000, { DVB(DvbVolt( 750, 725, 700)) }, },
{ 2400000, { DVB(DvbVolt( 775, 750, 725)) }, },
{ 2466000, { DVB(DvbVolt( 800, 775, 750)) }, },
{ 2533000, { DVB(DvbVolt( 810, 785, 760)) }, },
{ 2566000, { DVB(DvbVolt( 820, 795, 770)) }, },
{ 2600000, { DVB(DvbVolt( 830, 805, 780)) }, },
{ 2633000, { DVB(DvbVolt( 840, 815, 790)) }, },
{ 2666000, { DVB(DvbVolt( 850, 825, 800)) }, },
{ 2933000, { DVB(DvbVolt( 950, 925, 900)) }, },
{ 3200000, { DVB(DvbVolt(1050, 1025, 1000)) }, },
{ 2700000, { DVB(DvbVolt( 860, 835, 810)) }, },
{ 2733000, { DVB(DvbVolt( 870, 845, 820)) }, },
{ 2766000, { DVB(DvbVolt( 880, 855, 830)) }, },
{ 2800000, { DVB(DvbVolt( 895, 865, 840)) }, },
{ 2833000, { DVB(DvbVolt( 900, 875, 850)) }, },
{ 2866000, { DVB(DvbVolt( 910, 885, 860)) }, },
{ 2900000, { DVB(DvbVolt( 920, 895, 870)) }, },
{ 2933000, { DVB(DvbVolt( 950, 905, 880)) }, },
{ 2966000, { DVB(DvbVolt( 960, 915, 890)) }, },
{ 3000000, { DVB(DvbVolt( 970, 925, 900)) }, },
{ 3033000, { DVB(DvbVolt( 980, 940, 910)) }, },
{ 3066000, { DVB(DvbVolt(1000, 955, 920)) }, },
{ 3100000, { DVB(DvbVolt(1010, 990, 930)) }, },
{ 3133000, { DVB(DvbVolt(1025, 1005, 940)) }, },
{ 3166000, { DVB(DvbVolt(1035, 1015, 950)) }, },
{ 3200000, { DVB(DvbVolt(1050, 1025, 960)) }, },
{ ~0u, { }, },
};
#undef DVB