code wiki / _hdl_build / _nvme_oplist_gate.nx
_nvme_oplist_gate.nx source
↩ module page · 171 lines · 9633 B
1// _nvme_oplist_gate.nx -- CONSOLIDATION gate for X-DRV-W1: NVMe as a GENERIC op-list on the
2// CANONICAL emitter nx_drv_proto_emit (NOT the parallel bespoke nx_drvgen). Proves the no-sprawl
3// consolidation:
4// (1) NVME -- the GENERIC nx_drv_proto_emit, driven by knowledge/specs/nvme_oplist_virt.spec
5// alone (zero emitter change), authors an NVMe-class bring-up driver; the SOVEREIGN rv64 emu
6// (+ the rv64im_min_nvme device model) runs it: CC.EN -> confirm CSTS.RDY -> bind ASQ/ACQ by
7// base-address regs -> lay the 64B SQE -> ring the SQ-Tail doorbell -> device DMAs + posts the
8// phase-tagged CQE -> driver reads NvmeCqPeek back == 0x12340001. Serial CONTAINS the golden
9// "NVMEENASQSQECQ" + a clean SiFive halt (BOOTSOV verdict=GREEN).
10// (2) DISTINCT -- the SAME emitter binary, driven by the virtio-blk op-list, yields a DIFFERENT
11// golden; NVMe is a 3rd device class as just-a-spec, not virtio in disguise.
12// (3) TAMPER x2 on the NVMe image: bump the device-base lui imm (byte 7) -> all MMIO targets a
13// non-device address -> the VS identity verify fails -> the whole transcript collapses; bump
14// the VS-expected li high byte (byte 15) -> the identity verify mismatches -> collapses. Each
15// must drop the golden (the no-false-green handle; a no-op driver would be immune).
16//
17// Every verdict is a PRINTED marker off a REAL sovereign run, never an asserted GREEN; raw bytes are
18// read SOVEREIGNLY (sys_read). NO qemu/gcc/openssl/python -- the sovereign emu IS the runtime; NVMe
19// is a last-mile probe. Marker -> knowledge/status/driver_spec.log (NVMEOPGATE row). Sovereign
20// orchestration (fork/dup3/execve/wait4). license_tier: ORIGINAL
21import "nx_syscalls.nx"
22
23const EMIT_ELF: *u8 = "_offc/nx_drv_proto_emit.elf"
24const SOV_ELF: *u8 = "_offc/nx_boot_run_sov.elf"
25
26func q_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
27func q_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
28func q_fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 }
29
30// run prog with one arg; stdout/serial -> outpath; return WEXITSTATUS (or 128+sig).
31func q_run1(prog: *u8, a1: *u8, outpath: *u8) -> i64 {
32 let pid: i64 = sys_fork()
33 if pid == 0 {
34 let ofd: i64 = sys_openat_wr(outpath, 0x1a4)
35 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) }
36 let argv: *i64 = sys_mmap(32) as *i64
37 argv[0] = prog as i64
38 argv[1] = a1 as i64
39 argv[2] = 0
40 let envp: *i64 = sys_mmap(16) as *i64
41 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
42 sys_execve(prog, argv, envp)
43 sys_exit(127)
44 }
45 let st: *i64 = sys_mmap(16) as *i64
46 sys_wait4(pid, st, 0)
47 let sig: i64 = st[0] & 0x7f
48 if sig != 0 { return 128 + sig }
49 return (st[0] >> 8) & 0xff
50}
51
52func q_read(path: *u8, buf: *u8, cap: i64) -> i64 {
53 let fd: i64 = sys_openat_rd(path)
54 if fd < 0 { return 0 }
55 var n: i64 = 0
56 var go: i64 = 1
57 while go == 1 { let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap - 1 { go = 0 } }
58 sys_close(fd)
59 return n
60}
61
62func q_buf_has(buf: *u8, n: i64, pat: *u8, pl: i64) -> i64 {
63 if pl <= 0 { return 0 }
64 var i: i64 = 0
65 while i + pl <= n {
66 var k: i64 = 0; var hit: i64 = 1
67 while k < pl { if buf[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } }
68 if hit == 1 { return 1 }
69 i = i + 1
70 }
71 return 0
72}
73
74func q_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
75
76func q_streq(a: *u8, b: *u8) -> i64 {
77 var i: i64 = 0
78 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
79 if b[i] != (0 as u8) { return 0 }
80 return 1
81}
82
83// emit a driver from spec, run it on the sovereign emu; return 1 iff serial CONTAINS golden + clean
84// SiFive halt. golden read from <out>.gold into gbuf (NUL-terminated).
85func q_emit_run(spec: *u8, out: *u8, goldout: *u8, gbuf: *u8, gcap: i64, serialpath: *u8) -> i64 {
86 let est: i64 = q_run1(EMIT_ELF, spec, "/tmp/_nvmeopl_emit.out" as *u8)
87 if est != 0 { return 0 }
88 let gn: i64 = q_read(goldout, gbuf, gcap)
89 if gn <= 0 { return 0 }
90 gbuf[gn] = 0 as u8
91 let rst: i64 = q_run1(SOV_ELF, out, serialpath)
92 let sbuf: *u8 = sys_mmap(65536)
93 let sbn: i64 = q_read(serialpath, sbuf, 65536)
94 let has: i64 = q_buf_has(sbuf, sbn, gbuf, gn)
95 let halt: i64 = q_buf_has(sbuf, sbn, "BOOTSOV verdict=GREEN" as *u8, 21)
96 if rst == 0 { if has == 1 { if halt == 1 { return 1 } } }
97 return 0
98}
99
100// run the NVMe image with byte[pos] bumped by 1; return 1 iff golden is now ABSENT (tamper bites).
101func q_tamper(srcbin: *u8, pos: i64, golden: *u8, gn: i64, tampbin: *u8, serialpath: *u8) -> i64 {
102 let ibuf: *u8 = sys_mmap(16384)
103 let ibn: i64 = q_read(srcbin, ibuf, 16384)
104 if ibn <= pos { return 0 }
105 ibuf[pos] = (ibuf[pos] + 1) as u8
106 let tfd: i64 = sys_openat_wr(tampbin, 0x1a4)
107 if tfd < 0 { return 0 }
108 sys_write(tfd, ibuf, ibn); sys_close(tfd)
109 let rst: i64 = q_run1(SOV_ELF, tampbin, serialpath)
110 let sbuf: *u8 = sys_mmap(65536)
111 let sbn: i64 = q_read(serialpath, sbuf, 65536)
112 let has: i64 = q_buf_has(sbuf, sbn, golden, gn)
113 if has == 0 { return 1 } // golden gone -> tamper bites
114 return 0
115}
116
117func main() -> i64 {
118 q_p("=== NVMe-op-list consolidation gate (X-DRV-W1: NVMe = a SPEC on the canonical nx_drv_proto_emit, sovereign emu, no qemu) ===\n" as *u8)
119 let lfd: i64 = sys_openat_append("knowledge/status/driver_spec.log" as *u8, 0x1a4)
120
121 let nvme_out: *u8 = "runtime/_hdl_build/_nvme_oplist.bin" as *u8
122 let nvme_gold: *u8 = "runtime/_hdl_build/_nvme_oplist.bin.gold" as *u8
123 let blk_out: *u8 = "runtime/_hdl_build/_drv_proto_blk.bin" as *u8
124 let blk_gold: *u8 = "runtime/_hdl_build/_drv_proto_blk.bin.gold" as *u8
125
126 let gN: *u8 = sys_mmap(2048)
127 let gB: *u8 = sys_mmap(2048)
128
129 // (1) NVMe round-trip on the sovereign emu, authored by the GENERIC op-list emitter.
130 let nvme_ok: i64 = q_emit_run("knowledge/specs/nvme_oplist_virt.spec" as *u8, nvme_out, nvme_gold, gN, 2048, "/tmp/_nvmeopl_serial.txt" as *u8)
131 // (2) virtio-blk op-list on the SAME emitter binary, for the distinctness comparison.
132 let blk_ok: i64 = q_emit_run("knowledge/specs/drv_proto_blk_virt.spec" as *u8, blk_out, blk_gold, gB, 2048, "/tmp/_nvmeopl_blk_serial.txt" as *u8)
133 var distinct: i64 = 0
134 if q_strlen(gN) > 0 { if q_strlen(gB) > 0 { if q_streq(gN, gB) == 0 { distinct = 1 } } }
135
136 // (3) TAMPER x2 on the NVMe image (device-base lui imm byte 7, VS-expected li high byte 15).
137 let gNn: i64 = q_strlen(gN)
138 let t1: i64 = q_tamper(nvme_out, 7, gN, gNn, "/tmp/_nvmeopl_t1.bin" as *u8, "/tmp/_nvmeopl_t1.txt" as *u8)
139 let t2: i64 = q_tamper(nvme_out, 15, gN, gNn, "/tmp/_nvmeopl_t2.bin" as *u8, "/tmp/_nvmeopl_t2.txt" as *u8)
140 var tamper_bites: i64 = 0
141 if t1 == 1 { if t2 == 1 { tamper_bites = 1 } }
142 // restore the clean NVMe image (re-emit; additive: leave _nvme_oplist.bin == the GREEN image).
143 q_run1(EMIT_ELF, "knowledge/specs/nvme_oplist_virt.spec" as *u8, "/tmp/_nvmeopl_emit.out" as *u8)
144
145 q_p(" nvme_oplist=" as *u8)
146 if nvme_ok == 1 { q_p("GREEN(NVME..CQ: CC.EN->CSTS.RDY enable + ASQ/ACQ base-addr bind + 64B SQE + SQ-Tail doorbell + phase-CQE + NvmeCqPeek readback, clean halt)" as *u8) } else { q_p("RED" as *u8) }
147 q_p(" distinct_vs_virtio=" as *u8)
148 if distinct == 1 { q_p("yes(goldenNVMe!=goldenBLK, same emitter binary)" as *u8) } else { q_p("no" as *u8) }
149 q_p(" tamper_bites=" as *u8)
150 if tamper_bites == 1 { q_p("yes(base-imm + VS-const corrupt -> golden drops)\n" as *u8) } else { q_p("no\n" as *u8) }
151
152 var pass: i64 = 0
153 if nvme_ok == 1 { if distinct == 1 { if tamper_bites == 1 { pass = 1 } } }
154
155 if pass == 1 {
156 q_p("NVMEOPGATE verdict=GREEN (the CANONICAL op-list emitter nx_drv_proto_emit authored an NVMe-class driver from nvme_oplist_virt.spec ALONE -- a 3rd device class as just-a-spec, zero emitter change -- which round-tripped on the sovereign rv64 emu against rv64im_min_nvme; golden distinct from virtio-blk; two image tampers REJECTED. NVMe is now CONSOLIDATED onto the canonical emitter -- the bespoke nx_drvgen/nx_driver_shapes path is superseded)\n" as *u8)
157 if lfd >= 0 {
158 q_fp(lfd, "NVMEOPGATE verdict=GREEN keystone=nvme-consolidated-onto-canonical-op-list-emitter runtime=sovereign-emu device=nvme-class enable=CC.EN->CSTS.RDY queue=ASQ/ACQ-base-addr+doorbell sqe=64B cqe=phase-tagged cqpeek-readback=verified emitter=nx_drv_proto_emit(zero-change) goldenNVMe=" as *u8)
159 q_fp(lfd, gN); q_fp(lfd, " distinct_vs_virtio=yes tamper=rejected(base-imm+VS-const) supersedes=nx_drvgen+nx_driver_shapes epoch=" as *u8); q_fn(lfd, sys_now_realtime_sec()); q_fp(lfd, "\n" as *u8); sys_close(lfd)
160 }
161 sys_exit(0); return 0
162 }
163 q_p("NVMEOPGATE verdict=RED (nvme_ok/distinct/tamper not all green)\n" as *u8)
164 if lfd >= 0 {
165 q_fp(lfd, "NVMEOPGATE verdict=RED nvme_ok=" as *u8); q_fn(lfd, nvme_ok)
166 q_fp(lfd, " distinct=" as *u8); q_fn(lfd, distinct)
167 q_fp(lfd, " t1=" as *u8); q_fn(lfd, t1); q_fp(lfd, " t2=" as *u8); q_fn(lfd, t2); q_fp(lfd, "\n" as *u8); sys_close(lfd)
168 }
169 sys_exit(1)
170 return 1
171}