diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 09:13:00 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 09:13:00 -0400 |
| commit | 1e701396b1b6d204dfd8e5a8ddcd3007038029ac (patch) | |
| tree | 8dde895cf9d3e66ce912d01cb1a72ff674dc850f /debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md | |
| parent | ab48e44832db55fdedadcf44f55fa9904ca36f2f (diff) | |
| download | open-iov-1e701396b1b6d204dfd8e5a8ddcd3007038029ac.tar.gz open-iov-1e701396b1b6d204dfd8e5a8ddcd3007038029ac.zip | |
debug: green-eye wave 2 - injection SDK, Frida-like calls, Ghidra control bridge, long-term docs
Adds to debug/risc-v-gsp-rm-vm/:
- Session.call / run_until: Frida-like remote function calls and run-to-cursor,
with register restoration; verified live (rpc_ping -> 0xaffe).
- symbol+offset target resolution (gsp_ctrl+0x10) across all APIs and the REPL.
- Injection SDK (sdk/) and 'greeneye inject': position-independent RV64 service
blobs (verified zero relocations), loaded into RAM, registered in the demo
handler table, and invoked either directly or through the firmware mailbox
dispatcher. Demo ABI extended: mailbox 16..23 selects slots, arg0 carries the
service command, arg2 added (struct now 0x190; schema updated).
- Ghidra control bridge (greeneye ghidra + GreenEyeControl.java): run-until-here,
breakpoints, memory/register access, remote calls, hit export; verified
end-to-end with Ghidra headless (run_until reached rpc_sum from a GhidraScript).
- MarkGreenEyeHits.java fixed for the Ghidra 12 createBookmark API; verified
headless together with ExportForGreenEye.java.
- Analyzer renders a QEMU first-fault table for probe sessions (fault count,
epc with firmware vaddr translation, access address/size, reason).
- Tests now 35 green, including injection, Ghidra bridge, remote call, run-until
and REPL command smoke tests.
- Documentation: docs/11-16 (GSP RM service developer guide, injection SDK
specification, Ghidra control, adversarial interoperability guide, agentic
GSP IDE, custom simulator design) and GREEN-EYE-ROADMAP.md (long-term H1-H7
program); doc maps and the project RISC-V VM doc updated.
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md')
| -rw-r--r-- | debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md b/debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md new file mode 100644 index 0000000..6ba8d69 --- /dev/null +++ b/debug/risc-v-gsp-rm-vm/docs/11-GSP-RM-SERVICE-DEVELOPER-GUIDE.md @@ -0,0 +1,181 @@ +# 11 — GSP RM firmware service developer guide + +> **# TOOL IN DEVELOPMENT - NOT READY YET!** See 00 for status and 06 for the +> fidelity caveats. Exact proprietary API names are not reproduced in tracked +> docs; local provenance lives in the local analysis notes. + +## 1. What this guide is for + +The GSP runs a resource manager (RM) as **services**: message handlers, state +machines and engines that own objects (devices, address spaces, channels, +memory, notifiers) and answer controls. Open-IOV emulates those services; the +long-term goal of green-eye is to let a developer **write, inject, run and +debug their own versions of these services** before (or instead of) changing +the product emulation. + +This guide teaches the loop on the demo uproc — which implements the same +shape as a GSP service — and maps each step to the future GSP-RM work in +[`GREEN-EYE-ROADMAP.md`](../GREEN-EYE-ROADMAP.md) H1.3. + +## 2. Service anatomy + +| Concept | Demo uproc (today) | GSP-RM (roadmap H1.3) | +|---|---|---| +| Entry point | exported symbol `ge_demo_service_dispatch` | service entry registered with the RM core | +| Dispatch ABI | `u64 dispatch(u64 cmd, u64 a0, u64 a1)` | same shape via the service registry shim | +| Reachability | firmware mailbox commands 16..23 select handler slot 0..7; `arg0` is the service command, `arg1`/`arg2` are parameters | RM message/control dispatch routed by the simulator's RM-core | +| State | service-local (stack/registers) or the control block | RM objects and service-private memory | +| Talking to peers | control-block fields + mailbox; debugger calls | RM-core calls and inter-service messages | +| Observability | hooks/watchpoints/sessions/TCG trace | same, plus RM-core call interception | + +A service must be **position-independent**: no globals, no libc, no absolute +addresses. Everything it calls is either its own code or an address passed in +by the injector (the future RM-core shim will pass a table of callable +entry points, which is also the interception point). + +## 3. Writing a service + +1. Copy the SDK shape from `sdk/`: + * `greeneye_service.h` — the ABI header; + * `injected_demo.c` — a working multi-command service. +2. Implement `ge_service_fn`: + ```c + __attribute__((noinline)) ge_u64 my_service_dispatch(ge_u64 cmd, ge_u64 a0, ge_u64 a1) + { + switch (cmd) { + case 1: return a0 ^ 0xbeefu; + case 2: return a0 + a1; + default: return ~cmd; + } + } + ``` +3. Keep it PIC-clean: no `static` data with pointers, no string globals, no + division (the demo build has no libc), no stack beyond a few KiB. +4. Build: + ```bash + make -C sdk # or point the Makefile at your source + make -C sdk relocs # must print "no relocations in this file" + ``` +5. Fix any relocation the linker reports before injecting; relocations mean + the blob will not run at an arbitrary load address. + +## 4. Injecting and invoking + +```bash +./greeneye.sh inject --service sdk/build/injected_demo.elf \ + --cmd 1 --arg0 0x41 --arg1 0x42 +``` + +What happens (all recorded): +1. Every `PT_LOAD` is written into RAM (default `0x81000000`; auto-sized to + fit the target). +2. The service dispatch entry is patched into handler slot 6 + (`--slot` selects 0..7). +3. A **direct debugger-side call** runs the service immediately + (`greeneye.inject.invoke_remote`): this is the unit-test path, independent + of firmware state. +4. After the firmware settles, a **firmware-dispatched call** writes + `arg0=cmd, arg1=a0, arg2=a1, mailbox=16+slot` and reads `result` + (`greeneye.inject.invoke_via_firmware`): this is the integration path. + +Programmatic form: + +```python +from greeneye.inject import load_service, invoke_remote, invoke_via_firmware +svc = load_service(s, "sdk/build/injected_demo.elf", slot=6) +print(hex(invoke_remote(s, svc, 2, 0x10, 0x20))) # 0x30 +s.run(duration=0.3) +print(hex(invoke_via_firmware(s, svc, 2, 0x10, 0x20))) # 0x30 +``` + +## 5. Talking to other services and the host + +On the demo: +* the **control block** is the shared state (`gsp_ctrl`); services coordinate + through its fields and the mailbox command range; +* the **host/debugger** is a peer via hooks, watchpoints and `Session.call`; +* a service can call another service if it is handed the other entry address + (the SDK's second export `ge_demo_service_answer` demonstrates a second + callable point; the injector resolves any exported symbol). + +On real GSP-RM (H1.3) the same roles are filled by RM-core allocation and +control calls and by messages between services. The simulator will intercept +those calls so they can be logged, stubbed, or forwarded to the real +implementation — which is exactly what makes the environment powerful for +prototyping: a service you write can be exercised against recorded RM-core +behaviour before the product emulation implements it. + +## 6. Resource surfaces an engine can use + +Category map (details are RM-version-specific and tracked privately where +provenance requires it): + +| Surface | Purpose | How green-eye helps today | +|---|---|---| +| Memory / descriptors | allocate, map, free, register host or vidmem ranges | watchpoints on allocation state; snapshot/diff; schema decode | +| Address spaces / page tables | GPU VA translation, mapping updates | hooks on map/unmap routines; memory diffs; TCG trace of accesses | +| Channels / GPFIFO / USERD | submission plumbing | hooks and remote calls; observe ring state via snapshots | +| Sync: semaphores, notifiers, interrupts | completion and signalling | watchpoints on sem values; event ordering in sessions | +| Engine scheduling / runlists | prioritisation, preemption | call-graph and hook evidence; compare runs | +| Controls / messages | configuration and queries | declarative probes; replay/compare across versions | +| Device identity / caps / clocks | what the RM reports | schema decode of the static-config block; A/B vs hardware oracle | + +Everything here is observed through the same primitives, so an engine +prototype is analysed exactly like firmware code. + +## 7. Debugging workflow + +1. **Unit-test with `call`:** breakpoints and hooks around the service entry, + `Session.call(entry, (cmd, a0, a1))`, inspect the return and watchpoints on + its data. Failures raise `RspTimeout` and leave the session recording. +2. **Integration run:** `invoke_via_firmware` with the mailbox path, while + hooks on the firmware's dispatcher and watchpoints on the control block + record the full route. +3. **Ghidra-driven:** `greeneye ghidra` + `GreenEyeControl.java` — execute + until a service address, set breakpoints from the decompiler, read + registers/memory, export hits (docs/13). +4. **Coverage:** run with the TCG plugin filtered to the service load range + (`qemu/greeneye-trace.c`, `start=`/`end=` args) to see every access. +5. **Regression:** record a session per command; `greeneye compare` detects + changed hit/watch/write profiles when the service or firmware changes. + +## 8. Rules and pitfalls + +* **PIC purity first.** If the blob needs relocation, it is not injectable + at an arbitrary address. +* **No absolute addresses from the host.** Use exported symbols and + `load_service`, never hardcoded addresses. +* **No unbounded loops.** A service that never returns blocks the call loop + until the timeout and then leaves the target stopped; the recorder shows + the last PC. +* **Watchpoint the state, hook the entry.** Watchpoints are immediate (one + instruction step) and ideal for counters; hooks give arguments/returns. +* **Never ship a service.** Injected code is a development experiment; the + product changes go through `open-iov-vfio` with the accuracy loop. +* **Record everything.** A claim about a service without a session is not + evidence. + +## 9. Worked example: add a command + +```c +/* sdk/injected_demo.c */ +case 7: + return (a0 | (a1 << 8)) & 0xFFFFFFFFull; +``` + +```bash +make -C sdk +./greeneye.sh inject --cmd 7 --arg0 0xab --arg1 0xcd +# direct call -> 0xcdab +# firmware call -> 0xcdab +./greeneye.sh analyze <printed session dir> # event/hit report +``` + +## 10. What comes next (roadmap) + +* H1.3: services built against an RM shim, registered with a simulated RM + core, calling intercepted RM-core surfaces. +* H2: the device model that lets real GSP-RM run in the simulator at all. +* H4: adversarial navigation — diff service behaviour across firmware + versions, mutate inputs, infer capabilities. +* H5: services that interact with PMU/SEC2/ACR models. |
