#!/usr/bin/env python3 """Wrapping PSP ring submit — lifts the ~1008-invoke ceiling in our harness. tinygrad's `_ring_submit` advances the write pointer monotonically and never wraps it against `ring_size`, so after 1024 submits it writes past the ring allocation and the PSP stalls (pass 84). Every fuzz in this audit was therefore capped at ~1000 invokes per boot. This module monkeypatches a wrapping version onto the live PSP object. Import and call `install(psp, adev)`; it returns a submit function with identical semantics plus wraparound. """ import ctypes from tinygrad.helpers import wait_cond import tinygrad.runtime.autogen.am.am as am def install(psp, adev): frame_sz = ctypes.sizeof(am.struct_psp_gfx_rb_frame) step = frame_sz // 4 def submit(cmd): # The write pointer itself must stay within the ring, not merely the byte offset: # letting it grow unbounded is what breaks at 1024 submits. wptr_max = psp.ring_size // 4 prev = adev.reg(f"{psp.reg_pref}_67").read() % wptr_max byte_off = prev * 4 msg = am.struct_psp_gfx_rb_frame(fence_value=prev + 1, cmd_buf_addr_lo=adev.paddr2mc(psp.cmd_paddr) & 0xFFFFFFFF, cmd_buf_addr_hi=adev.paddr2mc(psp.cmd_paddr) >> 32, fence_addr_lo=adev.paddr2mc(psp.fence_paddr) & 0xFFFFFFFF, fence_addr_hi=adev.paddr2mc(psp.fence_paddr) >> 32) adev.vram.view(psp.cmd_paddr, ctypes.sizeof(cmd))[:] = memoryview(cmd).cast('B') adev.vram.view(psp.ring_paddr + byte_off, ctypes.sizeof(msg))[:] = memoryview(msg).cast('B') adev.reg(f"{psp.reg_pref}_67").write((prev + step) % wptr_max) wait_cond(lambda: adev.vram.view(psp.fence_paddr, 4, 'I')[0], value=msg.fence_value, msg="sOS ring not responding") return type(cmd).from_buffer(bytearray(adev.vram.view(psp.cmd_paddr, ctypes.sizeof(cmd))[:])) return submit