code wiki / _hdl_build / _gpu_dxg_r3_recon.nx
_gpu_dxg_r3_recon.nx source
↩ module page · 103 lines · 6585 B
1// _gpu_dxg_r3_recon.nx -- SOVEREIGN-GPU ladder R3 RECON (create a WDDM device on the RTX 5080).
2//
3// R2 opened a per-adapter kernel handle from the discrete LUID via LX_DXOPENADAPTERFROMLUID. R3 feeds
4// that adapter handle to LX_DXCREATEDEVICE (_IOWR(0x47,0x02,...)) to obtain a real WDDM DEVICE handle --
5// the object that GPU command submission (R4+) hangs off of.
6//
7// The WSL2 kernel ships no uapi header, so this RECON discovers the ABI live (rule: trust runtime):
8// (1) SIZE: _IOC_SIZE is encoded in the ioctl code. dxgkrnl dispatches on _IOC_NR=0x02 but rejects a
9// wrong _IOC_SIZE (-EINVAL) vs an unknown nr (-ENOTTY). So we sweep candidate sizes for nr=0x02
10// with the real adapter handle at offset 0 and watch for ret==0 -> that size is the real sizeof.
11// (2) DEVICE-HANDLE OFFSET: on the successful call, dxgkrnl writes the OUT device handle back into the
12// struct. dxgkrnl hands out handles in the 0x4000xxxx space (R0/R2 adapter handles were
13// 0x40000000/0x80/0xc0), so we scan the returned buffer for a fresh 0x4000xxxx value != the adapter
14// handle -> that 4-byte slot is `device`. Prints size + offset + value so the gate can pin them.
15// raw syscalls only (no libvulkan/cuda/dxcore/libc). Writes NOTHING to the status log. license_tier: ORIGINAL
16import "nx_syscalls.nx"
17
18const ENUM2_CODE: i64 = 0xC0104714 // LX_DXENUMADAPTERS2
19const QAI_CODE: i64 = 0xC0184709 // LX_DXQUERYADAPTERINFO (ADAPTERTYPE)
20const OAFL_CODE: i64 = 0xC00C4701 // LX_DXOPENADAPTERFROMLUID
21
22func p(s: *u8) -> i64 { var nn: i64=0; while s[nn]!=(0 as u8){nn=nn+1} sys_write(1,s,nn); return 0 }
23func 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 }
24func 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 }
25
26// build a Linux _IOWR(0x47, nr, size) ioctl code: (3<<30)|(size<<16)|(0x47<<8)|nr
27func iowr(nr: i64, size: i64) -> i64 { return (3 << 30) | ((size & 0x3fff) << 16) | (0x47 << 8) | (nr & 0xff) }
28
29func query_type(fd: i64, handle: i64, qtype: i64, psize: i64, outv: *i64) -> i64 {
30 let priv: *u8 = sys_mmap(64); var zz: i64 = 0; while zz < 64 { priv[zz] = 0 as u8; zz = zz + 1 }
31 let req: *u8 = sys_mmap(64); var y: i64 = 0; while y < 64 { req[y] = 0 as u8; y = y + 1 }
32 let h: *i64 = (req as i64 + 0) as *i64; h[0] = (handle & 0xffffffff) | ((qtype & 0xffffffff) << 32)
33 let pd: *i64 = (req as i64 + 8) as *i64; pd[0] = priv as i64
34 let pds: *i64 = (req as i64 + 16) as *i64; pds[0] = psize & 0xffffffff
35 let ret: i64 = sys_ioctl(fd, QAI_CODE, req as i64)
36 outv[0] = (priv[0] as i64)|((priv[1] as i64)<<8)|((priv[2] as i64)<<16)|((priv[3] as i64)<<24)
37 return ret
38}
39func open_from_luid(fd: i64, luid_lo: i64, luid_hi: i64, outh: *i64) -> i64 {
40 let req: *u8 = sys_mmap(64); var y: i64 = 0; while y < 64 { req[y] = 0 as u8; y = y + 1 }
41 let lo: *i64 = (req as i64 + 0) as *i64; lo[0] = (luid_lo & 0xffffffff) | ((luid_hi & 0xffffffff) << 32)
42 let ret: i64 = sys_ioctl(fd, OAFL_CODE, req as i64)
43 outh[0] = (req[8] as i64)|((req[9] as i64)<<8)|((req[10] as i64)<<16)|((req[11] as i64)<<24)
44 return ret
45}
46// read little-endian u32 from buf+off
47func rd32(buf: *u8, off: i64) -> i64 { return (buf[off] as i64)|((buf[off+1] as i64)<<8)|((buf[off+2] as i64)<<16)|((buf[off+3] as i64)<<24) }
48
49func main() -> i64 {
50 p("=== R3 RECON: discover LX_DXCREATEDEVICE size + device-handle offset (raw /dev/dxg) ===\n" as *u8)
51 let fd: i64 = sys_openat_rd("/dev/dxg" as *u8)
52 if fd < 0 { p("open(/dev/dxg) failed\n" as *u8); sys_exit(1); return 1 }
53
54 // enum + find discrete LUID, then open the adapter handle (R2).
55 let ainfo: *u8 = sys_mmap(4096); var z: i64 = 0; while z < 4096 { ainfo[z] = 0 as u8; z = z + 1 }
56 let ereq: *u8 = sys_mmap(64); ereq[0] = 8 as u8; let r8: *i64 = (ereq as i64 + 8) as *i64; r8[0] = ainfo as i64
57 sys_ioctl(fd, ENUM2_CODE, ereq as i64)
58 let nc: i64 = rd32(ereq, 0)
59 let v: *i64 = sys_mmap(16)
60 var disc_lo: i64 = 0; var disc_hi: i64 = 0
61 var ai: i64 = 0
62 while ai < nc {
63 let base: i64 = ai * 20
64 let eh: i64 = rd32(ainfo, base)
65 let qret: i64 = query_type(fd, eh, 15, 4, v); let t: i64 = v[0]
66 if qret == 0 { if ((t>>4)&1) == 1 { if ((t>>2)&1) == 0 { disc_lo = rd32(ainfo, base+4); disc_hi = rd32(ainfo, base+8) } } }
67 ai = ai + 1
68 }
69 let ah: *i64 = sys_mmap(16)
70 let aor: i64 = open_from_luid(fd, disc_lo, disc_hi, ah)
71 let adapter: i64 = ah[0]
72 p(" adapter open ret=" as *u8); n(aor); p(" adapter_handle=" as *u8); x(adapter); p("\n" as *u8)
73
74 // sweep candidate struct sizes for nr=0x02; adapter handle at offset 0; flags=0 (rest zero).
75 p("\n-- size sweep for LX_DXCREATEDEVICE (nr=0x02): ret==0 marks the real sizeof --\n" as *u8)
76 let sizes: *i64 = sys_mmap(256)
77 sizes[0]=24; sizes[1]=32; sizes[2]=40; sizes[3]=48; sizes[4]=56; sizes[5]=64; sizes[6]=72; sizes[7]=80; sizes[8]=88; sizes[9]=96; sizes[10]=104; sizes[11]=0
78 var si: i64 = 0
79 while sizes[si] != 0 {
80 let sz: i64 = sizes[si]
81 let buf: *u8 = sys_mmap(512); var bz: i64 = 0; while bz < 512 { buf[bz] = 0 as u8; bz = bz + 1 }
82 let a0: *i64 = (buf as i64) as *i64; a0[0] = adapter & 0xffffffff // adapter @0 (union), upper zero
83 let code: i64 = iowr(2, sz)
84 let ret: i64 = sys_ioctl(fd, code, buf as i64)
85 p(" size=" as *u8); n(sz); p(" code=" as *u8); x(code); p(" ret=" as *u8); n(ret)
86 if ret == 0 {
87 // scan for a fresh 0x4000xxxx handle != adapter -> the device handle slot.
88 var off: i64 = 0; var found_off: i64 = 0 - 1; var found_val: i64 = 0
89 while off + 4 <= sz {
90 let w: i64 = rd32(buf, off)
91 if (w & 0xffff0000) == 0x40000000 { if w != adapter { if found_off < 0 { found_off = off; found_val = w } } }
92 off = off + 4
93 }
94 p(" -> RECOGNIZED. device_handle_offset=" as *u8); n(found_off); p(" device_handle=" as *u8); x(found_val)
95 }
96 p("\n" as *u8)
97 si = si + 1
98 }
99
100 sys_close(fd)
101 p("=== R3 RECON DONE ===\n" as *u8)
102 return 0
103}