D449 - PPSA02664 regressed to the allocator wall; the policy-region/reserve collision is the mechanism (open)

measured - 2026-09-01 (user-directed /loop)

D443 recorded PPSA02664 reaching 1541 calls (fault image+0xb14be3, _Getpctype); it now walls at 234 (image+0xafcc08, the tlsf allocator) - the exact pre-D443 state. The saved run from 13:41 confirms the 1541 was real, so this is a genuine regression between then and 15:15, not a misreading. The status summary that said PPSA02664 reaches ~1500 is corrected: it currently walls at 234.

The mechanism, now understood. sceKernelReserveVirtualRange has a region policy (a learned measurement, 0x200000 bytes "handed back through argument 0", learned.rs::policy). At load, install_policy_writes reserves that region at POLICY_REGION_BASE (reserve_somewhere, which platform-reserves and leaks the range) and plants its base into the call's argument 0. But argument 0 of sceKernelReserveVirtualRange is the guest's own out-pointer, so the plant overwrites the guest's hint with the region base. The handler then tries to reserve that base - which orbistoun already holds as the policy region - so the reservation conflicts, falls back to the far-higher mapping arena (0x72…), writes that back, and the guest's allocator, addressing its arena from the base it was handed, underflows: tlsf_add_pool rejects the pool (size must be between 0x28 and 0x100000000), the next allocation returns null, and the guest writes through it. POLICYDBG/RVRDBG traces confirmed each step (hint arriving as 0x6b0000000000, reserve falling back to 0x720000140000).

Why D443 did not hit this and now does is not established. The region policy derives from a learned measurement whose activation may have shifted across the flexible/virtual-query/sysctl turns, or a concurrent session was restructuring shared project data at the same time (it was actively splitting obSCEne's decision log). That is left as the open question rather than guessed at.

Two speculative fixes were tried this turn and reverted, because neither was clean and piling changes onto the reservation path without understanding is the shortcut principle 11 refuses:

The fix direction, for a careful turn (not more loop speculation): a region delivered to a function the guest itself reserves (sceKernelReserveVirtualRange) must be one the guest can reserve - either not pre-reserved by orbistoun, or honoured with a distinct sub-range per call. The tree is left net-zero for this turn (both attempts reverted, no stray diagnostics); obSCEne still runs its full suite unaffected.

Update - the pool size is not the reserve base or the query extent (both tried and eliminated).

Chased the tlsf underflow directly. Handing the guest a low, backed arena (carving a sub-range of the policy region) and answering sceKernelVirtualQuery on it - first with the whole region extent, then with the exact reserved length - were all built and tested. Every one still ends in tlsf_add_pool: size must be between 0x28 and 0x100000000 at 234 calls. So the size the guest hands tlsf_add_pool is not computed from the reservation base or from what sceKernelVirtualQuery reports - those inputs were varied across their whole plausible range and the fault is invariant. It comes from some other value the guest holds, and finding it needs the size the guest actually passes to tlsf_add_pool (a trace or disassembly of that call site), not more trial against the reserve/query path. All of the above was reverted; the tree is back to the 234 baseline. This is a focused debugging task, not loop-tickable, and the reserve/query machinery is a dead end for it.