diff options
Diffstat (limited to 'tools/guest-diag/sysc_shim.c')
| -rw-r--r-- | tools/guest-diag/sysc_shim.c | 73 |
1 files changed, 73 insertions, 0 deletions
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 <dlfcn.h> +#include <stdarg.h> +#include <stddef.h> +#include <sys/syscall.h> +#include <unistd.h> + +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; +} |
