1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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;
}
|