code wiki / _hdl_build / _timer_irq_gate.nx

_timer_irq_gate.nx source

↩ module page · 121 lines · 6113 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" 11 12func 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 } 13func 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 } 14func 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 } 15 16func g_run1(prog: *u8, arg1: *u8, outpath: *u8) -> i64 { 17 let pid: i64 = sys_fork() 18 if pid == 0 { 19 if outpath != (0 as *u8) { 20 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 21 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 22 } else { 23 let dn: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 24 if dn >= 0 { sys_dup3(dn, 1, 0) } 25 } 26 let argv: *i64 = sys_mmap(32) as *i64 27 argv[0] = prog as i64 28 if arg1 != (0 as *u8) { argv[1] = arg1 as i64; argv[2] = 0 } else { argv[1] = 0 } 29 let envp: *i64 = sys_mmap(16) as *i64 30 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 31 sys_execve(prog, argv, envp) 32 sys_exit(127) 33 } 34 let st: *i64 = sys_mmap(16) as *i64 35 sys_wait4(pid, st, 0) 36 return st[0] 37} 38 39func g_read(path: *u8, buf: *u8, cap: i64) -> i64 { 40 let fd: i64 = sys_openat_rd(path) 41 if fd < 0 { return 0 } 42 var n: i64 = 0 43 var go: i64 = 1 44 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 } } 45 sys_close(fd) 46 return n 47} 48 49func g_buf_has(buf: *u8, n: i64, pat: *u8, pl: i64) -> i64 { 50 if pl <= 0 { return 0 } 51 var i: i64 = 0 52 while i + pl <= n { 53 var k: i64 = 0 54 var hit: i64 = 1 55 while k < pl { if buf[i+k] != pat[k] { hit = 0; k = pl } else { k = k + 1 } } 56 if hit == 1 { return 1 } 57 i = i + 1 58 } 59 return 0 60} 61 62func main() -> i64 { 63 let binpath: *u8 = "runtime/_hdl_build/_timer_irq_virt.bin" as *u8 64 let goldpath: *u8 = "runtime/_hdl_build/_timer_irq_virt.bin.gold" as *u8 65 let tamper_bin: *u8 = "/tmp/_timergate_tamper.bin" as *u8 66 let sov_serial: *u8 = "/tmp/_timergate_sov.txt" as *u8 67 let sov_tamper: *u8 = "/tmp/_timergate_sov_tamper.txt" as *u8 68 g_p("=== timer-interrupt gate (preemption mechanism: SOVEREIGN rv64 emu + tamper) ===\n" as *u8) 69 let lfd: i64 = sys_openat_append("knowledge/status/timer_irq.log" as *u8, 0x1a4) 70 71 // 1. AUTHOR the image + golden (the team's emitter, no mocks). 72 let est: i64 = g_run1("/tmp/nx_timer_irq_emit.sov.elf" as *u8, 0 as *u8, 0 as *u8) 73 if est != 0 { 74 g_p("TIMERIRQGATE verdict=RED reason=emit-failed\n" as *u8) 75 if lfd >= 0 { g_fp(lfd, "TIMERIRQGATE verdict=RED reason=emit-failed\n" as *u8); sys_close(lfd) } 76 sys_exit(1); return 1 77 } 78 let gold: *u8 = sys_mmap(64) 79 let gn: i64 = g_read(goldpath, gold, 64) 80 gold[gn] = 0 as u8 81 82 // 2. PRIMARY: sovereign emu runs the image; serial CONTAINS golden + clean finisher halt. 83 let sst: i64 = g_run1("_offc/nx_boot_run_sov.elf" as *u8, binpath, sov_serial) 84 let sbuf: *u8 = sys_mmap(65536) 85 let sbn: i64 = g_read(sov_serial, sbuf, 65536) 86 let trans_ok: i64 = g_buf_has(sbuf, sbn, gold, gn) 87 let halt_ok: i64 = g_buf_has(sbuf, sbn, "BOOTSOV verdict=GREEN" as *u8, 21) 88 var sov_ok: i64 = 0 89 if sst == 0 { if trans_ok == 1 { if halt_ok == 1 { sov_ok = 1 } } } 90 91 // 3. TAMPER: zero the mie.MTIE-enable immediate (addi t1,x0,0x80 at byte 36; imm byte=39). 92 // Without MTIE the CPU never takes the timer trap -> handler never runs -> 'T' vanishes. 93 let ibuf: *u8 = sys_mmap(8192) 94 let ibn: i64 = g_read(binpath, ibuf, 8192) 95 ibuf[36 + 3] = 0 as u8 96 let tfd: i64 = sys_openat_wr(tamper_bin, 0x1a4) 97 if tfd >= 0 { sys_write(tfd, ibuf, ibn); sys_close(tfd) } 98 let tst: i64 = g_run1("_offc/nx_boot_run_sov.elf" as *u8, tamper_bin, sov_tamper) 99 let tbuf: *u8 = sys_mmap(65536) 100 let tbn: i64 = g_read(sov_tamper, tbuf, 65536) 101 let tamper_trans: i64 = g_buf_has(tbuf, tbn, gold, gn) 102 var tamper_bites: i64 = 0 103 if tamper_trans == 0 { tamper_bites = 1 } 104 105 g_p(" sovereign_emu=" as *u8) 106 if sov_ok == 1 { g_p("GREEN(serial-contains-BT+clean-halt)" as *u8) } else { g_p("RED" as *u8) } 107 g_p(" tamper_bites=" as *u8) 108 if tamper_bites == 1 { g_p("yes\n" as *u8) } else { g_p("no\n" as *u8) } 109 110 var pass: i64 = 0 111 if sov_ok == 1 { if tamper_bites == 1 { pass = 1 } } 112 if pass == 1 { 113 g_p("TIMERIRQGATE verdict=GREEN (sovereign rv64 emu: timer interrupt delivered+handled, serial==BT, clean halt; tamper REJECTED)\n" as *u8) 114 if lfd >= 0 { 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); sys_close(lfd) } 115 sys_exit(0); return 0 116 } 117 g_p("TIMERIRQGATE verdict=RED (sov_ok/tamper not both green)\n" as *u8) 118 if lfd >= 0 { 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); sys_close(lfd) } 119 sys_exit(1) 120 return 1 121}