nx_gpu_sync_gate.nx source
↩ module page · 81 lines · 4805 B
1// nx_gpu_sync_gate.nx -- the sovereign GPU fence (nx_gpu_sync gpu_sync_fence) on the real device, driven directly.
2//
3// gpu GP7, the FENCE half: a monitored fence created on the discrete 5080 through raw /dev/dxg, signalled from the
4// CPU and waited on synchronously -- the round trip completes only when the signals advanced the real fence.
5// Teeth: the device resolves; the fence round-trips; an invalid sync-object type is REFUSED (the create is
6// type-sensitive, not a blind success); three tampers are rejected (a bogus handle, a zero object count, a non-dxg
7// fd); and a POSITIVE CONTROL after the tampers still round-trips, so this is not a guard that refuses everything.
8// THE THIRD STATE: the subject is a physical device most hosts lack (the NAS that builds this has no /dev/dxg).
9// Absent hardware is a gv_need precondition -> SKIP, never RED; a RED from this gate means the fence path broke.
10// The BARRIER half of GP7 is not claimed here (see nx_gpu_sync.nx); the board carries that scope.
11// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 (or 3 = SKIP where there is no /dev/dxg)
12import "nx_syscalls.nx"
13import "nx_dxg.nx"
14import "nx_gpu_sync.nx"
15import "nx_gate_verdict.nx"
16
17const GG_BAD_TYPE: i64 = 99
18const GG_BOGUS_SO: i64 = 0xdeadbeef
19
20func main() -> i64 {
21 let ctr: *i64 = gv_ctr()
22 gv_head("nx_gpu_sync_gate -- GP7 fence half: a monitored fence on the discrete 5080 through raw /dev/dxg, created, CPU-signalled, CPU-waited" as *u8)
23
24 let fd: i64 = dxg_open()
25 var have: i64 = 0
26 if fd >= 0 { have = 1 }
27 if gv_need("a /dev/dxg device to submit to (absent on every host but the GPU laptop)" as *u8, have, ctr) == 0 {
28 return gv_verdict("nx_gpu_sync_gate" as *u8, ctr, "subject absent: no /dev/dxg on this host" as *u8)
29 }
30
31 let dev: *i64 = sys_mmap(16) as *i64
32 let dr: i64 = gpu_sync_device(fd, dev)
33 gv_puts(" device resolve rc=" as *u8); gv_num(dr); gv_puts("\n" as *u8)
34 gv_check("T1-the-discrete-adapter-resolves-to-a-device-handle" as *u8, dr == 0, ctr)
35 if dr != 0 {
36 sys_close(fd)
37 return gv_verdict("nx_gpu_sync_gate" as *u8, ctr, "the device did not resolve; nothing below could run" as *u8)
38 }
39 let device: i64 = dev[0]
40
41 let so: *i64 = sys_mmap(16) as *i64
42 let fva: *i64 = sys_mmap(16) as *i64
43 let rt: i64 = gpu_sync_fence(fd, device, so, fva)
44 gv_puts(" fence round trip rc=" as *u8); gv_num(rt); gv_puts(" sync_object_nonzero=" as *u8)
45 var so_nz: i64 = 0
46 if so[0] != 0 { so_nz = 1 }
47 gv_num(so_nz); gv_puts(" fence_page_mapped=" as *u8)
48 var fva_nz: i64 = 0
49 if fva[0] != 0 { fva_nz = 1 }
50 gv_num(fva_nz); gv_puts("\n" as *u8)
51 gv_check("T2-the-monitored-fence-round-trips-create-signal-1-signal-2-wait-2" as *u8, rt == 0, ctr)
52 gv_check("T3-the-create-returned-a-real-sync-object-handle" as *u8, so_nz == 1, ctr)
53 gv_check("T4-the-create-mapped-a-kernel-fence-page-into-this-process" as *u8, fva_nz == 1, ctr)
54
55 // the create is type-sensitive: an invalid type must be refused
56 let bso: *i64 = sys_mmap(16) as *i64
57 let bfva: *i64 = sys_mmap(16) as *i64
58 let cr_bad: i64 = dxg_create_so(fd, device, GG_BAD_TYPE, bso, bfva)
59 gv_check("neg-control-T5-an-invalid-sync-object-type-is-refused-by-the-device" as *u8, cr_bad < 0, ctr)
60
61 // tampers: each from a different real rule, each must differ from the round trip's 0
62 let t1: i64 = dxg_wait_cpu(fd, device, GG_BOGUS_SO, 1)
63 let t2: i64 = dxg_signal_cpu(fd, device, so[0], 0, 1)
64 let nfd: i64 = sys_openat_rd("/dev/null" as *u8)
65 var t3: i64 = 0
66 if nfd >= 0 { t3 = dxg_wait_cpu(nfd, device, so[0], GS_FENCE_STEP2); sys_close(nfd) }
67 gv_puts(" tampers: wait-bogus-handle=" as *u8); gv_num(t1); gv_puts(" signal-count-0=" as *u8); gv_num(t2); gv_puts(" wait-on-non-dxg-fd=" as *u8); gv_num(t3); gv_puts("\n" as *u8)
68 gv_check("neg-control-T6-a-wait-on-a-bogus-handle-is-refused-not-blocked" as *u8, t1 < 0, ctr)
69 gv_check("neg-control-T7-a-signal-with-object-count-zero-is-refused" as *u8, t2 < 0, ctr)
70 gv_check("neg-control-T8-a-wait-on-a-non-dxg-fd-is-refused" as *u8, t3 < 0, ctr)
71
72 // positive control after the refusals: the channel still round-trips (not a guard that refuses everything)
73 let so2: *i64 = sys_mmap(16) as *i64
74 let fva2: *i64 = sys_mmap(16) as *i64
75 let rt2: i64 = gpu_sync_fence(fd, device, so2, fva2)
76 gv_check("T9-positive-control-a-second-fence-still-round-trips-after-the-refusals" as *u8, rt2 == 0, ctr)
77 gv_check("T10-the-second-fence-is-a-distinct-sync-object" as *u8, so2[0] != so[0], ctr)
78
79 sys_close(fd)
80 return gv_verdict("nx_gpu_sync_gate" as *u8, ctr, "the sovereign monitored fence round-trips on the 5080 through raw dxg; refusals are typed and the channel stays live" as *u8)
81}