code wiki / _hdl_build / nx_virtio_dma_probe.nx
nx_virtio_dma_probe.nx
buildroot/runtime/_hdl_build/nx_virtio_dma_probe.nx
about
nx_virtio_dma_probe.nx -- BISECT the virtio descriptor-DMA chain by calling the device model
DIRECTLY, with no emulated CPU anywhere in the path.
WHY IT EXISTS: two independent toolchains (nx_drv_proto_emit + nx_virtio_hs_emit, two different
specs, two different images) both drive the sovereign emu to EXACTLY `VIO ACK DRV FEAT OK VQ` and
then die at the first DESC-stage check. That isolates the defect to what they SHARE -- the
QueueNotify -> nx_virtio_notify_dma -> QueueDescPeek chain -- but it does NOT say which half:
(a) the DEVICE MODEL's DMA walk is broken, or
(b) the device model is fine and the SIM's store32 dispatch never delivers the driver's
descriptor writes / never routes the notify.
Reading the source could not separate those two, and I was wrong twice guessing, so this measures.
******BUILD THE INSTRUMENT BEFORE FORMING THE HYPOTHESIS -- the cheapest experiment that could
REFUTE runs first, and a bisection is cheaper than either fix.
This probe exercises ONLY leg (a). If DESCPEEK comes back correct here, the device model is
exonerated and the defect is in the sim's dispatch; if it comes back wrong, the defect is here.
Either way the next step is named by the RESULT rather than chosen by taste.
Geometry is taken from the REAL consumer (nx_bootcap): base 0x80000000, size 65536, ring page
0x80001000 (QueuePFN 0x80001), data buffer 0x80003000 -- a probe on different geometry than the
subject measures a different system.
exit 0 = device-model DMA WORKS (defect is downstream) | 1 = device-model DMA is the defect
| 2 = the probe could not observe (its own negative control failed -- trust nothing)
license_tier: ORIGINAL. Read-only. No hw writes (Rule 26).
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxrv64im_min_virtio.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 29 | const VP_MEM_BASE: i64 = 0x80000000 |
| 30 | const VP_MEM_SIZE: i64 = 65536 |
| 31 | const VP_RING_PHYS: i64 = 0x80001000 |
| 32 | const VP_PFN: i64 = 0x80001 |
| 33 | const VP_DATA_PHYS: i64 = 0x80003000 |
| 34 | const VP_QNUM: i64 = 8 |
functions
| 36 | func vp_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 37 | func vp_n(v: i64) -> i64 |
| 50 | func vp_wr32(mem: *u8, off: i64, val: i64) -> i64 called by 1: main |
| 58 | func main() -> i64 |