code wiki / _hdl_build / _timer_irq_gate.nx

_timer_irq_gate.nx source

↩ module page · 137 lines · 7507 B

1// _timer_irq_gate.nx -- gate for the TIMER-INTERRUPT (preemption mechanism) slice. 2// NO mocks: runs the REAL nx_timer_irq_emit (team AUTHORS the rv64 image + TABLE-COMPUTED 3// golden "BT"), RUNS it on the SOVEREIGN rv64 emu (PRIMARY: Nishi owns the runtime), asserts 4// the serial CONTAINS the golden (B=boot, T=timer-interrupt handler ran) AND a clean finisher 5// halt (BOOTSOV verdict=GREEN). Then a TAMPER: zero the mie.MTIE-enable immediate -> the CPU 6// never takes the timer trap -> the handler never runs -> 'T' disappears -> the gate MUST go RED 7// (proves the gate bites, not a rubber stamp -- the timer interrupt is REALLY what produces T). 8// Evidence -> knowledge/status/timer_irq.log (TIMERIRQGATE row). Sovereign orchestration. 9// license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_gate_verdict.nx" 12 13func 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 } 14func 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 } 15func g_fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(fd,"-" as *u8,1)}; 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 } 16 17func g_run1(prog: *u8, arg1: *u8, outpath: *u8) -> i64 { 18 let pid: i64 = sys_fork() 19 if pid == 0 { 20 if outpath != (0 as *u8) { 21 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 22 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 23 } else { 24 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 25 if dn >= 0 { sys_dup3(dn, 1, 0) } 26 } 27 let argv: *i64 = sys_mmap(32) as *i64 28 argv[0] = prog as i64 29 if arg1 != (0 as *u8) { argv[1] = arg1 as i64; argv[2] = 0 } else { argv[1] = 0 } 30 let envp: *i64 = sys_mmap(16) as *i64 31 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 32 sys_execve(prog, argv, envp) 33 sys_exit(127) 34 } 35 let st: *i64 = sys_mmap(16) as *i64 36 sys_wait4(pid, st, 0) 37 return st[0] 38} 39 40func g_read(path: *u8, buf: *u8, cap: i64) -> i64 { 41 let fd: i64 = sys_openat_rd(path) 42 if fd < 0 { return 0 } 43 var n: i64 = 0 44 var go: i64 = 1 45 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 } } 46 sys_close(fd) 47 return n 48} 49 50func g_buf_has(buf: *u8, n: i64, pat: *u8, pl: i64) -> i64 { 51 if pl <= 0 { return 0 } 52 var i: i64 = 0 53 while i + pl <= n { 54 var k: i64 = 0 55 var hit: i64 = 1 56 while k < pl { if buf[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } } 57 if hit == 1 { return 1 } 58 i = i + 1 59 } 60 return 0 61} 62 63func main() -> i64 { 64 let binpath: *u8 = "runtime/_hdl_build/_timer_irq_virt.bin" as *u8 65 let goldpath: *u8 = "runtime/_hdl_build/_timer_irq_virt.bin.gold" as *u8 66 let tamper_bin: *u8 = "/tmp/_timergate_tamper.bin" as *u8 67 let sov_serial: *u8 = "/tmp/_timergate_sov.txt" as *u8 68 let sov_tamper: *u8 = "/tmp/_timergate_sov_tamper.txt" as *u8 69 g_p("=== timer-interrupt gate (preemption mechanism: SOVEREIGN rv64 emu + tamper) ===\n" as *u8) 70 let lfd: i64 = sys_openat_append("knowledge/status/timer_irq.log" as *u8, 0x1a4) 71 72 // 1. AUTHOR the image + golden (the team's emitter, no mocks). 73 // 2026-08-06 LM-026: this fork named /tmp/nx_timer_irq_emit.sov.elf -- the VOLATILE build-time twin, 74 // cleared on idle -- while every other fork in this same file already used _offc/. So the moment /tmp 75 // was cleaned the gate could never emit again and reported reason=emit-failed forever, indicting the 76 // kernel for a missing temp file. The emitter itself was never broken: run directly it still writes 77 // _timer_irq_virt.bin (84 B, golden=BT). A GATE THAT FORKS A BUILD-TIME TEMP PATH STOPS TESTING THE 78 // MOMENT THE TEMP IS CLEARED, AND BLAMES ITS SUBJECT. 79 let est: i64 = g_run1("_offc/nx_timer_irq_emit.elf" as *u8, 0 as *u8, 0 as *u8) 80 if est != 0 { 81 g_p("TIMERIRQGATE verdict=RED reason=emit-failed\n" as *u8) 82 if lfd >= 0 { g_fp(lfd, "TIMERIRQGATE verdict=RED reason=emit-failed\n" as *u8); sys_close(lfd) } 83 sys_exit(1); return 1 84 } 85 let gold: *u8 = sys_mmap(64) 86 let gn: i64 = g_read(goldpath, gold, 64) 87 gold[gn] = 0 as u8 88 89 // 2. PRIMARY: sovereign emu runs the image; serial CONTAINS golden + clean finisher halt. 90 let sst: i64 = g_run1("_offc/nx_boot_run_sov.elf" as *u8, binpath, sov_serial) 91 let sbuf: *u8 = sys_mmap(65536) 92 let sbn: i64 = g_read(sov_serial, sbuf, 65536) 93 let trans_ok: i64 = g_buf_has(sbuf, sbn, gold, gn) 94 let halt_ok: i64 = g_buf_has(sbuf, sbn, "BOOTSOV verdict=GREEN" as *u8, 21) 95 var sov_ok: i64 = 0 96 if sst == 0 { if trans_ok == 1 { if halt_ok == 1 { sov_ok = 1 } } } 97 98 // 3. TAMPER: zero the mie.MTIE-enable immediate (addi t1,x0,0x80 at byte 36; imm byte=39). 99 // Without MTIE the CPU never takes the timer trap -> handler never runs -> 'T' vanishes. 100 let ibuf: *u8 = sys_mmap(8192) 101 let ibn: i64 = g_read(binpath, ibuf, 8192) 102 ibuf[36 + 3] = 0 as u8 103 let tfd: i64 = sys_openat_wr(tamper_bin, 0x1a4) 104 if tfd >= 0 { sys_write(tfd, ibuf, ibn); sys_close(tfd) } 105 let tst: i64 = g_run1("_offc/nx_boot_run_sov.elf" as *u8, tamper_bin, sov_tamper) 106 let tbuf: *u8 = sys_mmap(65536) 107 let tbn: i64 = g_read(sov_tamper, tbuf, 65536) 108 let tamper_trans: i64 = g_buf_has(tbuf, tbn, gold, gn) 109 var tamper_bites: i64 = 0 110 if tamper_trans == 0 { tamper_bites = 1 } 111 112 g_p(" sovereign_emu=" as *u8) 113 if sov_ok == 1 { g_p("GREEN(serial-contains-BT+clean-halt)" as *u8) } else { g_p("RED" as *u8) } 114 g_p(" tamper_bites=" as *u8) 115 if tamper_bites == 1 { g_p("yes\n" as *u8) } else { g_p("no\n" as *u8) } 116 117 // ---- D001 MIGRATION 2026-08-06 -- IDIOM G (boolean conjunction, no counter) ------------------- 118 // Fifth of the family; see _mmu_gate for the full reasoning. ONE gv_check PER CONJUNCT creates the 119 // counter that idioms A-F assume exists, and gv_verdict is GREEN iff pass==total -- exactly the old 120 // `sov_ok && tamper_bites`. Teeth unchanged; only the verdict reporter moves to the base class. 121 let ctr: *i64 = gv_ctr() 122 gv_check("T1 sovereign rv64 emu delivers+handles the timer interrupt (serial contains the table-computed golden BT, clean halt)" as *u8, sov_ok, ctr) 123 gv_check("T2 tamper BITES (the mutated image no longer produces the golden) -- proves the serial match is load-bearing, not incidental" as *u8, tamper_bites, ctr) 124 let rc: i64 = gv_verdict("TIMERIRQGATE" as *u8, ctr, "sovereign rv64 emu: timer interrupt delivered and handled, serial == golden BT, clean halt; tamper REJECTED. mechanism=clint-mtip-trap" as *u8) 125 // knowledge/status evidence row PRESERVED in both branches -- the rollup reads it. 126 if lfd >= 0 { 127 if rc == 0 { 128 g_fp(lfd, "TIMERIRQGATE verdict=GREEN runtime=sovereign-emu serial==golden=BT mechanism=clint-mtip-trap tamper=rejected epoch=" as *u8); g_fn(lfd, sys_now_realtime_sec()); g_fp(lfd, "\n" as *u8) 129 } 130 if rc != 0 { 131 g_fp(lfd, "TIMERIRQGATE verdict=RED sov_ok=" as *u8); g_fn(lfd, sov_ok); g_fp(lfd, " tamper_bites=" as *u8); g_fn(lfd, tamper_bites); g_fp(lfd, "\n" as *u8) 132 } 133 sys_close(lfd) 134 } 135 sys_exit(rc) 136 return rc 137}