simulation: tripwire + PC-bucketed diff + bitflip sweep

Ship the new simulation & verification stack under simulation/:

- mmio_regions.py — address → region classifier (DDRCTL, DDRPHY,
  OTP, SRAM, …). Shared by every other tool so trace output is
  scannable without memorising the memory map.
- sim_tripwire.py — Bin-style per-access capture. Records
  (seq, insn_tick, pc, addr, size, rw, val, region, fn_name) per
  MMIO access. PCResolver bisects the vendor funs table parsed
  from ddr_conservative_asm.s.
- tripwire_diff.py — PC-bucketed difflib.SequenceMatcher diff of
  two tripwire CSVs. Buckets by fn_name so bitflip-induced control
  flow divergence doesn't cascade noise.
- training_sim.py — DDR training simulator with --mode pass and
  --mode bitflip (flip first N reads per training status, exercise
  retry paths). BITFLIP_ONLY env var narrows to a single addr for
  the sweep.
- bitflip_sweep.py — Flip each of 23 training-status addresses
  one-at-a-time and tabulate retry convergence. Surfaces which
  function(s) react to a transient fault by writing different
  downstream register values.

Plus:

- mmio_diff.py updated: region-tagged divergence output,
  --show-regions histogram, --tripwire-out-{vendor,rebuilt} CSV
  capture, --capture-stack-writes for stack-allocated buffer diffs.
- debug_probes/tp_slot_{probe,writes}.py — ad-hoc Unicorn probes
  for chasing a single-slot divergence in an SRAM buffer. Kept as
  reference examples of how to extend the tripwire toolchain.

The stack found 6 silicon-hostile bugs in the rebuilt blob that
mmio_diff's write-sequence gate was structurally blind to, including
three ld-unresolved-symbol NULL derefs (case-mismatched externs,
missing DATA_SYMS) and one C-early-return-skips-shared-tail bug
where vendor's asm fell through to the tail via `b` after a `ret`.
This commit is contained in:
2026-04-22 05:55:28 +02:00
parent e20563e2ef
commit 46155bbe91
10 changed files with 1796 additions and 2 deletions
+39 -2
View File
@@ -14,8 +14,27 @@ n## Prerequisites
Decompilation, analysis, and patching of the closed-source Rockchip RK3588
DDR initialization binary blobs.
Decompilation, analysis, patching, and **pre-silicon simulation** of the
closed-source Rockchip RK3588 DDR initialization binary blobs.
The project has three layers:
1. **Static RE** — Ghidra-exported decompiled C + disassembly +
annotated register map (`ddr_annotated.c`, `rk3588_ddr.h`).
2. **Patch + flash**`patch_prod.py` rewrites specific poll loops
in the vendor blob to work around known hangs. Validated under
Unicorn via `blob_emu.py` before flash.
3. **Matching-decomp rebuild + simulation** — the goal is a buildable
working DDR blob (not bit-identical reproduction). Per-function C
ports are spliced into the vendor blob; `mmio_diff.py` gates
behavioral equivalence by MMIO write sequence. The `simulation/`
subdir adds read-side tripwire capture, PC-bucketed diff, and
per-address bitflip fault injection for retry-path validation.
> "Markus' insistence on simulation before flashing paid off. Big
> time. Again." — 2026-04-21. Tripwire + PC-bucket diff caught three
> silent NULL-derefs hidden behind `mmio_diff=3173/3173` green.
> `ld --unresolved-symbols=ignore-all` had zeroed undefined
> DATA_SYMS externs; silicon would have bricked.
## Quick Start
@@ -73,8 +92,26 @@ gcc -O2 -o ddr_emu ddr_emu2.c -lunicorn -lm
| File | Description |
|------|-------------|
| `ddr_emu2.c` | Unicorn-based C emulator with MMIO stubs |
| `blob_emu.py` | Python Unicorn harness — runs a blob, stubs MMIO, captures UART TX |
| `mmio_diff.py` | Runs vendor + rebuilt, diffs MMIO write sequences; region-tagged output |
| Ghidra project | On oppenheimer (CT131): `/opt/work/ghidra_project/` |
### Simulation & Verification Stack (`simulation/`)
| File | Description |
|------|-------------|
| `simulation/mmio_regions.py` | Address → region classifier (`DDRCTL`, `DDRPHY`, `OTP`, `SRAM`, …) |
| `simulation/sim_tripwire.py` | Bin-style per-access capture with PC → fn name resolver |
| `simulation/tripwire_diff.py` | PC-bucketed SequenceMatcher diff of two tripwire CSVs |
| `simulation/training_sim.py` | DDR-training simulator: `pass` and `bitflip-first-pass` modes |
| `simulation/bitflip_sweep.py` | Flip each training-status addr one-at-a-time, report retry convergence |
| `simulation/README.md` | Synopsis + usage for the above |
### Debug Probes (`debug_probes/`)
| File | Description |
|------|-------------|
| `debug_probes/tp_slot_probe.py` | Snapshot the `tp` timing buffer at fn_5540's read site |
| `debug_probes/tp_slot_writes.py` | List every write to a specific `tp` slot, both vendor and rebuilt |
### Ghidra Export Scripts
| File | Description |
|------|-------------|