aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/CONSTRAINTS.md
blob: e3b06bacf16196ce97d359302209423056dfa76e (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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Standing constraints (user-set)

## NO TSU / NO SPI FLASH WORK
The user does not want flash touched unattended. This rules out, until explicitly
re-authorised:

* the **TSU mailbox** update path (`C2PMSG_115/116` + doorbell `73`) — any command
  that can reach `spi_erase_range` / `spi_write_status` / `tsu_write_block`;
* the **TSU SRAM disclosure primitive** (`ANALYSIS-PSP-CODE-EXEC-AVENUES.md`) and
  the open `mapped_base` question it depends on — **dropped**, not deferred;
* `PLAN-BOOT-WINDOW-ROMSW.md` — its entire payoff is a mid-boot flash write
  (Phase 3). Phases 0-2 are read-only but lead nowhere else, so the plan is shelved;
* using **BIOS-1 as a sacrificial flash lab**;
* `extra/amdflash/romless.py` and `fw_live.py` in any writing mode
  (`flash`, `ifwi-step`, `live-flash`, `ifwi-all`).

Reading flash for analysis of an image we already hold on disk is fine; issuing
flash commands to the card is not.

### Still in scope
* static analysis of all modules (sOS, SYS_DRV, ASD, HDCP, DTM, RAS, MEC, VCN);
* the 38-build version-diff corpus (`decompiled/`, `phase3/`, `phase4_diffs.json`);
* non-destructive hardware probing: BAR5 register reads, SMN reads via the
  index/data windows, `regguard`-validated;
* host-reachable TA exercise via `INVOKE_CMD` (HDCP), which does not touch flash;
* the TRNG/canary line (`LEAD-TRNG-CANARY-PREDICTION.md`) — its remaining trigger
  is fault injection via power sequencing, not flash.

### Check before using
**Firmware rollback** (`CONFIRMED-FIRMWARE-ROLLBACK-WORKS.md`): confirm whether the
method used there writes flash or only supplies an alternate image over the normal
PSP load path. If it writes flash, it falls under this constraint too.

## LOAD_TA must not be aimed outside VRAM (added after wedging the card)

Submitting `GFX_CMD_ID_LOAD_TA` with `app_phy_addr` beyond the end of VRAM does
not produce an error status. It produces a flood of `SOC21_IH_CLIENTID_VMC`
VM-fault interrupts and wedges the SMU: `SMU msg 0x2 timeout`, `mode1_reset`
fails, and the device disappears (`0 devices available`). Recovery is a cold ATX
cycle (`$PSP_PY atx_power.py cycle 25`), which does restore it — heartbeat
confirmed advancing afterwards.

This is the **same wedge signature as the broad-SMN-sweep hazard**, reached by a
completely different route. That suggests the rule is general rather than
specific to SMN: **any probe that makes an on-die engine access unbacked memory
can take out the SMU.** Probe addresses must lie inside a real allocation unless
the resulting fault flood is bounded first.

## Do not sweep PSP LOAD_IP_FW firmware types (added 2026-09)

Submitting junk payloads across the `GFX_FW_TYPE_*` space to discover which types a
card supports **wedges the PSP**: the sOS ring stops responding ("sOS ring not
responding", fence stuck) and the SMU times out (`SMU msg 0x1a`), while the PCIe
link stays up. Only a cold ATX cycle (`work/atx_power.py cycle 25`) recovers it —
verified. The `SMU` and `PPTABLE` types are the suspected trigger.

The measured result is already recorded in `FIRMWARE-COVERAGE-MATRIX.md`, so there
is no reason to repeat the sweep.

## A compute pipe that will not fetch leaves a stuck HQD (added 2026-09)

Standing up a compute/KIQ queue on a pipe that is not fully initialised (see
`MEC-PM4-FOOTHOLD.md` round 8: pipe 3 without its HPD/EOP programming) produces a queue
that activates but never fetches — and then **cannot be dequeued**:
`CP_HQD_DEQUEUE_REQUEST` leaves `CP_HQD_ACTIVE = 1`, `GRBM_STATUS` sits at `0xa800302c`
instead of `0x0000302c`, and neither `AM_GFX.reset_mec()` nor a full driver re-init
clears it. Only a cold ATX cycle (`work/atx_power.py cycle 25`) recovers.

Do this work only when a power cycle is acceptable, and check `GRBM_STATUS` afterwards
rather than assuming the driver cleaned up.

## Never kill a hardware script mid-flight, and never delete its USB lock (added 2026-10)

Wedged the card this way: a probe was running (holding `/tmp/am_usb:2-11.lock` and the USB handle),
it was `kill`ed mid-operation, the lock file was then removed by hand, and a second process was
started. Result was the documented wedge signature -- `AMD:0 does not exist (0 devices available)`,
then `SMU msg 0x2 timeout` from `mode1_reset` inside tinygrad's own init. Only
`$PSP_PY work/atx_power.py cycle 25` recovered it (power-only, no flash, safe under this file).

Rules:
* Let hardware scripts finish. If one must be stopped, stop it and then ATX-cycle before the next
  run -- do not reuse the device in between.
* `env.sh` removes stale locks on purpose; that is for the case where NO process holds the device.
  Removing the lock while a process still holds the USB handle is the hazard, not the fix.
* Run long probes detached with a logfile (`setsid nohup ... > log 2>&1 < /dev/null &`) and poll the
  log. Piping to `tail` over ssh loses all output when the connection drops.
* Do not use `pkill -f <pattern>` over ssh when the pattern also matches your own command line --
  it kills the ssh session and returns silently, which reads exactly like a hang.

## FE0A with *(params+0x818) large leaves the TA unable to open a session (added 2026-10)

`*(params+0x818) = 0xFFFFFFFB` on an FE0A path makes the handler replicate the param block across
the whole command buffer, write no completion status, and leave GCP in a state where `FE07` fails
8/8. Needs an ATX cycle. Keep `0x818` small on FE0A; see Addendum 144 of
`fw/FINDING-GCP-FE09-CONFIGINIT-HOST-OFFSET-WRITE.md`.