aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/probe_vccc_control.py
blob: 5593cdb57706716d7af6beb54e207ffb3d75def0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
"""CONTROL for probe_vccc_0x26.py.

The negative result there (status invariant to request bytes at offset 928)
is only meaningful if those bytes actually reach the PSP's command buffer.
This verifies the write path and shows what the PSP does/doesn't overwrite.

Non-destructive: submits cmd 0x26 only.
"""
import ctypes
from tinygrad import Device
from tinygrad.runtime.autogen.am import am

d = Device["AMD"]; adev = d.iface.dev_impl; psp = adev.psp
SZ = ctypes.sizeof(am.struct_psp_gfx_cmd_resp)

def alive(): return adev.reg(f"{psp.reg_pref}_81").read() != 0

MARK = bytes(range(0x40, 0x40 + 32))          # distinctive, position-dependent
c = am.struct_psp_gfx_cmd_resp(cmd_id=0x26)
buf = bytearray(memoryview(c).cast('B'))
buf[928:960] = MARK

sent = bytes(((0x5A ^ (i & 0xFF)) & 0xFF) for i in range(SZ))
adev.vram.view(psp.cmd_paddr, SZ)[:] = sent
before = bytes(adev.vram.view(psp.cmd_paddr, SZ)[:])
print("pre-submit  928..960:", before[928:960].hex())

status = None
try:
    psp._ring_submit(am.struct_psp_gfx_cmd_resp.from_buffer_copy(bytes(buf)))
    status = 0
except RuntimeError:
    after = bytes(adev.vram.view(psp.cmd_paddr, SZ)[:])
    status = int.from_bytes(after[864:868], "little")
except TimeoutError:
    status = -1

after = bytes(adev.vram.view(psp.cmd_paddr, SZ)[:])
print("post-submit 928..960:", after[928:960].hex())
print("we wrote            :", MARK.hex())
print()
print("status:", hex(status) if status >= 0 else "TIMEOUT")
print("our MARK survived in VRAM :", after[928:960] == MARK)
print("sentinel still there      :", after[928:960] == sent[928:960])
print("resp area 864..880        :", after[864:880].hex())
print("sOS alive                 :", alive())