code wiki / _hdl_build / _mmu_gate.nx

_mmu_gate.nx source

↩ module page · 119 lines · 6289 B

1// _mmu_gate.nx -- gate for the Sv39 PAGE-TABLE-WALK device (virtual-memory-paging-mmu). NO mocks. 2// 3// (1) WALK WORKS -- emits the MMU driver (via nx_drv_proto_emit) + runs it on the sovereign emu: 4// it lays a Sv39 gigapage page table, programs satp, and the device WALKS the table -> the 5// mapped VA 0xC0009000 translates to PA 0x80009000 ("MAP") and an unmapped VA faults ("FLT"). 6// Serial must contain "MAPFLT" + a clean halt. 7// (2) TAMPER device-base -- bump the device-base lui imm (byte 7): the MMU regs are missed, the 8// walk never runs, "MAP" drops (the driver really talks to the MMU device). 9// (3) TAMPER bad-PTE -- run the variant whose leaf PTE has V=0: the mapped VA walk FAULTS, the 10// PADDR verify fails, "MAP" drops -> the Sv39 walk genuinely reads + validates the page table 11// (translation is not a rubber stamp). 12// 13// Evidence -> knowledge/status/mmu.log (MMUGATE row). Sovereign. license_tier: ORIGINAL 14import "nx_syscalls.nx" 15 16const M_EMIT: *u8 = "_offc/nx_drv_proto_emit.elf" 17const M_SOV: *u8 = "_offc/nx_boot_run_sov.elf" 18const M_SPEC: *u8 = "knowledge/specs/drv_proto_mmu.spec" 19const M_BIN: *u8 = "runtime/_hdl_build/_drv_proto_mmu.bin" 20const M_BADSPEC: *u8 = "knowledge/specs/drv_proto_mmu_badpte.spec" 21const M_BADBIN: *u8 = "runtime/_hdl_build/_drv_proto_mmu_badpte.bin" 22 23func 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 } 24func 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 } 25func 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 } 26 27func g_run(prog: *u8, a1: *u8, outpath: *u8) -> i64 { 28 let pid: i64 = sys_fork() 29 if pid == 0 { 30 if outpath != (0 as *u8) { let ofd: i64 = sys_openat_wr(outpath, 0x1a4); if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } } 31 let argv: *i64 = sys_mmap(32) as *i64 32 argv[0] = prog as i64 33 var k: i64 = 1 34 if a1 != (0 as *u8) { argv[k] = a1 as i64; k = k + 1 } 35 argv[k] = 0 36 let envp: *i64 = sys_mmap(16) as *i64 37 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 38 sys_execve(prog, argv, envp) 39 sys_exit(127) 40 } 41 let st: *i64 = sys_mmap(16) as *i64 42 sys_wait4(pid, st, 0) 43 let sg: i64 = st[0] & 0x7f 44 if sg != 0 { return 128 + sg } 45 return (st[0] >> 8) & 0xff 46} 47 48func g_read(path: *u8, buf: *u8, cap: i64) -> i64 { 49 let fd: i64 = sys_openat_rd(path) 50 if fd < 0 { return 0 } 51 var n: i64 = 0 52 var go: i64 = 1 53 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 } } 54 sys_close(fd) 55 return n 56} 57 58func g_has(buf: *u8, n: i64, pat: *u8, pl: i64) -> i64 { 59 if pl <= 0 { return 0 } 60 var i: i64 = 0 61 while i + pl <= n { var k: i64=0; var hit: i64=1; while k<pl { if buf[i+k]!=pat[k]{hit=0;k=pl}else{k=k+1} } if hit==1 { return 1 } i=i+1 } 62 return 0 63} 64 65func g_emit_run(spec: *u8, bin: *u8, serial: *u8) -> i64 { 66 if g_run(M_EMIT, spec, "/tmp/_mmu_emit.out" as *u8) != 0 { return 0 } 67 g_run(M_SOV, bin, serial) 68 let sb: *u8 = sys_mmap(65536); let sn: i64 = g_read(serial, sb, 65536) 69 let halt: i64 = g_has(sb, sn, "BOOTSOV verdict=GREEN" as *u8, 21) 70 let mapflt: i64 = g_has(sb, sn, "MAPFLT" as *u8, 6) 71 if halt == 1 { if mapflt == 1 { return 1 } } 72 return 0 73} 74 75func g_has_map(serial: *u8) -> i64 { 76 let sb: *u8 = sys_mmap(65536); let sn: i64 = g_read(serial, sb, 65536) 77 return g_has(sb, sn, "MAP" as *u8, 3) 78} 79 80func main() -> i64 { 81 g_p("=== Sv39 page-table-walk gate (virtual-memory-paging-mmu) ===\n" as *u8) 82 let lfd: i64 = sys_openat_append("knowledge/status/mmu.log" as *u8, 0x1a4) 83 84 // (1) walk works: mapped VA translates (MAP) + unmapped faults (FLT) 85 let walk_ok: i64 = g_emit_run(M_SPEC, M_BIN, "/tmp/_mmu_main.txt" as *u8) 86 87 // (2) tamper device base (byte 7): MMU regs missed -> MAP drops 88 let ib: *u8 = sys_mmap(16384); let ibn: i64 = g_read(M_BIN, ib, 16384) 89 var t1: i64 = 0 90 if ibn > 7 { 91 ib[7] = (ib[7] + 1) as u8 92 let tfd: i64 = sys_openat_wr("/tmp/_mmu_t1.bin" as *u8, 0x1a4) 93 if tfd >= 0 { sys_write(tfd, ib, ibn); sys_close(tfd) } 94 g_run(M_SOV, "/tmp/_mmu_t1.bin" as *u8, "/tmp/_mmu_t1.txt" as *u8) 95 if g_has_map("/tmp/_mmu_t1.txt" as *u8) == 0 { t1 = 1 } 96 } 97 98 // (3) tamper bad-PTE variant: leaf PTE V=0 -> mapped VA faults -> MAP drops 99 g_run(M_EMIT, M_BADSPEC, "/tmp/_mmu_bad_emit.out" as *u8) 100 g_run(M_SOV, M_BADBIN, "/tmp/_mmu_bad.txt" as *u8) 101 var t2: i64 = 0 102 if g_has_map("/tmp/_mmu_bad.txt" as *u8) == 0 { t2 = 1 } 103 104 g_p(" walk_works=" as *u8); if walk_ok==1 { g_p("GREEN(MAP=mapped-VA->PA, FLT=unmapped-faults)" as *u8) } else { g_p("RED" as *u8) } 105 g_p(" tamper_base=" as *u8); g_fn(1, t1); g_p(" tamper_badpte=" as *u8); g_fn(1, t2); g_p("\n" as *u8) 106 107 var pass: i64 = 0 108 if walk_ok == 1 { if t1 == 1 { if t2 == 1 { pass = 1 } } } 109 110 if pass == 1 { 111 g_p("MMUGATE verdict=GREEN (sovereign Sv39 page-table walk: programmed satp + a gigapage page table in guest RAM, the MMU WALKED the 3-level table and translated the mapped VA 0xC0009000 -> PA 0x80009000 [MAP] and FAULTED an unmapped VA [FLT]; device-base + bad-PTE[V=0] tampers both drop MAP = the walk genuinely reads+validates the page table. probe=virtual-memory-paging)\n" as *u8) 112 if lfd >= 0 { g_fp(lfd, "MMUGATE verdict=GREEN keystone=virtual-memory-paging probe=mmu_paging sv39-walk=3-level mapped=0xC0009000->0x80009000 fault=unmapped tamper=rejected(base+badpte) epoch=" as *u8); g_fn(lfd, sys_now_realtime_sec()); g_fp(lfd, "\n" as *u8); sys_close(lfd) } 113 sys_exit(0); return 0 114 } 115 g_p("MMUGATE verdict=RED (walk/tamper not all green)\n" as *u8) 116 if lfd >= 0 { g_fp(lfd, "MMUGATE verdict=RED walk=" as *u8); g_fn(lfd, walk_ok); g_fp(lfd, " t1=" as *u8); g_fn(lfd, t1); g_fp(lfd, " t2=" as *u8); g_fn(lfd, t2); g_fp(lfd, "\n" as *u8); sys_close(lfd) } 117 sys_exit(1) 118 return 1 119}