From ebd50fc8944e8f82c909ddf02f5f5a46c0564dcb Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 23 Sep 2026 07:29:35 -0400 Subject: userspace/cuda: host golden-reference descriptor dump for the crash path The host libcuda (570.211.01) has the identical engine-registration helper instruction sequence (byte-pattern matched, host vaddr 0x454470 vs guest 0x453ef0). scripts/host_gdb_descriptor.sh runs cdt on the host under gdb and prints the per-engine 6-dword registration record and the dispatch hook target. Host registers a copy engine {3, 0xd, 4, 0xc5b5, 0x3e6, 3} and cuCtxCreate succeeds; the guest registers GR {1, 1, 0, 0xc5c0, 0, 0} and crashes - so the divergence is in the engine records the driver builds from the emulated GSP static info engine table. --- .../cuda/570.144/docs/ANALYSIS-cuctxcreate-segv.md | 32 +++++++++++++ .../cuda/570.144/scripts/host_gdb_descriptor.sh | 52 ++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100755 userspace/cuda/570.144/scripts/host_gdb_descriptor.sh (limited to 'userspace/cuda') diff --git a/userspace/cuda/570.144/docs/ANALYSIS-cuctxcreate-segv.md b/userspace/cuda/570.144/docs/ANALYSIS-cuctxcreate-segv.md index 9a15b51..8775b6c 100644 --- a/userspace/cuda/570.144/docs/ANALYSIS-cuctxcreate-segv.md +++ b/userspace/cuda/570.144/docs/ANALYSIS-cuctxcreate-segv.md @@ -159,6 +159,38 @@ The engine-list construction path for this library is summarised here: * Only copy-engine records with a positive runlist become async channels; the runlist value is reused when a channel is created (0 for GR). +## Golden reference: the same code path on the host (real TU104) + +The host's libcuda (570.211.01) contains the **identical instruction +sequence** for the engine-registration helper (byte pattern match; host +vaddr `0x454470`, guest `0x453ef0`). Running the same `cdt` on the host under +gdb (`scripts/host_gdb_descriptor.sh`) shows the helper being called with: + +``` +HELPER desc=0x555555571de4 obj=0x7ffff07d4c30 + 0x555555571de4: 0x00000003 0x0000000d 0x00000004 0x0000c5b5 + 0x555555571df4: 0x000003e6 0x00000003 +HOOKCALL rax=0x7ffff7898d80 hook=0x7ffff3a67cd0 +... then cuCtxCreate succeeds, ALL OK +``` + +So the per-engine record is **six dwords**: + +| off | host (working, copy engine) | guest (crashing) | +|---|---|---| +| +0x00 | 3 (engine class enum) | 1 | +| +0x04 | 0xd (RM_ENGINE_TYPE COPY4) | 1 (GR0) | +| +0x08 | 4 (runlist) | 0 | +| +0x0c | 0xc5b5 (TURING_DMA_COPY_A) | 0xc5c0 (TURING_COMPUTE_A) | +| +0x10 | 0x3e6 | 0 | +| +0x14 | 3 | 0 | + +Both sides take the same code path and the host does not crash, so the +difference is in the **engine records the driver hands to libcuda** (built +from the GSP static info engine table we emulate) - in the guest the +registration walks the GR engine with `0xc5c0`, on the host a copy engine +with `0xc5b5` and non-zero `+0x10`/`+0x14`. + ## What is NOT (yet) analysed * No full auto-analysis output was reviewed beyond the functions above; diff --git a/userspace/cuda/570.144/scripts/host_gdb_descriptor.sh b/userspace/cuda/570.144/scripts/host_gdb_descriptor.sh new file mode 100755 index 0000000..beb4bd8 --- /dev/null +++ b/userspace/cuda/570.144/scripts/host_gdb_descriptor.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# +# host_gdb_descriptor.sh - dump libcuda's per-engine registration records on +# the HOST (real GPU = golden reference) at the same code path where the +# guest crashes. +# +# The host and guest libcuda builds share the exact instruction sequence of +# the engine-registration helper; the host's copy sits at file vaddr +# 0x454470 in 570.211.01 (guest: 0x453ef0 in 570.144). This script finds the +# pattern anywhere in a given library and runs cdt under gdb with breakpoints +# at the helper entry and the dispatch-hook call, printing the 6-dword engine +# record (rsi) and the hook target. +# +# Usage: scripts/host_gdb_descriptor.sh [binary-to-run] +# env: HOST_LIBCUDA (default /usr/lib/x86_64-linux-gnu/libcuda.so.1) +set -e + +BIN="${1:-/tmp/opencode/cdt_host}" +LIBCUDA="${HOST_LIBCUDA:-/usr/lib/x86_64-linux-gnu/libcuda.so.1}" +CUINIT_VADDR=$((16#30cb60)) # cuInit file vaddr (570.211.01) + +[ -x "$BIN" ] || { echo "build cdt first: gcc -O1 -o $BIN tools/test/cuda_drv_test.c -ldl"; exit 1; } + +python3 - "$LIBCUDA" <<'PY' +import sys +pat = bytes.fromhex("55b8000000004889e5415741564155" + "4989f5415441bc02000000534889fb4883ec18448b36") +dat = open(sys.argv[1], "rb").read() +i = dat.find(pat) +print("helper pattern at vaddr 0x%x" % i if i >= 0 else "pattern NOT FOUND") +PY + +gdb -batch \ + -ex "set pagination off" \ + -ex "set confirm off" \ + -ex "set breakpoint pending on" \ + -ex "break cuInit" \ + -ex "run" \ + -ex "python +import gdb +a = int(gdb.parse_and_eval('(unsigned long)cuInit')) +base = a - $CUINIT_VADDR +print('HOST libcuda base=0x%x' % base) +gdb.execute('delete 1') +b = gdb.Breakpoint('*0x%x' % (base+0x454470)) +gdb.execute('commands ' + str(b.number) + '\nsilent\nprintf \"HELPER desc=%p obj=%p thread=%d\\n\", \$rsi, \$rdi, \$_thread\nx/6wx \$rsi\ncontinue\nend') +c = gdb.Breakpoint('*0x%x' % (base+0x4544df)) +gdb.execute('commands ' + str(c.number) + '\nsilent\nprintf \"HOOKCALL rax=%p hook=%p\\n\", \$rax, *(void**)(\$rax+0x530)\ncontinue\nend') +end" \ + -ex "continue" \ + "$BIN" -- cgit v1.2.3