nso start check, timing tbreak and some horrendous ui code

This commit is contained in:
Lightos1
2026-04-18 23:00:21 +02:00
parent 822e9f2817
commit 6a851d4095
8 changed files with 143 additions and 14 deletions

View File

@@ -59,8 +59,15 @@ volatile CustomizeTable C = {
.t7_tWTR = 0,
.t8_tREFI = 0,
/* At 1333WL, for some reason (incorrect ram timing config in mtc table?), tRP causes crashes at high reductions - 2 seems to be the most common limit. */
/* This is a lazy workaround until I find the issue... */
.t2_tRP_cap = 2,
/* Frequency where non low timings gets used. */
.timingEmcTbreak = DISABLED,
.low_t6_tRTW = DISABLED,
.low_t7_tWTR = DISABLED,
.readLatency = {
2133000,
2400000,

View File

@@ -105,6 +105,10 @@ typedef struct CustomizeTable {
u32 t2_tRP_cap;
u32 timingEmcTbreak;
u32 low_t6_tRTW;
u32 low_t7_tWTR;
u32 readLatency[4];
u32 writeLatency[4];

View File

@@ -146,14 +146,17 @@ namespace ams::ldr::hoc::pcv::mariko {
tRAS = tRAS_values[C.t3_tRAS];
tRRD = tRRD_values[C.t4_tRRD];
tRFCpb = tRFC_values[C.t5_tRFC];
u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
u32 tRTW = C.t6_tRTW;
u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
if (freq < C.timingEmcTbreak) {
tRTW = C.low_t6_tRTW;
tWTR = 10 - tWTR_values[C.low_t7_tWTR];
}
s32 finetRTW = C.fineTune_t6_tRTW;
s32 finetWTR = C.fineTune_t7_tWTR;
Log("Freq: %u\n", freq);
Log("WL: %u\n", WL);
Log("tRP value: %u\n\n", tRPpb);
tRC = tRAS + tRPpb;
tRFCab = tRFCpb * 2;
tXSR = static_cast<double>(tRFCab + 7.5);
@@ -161,7 +164,7 @@ namespace ams::ldr::hoc::pcv::mariko {
tRPab = tRPpb + 3;
tR2P = CEIL((RL * 0.426) - 2.0);
tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW;
tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (tRTW * 3) + finetRTW;
tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
tRATM = CEIL((tRTM - 10.0) + (RL * 0.426));

View File

@@ -591,7 +591,11 @@ namespace ams::ldr::hoc::pcv::mariko {
}
}
std::vector<u32> newEmcList;
namespace {
std::vector<u32> newEmcList;
u32 *nsoStart;
}
void MtcGenerateJedecTable() {
const u32 jedecFreqs[] = { 1866000, 1996000, 2133000, 2400000, 2666000, 2933000, 3200000 };
constexpr u32 JedecFreqCount = std::size(jedecFreqs);
@@ -718,6 +722,7 @@ namespace ams::ldr::hoc::pcv::mariko {
static const DramId dramId = [] {
DramId id = GetDramId();
id = IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL;
return id;
}();
@@ -877,29 +882,37 @@ namespace ams::ldr::hoc::pcv::mariko {
}
Result MemMtcTableAsm(u32 *ptr) {
u32 adrp = *(ptr - 1);
constexpr u32 AddpOffset = 1;
constexpr u32 BrOffset = 12;
constexpr u32 MovOffset = 10;
/* Ensure we don't dereference memory before nso start. */
R_UNLESS(ptr - BrOffset >= nsoStart, ldr::ResultInvalidMtcTable());
u32 adrp = *(ptr - AddpOffset);
R_UNLESS(AsmCompareAdrpNoImm(adrp, MtcAdrpAsm), ldr::ResultInvalidMtcTable());
/* We don't check for matching register because both registers must be x0 in order to pass the previous checks. */
/* The correct instructions will always be x0 since the mtcTable pointer is returned. */
/* Pray this does not break. */
u32 br = *(ptr - 12);
u32 br = *(ptr - BrOffset);
R_UNLESS(AsmCompareBrNoRd(br, MtcBrAsm), ldr::ResultInvalidMtcTable());
/* Pray this does not break either. */
u32 mov = *(ptr - 10);
u32 mov = *(ptr - MovOffset);
R_UNLESS(asm_compare_no_rd(mov, MtcMovAsm), ldr::ResultInvalidMtcTable());
u8 movRd = asm_get_rd(mov);
u32 movCountPatch = asm_set_rd(asm_set_imm16(MtcMovAsm, newEmcList.size()), movRd);
PATCH_OFFSET(ptr - 12, NopIns);
PATCH_OFFSET(ptr - 10, movCountPatch);
PATCH_OFFSET(ptr - BrOffset, NopIns);
PATCH_OFFSET(ptr - MovOffset, movCountPatch);
R_SUCCEED();
}
void Patch(uintptr_t mapped_nso, size_t nso_size) {
nsoStart = reinterpret_cast<u32 *>(mapped_nso);
MtcGenerateFreqTables();
u32 CpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq);
u32 GpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq);