diff --git a/docs/re/data/heap-ledger-gpu-writeback-probe.txt b/docs/re/data/heap-ledger-gpu-writeback-probe.txt new file mode 100644 index 00000000..fea6ab4d --- /dev/null +++ b/docs/re/data/heap-ledger-gpu-writeback-probe.txt @@ -0,0 +1,183 @@ +d> F8000008 MmAllocatePhysicalMemoryEx = BC220000 Size: 03A80000 +d> F8000008 MmAllocatePhysicalMemoryEx = BC1A0000 Size: 00080000 +d> F8000008 MmAllocatePhysicalMemoryEx = B50C0000 Size: 070E0000 +d> F800002C MmFreePhysicalMemory(00000000, BE078D80) +d> F8000044 MmFreePhysicalMemory(00000000, BDB18CC0) +d> F800002C MmFreePhysicalMemory(00000000, BC79C900) +d> F800002C MmFreePhysicalMemory(00000000, BCA44980) +d> F800002C MmFreePhysicalMemory(00000000, BCD24A00) +d> F800002C MmFreePhysicalMemory(00000000, BCE24A40) +d> F800002C MmFreePhysicalMemory(00000000, BD17CAC0) +d> F800002C MmFreePhysicalMemory(00000000, BD8E0C00) +d> F800002C MmFreePhysicalMemory(00000000, BDA60C40) +d> F800002C MmFreePhysicalMemory(00000000, BDFB8D40) +d> F8000008 MmFreePhysicalMemory(00000000, BD07CA80) +d> F8000008 MmAllocatePhysicalMemoryEx = B50B0000 Size: 00010000 +d> F8000008 MmAllocatePhysicalMemoryEx = B4CB0000 Size: 00400000 +d> F8000008 MmAllocatePhysicalMemoryEx = FFCA8000 Size: 00001000 +d> F8000008 MmAllocatePhysicalMemoryEx = B4910000 Size: 003A0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B4570000 Size: 003A0000 +d> F8000008 MmFreePhysicalMemory(00000001, B4560000) +d> F8000044 MmFreePhysicalMemory(00000000, BED2A080) +d> F8000008 MmAllocatePhysicalMemoryEx = B4490000 Size: 000E0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B3540000 Size: 00F50000 +d> F8000044 MmFreePhysicalMemory(00000000, BF26A0C0) +d> F8000008 MmAllocatePhysicalMemoryEx = B2CB0000 Size: 00890000 +d> F8000044 MmFreePhysicalMemory(00000000, BE94CF80) +d> F8000044 MmFreePhysicalMemory(00000000, BF36A100) +d> F8000044 MmAllocatePhysicalMemoryEx = B2A10000 Size: 002A0000 +d> F8000044 MmAllocatePhysicalMemoryEx = B2770000 Size: 002A0000 +d> F8000044 MmFreePhysicalMemory(00000000, B2770000) +d> F8000044 MmFreePhysicalMemory(00000000, BE88CF40) +d> F8000044 MmAllocatePhysicalMemoryEx = B28B0000 Size: 00160000 +d> F8000044 MmAllocatePhysicalMemoryEx = B2750000 Size: 00160000 +d> F8000044 MmFreePhysicalMemory(00000000, B2750000) +d> F8000094 MmAllocatePhysicalMemoryEx = B26F0000 Size: 001C0000 +d> F8000044 MmFreePhysicalMemory(00000000, BEA7A040) +d> F8000094 MmAllocatePhysicalMemoryEx = B20C0000 Size: 00630000 +d> F8000094 MmAllocatePhysicalMemoryEx = B2070000 Size: 00050000 +d> F8000044 MmFreePhysicalMemory(00000000, BE4E8E40) +d> F8000044 MmFreePhysicalMemory(00000000, BE378DC0) +d> F8000008 MmAllocatePhysicalMemoryEx = B2000000 Size: 00070000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1C30000 Size: 003D0000 +d> F8000008 MmFreePhysicalMemory(00000000, B2000000) +d> F8000008 MmAllocatePhysicalMemoryEx = B1B30000 Size: 00100000 +d> F8000008 MmFreePhysicalMemory(00000000, B1B30000) +d> F8000008 MmAllocatePhysicalMemoryEx = B1B30000 Size: 00100000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1A30000 Size: 00100000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1980000 Size: 000B0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B2040000 Size: 00030000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1890000 Size: 000F0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1840000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = B17F0000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1700000 Size: 000F0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B16B0000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1660000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1570000 Size: 000F0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1520000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = B14D0000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0E30000 Size: 006A0000 +d> F800015C MmAllocatePhysicalMemoryEx = B0DA0000 Size: 00090000 +d> F800015C MmAllocatePhysicalMemoryEx = B0D10000 Size: 00090000 +d> F800015C MmAllocatePhysicalMemoryEx = B0C80000 Size: 00090000 +d> F800015C MmAllocatePhysicalMemoryEx = B0BF0000 Size: 00090000 +d> F800015C MmAllocatePhysicalMemoryEx = B0B60000 Size: 00090000 +d> F800015C MmAllocatePhysicalMemoryEx = B0AD0000 Size: 00090000 +d> F800015C MmAllocatePhysicalMemoryEx = B0A40000 Size: 00090000 +d> F800015C MmAllocatePhysicalMemoryEx = B09B0000 Size: 00090000 +d> F8000008 MmFreePhysicalMemory(00000000, B0E30000) +d> F8000008 MmFreePhysicalMemory(00000000, B1B30000) +d> F8000008 MmFreePhysicalMemory(00000000, B2040000) +d> F8000008 MmFreePhysicalMemory(00000000, B1980000) +d> F8000008 MmFreePhysicalMemory(00000000, B09B0000) +d> F8000008 MmFreePhysicalMemory(00000000, B0C80000) +d> F8000008 MmFreePhysicalMemory(00000000, B0A40000) +d> F8000008 MmFreePhysicalMemory(00000000, B0AD0000) +d> F8000008 MmFreePhysicalMemory(00000000, B0D10000) +d> F8000008 MmFreePhysicalMemory(00000000, B0DA0000) +d> F8000008 MmFreePhysicalMemory(00000000, B0B60000) +d> F8000008 MmFreePhysicalMemory(00000000, B0BF0000) +d> F8000008 MmFreePhysicalMemory(00000000, B1A30000) +d> F8000008 MmFreePhysicalMemory(00000000, B1890000) +d> F8000008 MmFreePhysicalMemory(00000000, B1840000) +d> F8000008 MmFreePhysicalMemory(00000000, B17F0000) +d> F8000008 MmFreePhysicalMemory(00000000, B1700000) +d> F8000008 MmFreePhysicalMemory(00000000, B16B0000) +d> F8000008 MmFreePhysicalMemory(00000000, B1660000) +d> F8000008 MmFreePhysicalMemory(00000000, B1570000) +d> F8000008 MmFreePhysicalMemory(00000000, B1520000) +d> F8000008 MmFreePhysicalMemory(00000000, B14D0000) +d> F8000008 MmFreePhysicalMemory(00000000, BE4B0E00) +d> F8000008 MmAllocatePhysicalMemoryEx = B1450000 Size: 007E0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B1060000 Size: 003F0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0C70000 Size: 003F0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0970000 Size: 00300000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0870000 Size: 00100000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0730000 Size: 00140000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0620000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0590000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0480000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = B03F0000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = B02E0000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0250000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = B0140000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = B00B0000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AFDB0000 Size: 00300000 +d> F8000008 MmAllocatePhysicalMemoryEx = AFCB0000 Size: 00100000 +d> F8000008 MmAllocatePhysicalMemoryEx = AFB70000 Size: 00140000 +d> F8000008 MmAllocatePhysicalMemoryEx = AFA60000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF9D0000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF8C0000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF830000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF720000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF690000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF580000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF4F0000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF1F0000 Size: 00300000 +d> F8000008 MmAllocatePhysicalMemoryEx = AF0F0000 Size: 00100000 +d> F8000008 MmAllocatePhysicalMemoryEx = AEFB0000 Size: 00140000 +d> F8000008 MmAllocatePhysicalMemoryEx = AEEA0000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AEE10000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AED00000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AEC70000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AEB60000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AEAD0000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AE9C0000 Size: 00110000 +d> F8000008 MmAllocatePhysicalMemoryEx = AE930000 Size: 00090000 +d> F8000008 MmAllocatePhysicalMemoryEx = AE540000 Size: 003F0000 +d> F8000008 MmAllocatePhysicalMemoryEx = B2020000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = ADE00000 Size: 00740000 +d> F8000008 MmAllocatePhysicalMemoryEx = ADD80000 Size: 00080000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD640000 Size: 00740000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD2A0000 Size: 003A0000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD220000 Size: 00080000 +d> F8000008 MmAllocatePhysicalMemoryEx = B2010000 Size: 00010000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD1D0000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD180000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD130000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = B2000000 Size: 00010000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD120000 Size: 00010000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD0E0000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD0A0000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD060000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = AD020000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACFE0000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACFA0000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACF60000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACF20000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACEE0000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACEA0000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACE60000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACE20000 Size: 00040000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACD20000 Size: 00100000 +d> F8000008 MmFreePhysicalMemory(00000000, ACD20000) +d> F8000008 MmAllocatePhysicalMemoryEx = ACD20000 Size: 00100000 +d> F8000008 MmFreePhysicalMemory(00000000, ACD20000) +d> F8000008 MmAllocatePhysicalMemoryEx = ACDD0000 Size: 00050000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACDC0000 Size: 00010000 +d> F8000008 MmAllocatePhysicalMemoryEx = ACCC0000 Size: 00100000 +d> F8000008 MmFreePhysicalMemory(00000000, ACCC0000) +d> F8000008 MmAllocatePhysicalMemoryEx = AC200000 Size: 00BC0000 +d> F8000008 MmAllocatePhysicalMemoryEx = ABE30000 Size: 003D0000 +d> F8000008 MmAllocatePhysicalMemoryEx = ABA60000 Size: 003D0000 +d> F8000008 MmAllocatePhysicalMemoryEx = AB690000 Size: 003D0000 +d> F8000008 MmAllocatePhysicalMemoryEx = AB2C0000 Size: 003D0000 +d> F8000008 MmFreePhysicalMemory(00000000, AC200000) +d> F8000008 MmFreePhysicalMemory(00000000, B2A10000) +d> F8000008 MmFreePhysicalMemory(00000000, BE7A8F00) +d> F8000008 MmFreePhysicalMemory(00000000, BDA98C80) +d> F8000008 MmAllocatePhysicalMemoryEx = B2C30000 Size: 00080000 +d> F8000008 MmAllocatePhysicalMemoryEx = B2B30000 Size: 00100000 +d> F8000008 MmFreePhysicalMemory(00000000, B2C30000) +d> F8000008 MmAllocatePhysicalMemoryEx = ACBC0000 Size: 00200000 +d> F8000008 MmFreePhysicalMemory(00000000, B2B30000) +d> F8000008 MmAllocatePhysicalMemoryEx = AC7C0000 Size: 00400000 +d> F8000008 MmFreePhysicalMemory(00000000, ACBC0000) +d> F8000008 MmAllocatePhysicalMemoryEx = AAAC0000 Size: 00800000 +d> F8000008 MmFreePhysicalMemory(00000000, AC7C0000) +d> F8000008 MmAllocatePhysicalMemoryEx = A9AC0000 Size: 01000000 +d> F8000008 MmFreePhysicalMemory(00000000, AAAC0000) +d> F8000008 MmAllocatePhysicalMemoryEx = A7AC0000 Size: 02000000 +d> F8000008 MmFreePhysicalMemory(00000000, A9AC0000) +d> F8000008 MmAllocatePhysicalMemoryEx = A3AC0000 Size: 04000000 +d> F8000008 MmFreePhysicalMemory(00000000, A7AC0000) diff --git a/docs/re/mission-freeze-heap-exhaustion.md b/docs/re/mission-freeze-heap-exhaustion.md index f987340b..74cfd5b4 100644 --- a/docs/re/mission-freeze-heap-exhaustion.md +++ b/docs/re/mission-freeze-heap-exhaustion.md @@ -310,3 +310,85 @@ Not fixed. The remaining candidates, in the order I would try them: be probing sizes by doubling. 3. **Reach flight another way.** The tutorial loads less; two attempts timed out before reaching it, and that is unfinished rather than refuted. + +--- + +# Two patched builds, and 🔴 the allocation failure is **not** the freeze + +**2026-08-26.** Both hypotheses about *why* the request is 128 MB, and the one +fix that removed the failure, were tested against a rebuilt canary. Result: the +oracle is still broken, and the headline above is now known to be incomplete. + +## 🔴 The game does not size anything from `MmQueryStatistics` + +`xeMmQueryStatistics` reports `kernel_pages = 0x100` — **1 MB** — under a comment +that admits *"These numbers are mostly guessed"*. A real console reserves far +more, so Xenia over-reports `title.available_pages`. The game **does** import and +call it: the only xref is `sub_82612440`, inside `sub_82612420`, which converts +`total_physical_pages` and `title.available_pages` to bytes and stores them in +its own struct; its caller keeps available-bytes in `r23` and then creates +1280×800 and 640×400 surfaces. That looked like over-reporting driving +over-allocation. + +Patched `kernel_pages` `0x100` → `0x2000` (1 MB → 32 MB, twice the shortfall) and +rebuilt: + +| | allocs | ever allocated | live at failure | failure line | +|---|---|---|---|---| +| stock (1 MB) | 122 | 484.5 MB | 379.5 MB / 84 blocks | `free 28969/131072` | +| patched (32 MB) | 122 | 484.5 MB | 379.5 MB / 84 blocks | `free 28969/131072` | + +**Byte-identical.** A 32× change in reported kernel memory changed nothing. +Refuted, and the patch was reverted. + +## ✅ The missing ~19 MB is Xenia's fixed startup reservations + +`memory.cc:240` reserves **16 MB** of the parent heap before the guest runs: + +```cpp +heaps_.vC0000000.AllocFixed(0xC0000000, 0x01000000, 32, ...); // GPU writeback +``` + +`vC0000000`'s parent **is** the 512 MB physical heap, so this comes straight off +the guest's budget — and 16 MB is larger than the 14.84 MB shortfall. That +accounts for nearly all of the 19.3 MB the ledger could not see. + +## 🔴 Shrinking it removes the allocation failure — and the game still freezes + +Patched that reservation `0x01000000` → `0x00100000` (16 MB → 1 MB) and rebuilt. +The stage load then completes with **zero** allocation failures and **zero** +`Guest attempted to throw` — the 128 MB request is gone. + +**And the game is still frozen.** Verified with one emulator running (the stale +one killed first): three frames at rmse 0.00, an 8 MB guest slab with 0 bytes +changed over 3 s, 389 % CPU across 3 running threads. + +Worse, the ledger says it froze **earlier**: the doubling sequence now stops at +**32 MB** (`A7AC0000 Size: 02000000`), where the stock build reached 64 MB before +failing at 128. Shrinking a live GPU region evidently hangs the GPU instead. The +probe was reverted. +[`data/heap-ledger-gpu-writeback-probe.txt`](data/heap-ledger-gpu-writeback-probe.txt). + +## 🔴 What this costs the earlier conclusion + +The section above says the freeze **is** the refused 128 MB allocation. That is +now **too strong**. Removing the refusal does not remove the freeze. The honest +statement is: + +* the 128 MB refusal is **real** and reproducible, and Xenia's fixed 16 MB + reservation is the swing factor that decides it; +* but the guest also hangs **without** it, at an earlier point, so the refusal is + at best *one* of the ways this stage load dies, not the single cause. + +❔ Still open, and the oracle remains unreliable: what hangs the guest when the +allocation succeeds. The stock build's `Guest attempted to throw a C++ exception!` +gave a mechanism for one path; the patched build reaches no exception at all, so +the other path needs its own diagnosis — the `log_stuck_waits` instrumentation +already on the canary branch is the obvious next tool. + +## 🔴 Three flags in this corpus's scripts do not exist in this build + +Checked with the 209-vs-67 000 byte log signature for a rejected argument: +`--eh_dispatch` (named in `newgame_path.sh` and `title-crash-stl-tree.md`), +`--mem_watch` (passed by `newgame_path.sh`), and `--audio`. All three are +silently rejected, which blocks boot entirely rather than warning.