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}