code wiki / _hdl_build / nx_gpu_mem.nx

nx_gpu_mem.nx source

↩ module page · 67 lines · 4038 B

1// nx_gpu_mem.nx -- HEAPS AND RESIDENCY over the dxg door (gpu GP6): allocate, place, make resident, EVICT, with the 2// budget READ from the device, never assumed. One heap = one EXISTINGHEAP allocation of a page-aligned size, 3// placed at a GPU virtual address through the paging queue and made resident; eviction is the device's own 4// EVICT, and the proof that it happened is the device's own paging state (a make-resident after an evict 5// answers DXG_MKRES_PENDING instead of 0). 6// 7// SCOPE, stated once: these heaps are SYSTEM-memory backed (the UMD-less EXISTINGHEAP path R4d measured), so they 8// live in the NON-LOCAL segment; a VRAM (local-segment) heap needs the vendor UMD's private allocation data, the 9// same blocker class as the command ring (gpu.plan GP5 lesson). Exhausting the non-local budget would exhaust the 10// host's RAM, so this lib walks a BOUNDED window under the budget and never crosses it; the exhaust-to-evict test on 11// the local segment is named on the board as owed, not claimed. 12// license_tier: ORIGINAL No hw writes (Rule 26): per-process allocations, released with the process. 13import "nx_syscalls.nx" 14import "nx_dxg.nx" 15import "nx_gpu_sync.nx" 16 17const GM_MAX_HEAPS: i64 = 64 18const GM_ERR_BUDGET: i64 = 0 - 21 // the budget query refused 19const GM_ERR_ALLOC: i64 = 0 - 22 // an allocation refused or returned no handle 20const GM_ERR_MAP: i64 = 0 - 23 // the GPU VA map refused (259 = pending is fine) 21const GM_ERR_RES: i64 = 0 - 24 // make-resident refused (259 = pending is fine) 22const GM_ERR_EVICT: i64 = 0 - 25 // evict refused 23const GM_ERR_TOOMANY: i64 = 0 - 26 // more heaps than the table holds 24 25// a heap table: handles[i], vas[i], sysmem[i], bytes[i] for i < count 26func gm_table_new() -> *i64 { let t: *i64 = sys_mmap(GM_MAX_HEAPS * 8 * 4) as *i64; return t } 27func gm_handle(t: *i64, i: i64) -> i64 { return t[i] } 28func gm_va(t: *i64, i: i64) -> i64 { return t[GM_MAX_HEAPS + i] } 29func gm_sysmem(t: *i64, i: i64) -> *u8 { return t[GM_MAX_HEAPS * 2 + i] as *u8 } 30func gm_bytes(t: *i64, i: i64) -> i64 { return t[GM_MAX_HEAPS * 3 + i] } 31 32// budget for a segment group, read from the device: out[0]=budget out[1]=usage out[2]=reservation out[3]=available 33func gpu_mem_budget(fd: i64, adapter: i64, group: i64, out: *i64) -> i64 { 34 if dxg_query_vidmem(fd, adapter, group, out) != 0 { return GM_ERR_BUDGET } 35 if out[0] <= 0 { return GM_ERR_BUDGET } 36 return 0 37} 38 39// allocate heap i of `bytes`, place it (GPU VA through the paging queue) and make it resident; returns 0 or a stage code. 40// mapf[0] / resf[0] receive the paging fence values (259 = pending, completes on the paging queue's fence). 41func gpu_mem_heap(fd: i64, device: i64, pq: i64, t: *i64, i: i64, bytes: i64, mapf: *i64, resf: *i64) -> i64 { 42 if i >= GM_MAX_HEAPS { return GM_ERR_TOOMANY } 43 let mem: *u8 = sys_mmap(bytes) 44 let h: *i64 = sys_mmap(16) as *i64 45 if dxg_alloc_eh_sz(fd, device, mem, bytes, h) != 0 { return GM_ERR_ALLOC } 46 if h[0] == 0 { return GM_ERR_ALLOC } 47 let va: *i64 = sys_mmap(16) as *i64 48 let mr: i64 = dxg_map_va(fd, pq, h[0], va, mapf) 49 if mr != 0 { if mr != DXG_MKRES_PENDING { return GM_ERR_MAP } } 50 let rr: i64 = dxg_makeresident(fd, pq, h[0], resf) 51 if rr != 0 { if rr != DXG_MKRES_PENDING { return GM_ERR_RES } } 52 t[i] = h[0]; t[GM_MAX_HEAPS + i] = va[0]; t[GM_MAX_HEAPS * 2 + i] = mem as i64; t[GM_MAX_HEAPS * 3 + i] = bytes 53 sys_munmap(h as *u8, 16); sys_munmap(va as *u8, 16) 54 return 0 55} 56 57// evict heap i; outtrim[0] = the device's num_bytes_to_trim 58func gpu_mem_evict(fd: i64, device: i64, t: *i64, i: i64, outtrim: *i64) -> i64 { 59 if dxg_evict(fd, device, t[i], outtrim) != 0 { return GM_ERR_EVICT } 60 return 0 61} 62 63// re-make heap i resident; returns the device's own answer: 0 = it was still resident, DXG_MKRES_PENDING = it had 64// been evicted and is paging back in, negative = refused 65func gpu_mem_reresident(fd: i64, pq: i64, t: *i64, i: i64, resf: *i64) -> i64 { 66 return dxg_makeresident(fd, pq, t[i], resf) 67}