evidence · 4.1 KiB

README.md

Committed at docs/evidence/card-shell/kernel-rvv/context-probe/README.md. This is what grounds the requirements that cite it.

Open raw source

Vector context probe: full Linux guest passes; current board skips

rvv-context-probe has a scalar RV64GC entrypoint. It calls standard hwprobe and exits 77 with SKIP when V is absent or probing fails. No vector instruction runs before that gate. Only its separate assembly unit requires RVV 1.0.

Two processes pin themselves to the same allowed CPU and each perform 2,000 checks. An interval timer asynchronously interrupts live vector arithmetic; the handler changes v8/v9, VL and VTYPE. Assembly waits for a signal, without calls or syscalls, then verifies control state and writes the vector for scalar checking. Both processes must complete, and each must have recorded involuntary context switches. This tests representative state preservation, not the entire ISA or every register. The pin affects only these test processes.

Linux permits syscalls to clobber vector registers. The probe deliberately does not demand their preservation across syscalls; see the pinned Xuantie source’s Documentation/riscv/vector.rst, section 3. Signal delivery and preemption are the relevant boundaries here.

nix build .#rvv-context-probe .#rvv-context-probe-corrupt --no-link --print-out-paths
python3 tools/rvv-context-qemu.py \
  --package /nix/store/4gn2z5fi5szrnflhzjsr1kq3f1b39wqx-k230-rvv-context-probe-riscv64-unknown-linux-gnu-0.1 \
  --corrupt-package /nix/store/yalzjvz5njqm5bqr5bqap1xsnsyfi51s-k230-rvv-context-probe-corrupt-riscv64-unknown-linux-gnu-0.1 \
  --kernel /nix/store/j6x14mc1bz3fh0ylya68qb9yj7qxjcdx-linux-riscv64-unknown-linux-gnu-6.18.52 \
  --output /tmp/new-vector-guest-evidence

The actual Nix builds and full-system QEMU harness passed on 2026-09-23:

Guest caseObservation
V absentSKIP, no vector execution
VLEN 128Both processes pass 2,000 checks; parent 2,068 signals and 524 involuntary switches
VLEN 256Both processes pass 2,000 checks; parent 2,031 signals and 500 involuntary switches
Deliberately corrupt v8Both processes reject the data with result 2; harness accepts this expected failure

result.json identifies exact artifacts, commands and QEMU version. Boot logs are retained with line endings and trailing whitespace normalized. The probe runs as guest PID 1 in a minimal generated initramfs; its exit after the report causes the expected “Attempted to kill init” panic. The harness checks the report, not that panic, as its result. No full NixOS image or compositor is exercised by this separate diagnostic guest.

The earlier negative control failed to emit its report because the probe left its timer active on error; previous-reporting-failure.json preserves that rejected run. The final probe stops its timer on both success and failure, and the corrupt control now reports the precise expected error. An absent report always fails the harness.

User emulation is insufficient for this test

The same final probe fails with VTYPE result 103 under QEMU user emulation; user-emulation-failure.json records it. QEMU’s inspected upstream linux-user/riscv/signal.c saves scalar and floating-point signal context without vector state. That source is consistent with the observed failure. The passing full-system guest runs Linux’s own signal handling instead. Do not label the user-emulation failure a board kernel defect or remove signal clobbering merely to make it pass.

Current physical board

After a transient missing UART prompt, the final probe transferred with matching MD5 and ran on the unchanged normal image. board-skip.json records SKIP/77, hwprobe value 59, active shell and seatd, and the unchanged boot ID. No new kernel was booted and no physical vector operation was performed. The existing Python capability probe and this compiled probe agree.

Board follow-up: after a verified recoverable vector-kernel boot, run timeout 15s /run/card-tools/rvv-context-probe (or the immutable package binary), require PASS, then test actual Pixman output and the card workload. Normal-image SKIP is the expected fallback check, not acceleration acceptance.