# Driving the RAS TA on real silicon, and what it settles The emulator cannot open RAS's init gate: SYS_DRV RPC opcode 0x000d fails a capacity check because the context at 0xE575B8 is zero (see `harness/sysdrv_bridge.py`). A bounded search found nothing that populates it -- not init, not any of RAS's RPCs, no low opcode, none of 36 sampled high opcodes, and not a full `full_system.py` boot. The open question was whether that is a **missing-state gap in our emulation** or something the firmware genuinely never does. That question is not answerable inside the emulator. It is answerable on a card. ## Tooling: a LOAD_TA path that did not exist tinygrad has no TA loading support, so `psp_out/load_ta.py` builds one on top of `AM_PSP._ring_submit`: allocate VRAM for the signed TA container and a shared command buffer, fill `cmd_load_ta` with MC addresses, submit `GFX_CMD_ID_LOAD_TA` to get a session id, then `GFX_CMD_ID_INVOKE_CMD` per command, and `GFX_CMD_ID_UNLOAD_TA` at the end. PSP heartbeat is checked before and after every submit. The TA driven is the card's own signed RAS 27.0.2.5 container, taken from `psp_13_0_0_ta.bin` -- the same TA whose body is byte-identical to our `ras2.elf`, so this is the exact code the emulator runs. ## The control that saved the result The first run reported `status=0` for commands 1, 2, 3 and 4 and looked like a clean sweep of successes. It was not. `resp.status` is **ring delivery only**: feeding it `0xdead` and `0x7fff` also returned `status=0` with byte-identical output. Reporting that would have been a fabricated "all RAS commands succeed on hardware". The TA's own verdict lives in the shared buffer, `struct ta_ras_shared_memory`: +0x00 cmd_id +0x04 resp_id +0x08 ras_status +0x0c if_version and the command id goes **in the buffer**, not only in the ring command -- the same shape as the HDCP invoke ABI decoded earlier in this tree. With that fixed, valid and invalid commands separate cleanly. ## The RAS command surface on this card | command | ring status | ras_status | | --- | --- | --- | | 1 | 0x0 | **0x0 -- success** | | 2 | 0x0 | 0xa002 | | 3 | 0x0 | 0xa010 | | 4 | 0x0 | 0xa010 | | 5 .. 0x10 | **0xFFFF000A (rejected at the ring)** | -- | So RAS exposes exactly four commands, 1 through 4; everything above is refused before reaching the TA. Command 1 completes successfully, 2 and 3/4 return TA-level errors in RAS's `0xa0XX` family. (3 and 4 returning "not available" on a consumer card with no ECC memory is unsurprising, but that reading is an interpretation, not something measured here.) ## What this settles **RAS initialises on real hardware.** Command 1 returns `ras_status = 0`, which means the TA processed it rather than short-circuiting on its init gate. RAS gates every command on the byte at 0x4060E0, written only inside `TA_OpenSessionEntryPoint` on a path that bottoms out in the SYS_DRV RPC chain including opcode 0x000d. For command 1 to succeed, that chain must have succeeded, so **the SYS_DRV context at 0xE575B8 is populated on a real boot.** The emulator blocker is therefore a **missing-state gap in our emulation, not a firmware defect** -- which was always the suspicion, and is now evidence. The harness note was already careful to say "uninitialised SYS_DRV state, NOT a defect"; that call is now confirmed from outside the emulator. ## What this does NOT settle It does not reveal **what** populates 0xE575B8. That is PSP-internal state on a path the host cannot observe -- the host speaks GFX ring commands, and the capacity is set somewhere inside SYS_DRV. Hardware confirms the destination; finding the writer remains an emulator-side problem. It also does not make RAS command coverage reportable in the emulator. What it does provide is an **oracle**: once the gate opens, the emulator must reproduce 1 -> 0x0, 2 -> 0xa002, 3/4 -> 0xa010, and reject 5+ at the ring. Any emulated RAS result that disagrees with that table is wrong. ## Housekeeping `LOAD_TA` allocates a fresh session id on every call (observed climbing 0, 1, 2, ... across runs), so sessions are a finite resource that leaks if not released. `load_ta.py` now issues `UNLOAD_TA` before exiting. The card was verified healthy after every run: heartbeat advancing, LTSSM 0x78 (L0, link up). No ATX cycle was needed at any point.