summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/firmware/uproc_demo
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 09:13:00 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 09:13:00 -0400
commit3fe5360d0efc439d59f2b7a9bf2f713aa9cdb918 (patch)
treee30e26701f5a67080404e5f9cb71967ee275e604 /debug/risc-v-gsp-rm-vm/firmware/uproc_demo
parent964f34ee2e49d14ce81ee9a6bd9297c88e320c52 (diff)
downloadopen-iov-3fe5360d0efc439d59f2b7a9bf2f713aa9cdb918.tar.gz
open-iov-3fe5360d0efc439d59f2b7a9bf2f713aa9cdb918.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/firmware/uproc_demo')
-rw-r--r--debug/risc-v-gsp-rm-vm/firmware/uproc_demo/gsp_ctrl.schema.json103
-rw-r--r--debug/risc-v-gsp-rm-vm/firmware/uproc_demo/main.c43
2 files changed, 117 insertions, 29 deletions
diff --git a/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/gsp_ctrl.schema.json b/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/gsp_ctrl.schema.json
index ca18f81..e0d6cbc 100644
--- a/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/gsp_ctrl.schema.json
+++ b/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/gsp_ctrl.schema.json
@@ -1,19 +1,94 @@
{
"name": "gsp_ctrl",
- "size": 392,
+ "size": 400,
"fields": [
- {"name": "magic", "offset": 0, "fmt": "u32", "note": "GSP-like control block magic 0x47535031"},
- {"name": "version", "offset": 4, "fmt": "u32"},
- {"name": "state", "offset": 8, "fmt": "u32", "enum": {"0": "S0", "1": "S1", "2": "S2", "3": "S3"}},
- {"name": "heartbeat", "offset": 12, "fmt": "u32"},
- {"name": "rpc_count", "offset": 16, "fmt": "u64"},
- {"name": "last_rpc", "offset": 24, "fmt": "u64"},
- {"name": "mailbox", "offset": 32, "fmt": "u64", "enum": {"0": "idle", "1": "PING", "2": "ECHO", "3": "FILL", "4": "SUM", "5": "STATE", "6": "FAULT"}},
- {"name": "arg0", "offset": 40, "fmt": "u64"},
- {"name": "arg1", "offset": 48, "fmt": "u64"},
- {"name": "result", "offset": 56, "fmt": "u64"},
- {"name": "buf", "offset": 64, "fmt": "bytes", "size": 256},
- {"name": "handler_count", "offset": 320, "fmt": "u64"},
- {"name": "handlers", "offset": 328, "fmt": "u64", "count": 8}
+ {
+ "name": "magic",
+ "offset": 0,
+ "fmt": "u32",
+ "note": "GSP-like control block magic 0x47535031"
+ },
+ {
+ "name": "version",
+ "offset": 4,
+ "fmt": "u32"
+ },
+ {
+ "name": "state",
+ "offset": 8,
+ "fmt": "u32",
+ "enum": {
+ "0": "S0",
+ "1": "S1",
+ "2": "S2",
+ "3": "S3"
+ }
+ },
+ {
+ "name": "heartbeat",
+ "offset": 12,
+ "fmt": "u32"
+ },
+ {
+ "name": "rpc_count",
+ "offset": 16,
+ "fmt": "u64"
+ },
+ {
+ "name": "last_rpc",
+ "offset": 24,
+ "fmt": "u64"
+ },
+ {
+ "name": "mailbox",
+ "offset": 32,
+ "fmt": "u64",
+ "enum": {
+ "0": "idle",
+ "1": "PING",
+ "2": "ECHO",
+ "3": "FILL",
+ "4": "SUM",
+ "5": "STATE",
+ "6": "FAULT"
+ }
+ },
+ {
+ "name": "arg0",
+ "offset": 40,
+ "fmt": "u64"
+ },
+ {
+ "name": "arg1",
+ "offset": 48,
+ "fmt": "u64"
+ },
+ {
+ "name": "arg2",
+ "offset": 56,
+ "fmt": "u64"
+ },
+ {
+ "name": "result",
+ "offset": 64,
+ "fmt": "u64"
+ },
+ {
+ "name": "buf",
+ "offset": 72,
+ "fmt": "bytes",
+ "size": 256
+ },
+ {
+ "name": "handler_count",
+ "offset": 328,
+ "fmt": "u64"
+ },
+ {
+ "name": "handlers",
+ "offset": 336,
+ "fmt": "u64",
+ "count": 8
+ }
]
}
diff --git a/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/main.c b/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/main.c
index d23b00c..9b4f98a 100644
--- a/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/main.c
+++ b/debug/risc-v-gsp-rm-vm/firmware/uproc_demo/main.c
@@ -21,12 +21,13 @@ typedef struct {
u64 rpc_count; /* +0x10 */
u64 last_rpc; /* +0x18 */
u64 mailbox; /* +0x20 */
- u64 arg0; /* +0x28 */
+ u64 arg0; /* +0x28 service command for injected dispatch */
u64 arg1; /* +0x30 */
- u64 result; /* +0x38 */
- char buf[256]; /* +0x40 */
- u64 handler_count; /* +0x140 */
- u64 handlers[8]; /* +0x148 */
+ u64 arg2; /* +0x38 */
+ u64 result; /* +0x40 */
+ char buf[256]; /* +0x48 */
+ u64 handler_count; /* +0x148 */
+ u64 handlers[8]; /* +0x150 */
} gsp_ctrl_t;
volatile gsp_ctrl_t gsp_ctrl __attribute__((section(".gsp_data"), aligned(64)));
@@ -134,8 +135,9 @@ __attribute__((noinline)) u64 rpc_fault(u64 a0, u64 a1)
/* ---- dispatcher ---- */
typedef u64 (*rpc_fn)(u64, u64);
+typedef u64 (*ge_inject_fn)(u64, u64, u64);
-void rpc_dispatch(u64 cmd, u64 a0, u64 a1)
+void rpc_dispatch(u64 cmd, u64 a0, u64 a1, u64 a2)
{
u64 result;
switch (cmd) {
@@ -158,7 +160,17 @@ void rpc_dispatch(u64 cmd, u64 a0, u64 a1)
result = rpc_fault(a0, a1);
break;
default:
- result = ~cmd;
+ /* Injected-service dispatch: commands 16..23 call handler slots 0..7.
+ * A debugger can load a new service and store its entry in
+ * gsp_ctrl.handlers[n] while the firmware is running; this is the
+ * demo's stand-in for injecting an RM engine/service. */
+ if (cmd >= 16 && cmd < 24) {
+ ge_inject_fn injected = (ge_inject_fn)(unsigned long)gsp_ctrl.handlers[cmd - 16];
+ /* a0 carries the service command; a1/a2 are its parameters. */
+ result = injected ? injected(a0, a1, a2) : ~cmd;
+ } else {
+ result = ~cmd;
+ }
break;
}
gsp_ctrl.result = result;
@@ -187,6 +199,7 @@ int main(void)
ctl->rpc_count = 0;
ctl->last_rpc = 0;
ctl->mailbox = 0;
+ ctl->arg2 = 0;
ctl->result = 0;
ctl->buf[0] = '\0';
install_handlers();
@@ -199,13 +212,13 @@ int main(void)
uart_puts("\n");
/* Deterministic self-test so freshly attached instrumentation sees events. */
- rpc_dispatch(1, 0x1111, 0);
- rpc_dispatch(2, (u64)(unsigned long)"hello-green-eye", 0);
- rpc_dispatch(3, 0x5a, 32);
- rpc_dispatch(4, (u64)(unsigned long)ctl->buf, 16);
- rpc_dispatch(5, 0, 0);
- rpc_dispatch(5, 0, 0);
- rpc_dispatch(5, 0, 0);
+ rpc_dispatch(1, 0x1111, 0, 0);
+ rpc_dispatch(2, (u64)(unsigned long)"hello-green-eye", 0, 0);
+ rpc_dispatch(3, 0x5a, 32, 0);
+ rpc_dispatch(4, (u64)(unsigned long)ctl->buf, 16, 0);
+ rpc_dispatch(5, 0, 0, 0);
+ rpc_dispatch(5, 0, 0, 0);
+ rpc_dispatch(5, 0, 0, 0);
uart_puts("SELFTEST DONE\n");
for (;;) {
@@ -213,7 +226,7 @@ int main(void)
u64 cmd = ctl->mailbox;
if (cmd != 0) {
ctl->mailbox = 0;
- rpc_dispatch(cmd, ctl->arg0, ctl->arg1);
+ rpc_dispatch(cmd, ctl->arg0, ctl->arg1, ctl->arg2);
}
for (volatile int i = 0; i < 2000; i++) {
__asm__ volatile("");