code wiki / _hdl_build / _k_r2_001a_gate.nx

_k_r2_001a_gate.nx source

↩ module page · 287 lines · 13338 B

1// _k_r2_001a_gate.nx -- the K-R2-001a gate (virtio-MMIO transport HANDSHAKE). Drives the 2// full author->handshake chain with NO mocks: runs the REAL nx_virtio_hs_emit (the team 3// AUTHORS the rv64 handshake image + the TABLE-COMPUTED golden transcript from the spec), 4// then RUNS the image on the SOVEREIGN rv64 emulator (rv64im_min_sim with the new 5// rv64im_min_virtio device carved into load32/store32 -- the PRIMARY, gating lane: Nishi 6// owns the runtime) and asserts the captured serial transcript CONTAINS the emitter's 7// golden ("VIO ACK DRV FEAT OK\n" -- the driver verified magic/version/device-id, drove 8// Status through ACK/DRIVER/FEATURES_OK/DRIVER_OK, read HostFeatures, wrote GuestFeatures, 9// re-read Status to confirm FEATURES_OK stuck) AND the sovereign emu reports a clean 10// SiFive-finisher halt (BOOTSOV verdict=GREEN). 11// 12// Then the ALIGNMENT lane: qemu-system-riscv64 -machine virt -global 13// virtio-mmio.force-legacy=true with a REAL virtio-blk-device backing. qemu fills its 14// virtio-mmio slots in REVERSE (the blk device lands at the highest slot 0x10008000, not 15// the spec's sovereign base 0x10001000), so the gate authors a SECOND image from a derived 16// spec whose base = the qemu blk slot and runs THAT on qemu; the SAME handshake driver 17// completes against the REAL legacy virtio-blk transport and emits the SAME golden 18// transcript -> lanes AGREE on the handshake (alignment = handshake-completes-on-real-hw, 19// transcript-identical). 20// 21// Finally a TAMPER test: corrupt the magic-expected constant in the sovereign image -> the 22// driver's magic verify fails -> it branches PAST the whole handshake straight to the 23// finisher -> the transcript loses its golden -> the gate MUST go RED (proves the gate 24// bites, not a rubber stamp). Evidence -> knowledge/status/virtio_blk.log (VIRTGATE row; 25// the queue row's ||MARK= reads it). Sovereign orchestration (fork/dup3/execve/wait4). 26// license_tier: ORIGINAL 27import "nx_syscalls.nx" 28 29const G_QEMU_BASE: i64 = 0x10008000 // the slot qemu-virt assigns the first blk device 30 31func g_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 32func g_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 } 33func g_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 } 34 35// run nx_virtio_hs_emit <spec>; return child wait status (0 = ok) 36func g_run_emit(spec: *u8) -> i64 { 37 let pid: i64 = sys_fork() 38 if pid == 0 { 39 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 40 if dn >= 0 { sys_dup3(dn, 1, 0) } 41 let argv: *i64 = sys_mmap(32) as *i64 42 argv[0] = "_offc/nx_virtio_hs_emit.elf" as *u8 as i64 43 argv[1] = spec as i64 44 argv[2] = 0 45 let envp: *i64 = sys_mmap(16) as *i64 46 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64 47 envp[1] = 0 48 sys_execve("_offc/nx_virtio_hs_emit.elf" as *u8, argv, envp) 49 sys_exit(127) 50 } 51 let st: *i64 = sys_mmap(16) as *i64 52 sys_wait4(pid, st, 0) 53 return st[0] 54} 55 56// run the SOVEREIGN rv64 emulator on binpath; serial -> outpath; return wait status 57func g_run_sov(binpath: *u8, outpath: *u8) -> i64 { 58 let pid: i64 = sys_fork() 59 if pid == 0 { 60 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 61 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 62 let argv: *i64 = sys_mmap(32) as *i64 63 argv[0] = "_offc/nx_boot_run_sov.elf" as *u8 as i64 64 argv[1] = binpath as i64 65 argv[2] = 0 66 let envp: *i64 = sys_mmap(16) as *i64 67 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64 68 envp[1] = 0 69 sys_execve("_offc/nx_boot_run_sov.elf" as *u8, argv, envp) 70 sys_exit(127) 71 } 72 let st: *i64 = sys_mmap(16) as *i64 73 sys_wait4(pid, st, 0) 74 return st[0] 75} 76 77// run qemu-system-riscv64 virt + legacy virtio-blk-device on binpath; serial -> outpath. 78// the backing image must exist; the gate creates a small raw file first via g_make_backing. 79func g_run_qemu(binpath: *u8, outpath: *u8, backing: *u8) -> i64 { 80 let pid: i64 = sys_fork() 81 if pid == 0 { 82 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 83 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 84 let argv: *i64 = sys_mmap(128) as *i64 85 argv[0] = "/usr/bin/qemu-system-riscv64" as *u8 as i64 86 argv[1] = "-machine" as *u8 as i64 87 argv[2] = "virt" as *u8 as i64 88 argv[3] = "-global" as *u8 as i64 89 argv[4] = "virtio-mmio.force-legacy=true" as *u8 as i64 90 argv[5] = "-nographic" as *u8 as i64 91 argv[6] = "-bios" as *u8 as i64 92 argv[7] = binpath as i64 93 argv[8] = "-drive" as *u8 as i64 94 argv[9] = "file=/tmp/_vqgate_backing.img,if=none,format=raw,id=hd0" as *u8 as i64 95 argv[10] = "-device" as *u8 as i64 96 argv[11] = "virtio-blk-device,drive=hd0" as *u8 as i64 97 argv[12] = 0 98 let envp: *i64 = sys_mmap(16) as *i64 99 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64 100 envp[1] = 0 101 sys_execve("/usr/bin/qemu-system-riscv64" as *u8, argv, envp) 102 sys_exit(127) 103 } 104 let st: *i64 = sys_mmap(16) as *i64 105 sys_wait4(pid, st, 0) 106 return st[0] 107} 108 109// create a small raw backing file for the qemu virtio-blk device (4 sectors of zeros). 110func g_make_backing(path: *u8) -> i64 { 111 let fd: i64 = sys_openat_wr(path, 0x1a4) 112 if fd < 0 { return 0 - 1 } 113 let z: *u8 = sys_mmap(2048) 114 var i: i64 = 0 115 while i < 2048 { z[i] = 0 as u8; i = i + 1 } 116 sys_write(fd, z, 2048) 117 sys_close(fd) 118 return 0 119} 120 121// read whole file into buf (cap-1 max); return byte count (0 if absent) 122func g_read(path: *u8, buf: *u8, cap: i64) -> i64 { 123 let fd: i64 = sys_openat_rd(path) 124 if fd < 0 { return 0 } 125 var n: i64 = 0 126 var go: i64 = 1 127 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 } } 128 sys_close(fd) 129 return n 130} 131 132// does buf[0,n) contain pat (length pl)? 1/0 133func g_buf_has(buf: *u8, n: i64, pat: *u8, pl: i64) -> i64 { 134 if pl <= 0 { return 0 } 135 var i: i64 = 0 136 while i + pl <= n { 137 var k: i64 = 0 138 var hit: i64 = 1 139 while k < pl { if buf[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } } 140 if hit == 1 { return 1 } 141 i = i + 1 142 } 143 return 0 144} 145 146func g_strlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 147 148// does line [ls,le) of buf begin with key? 1/0 149func g_line_is(buf: *u8, ls: i64, le: i64, key: *u8) -> i64 { 150 var k: i64 = 0 151 while key[k] != (0 as u8) { 152 if ls + k >= le { return 0 } 153 if buf[ls + k] != key[k] { return 0 } 154 k = k + 1 155 } 156 return 1 157} 158 159// author the qemu-alignment spec: copy the main spec, but replace the `base ` line value 160// with G_QEMU_BASE and the `out ` line with the qemu image path. Writes derived spec. 161func g_write_qemu_spec(mainspec: *u8, derived: *u8, qemu_out: *u8) -> i64 { 162 let buf: *u8 = sys_mmap(8192) 163 let n: i64 = g_read(mainspec, buf, 8192) 164 if n <= 0 { return 0 - 1 } 165 let ofd: i64 = sys_openat_wr(derived, 0x1a4) 166 if ofd < 0 { return 0 - 1 } 167 var ls: i64 = 0 168 while ls < n { 169 var le: i64 = ls 170 var scan: i64 = 1 171 while scan == 1 { if le >= n { scan = 0 } else { if buf[le] == (10 as u8) { scan = 0 } else { le = le + 1 } } } 172 // [ls,le) is one line (without newline). Rewrite base/out lines. 173 if g_line_is(buf, ls, le, "base " as *u8) == 1 { 174 g_fp(ofd, "base 0x10008000\n" as *u8) 175 } else { 176 if g_line_is(buf, ls, le, "out " as *u8) == 1 { 177 g_fp(ofd, "out " as *u8); g_fp(ofd, qemu_out); g_fp(ofd, "\n" as *u8) 178 } else { 179 sys_write(ofd, (buf as i64 + ls) as *u8, le - ls) 180 g_fp(ofd, "\n" as *u8) 181 } 182 } 183 ls = le + 1 184 } 185 sys_close(ofd) 186 return 0 187} 188 189func main() -> i64 { 190 let spec: *u8 = "knowledge/specs/virtio_blk_handshake_virt.spec" as *u8 191 let binpath: *u8 = "runtime/_hdl_build/_virtio_hs_virt.bin" as *u8 192 let goldpath: *u8 = "runtime/_hdl_build/_virtio_hs_virt.bin.gold" as *u8 193 let qemu_spec: *u8 = "/tmp/_vqgate_qemu.spec" as *u8 194 let qemu_bin: *u8 = "/tmp/_vqgate_qemu.bin" as *u8 195 let backing: *u8 = "/tmp/_vqgate_backing.img" as *u8 196 let tamper_bin: *u8 = "/tmp/_vqgate_tamper.bin" as *u8 197 let sov_serial: *u8 = "/tmp/_vqgate_sov.txt" as *u8 198 let qemu_serial: *u8 = "/tmp/_vqgate_qemu.txt" as *u8 199 let sov_tamper: *u8 = "/tmp/_vqgate_sov_tamper.txt" as *u8 200 g_p("=== virtio-MMIO handshake gate (K-R2-001a: SOVEREIGN rv64 transport + qemu virtio-blk alignment) ===\n" as *u8) 201 202 let lfd: i64 = sys_openat_append("knowledge/status/virtio_blk.log" as *u8, 0x1a4) 203 204 // STEP 1: author the SOVEREIGN handshake image (base 0x10001000) + the golden transcript. 205 let est: i64 = g_run_emit(spec) 206 if est != 0 { 207 g_p("VIRTGATE verdict=RED reason=emit-failed\n" as *u8) 208 if lfd >= 0 { g_fp(lfd, "VIRTGATE verdict=RED reason=emit-failed\n" as *u8); sys_close(lfd) } 209 sys_exit(1); return 1 210 } 211 let gold: *u8 = sys_mmap(512) 212 let gn: i64 = g_read(goldpath, gold, 512) 213 gold[gn] = 0 as u8 214 if gn <= 0 { 215 g_p("VIRTGATE verdict=RED reason=golden-missing\n" as *u8) 216 if lfd >= 0 { g_fp(lfd, "VIRTGATE verdict=RED reason=golden-missing\n" as *u8); sys_close(lfd) } 217 sys_exit(1); return 1 218 } 219 220 // STEP 2 (PRIMARY): the Nishi sovereign rv64 emulator RUNS the handshake image. 221 let sst: i64 = g_run_sov(binpath, sov_serial) 222 let sbuf: *u8 = sys_mmap(65536) 223 let sbn: i64 = g_read(sov_serial, sbuf, 65536) 224 let trans_ok: i64 = g_buf_has(sbuf, sbn, gold, gn) // serial CONTAINS golden 225 let halt_ok: i64 = g_buf_has(sbuf, sbn, "BOOTSOV verdict=GREEN" as *u8, 21) 226 var sov_ok: i64 = 0 227 if sst == 0 { if trans_ok == 1 { if halt_ok == 1 { sov_ok = 1 } } } 228 229 // STEP 3 (ALIGNMENT): author the qemu-base image (slot 0x10008000) + run qemu with a 230 // REAL legacy virtio-blk-device; assert the SAME golden transcript appears (lanes agree). 231 g_make_backing(backing) 232 g_write_qemu_spec(spec, qemu_spec, qemu_bin) 233 let qest: i64 = g_run_emit(qemu_spec) 234 var align: i64 = 0 235 if qest == 0 { 236 let qst: i64 = g_run_qemu(qemu_bin, qemu_serial, backing) 237 let qbuf: *u8 = sys_mmap(65536) 238 let qbn: i64 = g_read(qemu_serial, qbuf, 65536) 239 let qtrans: i64 = g_buf_has(qbuf, qbn, gold, gn) 240 if qst == 0 { if qtrans == 1 { align = 1 } } 241 } 242 243 // STEP 4 (TAMPER): corrupt the magic-expected constant in the sovereign image. Image 244 // layout (emitter-known): word0 lui t0, word1 lui t2, then verify_magic = lw(word2) + 245 // li-expected(words3-4) + bne(word5). The magic-expected li is at bytes 12..19; bump a 246 // byte of it so expected != 0x74726976 -> the magic verify fails -> driver jumps to the 247 // finisher -> transcript loses its golden. Gate MUST then go RED. 248 let ibuf: *u8 = sys_mmap(8192) 249 let ibn: i64 = g_read(binpath, ibuf, 8192) 250 ibuf[14] = (ibuf[14] + 1) as u8 251 let tfd: i64 = sys_openat_wr(tamper_bin, 0x1a4) 252 if tfd >= 0 { sys_write(tfd, ibuf, ibn); sys_close(tfd) } 253 let tst: i64 = g_run_sov(tamper_bin, sov_tamper) 254 let tbuf: *u8 = sys_mmap(65536) 255 let tbn: i64 = g_read(sov_tamper, tbuf, 65536) 256 let tamper_trans: i64 = g_buf_has(tbuf, tbn, gold, gn) // should now MISS 257 var tamper_bites: i64 = 0 258 if tamper_trans == 0 { tamper_bites = 1 } 259 260 g_p(" sovereign_emu=" as *u8) 261 if sov_ok == 1 { g_p("GREEN(transcript==golden+clean-halt)" as *u8) } else { g_p("RED" as *u8) } 262 g_p(" qemu_align=" as *u8) 263 if align == 1 { g_p("yes(real-virtio-blk @0x10008000)" as *u8) } else { g_p("no" as *u8) } 264 g_p(" tamper_bites=" as *u8) 265 if tamper_bites == 1 { g_p("yes\n" as *u8) } else { g_p("no\n" as *u8) } 266 267 var pass: i64 = 0 268 if sov_ok == 1 { if align == 1 { if tamper_bites == 1 { pass = 1 } } } 269 270 if pass == 1 { 271 g_p("VIRTGATE verdict=GREEN (sovereign rv64 emu drove the virtio-MMIO transport handshake; transcript==golden; clean halt; qemu virtio-blk-device cross-check AGREES; tamper REJECTED)\n" as *u8) 272 if lfd >= 0 { 273 g_fp(lfd, "VIRTGATE verdict=GREEN runtime=sovereign-emu transport=legacy-virtio-mmio device-id=2 handshake=ACK|DRIVER|FEATURES_OK|DRIVER_OK transcript==golden align_qemu=yes(virtio-blk-device) tamper=rejected golden=" as *u8) 274 g_fp(lfd, gold) 275 g_fp(lfd, " epoch=" as *u8); g_fn(lfd, sys_now_realtime_sec()); g_fp(lfd, "\n" as *u8); sys_close(lfd) 276 } 277 sys_exit(0); return 0 278 } 279 g_p("VIRTGATE verdict=RED (sov_ok/align/tamper not all green)\n" as *u8) 280 if lfd >= 0 { 281 g_fp(lfd, "VIRTGATE verdict=RED sov_ok=" as *u8); g_fn(lfd, sov_ok) 282 g_fp(lfd, " align=" as *u8); g_fn(lfd, align) 283 g_fp(lfd, " tamper_bites=" as *u8); g_fn(lfd, tamper_bites); g_fp(lfd, "\n" as *u8); sys_close(lfd) 284 } 285 sys_exit(1) 286 return 1 287}