diff options
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/harness/value_demos/s04_run_until_function.py')
| -rw-r--r-- | debug/risc-v-gsp-rm-vm/harness/value_demos/s04_run_until_function.py | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/harness/value_demos/s04_run_until_function.py b/debug/risc-v-gsp-rm-vm/harness/value_demos/s04_run_until_function.py new file mode 100644 index 0000000..a74c83f --- /dev/null +++ b/debug/risc-v-gsp-rm-vm/harness/value_demos/s04_run_until_function.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +"""s04 - run-until a function: is this code on the live path, and with what args? + +Real scenario (docs/19-CONTROL-DISCOVERY.md 4.4 and +Handoff-vGPU-IO.md PART 91 ADDENDUM 9, 2026-10-01 cycles 18-25): the +``gsp-phys-rm-call`` RM-client ladder asked, per cycle, whether a symbolized +function had executed under the current stimulus (VAS commit, token, BIND, +fetch, semaphore). Cycles 18->25 (~1 h 41 m, eight supervised boots) walked +the ladder one reachability question at a time; ``reach.py`` answers that +question in ~0.5 s per target, and a ``run_until`` timeout means "not executed +under this stimulus at this fidelity", never "unreachable". + +Analog: run to the self-test's ``rpc_sum``, show ``rpc_fault`` is *not* on the +natural path (timeout), then trigger it through the mailbox and reach it with +the dispatch arguments captured; finally call ``rpc_ping`` directly +(Frida NativeFunction) to show the unit-test route. +""" +from __future__ import annotations + +import os + +try: # package import (tests) or direct script execution (run_all) + from . import _common as C +except ImportError: + import sys as _sys + + _sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + import _common as C + + +def run() -> dict: + import greeneye as ge + from greeneye.errors import RspTimeout + + backend = C.choose_backend("native") + out = C.artifact_dir("s04_run_until_function") + commands = [ + 's.run_until("rpc_sum", timeout=5.0) # natural path', + 's.run_until("rpc_fault", timeout=0.2) # not on natural path', + 'write mailbox cmd=6; s.run_until("rpc_fault") # trigger route', + 's.call("rpc_ping", (0x41,)) # Frida-like direct call', + ] + scenario = C.scenario( + ids=[ + "docs/19-CONTROL-DISCOVERY.md 4.4 (2026-10-02): reach.py measured ~0.5 s per target", + "Handoff-vGPU-IO.md PART 91 ADDENDUM 9 (2026-10-01): RM-client ladder cycles 18-25", + "docs/14-ADVERSARIAL-INTEROP-GUIDE.md 5: run_until timeouts are not unreachability", + ], + baseline=( + "cycles 18-25 took ~1 h 41 m of supervised hardware cycles (full " + "boot + RPC ladder per hypothesis) to answer the same class of " + "'did this function execute under this stimulus' question" + ), + projection=( + "real RM ladder reachability needs the live GSP-RM (H1.3/H2.2); " + "run_until/hook/call already work against the re-hosted firmware " + "shape and every probe spec emitted here replays" + ), + blocked=True, + device="H1.3 live RM method entry / H2.2 device model", + ) + C.render_banner( + "s04_run_until_function", + "Is a symbolized function on the live path under this stimulus, what args does it take, and can it be called directly?", + "RM-client ladder: reachability of each rung, one supervised boot per question", + scenario["static_baseline"], + commands, + ) + + session = ge.launch(kernel=C.DEMO_ELF, backend=backend, name="vd-s04") + try: + ctrl = session.symbols.lookup("gsp_ctrl") + dispatch_args = [] + session.hook( + "rpc_dispatch", + on_enter=lambda hit: dispatch_args.append( + {"cmd": hit.arg(0), "a0": hit.arg(1), "a1": hit.arg(2), "a2": hit.arg(3)} + ), + ) + natural_hit = session.run_until("rpc_sum", timeout=5.0) + natural = { + "target": "rpc_sum", + "method": "run", + "reachable": True, + "pc": f"{natural_hit.addr:#x}", + "dispatch_args": list(dispatch_args), + } + timeout_hit = None + try: + timeout_hit = session.run_until("rpc_fault", timeout=0.2) + timeout_seen = False + except RspTimeout: + timeout_seen = True + fault_before = { + "target": "rpc_fault", + "method": "run_until", + "reachable": timeout_hit is not None, + "timeout": timeout_seen, + "reading": "not executed under this stimulus at this fidelity (docs/14 section 5)", + } + session.memory.write_u64(ctrl + C.CTRL_MAILBOX, 6) + trigger_hit = session.run_until("rpc_fault", timeout=5.0) + triggered = { + "target": "rpc_fault", + "method": "trigger (mailbox cmd=6)", + "reachable": True, + "pc": f"{trigger_hit.addr:#x}", + "dispatch_args": list(dispatch_args[-1:]), + } + direct = session.call("rpc_ping", (0x41,)) + payload = { + "success": natural["reachable"] and fault_before["timeout"] and triggered["reachable"] + and direct == (0x41 ^ C.PING_XOR), + "backend": backend, + "natural_path": natural, + "before_trigger": fault_before, + "after_trigger": triggered, + "direct_call": {"target": "rpc_ping", "args": [0x41], "result": direct, "expected": 0x41 ^ C.PING_XOR}, + "question": "reachability and required arguments per symbolized function", + "answer": ( + f"rpc_sum reached on the self-test path (pc {natural['pc']}); rpc_fault " + f"times out (reachable=False) until mailbox cmd=6 triggers it " + f"(pc {triggered['pc']}, args {triggered['dispatch_args']}); direct call " + f"rpc_ping(0x41)={direct:#x} - three reachability answers, one session" + ), + "success_criteria": { + "pass": "natural target reached, un-triggered target times out, trigger route reaches it, direct call matches", + "fail": "a route reports reachable without a hit, or the direct call disagrees", + }, + "real_case": scenario, + } + C.write_json(os.path.join(out, "reach.json"), payload) + finally: + session.close() + return payload + + +def main() -> int: + return 0 if C.timed_demo(run, C.artifact_dir("s04_run_until_function"))["success"] else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) |
