code wiki / _hdl_build / _gpu_bm_copy_gate.nx
_gpu_bm_copy_gate.nx source
↩ module page · 128 lines · 10103 B
1// _gpu_bm_copy_gate.nx -- BARE-METAL SOVEREIGN-GPU rung BM-GPU-CE1: Copy Engine (DMA) through the sovereign GPFIFO.
2//
3// Adds a SECOND real engine class: NVC6B5 (AMPERE_DMA_COPY_A) -- GPU memcpy, the data-movement primitive (H2D/D2H/D2D).
4// NVC56F SET_OBJECT (faithful) binds the copy class to a subchannel; the FAITHFUL NVC6B5 methods (offsets verified vs
5// open spec: OFFSET_IN_UPPER@0x400/LOWER@0x404, OFFSET_OUT_UPPER@0x408/LOWER@0x40C, LINE_LENGTH_IN@0x418,
6// LINE_COUNT@0x41C, LAUNCH_DMA@0x300 with DATA_TRANSFER_TYPE 1:0 [NONE=0/PIPELINED=1/NON_PIPELINED=2]) drive the
7// modeled copy engine: LAUNCH_DMA with type!=NONE copies LINE_LENGTH_IN*LINE_COUNT bytes src->dst.
8// NISHI-ECOSYSTEM-ONLY: our model+driver; NVC6B5 method encoding = last-mile hardware spec (VERIFIED, faithful).
9// HONEST SCOPE: copy-DISPATCH+result LOGIC vs spec model; real copy-engine on real silicon = BM-GPU-6.
10//
11// GREEN iff: after dispatch dst == src over the copied range AND bytes beyond are untouched; tampers
12// (LAUNCH_DMA type=NONE / no SET_OBJECT) leave dst unwritten.
13// Marker -> knowledge/status/gpu_baremetal.log (BMCOPYGATE). license_tier: ORIGINAL
14import "nx_syscalls.nx"
15
16const DMA_COPY_CLASS: i64 = 0xC6B5 // AMPERE_DMA_COPY_A (NVC6B5)
17const NBYTES: i64 = 256
18
19func p(s: *u8) -> i64 { var nn: i64=0; while s[nn]!=(0 as u8){nn=nn+1} sys_write(1,s,nn); return 0 }
20func fp(fd: i64, s: *u8) -> i64 { var nn: i64=0; while s[nn]!=(0 as u8){nn=nn+1} sys_write(fd,s,nn); return 0 }
21func n(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" 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(1,bb,k); return 0 }
22func x(v: i64) -> i64 { p("0x" as *u8); let bb:*u8=sys_mmap(20); var k:i64=0; var m:i64=v; if m==0{bb[0]=48;k=1}; while m>0{ let d:i64=m&15; if d<10{bb[k]=(48+d) as u8}else{bb[k]=(87+d) as u8}; m=(m>>4); k=k+1 } var i:i64=0; let o:*u8=sys_mmap(20); while i<k{o[i]=bb[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
23func fx(fd: i64, v: i64) -> i64 { let bb:*u8=sys_mmap(20); var k:i64=0; var m:i64=v; if m==0{bb[0]=48;k=1}; while m>0{ let d:i64=m&15; if d<10{bb[k]=(48+d) as u8}else{bb[k]=(87+d) as u8}; m=(m>>4); k=k+1 } let o:*u8=sys_mmap(20); var i:i64=0; while i<k{o[i]=bb[k-1-i];i=i+1} fp(fd,"0x" as *u8); sys_write(fd,o,k); return 0 }
24func rd32(b: *u8, o: i64) -> i64 { return (b[o] as i64)|((b[o+1] as i64)<<8)|((b[o+2] as i64)<<16)|((b[o+3] as i64)<<24) }
25func wr32(b: *u8, o: i64, v: i64) -> i64 { b[o]=(v&0xff) as u8; b[o+1]=((v>>8)&0xff) as u8; b[o+2]=((v>>16)&0xff) as u8; b[o+3]=((v>>24)&0xff) as u8; return 0 }
26
27// ===== FIFO model with the NVC6B5 copy engine =====
28// cs: [0]=src [1]=dst [2]=line_length [3]=line_count [4]=bound_class
29func gpfifo_run_copy(gmem: *u8, pb_off: i64, pb_dwords: i64, cs: *i64) -> i64 {
30 var i: i64 = 0
31 while i < pb_dwords {
32 let hdr: i64 = rd32(gmem, pb_off + i*4); i = i + 1
33 let mode: i64 = (hdr >> 29) & 0x7; let count: i64 = (hdr >> 16) & 0x1fff; let method0: i64 = (hdr & 0xfff) << 2
34 var j: i64 = 0
35 while j < count {
36 if i >= pb_dwords { j = count } else {
37 let data: i64 = rd32(gmem, pb_off + i*4); i = i + 1
38 var m: i64 = method0; if mode == 1 { m = method0 + j*4 }
39 if m == 0x0 { cs[4] = data } // SET_OBJECT
40 if cs[4] == DMA_COPY_CLASS {
41 if m == 0x400 { cs[0] = (cs[0] & 0xffffffff) | (data << 32) } // OFFSET_IN_UPPER
42 if m == 0x404 { cs[0] = (cs[0] & (0-1<<32)) | (data & 0xffffffff) } // OFFSET_IN_LOWER
43 if m == 0x408 { cs[1] = (cs[1] & 0xffffffff) | (data << 32) } // OFFSET_OUT_UPPER
44 if m == 0x40c { cs[1] = (cs[1] & (0-1<<32)) | (data & 0xffffffff) } // OFFSET_OUT_LOWER
45 if m == 0x418 { cs[2] = data } // LINE_LENGTH_IN
46 if m == 0x41c { cs[3] = data } // LINE_COUNT
47 if m == 0x300 { if (data & 0x3) != 0 { // LAUNCH_DMA, DATA_TRANSFER_TYPE != NONE
48 let total: i64 = cs[2] * cs[3]; var b: i64 = 0
49 while b < total { gmem[cs[1] + b] = gmem[cs[0] + b]; b = b + 1 }
50 } }
51 }
52 j = j + 1
53 }
54 }
55 }
56 return 0
57}
58func emit_hdr(gmem: *u8, off: i64, mode: i64, count: i64, subch: i64, method: i64) -> i64 {
59 wr32(gmem, off, (mode << 29) | (count << 16) | (subch << 13) | ((method >> 2) & 0xfff)); return 0
60}
61
62func main() -> i64 {
63 p("=== BARE-METAL SOVEREIGN-GPU BM-GPU-CE1: Copy Engine (NVC6B5 DMA) through the GPFIFO pipeline ===\n" as *u8)
64 let gmem: *u8 = sys_mmap(8388608)
65 let SRC: i64 = 0x30000; let DST: i64 = 0x31000; let PB: i64 = 0x40000
66
67 // fill SRC with a known pattern
68 var f: i64 = 0; while f < NBYTES { gmem[SRC + f] = ((f*7 + 13) & 0xff) as u8; f = f + 1 }
69
70 // emit the DMA-copy pushbuffer: SET_OBJECT(copy) + OFFSET_IN/OUT(4) + LINE_LENGTH/COUNT(2) + LAUNCH_DMA
71 var o: i64 = 0
72 emit_hdr(gmem, PB+o, 1, 1, 2, 0x0); o=o+4; wr32(gmem, PB+o, DMA_COPY_CLASS); o=o+4 // SET_OBJECT copy on subch2
73 emit_hdr(gmem, PB+o, 1, 4, 2, 0x400); o=o+4 // OFFSET_IN_UPPER..OFFSET_OUT_LOWER
74 wr32(gmem, PB+o, (SRC>>32)&0xffffffff); o=o+4; wr32(gmem, PB+o, SRC&0xffffffff); o=o+4
75 wr32(gmem, PB+o, (DST>>32)&0xffffffff); o=o+4; wr32(gmem, PB+o, DST&0xffffffff); o=o+4
76 emit_hdr(gmem, PB+o, 1, 2, 2, 0x418); o=o+4 // LINE_LENGTH_IN, LINE_COUNT
77 wr32(gmem, PB+o, NBYTES); o=o+4; wr32(gmem, PB+o, 1); o=o+4
78 emit_hdr(gmem, PB+o, 1, 1, 2, 0x300); o=o+4; wr32(gmem, PB+o, 0x2); o=o+4 // LAUNCH_DMA NON_PIPELINED
79 let pb_dwords: i64 = o / 4
80
81 let cs: *i64 = sys_mmap(128); cs[4] = 0
82 gpfifo_run_copy(gmem, PB, pb_dwords, cs)
83 // verify dst == src over NBYTES, and byte NBYTES is untouched (0)
84 var matched: i64 = 1; var b: i64 = 0
85 while b < NBYTES { if gmem[DST + b] != gmem[SRC + b] { matched = 0 } b = b + 1 }
86 let beyond: i64 = gmem[DST + NBYTES] as i64
87 p(" DMA dispatched. dst[0]=" as *u8); x(gmem[DST] as i64); p(" src[0]=" as *u8); x(gmem[SRC] as i64); p(" | dst[255]=" as *u8); x(gmem[DST+255] as i64); p(" src[255]=" as *u8); x(gmem[SRC+255] as i64); p(" | all_match=" as *u8); n(matched); p(" beyond_untouched=" as *u8); n(beyond==0); p("\n" as *u8)
88
89 // ---- TAMPERS ----
90 var z: i64 = 0; while z < NBYTES+8 { gmem[DST + z] = 0 as u8; z=z+1 }
91 // T1: LAUNCH_DMA type NONE -> no copy
92 var o2: i64 = 0
93 emit_hdr(gmem, PB+o2, 1, 1, 2, 0x0); o2=o2+4; wr32(gmem, PB+o2, DMA_COPY_CLASS); o2=o2+4
94 emit_hdr(gmem, PB+o2, 1, 4, 2, 0x400); o2=o2+4
95 wr32(gmem,PB+o2,(SRC>>32)&0xffffffff);o2=o2+4; wr32(gmem,PB+o2,SRC&0xffffffff);o2=o2+4; wr32(gmem,PB+o2,(DST>>32)&0xffffffff);o2=o2+4; wr32(gmem,PB+o2,DST&0xffffffff);o2=o2+4
96 emit_hdr(gmem, PB+o2, 1, 2, 2, 0x418); o2=o2+4; wr32(gmem,PB+o2,NBYTES);o2=o2+4; wr32(gmem,PB+o2,1);o2=o2+4
97 emit_hdr(gmem, PB+o2, 1, 1, 2, 0x300); o2=o2+4; wr32(gmem, PB+o2, 0x0); o2=o2+4 // type NONE
98 let cs2: *i64 = sys_mmap(128); cs2[4]=0; gpfifo_run_copy(gmem, PB, o2/4, cs2)
99 var t_none: i64 = 1; z=0; while z < NBYTES { if gmem[DST+z] != 0 as u8 { t_none = 0 } z=z+1 }
100 // T2: no SET_OBJECT -> class unbound -> no copy
101 z=0; while z < NBYTES { gmem[DST + z] = 0 as u8; z=z+1 }
102 var o3: i64 = 0
103 emit_hdr(gmem, PB+o3, 1, 4, 2, 0x400); o3=o3+4
104 wr32(gmem,PB+o3,(SRC>>32)&0xffffffff);o3=o3+4; wr32(gmem,PB+o3,SRC&0xffffffff);o3=o3+4; wr32(gmem,PB+o3,(DST>>32)&0xffffffff);o3=o3+4; wr32(gmem,PB+o3,DST&0xffffffff);o3=o3+4
105 emit_hdr(gmem, PB+o3, 1, 2, 2, 0x418); o3=o3+4; wr32(gmem,PB+o3,NBYTES);o3=o3+4; wr32(gmem,PB+o3,1);o3=o3+4
106 emit_hdr(gmem, PB+o3, 1, 1, 2, 0x300); o3=o3+4; wr32(gmem, PB+o3, 0x2); o3=o3+4
107 let cs3: *i64 = sys_mmap(128); cs3[4]=0; gpfifo_run_copy(gmem, PB, o3/4, cs3)
108 var t_noobj: i64 = 1; z=0; while z < NBYTES { if gmem[DST+z] != 0 as u8 { t_noobj = 0 } z=z+1 }
109 p(" [tamper] launch-type-NONE no-copy=" as *u8); n(t_none); p(" no-SET_OBJECT no-copy=" as *u8); n(t_noobj); p("\n" as *u8)
110
111 var pass: i64 = 0
112 if matched == 1 { if beyond == 0 { if t_none == 1 { if t_noobj == 1 { pass = 1 } } } }
113 p(" checks: dma_copy_correct=" as *u8); n(matched); p(" beyond_untouched=" as *u8); n(beyond==0); p(" launch-required=" as *u8); n(t_none); p(" class-bind-required=" as *u8); n(t_noobj); p("\n" as *u8)
114
115 let lfd: i64 = sys_openat_append("knowledge/status/gpu_baremetal.log" as *u8, 0x1a4)
116 if pass == 1 {
117 p("BMCOPYGATE verdict=GREEN reason=sovereign-DMA-copy-engine-through-GPFIFO (NVC56F SET_OBJECT binds NVC6B5 copy class 0xC6B5; FAITHFUL NVC6B5 methods OFFSET_IN/OUT@0x400-40c + LINE_LENGTH@0x418 + LINE_COUNT@0x41c + LAUNCH_DMA@0x300; LAUNCH type!=NONE copies 256B src->dst MATCHES exactly, bytes-beyond untouched; tampers launch-NONE + no-class-bind leave dst unwritten) SCOPE=copy-dispatch+result-LOGIC-vs-spec[NVC6B5-offsets-VERIFIED-faithful,engine-models-the-DMA]; real-copy-engine=BM-GPU-6\n" as *u8)
118 if lfd >= 0 {
119 fp(lfd, "BMCOPYGATE verdict=GREEN rung=BM-GPU-CE1-copy-engine-dma device=sovereign-NVC6B5-copy-FIFO-model class=0xC6B5 copied=256B src->dst match=exact beyond_untouched=1 tampers=held(launch-NONE+no-class-bind) NVC6B5-method-offsets=VERIFIED-vs-open-spec scope=copy-dispatch+result-logic-vs-spec next=BM-GPU-6-real-silicon / harden(real-NVC6C0-QMD,GMMU-page-tables)\n" as *u8)
120 sys_close(lfd)
121 }
122 sys_exit(0); return 0
123 }
124 p("BMCOPYGATE verdict=RED (copy mismatch or tamper not satisfied)\n" as *u8)
125 if lfd >= 0 { fp(lfd, "BMCOPYGATE verdict=RED see-console\n" as *u8); sys_close(lfd) }
126 sys_exit(1)
127 return 1
128}