cpu lut patch fixes + crash fixes
This commit is contained in:
1 parent
87d0214288
commit
9ca050d3b5
6 files changed
+126
-9
No files matched your search
@@ -95,7 +95,7 @@ namespace ams::ldr {
|
||||
R_DEFINE_ERROR_RESULT(InvalidForceVerbosityPattern, 1032);
|
||||
R_DEFINE_ERROR_RESULT(InvalidCpuLutMaxAsmPattern, 1033);
|
||||
R_DEFINE_ERROR_RESULT(InvalidCpuLutHook, 1034);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(InvalidDvcoRateConfig, 1035);
|
||||
}
|
||||
|
||||
namespace ams::ldr::hoc {
|
||||
|
||||
@@ -95,6 +95,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
{ "CPU Lut Max Asm", &CpuLutMaxAsm, 1, &CpuLutAsmPatternFn },
|
||||
{ "CPU Lut Max Asm2", &CpuLutMaxAsm2, 1, &CpuLutAsmPatternFn2 },
|
||||
{ "CPU Lut Writer", &LutWriterFind, 1, &LutWriterPatternFn },
|
||||
{ "CPU Dvco Rate Cfg", &CpuLutDvcoRateCfg, 1, &CpuLutDvcoRateCfgPatternFn },
|
||||
|
||||
/* Debugging patches */
|
||||
#if HOC_UART_LOG
|
||||
|
||||
@@ -273,8 +273,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
PATCH_OFFSET(prod, nw); /* movz wD,#0x3F */
|
||||
}
|
||||
|
||||
/* Set SAFE to entry 32 */
|
||||
PATCH_OFFSET(ptr + 1, _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, _asm::Get(ptr[1], _asm::field::Rd)}, {_asm::field::Imm16, 0x20}));
|
||||
/* Set SAFE to entry 31 */
|
||||
PATCH_OFFSET(ptr + 1, _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, _asm::Get(ptr[1], _asm::field::Rd)}, {_asm::field::Imm16, 0x1F}));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -355,4 +355,99 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
/* FW 20.4.0
|
||||
71000571dc 01 01 00 d0 adrp param_2=>aCldvfssetdvcor,aSSRequestedDKh+0x1f = "ClDvfsSetDvcoRateMin"
|
||||
= " %s divider %#x diff %d\n"
|
||||
71000571e0 21 40 27 91 add param_2=>aCldvfssetdvcor,param_2,#0x9d0 = "ClDvfsSetDvcoRateMin"
|
||||
71000571e4 c3 9f ff 97 bl nn::pcv::NvLog undefined NvLog(char * fmt, ...)
|
||||
loc_71000571E8 XREF[1]: 71000571b4(j)
|
||||
71000571e8 69 aa 42 a9 ldp x9,x10,[x19, #0x28]
|
||||
71000571ec 4a fd 41 d3 lsr x10,x10,#0x1
|
||||
71000571f0 68 26 41 f9 ldr x8,[x19, #0x248] Anchor
|
||||
71000571f4 0b 0d 0a cb sub x11,x8,x10, LSL #0x3 Target
|
||||
71000571f8 6b 4e 01 f9 str x11,[x19, #0x298] Verify1
|
||||
71000571fc 2c 0d 40 f9 ldr x12,[x9, #0x18] Verify2
|
||||
7100057200 7f 01 0c eb cmp x11,x12
|
||||
7100057204 6b 81 8c 9a csel x11,x11,x12,hi
|
||||
7100057208 6b 4e 01 f9 str x11,[x19, #0x298]
|
||||
710005720c 2b c9 40 f9 ldr x11,[x9, #0x190]
|
||||
7100057210 6b 52 01 f9 str x11,[x19, #0x2a0]
|
||||
7100057214 8b 00 00 b4 cbz x11,loc_7100057224
|
||||
7100057218 f4 4f 41 a9 ldp x20,x19,[sp, #local_10]
|
||||
710005721c fd 7b c2 a8 ldp x29=>local_20,x30,[sp], #0x20
|
||||
7100057220 c0 03 5f d6 ret
|
||||
loc_7100057224 XREF[1]: 7100057214(j)
|
||||
7100057224 08 15 0a 8b add x8,x8,x10, LSL #0x5 Target
|
||||
7100057228 2a 55 81 b9 ldrsw x10,[x9, #0x154] Anchor
|
||||
710005722c 68 52 01 f9 str x8,[x19, #0x2a0] Verify1
|
||||
|
||||
*/
|
||||
|
||||
Result CpuLutDvcoRateCfg(u32* ptr) {
|
||||
/* Anchor via scanning to prevent ordering issues */
|
||||
u32 *sub = _asm::ScanAssembly(ptr + 1, 4,
|
||||
_asm::Encode(_asm::op::SubShifted64, {_asm::field::Rd, 0}, {_asm::field::Rn, 0}, {_asm::field::Rm, 0},
|
||||
{_asm::field::Shift, 0}, {_asm::field::Imm6, 3}),
|
||||
_asm::field::Rd, _asm::field::Rn, _asm::field::Rm);
|
||||
R_UNLESS(sub != nullptr, ldr::ResultInvalidDvcoRateConfig());
|
||||
|
||||
/* Verify */
|
||||
R_UNLESS(_asm::IsOp(sub[1], _asm::op::StrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8)
|
||||
&& _asm::Get(sub[1], _asm::field::Off8) == 0x298, ldr::ResultInvalidDvcoRateConfig());
|
||||
|
||||
/* 22.x uses pre-index ldr x?,[x?,#0x18]! here (0xF8418D6D class). */
|
||||
const bool isLdr18 = _asm::IsOp(sub[2], _asm::op::LdrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8)
|
||||
&& _asm::Get(sub[2], _asm::field::Off8) == 0x18;
|
||||
const bool isLdrPre18 = _asm::IsOp(sub[2], _asm::op::LdrPreImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Imm9)
|
||||
&& _asm::Get(sub[2], _asm::field::Imm9) == 0x18;
|
||||
R_UNLESS(isLdr18 || isLdrPre18, ldr::ResultInvalidDvcoRateConfig());
|
||||
|
||||
/* Patch the target */
|
||||
PATCH_OFFSET(sub, _asm::Encode(_asm::op::SubShifted64,
|
||||
{_asm::field::Rd, _asm::Get(*sub, _asm::field::Rd)},
|
||||
{_asm::field::Rn, _asm::Get(*sub, _asm::field::Rn)},
|
||||
{_asm::field::Rm, _asm::Get(*sub, _asm::field::Rm)},
|
||||
{_asm::field::Shift, 0}, {_asm::field::Imm6, 4}));
|
||||
|
||||
/* Search for the second anchor */
|
||||
u32* ldrsw = _asm::ScanAssembly(sub, 20,
|
||||
_asm::Encode(_asm::op::LdrsWImm64, {_asm::field::Rt, 0}, {_asm::field::Rn, 0}, {_asm::field::Off4, 0x154}),
|
||||
_asm::field::Rt, _asm::field::Rn);
|
||||
|
||||
R_UNLESS(ldrsw != nullptr, ldr::ResultInvalidDvcoRateConfig());
|
||||
|
||||
/* Validate the str #0x2a0 */
|
||||
auto isCorrectStr = [](u32 w) {
|
||||
return _asm::IsOp(w, _asm::op::StrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8)
|
||||
&& _asm::Get(w, _asm::field::Off8) == 0x2a0;
|
||||
};
|
||||
R_UNLESS(isCorrectStr(ldrsw[1]) || isCorrectStr(ldrsw[2]), ldr::ResultInvalidDvcoRateConfig());
|
||||
|
||||
/* Validate the target in both directuins */
|
||||
/* Due to codegen difference */
|
||||
u32 *add = nullptr;
|
||||
if (_asm::IsOp(ldrsw[-1], _asm::op::AddShifted64, _asm::field::Rd, _asm::field::Rn, _asm::field::Rm, _asm::field::Shift, _asm::field::Imm6)
|
||||
&& _asm::Get(ldrsw[-1], _asm::field::Shift) == 0
|
||||
&& _asm::Get(ldrsw[-1], _asm::field::Imm6) == 5) {
|
||||
add = ldrsw - 1;
|
||||
}
|
||||
else if (_asm::IsOp(ldrsw[1], _asm::op::AddShifted64, _asm::field::Rd, _asm::field::Rn, _asm::field::Rm, _asm::field::Shift, _asm::field::Imm6)
|
||||
&& _asm::Get(ldrsw[1], _asm::field::Shift) == 0
|
||||
&& _asm::Get(ldrsw[1], _asm::field::Imm6) == 5) {
|
||||
add = ldrsw + 1;
|
||||
}
|
||||
|
||||
R_UNLESS(add != nullptr, ldr::ResultInvalidDvcoRateConfig());
|
||||
|
||||
/* Patch the second target */
|
||||
PATCH_OFFSET(add, _asm::Encode(_asm::op::AddShifted64,
|
||||
{_asm::field::Rd, _asm::Get(*add, _asm::field::Rd)},
|
||||
{_asm::field::Rn, _asm::Get(*add, _asm::field::Rn)},
|
||||
{_asm::field::Rm, _asm::Get(*add, _asm::field::Rm)},
|
||||
{_asm::field::Shift, 0}, {_asm::field::Imm6, 6}));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
Result CpuVoltDfll(u32 *ptr);
|
||||
Result CpuLutMaxAsm(u32* ptr);
|
||||
Result CpuLutMaxAsm2(u32* ptr);
|
||||
|
||||
Result CpuLutDvcoRateCfg(u32* ptr);
|
||||
|
||||
ALWAYS_INLINE bool CpuLutAsmPatternFn(u32* ptr) {
|
||||
/* Check if it is a DSB ST, a common indication of CL-DVFS related functions */
|
||||
return *ptr == _asm::Dsb(_asm::barrier::St);
|
||||
@@ -100,4 +101,10 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
&& _asm::Get(*ptr, _asm::field::Imm16) == 0xC0FF
|
||||
&& _asm::Get(*ptr, _asm::field::Hw) == 0;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool CpuLutDvcoRateCfgPatternFn(u32* ptr) {
|
||||
/* Again, cleaner to ensure we are on the correct instruction here */
|
||||
return _asm::IsOp(*ptr, _asm::op::LdrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8)
|
||||
&& _asm::Get(*ptr, _asm::field::Off8) == 0x248;
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,7 @@ namespace ams::ldr::hoc::pcv::_asm {
|
||||
|
||||
constexpr Descriptor Off1 {10, 12, 0}; /* LDRB/STRB */
|
||||
constexpr Descriptor Off4 {10, 12, 2}; /* 32-bit LDR/STR */
|
||||
constexpr Descriptor Imm9 {12, 9}; /* pre/post-index offset */
|
||||
|
||||
constexpr Descriptor Barrier { 8, 4}; /* DSB/DMB option (CRm) */
|
||||
constexpr Descriptor Off8 {10, 12, 3}; /* 64-bit LDR/STR */
|
||||
@@ -117,6 +118,7 @@ namespace ams::ldr::hoc::pcv::_asm {
|
||||
constexpr u32 MovnW = 0x12800000;
|
||||
|
||||
constexpr u32 AddShifted64 = 0x8B000000;
|
||||
constexpr u32 SubShifted64 = 0xCB000000;
|
||||
constexpr u32 AndImm32 = 0x12000000;
|
||||
constexpr u32 AndImm64 = 0x92400000;
|
||||
constexpr u32 Ubfm32 = 0x53000000; /* UBFIZ/UBFX/LSL aliases */
|
||||
@@ -130,8 +132,10 @@ namespace ams::ldr::hoc::pcv::_asm {
|
||||
constexpr u32 LdrbImm = 0x39400000;
|
||||
constexpr u32 StrbImm = 0x39000000;
|
||||
constexpr u32 LdrImm32 = 0xB9400000;
|
||||
constexpr u32 LdrsWImm64 = 0xB9800000; /* LDRSW x, 32-bit mem, Off4-scaled */
|
||||
constexpr u32 StrImm32 = 0xB9000000;
|
||||
constexpr u32 LdrImm64 = 0xF9400000;
|
||||
constexpr u32 LdrPreImm64 = 0xF8400C00; /* LDR (pre-index): bits 11:10 fixed */
|
||||
constexpr u32 StrImm64 = 0xF9000000;
|
||||
|
||||
constexpr u32 StpImm64 = 0xA9000000;
|
||||
|
||||
Reference in new issue
Block a user