summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-28 09:09:13 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-28 09:09:13 -0400
commit448d1d9a6f9168006910a79e177d4bed331bacc6 (patch)
tree5e628d80c4a07f1e6f50824ba63ce2a42715f399 /tools
parent17e1f522e4e9e04d13c4ca9495a2f4f1bdc58c36 (diff)
downloadopen-iov-448d1d9a6f9168006910a79e177d4bed331bacc6.tar.gz
open-iov-448d1d9a6f9168006910a79e177d4bed331bacc6.zip
sem: run GR channels - accept CE methods on subchannel 0, discover GR rings
- The CE semaphore/memset method groups also arrive on subchannel 0 (CUDA's push library binds the copy class on compute channels to carry the work-submission releases), so the stream decoder accepts both 0 and 4. - GR (compute) channel rings live in the same video-memory allocation as the CE rings, 0x3000 bytes per channel after them: ring (0x2000) at ce_end + 0x3000*rank, USERD at +0x2000. Discover and pin them once the CE ranks are known; verified against ring entry 0 (1 MB aligned push VA in the client window, sane length) and the USERD's put/get, so a layout change costs a failed pin, not a wrong one. Gated by sema_gr_rings (default on). - memprobe: require the sem-VA triple in the sem-object scanner (a bare qword in the window matches thousands of unrelated pointers once the ring/pushbuffer windows are part of the range). Live evidence: ring entries read through the guest's /proc/pid/mem decode to the GR channels' first pushes; pinning the ring (fb 0x140000+0x3000*rank), USERD (ring+0x2000) and first-push pages made all 20 GR channels execute their entry 0 for the first time (get=1 sub=1).
Diffstat (limited to 'tools')
-rw-r--r--tools/guest-diag/memprobe.py20
1 files changed, 16 insertions, 4 deletions
diff --git a/tools/guest-diag/memprobe.py b/tools/guest-diag/memprobe.py
index 96dd40b..c2bab9f 100644
--- a/tools/guest-diag/memprobe.py
+++ b/tools/guest-diag/memprobe.py
@@ -72,12 +72,24 @@ def scan_qwords(pid, fd, lo, hi, needle_lo=None, needle_hi=None, needle_set=None
return hits
def sem_objs(pid, fd, lo, hi):
- # qword in [lo,hi) at address A -> a sem object holds it at +0x10
+ # A real sem object stores its GPU VA three times, at so+0x08, so+0x10 and
+ # so+0x18. Requiring a duplicated neighbour keeps the scan selective: a
+ # bare qword in the window matches thousands of unrelated pointers once
+ # the ring/pushbuffer windows are part of the range.
first = scan_qwords(pid, fd, None, None, needle_lo=lo, needle_hi=hi)
- out = {}
+ cand = {}
for addr, val in first:
- so = addr - 0x10
- out.setdefault(val, set()).add(so)
+ cand.setdefault(val, set()).add(addr)
+ out = {}
+ for val, addrs in cand.items():
+ for a in addrs:
+ buf = rd(fd, a - 8, 0x20)
+ if not buf or len(buf) < 0x20:
+ continue
+ q0, q1, q2, q3 = (r64(buf, i) for i in (0, 8, 0x10, 0x18))
+ if q1 == val and (q0 == val or q2 == val) and \
+ (q2 == val or q3 == val):
+ out.setdefault(val, set()).add(a - 0x10)
return out
def find_trackers(pid, fd, lo, hi, limit=8):