From 7897fe79ba6a00cc59b7a357903ecfc70480ce97 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 23 Sep 2026 00:51:55 -0400 Subject: tools: add guest-diag (ptrace ioctl tracer, vmcycle, root-port QEMU cmdline) The ptrace tracer resolves the current CUDA blocker: libcuda issues raw syscall instructions, so LD_PRELOAD shims and ltrace see nothing; following the child with PTRACE_SYSCALL + PTRACE_GET_SYSCALL_INFO does. It found UVM_REGISTER_GPU (ioctl 0x25) returning rmStatus=0x56 NV_ERR_NOT_SUPPORTED, with inputs identical to the working host run (rmCtrlFd=-1, hClient=0, hSmcPartRef=0). Also dumps NV_ESC_RM_CONTROL cmd/status and RM alloc/free statuses (all zero) and the UVM ioctl set (guest stops after 0x27,0x1,0x25,0x2 vs 141 ioctls on the host). launch_qemu_rootport.sh is the working QEMU command line with the pcie-root-port fix (see its header + the handoff PART 4); vmcycle.sh drives the module/mdev/VM reload cycle around it. --- tools/guest-diag/sysc_shim.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tools/guest-diag/sysc_shim.c (limited to 'tools/guest-diag/sysc_shim.c') diff --git a/tools/guest-diag/sysc_shim.c b/tools/guest-diag/sysc_shim.c new file mode 100644 index 0000000..9b07e4c --- /dev/null +++ b/tools/guest-diag/sysc_shim.c @@ -0,0 +1,73 @@ +/* sysc_shim.c - intercept syscall() so we can dump ioctl buffer *results* + * for UVM ioctls (libcuda calls syscall(SYS_ioctl, ...) directly, so an + * ioctl() wrapper is bypassed but syscall() is not). + * Build in guest: gcc -shared -fPIC -O1 -o /tmp/sysc.so sysc_shim.c -ldl + * Run: LD_PRELOAD=/tmp/sysc.so /tmp/cdt + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static long (*real_syscall)(long, ...); + +static void dump(const char *tag, unsigned long req, void *arg, long ret) +{ + unsigned int *p = (unsigned int *)arg; + char buf[512]; + int n, i; + long *vp = (long *)arg; + + if (!p) + return; + n = 0; + n += __builtin_snprintf(buf + n, sizeof(buf) - n, + "SYSC[%s] req=0x%lx ret=%ld dwords: ", tag, req, + ret); + for (i = 0; i < 16 && n < (int)sizeof(buf) - 16; i++) + n += __builtin_snprintf(buf + n, sizeof(buf) - n, "%08x ", + p[i]); + (void)vp; + write(2, buf, n); + write(2, "\n", 1); +} + +long syscall(long nr, ...) +{ + va_list ap; + long a1, a2, a3, a4, a5, a6; + long ret; + + if (!real_syscall) + real_syscall = dlsym(RTLD_NEXT, "syscall"); + + va_start(ap, nr); + a1 = va_arg(ap, long); + a2 = va_arg(ap, long); + a3 = va_arg(ap, long); + a4 = va_arg(ap, long); + a5 = va_arg(ap, long); + a6 = va_arg(ap, long); + va_end(ap); + + ret = real_syscall(nr, a1, a2, a3, a4, a5, a6); + + if (nr == SYS_ioctl) { + unsigned long req = (unsigned long)a2; + switch (req) { + case 0x1: /* UVM_RESERVE_VA */ + case 0x2: /* UVM_RELEASE_VA */ + case 0x25: /* UVM_REGISTER_GPU */ + case 0x27: /* UVM_PAGEABLE_MEM_ACCESS */ + case 0x17: /* UVM_EVENT_CTRL */ + case 0x19: /* UVM_REGISTER_MPS_CLIENT */ + dump("uvmioctl", req, (void *)a3, ret); + break; + default: + break; + } + } + return ret; +} -- cgit v1.2.3