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
|
# 46 — Surgical rehost of firmware functions (in development)
> **Status: in development (2026-10-06, rehost wave).** Documents
> `harness/rehost.py`: run one bounded function of a real/modelled firmware
> image on the native emulator, starting at a chosen entry with a crafted
> register/memory state, and record a session + report. This is the workflow
> the RE review ranks first for the live GR wall (docs/39 U2): answer
> server-side hypotheses from rehosted execution with hooks/watchpoints/
> memory tools instead of another static read or another hardware cycle.
>
> Development-only: executes firmware on the simulator. Never touches a GPU,
> kernel module, mdev, guest or network. No timing/cycle claim (L0/L1).
>
> **See also:** `39-RE-WORKFLOW-REVIEW.md` (U2), `44-GMMU-ORACLE-AND-WORKFLOW.md`
> (the same evidence discipline), `03-SCRIPTING.md` (hooks/watch/memory),
> `16-CUSTOM-SIMULATOR.md` (backend design), `45-RM-RPC-CAPTURE-AND-REPLAY.md`
> (the capture whose sequence a rehost can seed).
## 1. What it does
* Loads an ELF image into the native machine exactly like `sim.gsp_boot`
(device registry from the profile, optional boot shim, libos syscall model,
lenient MMIO).
* Writes caller-supplied memory (`--mem addr=hex`), sets `a0..a7`
(`--arg`), installs a return trampoline (`ra` + `ebreak` sentinel) and a
private stack, and starts at `--entry` (hex address or ELF symbol).
* Runs under `--budget` instructions and a wall-clock `--timeout`, stopping on
return (`R_BP` at the sentinel), fault, unhandled ecall, timeout or budget.
* Snapshots regions before/after (`--snap addr:size`) with per-region changed
bytes, first-difference offset and sha256s; dumps nonzero registers on entry
and exit; records a `greeneye-session/1` directory and a
`greeneye-rehost/1` report.
```
python3 harness/rehost.py run --entry 0x5b01210 --arg 0 --budget 50000 \
--snap 0x1000000:64 --out dumps/rehost-gate
python3 harness/rehost.py demo # synthetic self-test (demo firmware)
```
## 2. Report schema (`greeneye-rehost/1`)
`status` is one of `return | fault | ecall | timeout | budget`; `fault`
carries the trap cause and `tval`; `retval` is `a0` at the stop; snapshots
carry the before/after diff. The report states its limits explicitly: it is
**not a boot** (the function ran with only the supplied state), a fault is the
**first missing state observed**, not a product defect, and there is no
timing claim.
## 3. First probes on the 570.144 image (2026-10-06)
All offline, one bounded call each, `a0=0`, budget 300k (numeric vaddrs from
the campaign analysis):
| entry | status | stop pc | `a0` at stop | insns | fault |
|---|---|---|---|---|---|
| GR per-buffer commit gate `0x5b01210` | fault | `0x0` | `0x40` | 24 | illegal @ `0x0` |
| per-buffer commit `0x5b00d2c` | budget | `0x5b0110c` | `0x40` | 189 | — |
| commit caller `0x5b00dd8` | budget | `0x5b0120c` | `0x40` | 110 | — |
| engine-ctx memdesc install `0x514cab8` | fault | `0x0` | `0x429b450` | 97 | illegal @ `0x0` |
| promote handler `0x526a530` | budget | `0x5244134` | `0x40` | 167 | — |
| per-entry commit `0x5290a48` | budget | `0x5897fdc` | `0x40` | 258 | — |
| engine-class commit `0x5350078` | budget | `0x5350484` | `0x40` | 197 | — |
Reading: with no engine-context state, the whole gate family bottoms out in
`NV_ERR_INVALID_STATE (0x40)` — the same family the live campaign observes —
and the memdesc-install path faults on a NULL callback early. That is a
reproduction of known behaviour, not an answer: the next step is to **seed the
context objects** (from the B4 message-loop state or from crafted structures)
and A/B the promote entry shapes against these entries.
## 4. Admission record (draft — pending maintainer filing)
Per the project admission rule (docs/eng-ops.md §2), all five fields:
| Field | Value |
|---|---|
| Scenario | dynamic-RE loop: run the GR promote/commit functions of the real 570.144 image off-hardware at a chosen entry with crafted state, to answer server-side hypotheses (gate/entry/context requirements) without hardware cycles. |
| Measurable outcome | sessions per hypothesis; wall time per probe; zero hardware cycles; rehost status/fault map. |
| Baseline | the live campaign's modes 4–22 day (docs/39: 730+ lines of static RE, three wedge-reboot cycles for one accepted root cause). |
| Evaluation threshold | ≥1 wall hypothesis answered with a session pair and **zero** hardware cycles; probe loop ≤ 2 minutes per entry (measured: ≈0.1 s per probe); deterministic status/`a0` across runs. |
| Failure signal | a probe cannot be driven because required device semantics are absent, and crafted-state seeding cannot reach the failing branch after two bounded attempts → record the gap and fall back to static + physical. |
## 5. Limits
* Not a boot: entry-state dependence is the whole difficulty; a `budget` stop
usually means the entry is mid-function or the path loops without returning.
* The first probes use caller-supplied `a0`; the real argument conventions and
context layouts are to be supplied by seeding (or by B4/B5 state).
* Single hart, flat memory, no interrupts/scheduling; unknown MMIO is lenient
and counted, and can mask environment dependence.
* No cycle/timing/security claim; L0/L1 fidelity only.
|