code wiki / _hdl_build / nx_nv.nx

nx_nv.nx source

↩ module page · 37 lines · 2527 B

1// nx_nv.nx -- the native-Linux NVIDIA OPEN-KERNEL-MODULE device shim (TIER-1 sovereign executor), sibling to 2// nx_dxg (the WSL2 GPU-PV shim). This is the path that ACTUALLY EXECUTES on real silicon -- modeled on tinygrad's 3// ops_nv.py, which submits via /dev/nvidia* + a GPFIFO ring + a usermode doorbell, bypassing the CUDA runtime 4// (and bypassing the proprietary dxg priv-data handshake that walls WSL2). Runs on a native-Linux / rented cloud 5// GPU instance (brick-safe, rule #26). 6// 7// LOCALLY-VERIFIABLE (gated bit-exact here): the GPFIFO entry encoder + the doorbell offset. 8// CLOUD-PENDING (structured, completed against the instance's open-gpu-kernel-modules headers on first run): 9// the full RM-API object tree -- NV_ESC_RM_ALLOC on /dev/nvidiactl for root client -> device -> subdevice -> 10// channel-group -> GPFIFO channel (NV_CHANNELGPFIFO_ALLOCATION_PARAMETERS) -> compute object; NV_ESC_RM_CONTROL 11// for GPFIFO_SCHEDULE + GET_WORK_SUBMIT_TOKEN; NV_ESC_RM_MAP_MEMORY for the usermode doorbell BAR. 12// Pure funcs, no main. license_tier: ORIGINAL 13import "nx_syscalls.nx" 14 15// NVIDIA RM ioctl escapes (NV_IOCTL_MAGIC='F'=0x46): the ioctl = _IOWR(0x46, NV_ESC_*, sizeof(param)). 16// (numbers from the open-gpu-kernel-modules ABI; struct sizes resolved on the cloud instance = TODO_CLOUD) 17const NV_ESC_RM_ALLOC: i64 = 0x2b 18const NV_ESC_RM_CONTROL: i64 = 0x2a 19const NV_ESC_RM_MAP_MEMORY: i64 = 0x4e 20// usermode doorbell: tinygrad writes the channel work-submit token to MMIO byte offset 0x90 (gpu_mmio[0x90/4]). 21const NV_DOORBELL_OFF: i64 = 0x90 22 23func nv_open_ctl() -> i64 { return sys_openat_rd("/dev/nvidiactl" as *u8) } 24func nv_open_dev() -> i64 { return sys_openat_rd("/dev/nvidia0" as *u8) } 25func nv_open_uvm() -> i64 { return sys_openat_rd("/dev/nvidia-uvm" as *u8) } 26 27// GPFIFO entry (real hardware format, per tinygrad ops_nv.py _submit_to_gpfifo): 28// entry = (gpu_va aligned to 4) | (len_dwords << 42) | (1 << 41) 29// = ((gpu_va>>2)<<2) clears the low 2 bits (matches tinygrad's `cmdq_addr//4 << 2`). 30func nv_gpfifo_entry(gpu_va: i64, len_dwords: i64) -> i64 { return ((gpu_va >> 2) << 2) | (len_dwords << 42) | (1 << 41) } 31 32// ring the doorbell: 32-bit write of the channel work-submit token to the mapped usermode MMIO at NV_DOORBELL_OFF. 33func nv_doorbell_ring(mmio_base: i64, token: i64) -> i64 { 34 let b: *u8 = (mmio_base + NV_DOORBELL_OFF) as *u8 35 b[0]=(token&0xff) as u8; b[1]=((token>>8)&0xff) as u8; b[2]=((token>>16)&0xff) as u8; b[3]=((token>>24)&0xff) as u8 36 return 0 37}