summaryrefslogtreecommitdiff
path: root/mmt
diff options
context:
space:
mode:
authorMarcin Slusarz <marcin.slusarz@gmail.com>2011-09-07 19:20:24 +0200
committerMarcin Slusarz <marcin.slusarz@gmail.com>2011-09-17 22:57:22 +0200
commitce6e73784f9ec1f1ad7bb0cfbdfb66afa8cb9d9b (patch)
treea7ddd00b468c74a1c8ecb29f78da3c8ac2f6a88d /mmt
parent84556ed7a14d696bac6b63beafa51ce4ac6cb639 (diff)
mmt: move nvidia ioctl tracing to separate file
Diffstat (limited to 'mmt')
-rw-r--r--mmt/Makefile.am2
-rw-r--r--mmt/mmt_main.c635
-rw-r--r--mmt/mmt_main.h24
-rw-r--r--mmt/mmt_nv_ioctl.c654
-rw-r--r--mmt/mmt_nv_ioctl.h22
5 files changed, 729 insertions, 608 deletions
diff --git a/mmt/Makefile.am b/mmt/Makefile.am
index d964a5e8..639324e4 100644
--- a/mmt/Makefile.am
+++ b/mmt/Makefile.am
@@ -5,7 +5,7 @@ if VGCONF_HAVE_PLATFORM_SEC
noinst_PROGRAMS += mmt-@VGCONF_ARCH_SEC@-@VGCONF_OS@
endif
-MMT_SOURCES_COMMON = mmt_main.c
+MMT_SOURCES_COMMON = mmt_main.c mmt_nv_ioctl.c
mmt_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES = \
$(MMT_SOURCES_COMMON)
diff --git a/mmt/mmt_main.c b/mmt/mmt_main.c
index 90d656db..b3aa3c75 100644
--- a/mmt/mmt_main.c
+++ b/mmt/mmt_main.c
@@ -54,130 +54,19 @@
#include <fcntl.h>
#include <string.h>
-#define MAX_REGIONS 100
+#include "mmt_nv_ioctl.h"
+#include "mmt_main.h"
+
#define MAX_TRACE_FILES 10
#ifdef __LP64__
#define MMT_64BIT
#endif
-static struct mmt_mmap_data {
- Addr start;
- Addr end;
- int fd;
- Off64T offset;
- UInt id;
- UWord data1;
- UWord data2;
-} mmt_mmaps[MAX_REGIONS];
-static int last_region = -1;
-
-static struct object_type {
- UInt id; // type id
- char *name; // some name
- UInt cargs; // number of constructor args (uint32)
-} object_types[] =
-{
- {0x0000, "NV_CONTEXT_NEW", 0},
-
- {0x0004, "NV_PTIMER", 0},
-
- {0x0041, "NV_CONTEXT", 0},
-
- {0x502d, "NV50_2D", 0},
- {0x902d, "NVC0_2D", 0},
-
- {0x5039, "NV50_M2MF", 0},
- {0x9039, "NVC0_M2MF", 0},
-
- {0x9068, "NVC0_PEEPHOLE", 0},
-
- {0x406e, "NV40_FIFO_DMA", 6},
-
- {0x506f, "NV50_FIFO_IB", 6},
- {0x826f, "NV84_FIFO_IB", 6},
- {0x906f, "NVC0_FIFO_IB", 6},
-
- {0x5070, "NV84_DISPLAY", 4},
- {0x8270, "NV84_DISPLAY", 4},
- {0x8370, "NVA0_DISPLAY", 4},
- {0x8870, "NV98_DISPLAY", 4},
- {0x8570, "NVA3_DISPLAY", 4},
-
- {0x5072, NULL, 8},
-
- {0x7476, "NV84_VP", 0},
-
- {0x507a, "NV50_DISPLAY_CURSOR", 0},
- {0x827a, "NV84_DISPLAY_CURSOR", 0},
- {0x857a, "NVA3_DISPLAY_CURSOR", 0},
-
- {0x507b, "NV50_DISPLAY_OVERLAY", 0},
- {0x827b, "NV84_DISPLAY_OVERLAY", 0},
- {0x857b, "NVA3_DISPLAY_OVERLAY", 0},
-
- {0x507c, "NV50_DISPLAY_SYNC_FIFO", 8},
- {0x827c, "NV84_DISPLAY_SYNC_FIFO", 8},
- {0x837c, "NVA0_DISPLAY_SYNC_FIFO", 8},
- {0x857c, "NVA3_DISPLAY_SYNC_FIFO", 8},
-
- {0x507d, "NV50_DISPLAY_MASTER_FIFO", 0},
- {0x827d, "NV84_DISPLAY_MASTER_FIFO", 0},
- {0x837d, "NVA0_DISPLAY_MASTER_FIFO", 0},
- {0x887d, "NV98_DISPLAY_MASTER_FIFO", 0},
- {0x857d, "NVA3_DISPLAY_MASTER_FIFO", 0},
-
- {0x307e, "NV30_PEEPHOLE", 0},
-
- {0x507e, "NV50_DISPLAY_OVERLAY_FIFO", 8},
- {0x827e, "NV84_DISPLAY_OVERLAY_FIFO", 8},
- {0x837e, "NVA0_DISPLAY_OVERLAY_FIFO", 8},
- {0x857e, "NVA3_DISPLAY_OVERLAY_FIFO", 8},
-
- {0x0080, "NV_DEVICE", 1},
- {0x2080, "NV_SUBDEVICE_0", 0},
- {0x2081, "NV_SUBDEVICE_1", 0},
- {0x2082, "NV_SUBDEVICE_2", 0},
- {0x2083, "NV_SUBDEVICE_3", 0},
-
- {0x5097, "NV50_3D", 0},
- {0x8297, "NV84_3D", 0},
- {0x8397, "NVA0_3D", 0},
- {0x8597, "NVA3_3D", 0},
- {0x8697, "NVAF_3D", 0},
- {0x9097, "NVC0_3D", 0},
-
- {0x74b0, "NV84_BSP", 0},
-
- {0x88b1, "NV98_BSP", 0},
- {0x85b1, "NVA3_BSP", 0},
- {0x86b1, "NVAF_BSP", 0},
- {0x90b1, "NVC0_BSP", 0},
-
- {0x88b2, "NV98_VP", 0},
- {0x85b2, "NVA3_VP", 0},
- {0x90b2, "NVC0_VP", 0},
-
- {0x88b3, "NV98_PPP", 0},
- {0x85b3, "NVA3_PPP", 0},
- {0x90b3, "NVC0_PPP", 0},
-
- {0x88b4, "NV98_CRYPT", 0},
+struct mmt_mmap_data mmt_mmaps[MMT_MAX_REGIONS];
+int mmt_last_region = -1;
- {0x85b5, "NVA3_COPY", 0},
- {0x90b5, "NVC0_COPY0", 0},
-
- {0x50c0, "NV50_COMPUTE", 0},
- {0x85c0, "NVA3_COMPUTE", 0},
- {0x90c0, "NVC0_COMPUTE", 0},
-
- {0x74c1, "NV84_CRYPT", 0},
-
- {0x50e0, "NV50_PGRAPH", 0},
- {0x50e2, "NV50_PFIFO", 0},
-};
-
-static UInt current_item = 1;
+UInt current_item = 1;
/* Command line options */
//UInt mmt_clo_offset = (UInt) -1;
@@ -190,19 +79,12 @@ static struct trace_file {
} trace_files[MAX_TRACE_FILES];
static int trace_all_files = False;
-static int trace_nvidia_ioctls = False;
-static int trace_marks = False;
-static int trace_mark_fd;
-static int trace_mark_cnt = 0;
-static fd_set nvidiactl_fds;
-static fd_set nvidia0_fds;
-
static struct mmt_mmap_data *find_mmap(Addr addr)
{
struct mmt_mmap_data *region = NULL;
int i;
- for (i = 0; i <= last_region; i++)
+ for (i = 0; i <= mmt_last_region; i++)
{
region = &mmt_mmaps[i];
if (addr >= region->start && addr < region->end)
@@ -212,18 +94,6 @@ static struct mmt_mmap_data *find_mmap(Addr addr)
return NULL;
}
-static struct object_type *find_objtype(UInt id)
-{
- int i;
- int n = sizeof(object_types) / sizeof(struct object_type);
-
- for (i = 0; i < n; ++i)
- if (object_types[i].id == id)
- return &object_types[i];
-
- return NULL;
-}
-
static void mydescribe(Addr inst_addr, char *namestr, int len)
{
#if 0
@@ -1000,7 +870,7 @@ static Bool mmt_process_cmd_line_option(Char * arg)
}
else if (VG_(strcmp)(arg, TN_OPT) == 0)
{
- trace_nvidia_ioctls = True;
+ mmt_trace_nvidia_ioctls = True;
return True;
}
else if (VG_(strcmp)(arg, TO_OPT) == 0)
@@ -1015,7 +885,7 @@ static Bool mmt_process_cmd_line_option(Char * arg)
}
else if (VG_(strcmp)(arg, TM_OPT) == 0)
{
- trace_marks = True;
+ mmt_trace_marks = True;
return True;
}
@@ -1028,7 +898,7 @@ static void mmt_print_usage(void)
" this file (e.g. /dev/nvidia0) (you can pass \n"
" this option multiple times)\n");
VG_(printf)(" " TA_OPT " trace loads and store to memory mapped for all files\n");
- VG_(printf)(" " TN_OPT " trace ioctls on /dev/nvidiactl\n");
+ VG_(printf)(" " TN_OPT " trace ioctls on /dev/nvidiactl\n");
VG_(printf)(" " TO_OPT " trace all 'open' syscalls\n");
VG_(printf)(" " TM_OPT " send mmiotrace marks before and after ioctls\n");
}
@@ -1039,446 +909,26 @@ static void mmt_print_debug_usage(void)
static void mmt_fini(Int exitcode)
{
- if (trace_marks) {
- VG_(close)(trace_mark_fd);
- }
+ mmt_nv_ioctl_fini();
}
static void mmt_post_clo_init(void)
{
- if (trace_marks) {
- SysRes ff;
- ff = VG_(open)("/sys/kernel/debug/tracing/trace_marker", O_WRONLY, 0777);
- if (ff._isError) {
- VG_(message) (Vg_UserMsg, "Cannot open marker file!\n");
- trace_marks = 0;
- }
- trace_mark_fd = ff._val;
- }
-}
-
-static void dumpmem(char *s, Addr addr, UInt size)
-{
- char line[4096];
- int idx = 0;
- line[0] = 0;
-
- UInt i;
- if (!addr || (addr & 0xffff0000) == 0xbeef0000)
- return;
-
- size = size / 4;
-
- for (i = 0; i < size; ++i)
- {
- if (idx + 11 >= 4095)
- break;
- VG_(sprintf) (line + idx, "0x%08x ", ((UInt *) addr)[i]);
- idx += 11;
- }
- VG_(message) (Vg_DebugMsg, "%s%s\n", s, line);
-}
-
-static inline unsigned long long mmt_2x4to8(UInt h, UInt l)
-{
- return (((unsigned long long)h) << 32) | l;
-}
-
-static void pre_ioctl(ThreadId tid, UWord *args, UInt nArgs)
-{
- int fd = args[0];
- UInt id = args[1];
- UInt *data = (UInt *) args[2];
- UWord addr;
- UInt obj1, obj2, size;
- int i;
-
- if (!FD_ISSET(fd, &nvidiactl_fds) && !FD_ISSET(fd, &nvidia0_fds))
- return;
-
- if (trace_marks) {
- char buf[50];
- VG_(snprintf)(buf, 50, "VG-%d-%d-PRE\n", VG_(getpid)(), trace_mark_cnt);
- VG_(write)(trace_mark_fd, buf, VG_(strlen)(buf));
- VG_(message)(Vg_DebugMsg, "MARK: %s", buf);
- }
-
- if ((id & 0x0000FF00) == 0x4600)
- {
- char line[4096];
- int idx = 0;
-
- size = ((id & 0x3FFF0000) >> 16) / 4;
- VG_(sprintf) (line, "pre_ioctl: fd:%d, id:0x%02x (full:0x%x), data: ", fd, id & 0xFF, id);
- idx = strlen(line);
-
- for (i = 0; i < size; ++i)
- {
- if (idx + 11 >= 4095)
- break;
- VG_(sprintf) (line + idx, "0x%08x ", data[i]);
- idx += 11;
- }
- VG_(message) (Vg_DebugMsg, "%s\n", line);
- }
- else
- VG_(message)(Vg_DebugMsg, "pre_ioctl, fd: %d, wrong id:0x%x\n", fd, id);
-
- switch (id)
- {
- // 0x23
- // c1d00041 5c000001 00000080 00000000 00000000 00000000 00000000 00000000
- // c1d0004a beef0003 000000ff 00000000 04fe8af8 00000000 00000000 00000000
- case 0xc0204623:
- obj1 = data[1];
- VG_(message) (Vg_DebugMsg, "create device object 0x%08x\n", obj1);
-
- // argument can be a string (7:0, indicating the bus number), but only if
- // argument is 0xff
- dumpmem("in ", data[4], 0x3C);
-
- break;
- // 0x37 read stuff from video ram?
- //case 0xc0204637:
- case 0xc0204638:
- dumpmem("in ", data[4], data[6]);
- break;
-#if 1
- case 0xc0204637:
- {
- UInt *addr2;
- dumpmem("in ", data[4], data[6]);
-
- addr2 = (*(UInt **) (&data[4]));
- //if(data[2]==0x14c && addr2[2])
- // dumpmem("in2 ", addr2[2], 0x40);
- break;
- }
-#endif
- case 0xc020462a:
- VG_(message) (Vg_DebugMsg, "call method 0x%08x:0x%08x\n", data[1], data[2]);
- dumpmem("in ", mmt_2x4to8(data[5], data[4]), mmt_2x4to8(data[7], data[6]));
- // 0x10000002
- // word 2 is an address
- // what is there?
- if (data[2] == 0x10000002)
- {
- UInt *addr2 = (*(UInt **) (&data[4]));
- dumpmem("in2 ", addr2[2], 0x3c);
- }
- break;
-
- case 0xc040464d:
- VG_(message) (Vg_DebugMsg, "in %s\n", *(char **) (&data[6]));
- break;
- case 0xc028465e:
- {
- // Copy data from mem to GPU
-#if 0
- SysRes ff;
- ff = VG_(open) ("dump5e", O_CREAT | O_WRONLY | O_TRUNC, 0777);
- if (!ff.isError)
- {
- VG_(write) (ff.res, (void *) data[6], 0x01000000);
- VG_(close) (ff.res);
- }
-#endif
- break;
- }
- case 0xc0104629:
- obj1 = data[1];
- obj2 = data[2];
- VG_(message) (Vg_DebugMsg, "destroy object 0x%08x:0x%08x\n", obj1, obj2);
- break;
- case 0xc020462b:
- {
- struct object_type *objtype;
- char *name = "???";
- obj1 = data[1];
- obj2 = data[2];
- addr = data[3];
- objtype = find_objtype(addr);
- if (objtype && objtype->name)
- name = objtype->name;
- VG_(message) (Vg_DebugMsg,
- "create gpu object 0x%08x:0x%08x type 0x%04lx (%s)\n",
- obj1, obj2, addr, name);
- if (data[4])
- {
- if (objtype)
- dumpmem("in ", mmt_2x4to8(data[5], data[4]), objtype->cargs * 4);
- else
- dumpmem("in ", mmt_2x4to8(data[5], data[4]), 0x40);
- }
-
- break;
- }
- case 0xc014462d:
- obj1 = data[1];
- obj2 = data[2];
- addr = data[3];
- VG_(message) (Vg_DebugMsg,
- "create driver object 0x%08x:0x%08x type 0x%04lx\n", obj1, obj2, addr);
- break;
-
- }
+ mmt_nv_ioctl_post_clo_init();
}
static void pre_syscall(ThreadId tid, UInt syscallno, UWord *args, UInt nArgs)
{
if (syscallno == __NR_ioctl)
- pre_ioctl(tid, args, nArgs);
+ mmt_nv_ioctl_pre(args);
}
-static struct mmt_mmap_data *get_nvidia_mapping(Off64T offset)
+void mmt_free_region(int idx)
{
- struct mmt_mmap_data *region;
- int i;
- for (i = 0; i <= last_region; ++i)
- {
- region = &mmt_mmaps[i];
- if (FD_ISSET(region->fd, &nvidia0_fds))
- if (region->offset == offset)
- return region;
- }
-
- if (last_region + 1 >= MAX_REGIONS)
- {
- VG_(message)(Vg_UserMsg, "no space for new mapping!\n");
- return NULL;
- }
-
- region = &mmt_mmaps[++last_region];
- region->id = current_item++;
- region->fd = 0;
- region->offset = offset;
- return region;
-}
-
-static inline void free_region(int idx)
-{
- if (last_region != idx)
+ if (mmt_last_region != idx)
VG_(memmove)(mmt_mmaps + idx, mmt_mmaps + idx + 1,
- (last_region - idx) * sizeof(struct mmt_mmap_data));
- VG_(memset)(&mmt_mmaps[last_region--], 0, sizeof(struct mmt_mmap_data));
-}
-
-static Addr release_nvidia_mapping(Off64T offset)
-{
- int i;
- for (i = 0; i <= last_region; ++i)
- {
- struct mmt_mmap_data *region = &mmt_mmaps[i];
- if (FD_ISSET(region->fd, &nvidia0_fds))
- if (region->offset == offset)
- {
- Addr addr = region->start;
- free_region(i);
- return addr;
- }
- }
- return 0;
-}
-
-static Addr release_nvidia_mapping2(UWord data1, UWord data2)
-{
- int i;
- for (i = 0; i <= last_region; ++i)
- {
- struct mmt_mmap_data *region = &mmt_mmaps[i];
- if (FD_ISSET(region->fd, &nvidia0_fds))
- if (region->data1 == data1 && region->data2 == data2)
- {
- Addr addr = region->start;
- free_region(i);
- return addr;
- }
- }
- return 0;
-}
-
-static void post_ioctl(ThreadId tid, UWord *args, UInt nArgs)
-{
- int fd = args[0];
- UInt id = args[1];
- UInt *data = (UInt *) args[2];
- UWord addr;
- UInt obj1, obj2, size, type;
- int i;
- struct mmt_mmap_data *region;
-
- if (!FD_ISSET(fd, &nvidiactl_fds) && !FD_ISSET(fd, &nvidia0_fds))
- return;
-
- if (trace_marks) {
- char buf[50];
- VG_(snprintf)(buf, 50, "VG-%d-%d-POST\n", VG_(getpid)(), trace_mark_cnt++);
- VG_(write)(trace_mark_fd, buf, VG_(strlen)(buf));
- VG_(message)(Vg_DebugMsg, "MARK: %s", buf);
- }
-
- if ((id & 0x0000FF00) == 0x4600)
- {
- char line[4096];
- int idx = 0;
-
- size = ((id & 0x3FFF0000) >> 16) / 4;
- VG_(sprintf) (line, "post_ioctl: fd:%d, id:0x%02x (full:0x%x), data: ", fd, id & 0xFF, id);
- idx = strlen(line);
-
- for (i = 0; i < size; ++i)
- {
- if (idx + 11 >= 4095)
- break;
- VG_(sprintf) (line + idx, "0x%08x ", data[i]);
- idx += 11;
- }
- VG_(message) (Vg_DebugMsg, "%s\n", line);
- }
- else
- VG_(message)(Vg_DebugMsg, "post_ioctl, fd: %d, wrong id:0x%x\n", fd, id);
-
- switch (id)
- {
- // NVIDIA
- case 0xc00c4622: // Initialize
- obj1 = data[0];
- VG_(message) (Vg_DebugMsg, "created context object 0x%08x\n", obj1);
- break;
-
- case 0xc0204623:
- dumpmem("out", data[4], 0x3C);
- break;
-
- case 0xc030464e: // Allocate map for existing object
- obj1 = data[1];
- obj2 = data[2];
- addr = data[8];
- VG_(message) (Vg_DebugMsg, "allocate map 0x%08x:0x%08x 0x%08lx\n", obj1, obj2, addr);
-
- region = get_nvidia_mapping(addr);
- if (region)
- {
- region->data1 = obj1;
- region->data2 = obj2;
- }
-
- break;
- case 0xc020464f: // Deallocate map for existing object
- obj1 = data[1];
- obj2 = data[2];
- addr = data[4];
- /// XXX some currently mapped memory might be orphaned
-
- if (release_nvidia_mapping(addr))
- VG_(message) (Vg_DebugMsg, "deallocate map 0x%08x:0x%08x 0x%08lx\n", obj1, obj2, addr);
-
- break;
- case 0xc0304627: // 0x27 Allocate map (also create object)
- obj1 = data[1];
- obj2 = data[2];
- type = data[3];
- addr = data[6];
- VG_(message) (Vg_DebugMsg,
- "create mapped object 0x%08x:0x%08x type=0x%08x 0x%08lx\n",
- obj1, obj2, type, addr);
- if (addr == 0)
- break;
-
- region = get_nvidia_mapping(addr);
- if (region)
- {
- region->data1 = obj1;
- region->data2 = obj2;
- }
-#if 0
- dumpmem("out ", data[2], 0x40);
-#endif
- break;
- // 0x29 seems to destroy/deallocate
- case 0xc0104629:
- obj1 = data[1];
- obj2 = data[2];
- /// XXX some currently mapped memory might be orphaned
-
- {
- Addr addr1 = release_nvidia_mapping2(obj1, obj2);
- if ((void *)addr1 != NULL)
- VG_(message) (Vg_DebugMsg, "deallocate map 0x%08x:0x%08x %p\n",
- obj1, obj2, (void *)addr1);
- }
- break;
- // 0x2a read stuff from video ram?
- // i 3 pre 2a: c1d00046 c1d00046 02000014 00000000 be88a948 00000000 00000080 00000000
- case 0xc020462a:
- dumpmem("out ", mmt_2x4to8(data[5], data[4]), mmt_2x4to8(data[7], data[6]));
-
- if (data[2] == 0x10000002)
- {
- UInt *addr2 = (*(UInt **) (&data[4]));
- dumpmem("out2 ", addr2[2], 0x3c);
- }
- break;
- // 0x37 read configuration parameter
- case 0xc0204638:
- dumpmem("out", data[4], data[6]);
- break;
- case 0xc0204637:
- {
- UInt *addr2 = (*(UInt **) (&data[4]));
- dumpmem("out", data[4], data[6]);
- if (data[2] == 0x14c && addr2[2])
- /// List supported object types
- dumpmem("out2 ", addr2[2], addr2[0] * 4);
- }
- break;
- case 0xc0384657: // map GPU address
- VG_(message) (Vg_DebugMsg,
- "gpu map 0x%08x:0x%08x:0x%08x, addr 0x%08x, len 0x%08x\n",
- data[1], data[2], data[3], data[10], data[6]);
- break;
- case 0xc0284658: // unmap GPU address
- VG_(message) (Vg_DebugMsg,
- "gpu unmap 0x%08x:0x%08x:0x%08x addr 0x%08x\n", data[1],
- data[2], data[3], data[6]);
- break;
- case 0xc0304654: // create DMA object [3] is some kind of flags, [6] is an offset?
- VG_(message) (Vg_DebugMsg,
- "create dma object 0x%08x, type 0x%08x, parent 0x%08x\n",
- data[1], data[2], data[5]);
- break;
- case 0xc0104659: // bind
- VG_(message) (Vg_DebugMsg, "bind 0x%08x 0x%08x\n", data[1], data[2]);
- break;
- //case 0xc01c4634:
- // dumpmem("out", data[4], 0x40);
- // break;
- // to c1d00046 c1d00046 02000014 00000000, from be88a948 00000000, size 00000080 00000000
- // 2b: c1d00046 5c000001 5c000009 0000506f be88a888 00000000 00000000 00000000
- // same, but other way around?
- // i 5 pre 37: c1d00046 5c000001 0000014c 00000000 be88a9c8 00000000 00000010 00000000
-
- // 0x23 create first object??
- // 0x2a method call? args/in/out depend
- // 0x2b object creation
- // c1d00046 beef0003 beef0028 0000307e
- // 0x32 gets some value
- // 0x37 read from GPU object? seems a read, not a write
- // 0x4a memory allocation
- // 0x4d after opening /dev/nvidiaX
- // 0xd2 version id check
- // 0x22 initialize (get context)
- // 0x54 bind? 0xc0304654
- // 0x57 map to card 0xc0384657
- // 0x58 unmap from card 0xc0284658
- // 0xca ??
-
- // These have external pointer:
- // 0x2a (offset 0x10, size 0x18)
- // 0x2b (offset 0x10, no size specified)
- // 0x37 (offset 0x10, size 0x18)
- // 0x38 (offset 0x10, size 0x18)
- }
+ (mmt_last_region - idx) * sizeof(struct mmt_mmap_data));
+ VG_(memset)(&mmt_mmaps[mmt_last_region--], 0, sizeof(struct mmt_mmap_data));
}
static void post_open(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
@@ -1509,13 +959,7 @@ static void post_open(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
}
}
- if (trace_nvidia_ioctls)
- {
- if (VG_(strcmp)(path, "/dev/nvidiactl") == 0)
- FD_SET(res._val, &nvidiactl_fds);
- else if (VG_(strncmp)(path, "/dev/nvidia", 11) == 0)
- FD_SET(res._val, &nvidia0_fds);
- }
+ mmt_nv_ioctl_post_open(args, res);
}
static void post_close(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
@@ -1533,11 +977,7 @@ static void post_close(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
}
}
- if (trace_nvidia_ioctls)
- {
- FD_CLR(fd, &nvidiactl_fds);
- FD_CLR(fd, &nvidia0_fds);
- }
+ mmt_nv_ioctl_post_close(args);
}
static void post_mmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res, int offset_unit)
@@ -1570,34 +1010,15 @@ static void post_mmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res, int off
}
}
- if (trace_nvidia_ioctls && FD_ISSET(fd, &nvidia0_fds))
- {
- for (i = 0; i <= last_region; ++i)
- {
- region = &mmt_mmaps[i];
- if (region->id > 0 &&
- (region->fd == fd || region->fd == 0) && //region->fd=0 when created from get_nvidia_mapping
- region->offset == offset * offset_unit)
- {
- region->fd = fd;
- region->start = (Addr)start;
- region->end = (Addr)(((char *)start) + len);
- VG_(message) (Vg_DebugMsg,
- "got new mmap for 0x%08lx:0x%08lx at %p, len: 0x%08lx, offset: 0x%llx, serial: %d\n",
- region->data1, region->data2, (void *)region->start, len,
- region->offset, region->id);
- return;
- }
- }
- }
+ mmt_nv_ioctl_post_mmap(args, res, offset_unit);
- if (last_region + 1 >= MAX_REGIONS)
+ if (mmt_last_region + 1 >= MMT_MAX_REGIONS)
{
VG_(message)(Vg_UserMsg, "not enough space for new mmap!\n");
return;
}
- region = &mmt_mmaps[++last_region];
+ region = &mmt_mmaps[++mmt_last_region];
region->fd = fd;
region->id = current_item++;
@@ -1620,7 +1041,7 @@ static void post_munmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
if (res._isError)
return;
- for (i = 0; i <= last_region; ++i)
+ for (i = 0; i <= mmt_last_region; ++i)
{
region = &mmt_mmaps[i];
if (region->start == (Addr)start)
@@ -1629,7 +1050,7 @@ static void post_munmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
"removed mmap 0x%lx:0x%lx for: %p, len: 0x%08lx, offset: 0x%llx, serial: %d\n",
region->data1, region->data2, (void *)region->start,
region->end - region->start, region->offset, region->id);
- free_region(i);
+ mmt_free_region(i);
return;
}
}
@@ -1647,7 +1068,7 @@ static void post_mremap(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
if (res._isError)
return;
- for (i = 0; i <= last_region; ++i)
+ for (i = 0; i <= mmt_last_region; ++i)
{
region = &mmt_mmaps[i];
if (region->start == (Addr)start)
@@ -1669,7 +1090,7 @@ static void post_syscall(ThreadId tid, UInt syscallno, UWord *args,
UInt nArgs, SysRes res)
{
if (syscallno == __NR_ioctl)
- post_ioctl(tid, args, nArgs);
+ mmt_nv_ioctl_post(args);
else if (syscallno == __NR_open)
post_open(tid, args, nArgs, res);
else if (syscallno == __NR_close)
@@ -1706,8 +1127,8 @@ static void mmt_pre_clo_init(void)
for (i = 0; i < MAX_TRACE_FILES; ++i)
FD_ZERO(&trace_files[i].fds);
- FD_ZERO(&nvidiactl_fds);
- FD_ZERO(&nvidia0_fds);
+
+ mmt_nv_ioctl_pre_clo_init();
}
VG_DETERMINE_INTERFACE_VERSION(mmt_pre_clo_init)
diff --git a/mmt/mmt_main.h b/mmt/mmt_main.h
new file mode 100644
index 00000000..410c3a71
--- /dev/null
+++ b/mmt/mmt_main.h
@@ -0,0 +1,24 @@
+#ifndef MMT_MAIN_H_
+#define MMT_MAIN_H_
+
+#include "pub_tool_basics.h"
+
+#define MMT_MAX_REGIONS 100
+
+struct mmt_mmap_data {
+ Addr start;
+ Addr end;
+ int fd;
+ Off64T offset;
+ UInt id;
+ UWord data1;
+ UWord data2;
+};
+
+extern struct mmt_mmap_data mmt_mmaps[MMT_MAX_REGIONS];
+extern int mmt_last_region;
+extern UInt current_item;
+
+void mmt_free_region(int idx);
+
+#endif /* MMT_MAIN_H_ */
diff --git a/mmt/mmt_nv_ioctl.c b/mmt/mmt_nv_ioctl.c
new file mode 100644
index 00000000..4e7170ef
--- /dev/null
+++ b/mmt/mmt_nv_ioctl.c
@@ -0,0 +1,654 @@
+/*
+ Copyright (C) 2006 Dave Airlie
+ Copyright (C) 2007 Wladimir J. van der Laan
+ Copyright (C) 2009 Marcin Slusarz <marcin.slusarz@gmail.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+#include "mmt_nv_ioctl.h"
+#include "mmt_main.h"
+#include "pub_tool_vki.h"
+#include "pub_tool_libcprint.h"
+#include "pub_tool_libcfile.h"
+#include "pub_tool_libcbase.h"
+#include "pub_tool_libcproc.h"
+
+#include <sys/select.h>
+#include <fcntl.h>
+#include <string.h>
+
+static fd_set nvidiactl_fds;
+static fd_set nvidia0_fds;
+
+int mmt_trace_nvidia_ioctls = False;
+int mmt_trace_marks = False;
+static int trace_mark_fd;
+static int trace_mark_cnt = 0;
+
+static inline unsigned long long mmt_2x4to8(UInt h, UInt l)
+{
+ return (((unsigned long long)h) << 32) | l;
+}
+
+void mmt_nv_ioctl_fini()
+{
+ if (mmt_trace_marks) {
+ VG_(close)(trace_mark_fd);
+ }
+}
+
+void mmt_nv_ioctl_post_clo_init(void)
+{
+ if (mmt_trace_marks) {
+ SysRes ff;
+ ff = VG_(open)("/sys/kernel/debug/tracing/trace_marker", O_WRONLY, 0777);
+ if (ff._isError) {
+ VG_(message) (Vg_UserMsg, "Cannot open marker file!\n");
+ mmt_trace_marks = 0;
+ }
+ trace_mark_fd = ff._val;
+ }
+}
+
+static struct mmt_mmap_data *get_nvidia_mapping(Off64T offset)
+{
+ struct mmt_mmap_data *region;
+ int i;
+ for (i = 0; i <= mmt_last_region; ++i)
+ {
+ region = &mmt_mmaps[i];
+ if (FD_ISSET(region->fd, &nvidia0_fds))
+ if (region->offset == offset)
+ return region;
+ }
+
+ if (mmt_last_region + 1 >= MMT_MAX_REGIONS)
+ {
+ VG_(message)(Vg_UserMsg, "no space for new mapping!\n");
+ return NULL;
+ }
+
+ region = &mmt_mmaps[++mmt_last_region];
+ region->id = current_item++;
+ region->fd = 0;
+ region->offset = offset;
+ return region;
+}
+
+
+static Addr release_nvidia_mapping(Off64T offset)
+{
+ int i;
+ for (i = 0; i <= mmt_last_region; ++i)
+ {
+ struct mmt_mmap_data *region = &mmt_mmaps[i];
+ if (FD_ISSET(region->fd, &nvidia0_fds))
+ if (region->offset == offset)
+ {
+ Addr addr = region->start;
+ mmt_free_region(i);
+ return addr;
+ }
+ }
+ return 0;
+}
+
+static Addr release_nvidia_mapping2(UWord data1, UWord data2)
+{
+ int i;
+ for (i = 0; i <= mmt_last_region; ++i)
+ {
+ struct mmt_mmap_data *region = &mmt_mmaps[i];
+ if (FD_ISSET(region->fd, &nvidia0_fds))
+ if (region->data1 == data1 && region->data2 == data2)
+ {
+ Addr addr = region->start;
+ mmt_free_region(i);
+ return addr;
+ }
+ }
+ return 0;
+}
+
+static void dumpmem(char *s, Addr addr, UInt size)
+{
+ char line[4096];
+ int idx = 0;
+ line[0] = 0;
+
+ UInt i;
+ if (!addr || (addr & 0xffff0000) == 0xbeef0000)
+ return;
+
+ size = size / 4;
+
+ for (i = 0; i < size; ++i)
+ {
+ if (idx + 11 >= 4095)
+ break;
+ VG_(sprintf) (line + idx, "0x%08x ", ((UInt *) addr)[i]);
+ idx += 11;
+ }
+ VG_(message) (Vg_DebugMsg, "%s%s\n", s, line);
+}
+
+void mmt_nv_ioctl_post_open(UWord *args, SysRes res)
+{
+ const char *path = (const char *)args[0];
+
+ if (mmt_trace_nvidia_ioctls)
+ {
+ if (VG_(strcmp)(path, "/dev/nvidiactl") == 0)
+ FD_SET(res._val, &nvidiactl_fds);
+ else if (VG_(strncmp)(path, "/dev/nvidia", 11) == 0)
+ FD_SET(res._val, &nvidia0_fds);
+ }
+}
+
+void mmt_nv_ioctl_post_close(UWord *args)
+{
+ int fd = (int)args[0];
+
+ if (mmt_trace_nvidia_ioctls)
+ {
+ FD_CLR(fd, &nvidiactl_fds);
+ FD_CLR(fd, &nvidia0_fds);
+ }
+}
+
+void mmt_nv_ioctl_post_mmap(UWord *args, SysRes res, int offset_unit)
+{
+ void *start = (void *)args[0];
+ unsigned long len = args[1];
+// unsigned long prot = args[2];
+// unsigned long flags = args[3];
+ unsigned long fd = args[4];
+ unsigned long offset = args[5];
+ int i;
+ struct mmt_mmap_data *region;
+
+ start = (void *)res._val;
+
+ if (mmt_trace_nvidia_ioctls && FD_ISSET(fd, &nvidia0_fds))
+ {
+ for (i = 0; i <= mmt_last_region; ++i)
+ {
+ region = &mmt_mmaps[i];
+ if (region->id > 0 &&
+ (region->fd == fd || region->fd == 0) && //region->fd=0 when created from get_nvidia_mapping
+ region->offset == offset * offset_unit)
+ {
+ region->fd = fd;
+ region->start = (Addr)start;
+ region->end = (Addr)(((char *)start) + len);
+ VG_(message) (Vg_DebugMsg,
+ "got new mmap for 0x%08lx:0x%08lx at %p, len: 0x%08lx, offset: 0x%llx, serial: %d\n",
+ region->data1, region->data2, (void *)region->start, len,
+ region->offset, region->id);
+ return;
+ }
+ }
+ }
+}
+
+static struct object_type {
+ UInt id; // type id
+ char *name; // some name
+ UInt cargs; // number of constructor args (uint32)
+} object_types[] =
+{
+ {0x0000, "NV_CONTEXT_NEW", 0},
+
+ {0x0004, "NV_PTIMER", 0},
+
+ {0x0041, "NV_CONTEXT", 0},
+
+ {0x502d, "NV50_2D", 0},
+ {0x902d, "NVC0_2D", 0},
+
+ {0x5039, "NV50_M2MF", 0},
+ {0x9039, "NVC0_M2MF", 0},
+
+ {0x9068, "NVC0_PEEPHOLE", 0},
+
+ {0x406e, "NV40_FIFO_DMA", 6},
+
+ {0x506f, "NV50_FIFO_IB", 6},
+ {0x826f, "NV84_FIFO_IB", 6},
+ {0x906f, "NVC0_FIFO_IB", 6},
+
+ {0x5070, "NV84_DISPLAY", 4},
+ {0x8270, "NV84_DISPLAY", 4},
+ {0x8370, "NVA0_DISPLAY", 4},
+ {0x8870, "NV98_DISPLAY", 4},
+ {0x8570, "NVA3_DISPLAY", 4},
+
+ {0x5072, NULL, 8},
+
+ {0x7476, "NV84_VP", 0},
+
+ {0x507a, "NV50_DISPLAY_CURSOR", 0},
+ {0x827a, "NV84_DISPLAY_CURSOR", 0},
+ {0x857a, "NVA3_DISPLAY_CURSOR", 0},
+
+ {0x507b, "NV50_DISPLAY_OVERLAY", 0},
+ {0x827b, "NV84_DISPLAY_OVERLAY", 0},
+ {0x857b, "NVA3_DISPLAY_OVERLAY", 0},
+
+ {0x507c, "NV50_DISPLAY_SYNC_FIFO", 8},
+ {0x827c, "NV84_DISPLAY_SYNC_FIFO", 8},
+ {0x837c, "NVA0_DISPLAY_SYNC_FIFO", 8},
+ {0x857c, "NVA3_DISPLAY_SYNC_FIFO", 8},
+
+ {0x507d, "NV50_DISPLAY_MASTER_FIFO", 0},
+ {0x827d, "NV84_DISPLAY_MASTER_FIFO", 0},
+ {0x837d, "NVA0_DISPLAY_MASTER_FIFO", 0},
+ {0x887d, "NV98_DISPLAY_MASTER_FIFO", 0},
+ {0x857d, "NVA3_DISPLAY_MASTER_FIFO", 0},
+
+ {0x307e, "NV30_PEEPHOLE", 0},
+
+ {0x507e, "NV50_DISPLAY_OVERLAY_FIFO", 8},
+ {0x827e, "NV84_DISPLAY_OVERLAY_FIFO", 8},
+ {0x837e, "NVA0_DISPLAY_OVERLAY_FIFO", 8},
+ {0x857e, "NVA3_DISPLAY_OVERLAY_FIFO", 8},
+
+ {0x0080, "NV_DEVICE", 1},
+ {0x2080, "NV_SUBDEVICE_0", 0},
+ {0x2081, "NV_SUBDEVICE_1", 0},
+ {0x2082, "NV_SUBDEVICE_2", 0},
+ {0x2083, "NV_SUBDEVICE_3", 0},
+
+ {0x5097, "NV50_3D", 0},
+ {0x8297, "NV84_3D", 0},
+ {0x8397, "NVA0_3D", 0},
+ {0x8597, "NVA3_3D", 0},
+ {0x8697, "NVAF_3D", 0},
+ {0x9097, "NVC0_3D", 0},
+
+ {0x74b0, "NV84_BSP", 0},
+
+ {0x88b1, "NV98_BSP", 0},
+ {0x85b1, "NVA3_BSP", 0},
+ {0x86b1, "NVAF_BSP", 0},
+ {0x90b1, "NVC0_BSP", 0},
+
+ {0x88b2, "NV98_VP", 0},
+ {0x85b2, "NVA3_VP", 0},
+ {0x90b2, "NVC0_VP", 0},
+
+ {0x88b3, "NV98_PPP", 0},
+ {0x85b3, "NVA3_PPP", 0},
+ {0x90b3, "NVC0_PPP", 0},
+
+ {0x88b4, "NV98_CRYPT", 0},
+
+ {0x85b5, "NVA3_COPY", 0},
+ {0x90b5, "NVC0_COPY0", 0},
+
+ {0x50c0, "NV50_COMPUTE", 0},
+ {0x85c0, "NVA3_COMPUTE", 0},
+ {0x90c0, "NVC0_COMPUTE", 0},
+
+ {0x74c1, "NV84_CRYPT", 0},
+
+ {0x50e0, "NV50_PGRAPH", 0},
+ {0x50e2, "NV50_PFIFO", 0},
+};
+
+static struct object_type *find_objtype(UInt id)
+{
+ int i;
+ int n = sizeof(object_types) / sizeof(struct object_type);
+
+ for (i = 0; i < n; ++i)
+ if (object_types[i].id == id)
+ return &object_types[i];
+
+ return NULL;
+}
+
+void mmt_nv_ioctl_pre(UWord *args)
+{
+ int fd = args[0];
+ UInt id = args[1];
+ UInt *data = (UInt *) args[2];
+ UWord addr;
+ UInt obj1, obj2, size;
+ int i;
+
+ if (!FD_ISSET(fd, &nvidiactl_fds) && !FD_ISSET(fd, &nvidia0_fds))
+ return;
+
+ if (mmt_trace_marks) {
+ char buf[50];
+ VG_(snprintf)(buf, 50, "VG-%d-%d-PRE\n", VG_(getpid)(), trace_mark_cnt);
+ VG_(write)(trace_mark_fd, buf, VG_(strlen)(buf));
+ VG_(message)(Vg_DebugMsg, "MARK: %s", buf);
+ }
+
+ if ((id & 0x0000FF00) == 0x4600)
+ {
+ char line[4096];
+ int idx = 0;
+
+ size = ((id & 0x3FFF0000) >> 16) / 4;
+ VG_(sprintf) (line, "pre_ioctl: fd:%d, id:0x%02x (full:0x%x), data: ", fd, id & 0xFF, id);
+ idx = strlen(line);
+
+ for (i = 0; i < size; ++i)
+ {
+ if (idx + 11 >= 4095)
+ break;
+ VG_(sprintf) (line + idx, "0x%08x ", data[i]);
+ idx += 11;
+ }
+ VG_(message) (Vg_DebugMsg, "%s\n", line);
+ }
+ else
+ VG_(message)(Vg_DebugMsg, "pre_ioctl, fd: %d, wrong id:0x%x\n", fd, id);
+
+ switch (id)
+ {
+ // 0x23
+ // c1d00041 5c000001 00000080 00000000 00000000 00000000 00000000 00000000
+ // c1d0004a beef0003 000000ff 00000000 04fe8af8 00000000 00000000 00000000
+ case 0xc0204623:
+ obj1 = data[1];
+ VG_(message) (Vg_DebugMsg, "create device object 0x%08x\n", obj1);
+
+ // argument can be a string (7:0, indicating the bus number), but only if
+ // argument is 0xff
+ dumpmem("in ", data[4], 0x3C);
+
+ break;
+ // 0x37 read stuff from video ram?
+ //case 0xc0204637:
+ case 0xc0204638:
+ dumpmem("in ", data[4], data[6]);
+ break;
+#if 1
+ case 0xc0204637:
+ {
+ //UInt *addr2;
+ dumpmem("in ", data[4], data[6]);
+
+ //addr2 = (*(UInt **) (&data[4]));
+ //if(data[2]==0x14c && addr2[2])
+ // dumpmem("in2 ", addr2[2], 0x40);
+ break;
+ }
+#endif
+ case 0xc020462a:
+ VG_(message) (Vg_DebugMsg, "call method 0x%08x:0x%08x\n", data[1], data[2]);
+ dumpmem("in ", mmt_2x4to8(data[5], data[4]), mmt_2x4to8(data[7], data[6]));
+ // 0x10000002
+ // word 2 is an address
+ // what is there?
+ if (data[2] == 0x10000002)
+ {
+ UInt *addr2 = (*(UInt **) (&data[4]));
+ dumpmem("in2 ", addr2[2], 0x3c);
+ }
+ break;
+
+ case 0xc040464d:
+ VG_(message) (Vg_DebugMsg, "in %s\n", *(char **) (&data[6]));
+ break;
+ case 0xc028465e:
+ {
+ // Copy data from mem to GPU
+#if 0
+ SysRes ff;
+ ff = VG_(open) ("dump5e", O_CREAT | O_WRONLY | O_TRUNC, 0777);
+ if (!ff.isError)
+ {
+ VG_(write) (ff.res, (void *) data[6], 0x01000000);
+ VG_(close) (ff.res);
+ }
+#endif
+ break;
+ }
+ case 0xc0104629:
+ obj1 = data[1];
+ obj2 = data[2];
+ VG_(message) (Vg_DebugMsg, "destroy object 0x%08x:0x%08x\n", obj1, obj2);
+ break;
+ case 0xc020462b:
+ {
+ struct object_type *objtype;
+ char *name = "???";
+ obj1 = data[1];
+ obj2 = data[2];
+ addr = data[3];
+ objtype = find_objtype(addr);
+ if (objtype && objtype->name)
+ name = objtype->name;
+ VG_(message) (Vg_DebugMsg,
+ "create gpu object 0x%08x:0x%08x type 0x%04lx (%s)\n",
+ obj1, obj2, addr, name);
+ if (data[4])
+ {
+ if (objtype)
+ dumpmem("in ", mmt_2x4to8(data[5], data[4]), objtype->cargs * 4);
+ else
+ dumpmem("in ", mmt_2x4to8(data[5], data[4]), 0x40);
+ }
+
+ break;
+ }
+ case 0xc014462d:
+ obj1 = data[1];
+ obj2 = data[2];
+ addr = data[3];
+ VG_(message) (Vg_DebugMsg,
+ "create driver object 0x%08x:0x%08x type 0x%04lx\n", obj1, obj2, addr);
+ break;
+
+ }
+}
+
+void mmt_nv_ioctl_post(UWord *args)
+{
+ int fd = args[0];
+ UInt id = args[1];
+ UInt *data = (UInt *) args[2];
+ UWord addr;
+ UInt obj1, obj2, size, type;
+ int i;
+ struct mmt_mmap_data *region;
+
+ if (!FD_ISSET(fd, &nvidiactl_fds) && !FD_ISSET(fd, &nvidia0_fds))
+ return;
+
+ if (mmt_trace_marks) {
+ char buf[50];
+ VG_(snprintf)(buf, 50, "VG-%d-%d-POST\n", VG_(getpid)(), trace_mark_cnt++);
+ VG_(write)(trace_mark_fd, buf, VG_(strlen)(buf));
+ VG_(message)(Vg_DebugMsg, "MARK: %s", buf);
+ }
+
+ if ((id & 0x0000FF00) == 0x4600)
+ {
+ char line[4096];
+ int idx = 0;
+
+ size = ((id & 0x3FFF0000) >> 16) / 4;
+ VG_(sprintf) (line, "post_ioctl: fd:%d, id:0x%02x (full:0x%x), data: ", fd, id & 0xFF, id);
+ idx = strlen(line);
+
+ for (i = 0; i < size; ++i)
+ {
+ if (idx + 11 >= 4095)
+ break;
+ VG_(sprintf) (line + idx, "0x%08x ", data[i]);
+ idx += 11;
+ }
+ VG_(message) (Vg_DebugMsg, "%s\n", line);
+ }
+ else
+ VG_(message)(Vg_DebugMsg, "post_ioctl, fd: %d, wrong id:0x%x\n", fd, id);
+
+ switch (id)
+ {
+ // NVIDIA
+ case 0xc00c4622: // Initialize
+ obj1 = data[0];
+ VG_(message) (Vg_DebugMsg, "created context object 0x%08x\n", obj1);
+ break;
+
+ case 0xc0204623:
+ dumpmem("out", data[4], 0x3C);
+ break;
+
+ case 0xc030464e: // Allocate map for existing object
+ obj1 = data[1];
+ obj2 = data[2];
+ addr = data[8];
+ VG_(message) (Vg_DebugMsg, "allocate map 0x%08x:0x%08x 0x%08lx\n", obj1, obj2, addr);
+
+ region = get_nvidia_mapping(addr);
+ if (region)
+ {
+ region->data1 = obj1;
+ region->data2 = obj2;
+ }
+
+ break;
+ case 0xc020464f: // Deallocate map for existing object
+ obj1 = data[1];
+ obj2 = data[2];
+ addr = data[4];
+ /// XXX some currently mapped memory might be orphaned
+
+ if (release_nvidia_mapping(addr))
+ VG_(message) (Vg_DebugMsg, "deallocate map 0x%08x:0x%08x 0x%08lx\n", obj1, obj2, addr);
+
+ break;
+ case 0xc0304627: // 0x27 Allocate map (also create object)
+ obj1 = data[1];
+ obj2 = data[2];
+ type = data[3];
+ addr = data[6];
+ VG_(message) (Vg_DebugMsg,
+ "create mapped object 0x%08x:0x%08x type=0x%08x 0x%08lx\n",
+ obj1, obj2, type, addr);
+ if (addr == 0)
+ break;
+
+ region = get_nvidia_mapping(addr);
+ if (region)
+ {
+ region->data1 = obj1;
+ region->data2 = obj2;
+ }
+#if 0
+ dumpmem("out ", data[2], 0x40);
+#endif
+ break;
+ // 0x29 seems to destroy/deallocate
+ case 0xc0104629:
+ obj1 = data[1];
+ obj2 = data[2];
+ /// XXX some currently mapped memory might be orphaned
+
+ {
+ Addr addr1 = release_nvidia_mapping2(obj1, obj2);
+ if ((void *)addr1 != NULL)
+ VG_(message) (Vg_DebugMsg, "deallocate map 0x%08x:0x%08x %p\n",
+ obj1, obj2, (void *)addr1);
+ }
+ break;
+ // 0x2a read stuff from video ram?
+ // i 3 pre 2a: c1d00046 c1d00046 02000014 00000000 be88a948 00000000 00000080 00000000
+ case 0xc020462a:
+ dumpmem("out ", mmt_2x4to8(data[5], data[4]), mmt_2x4to8(data[7], data[6]));
+
+ if (data[2] == 0x10000002)
+ {
+ UInt *addr2 = (*(UInt **) (&data[4]));
+ dumpmem("out2 ", addr2[2], 0x3c);
+ }
+ break;
+ // 0x37 read configuration parameter
+ case 0xc0204638:
+ dumpmem("out", data[4], data[6]);
+ break;
+ case 0xc0204637:
+ {
+ UInt *addr2 = (*(UInt **) (&data[4]));
+ dumpmem("out", data[4], data[6]);
+ if (data[2] == 0x14c && addr2[2])
+ /// List supported object types
+ dumpmem("out2 ", addr2[2], addr2[0] * 4);
+ }
+ break;
+ case 0xc0384657: // map GPU address
+ VG_(message) (Vg_DebugMsg,
+ "gpu map 0x%08x:0x%08x:0x%08x, addr 0x%08x, len 0x%08x\n",
+ data[1], data[2], data[3], data[10], data[6]);
+ break;
+ case 0xc0284658: // unmap GPU address
+ VG_(message) (Vg_DebugMsg,
+ "gpu unmap 0x%08x:0x%08x:0x%08x addr 0x%08x\n", data[1],
+ data[2], data[3], data[6]);
+ break;
+ case 0xc0304654: // create DMA object [3] is some kind of flags, [6] is an offset?
+ VG_(message) (Vg_DebugMsg,
+ "create dma object 0x%08x, type 0x%08x, parent 0x%08x\n",
+ data[1], data[2], data[5]);
+ break;
+ case 0xc0104659: // bind
+ VG_(message) (Vg_DebugMsg, "bind 0x%08x 0x%08x\n", data[1], data[2]);
+ break;
+ //case 0xc01c4634:
+ // dumpmem("out", data[4], 0x40);
+ // break;
+ // to c1d00046 c1d00046 02000014 00000000, from be88a948 00000000, size 00000080 00000000
+ // 2b: c1d00046 5c000001 5c000009 0000506f be88a888 00000000 00000000 00000000
+ // same, but other way around?
+ // i 5 pre 37: c1d00046 5c000001 0000014c 00000000 be88a9c8 00000000 00000010 00000000
+
+ // 0x23 create first object??
+ // 0x2a method call? args/in/out depend
+ // 0x2b object creation
+ // c1d00046 beef0003 beef0028 0000307e
+ // 0x32 gets some value
+ // 0x37 read from GPU object? seems a read, not a write
+ // 0x4a memory allocation
+ // 0x4d after opening /dev/nvidiaX
+ // 0xd2 version id check
+ // 0x22 initialize (get context)
+ // 0x54 bind? 0xc0304654
+ // 0x57 map to card 0xc0384657
+ // 0x58 unmap from card 0xc0284658
+ // 0xca ??
+
+ // These have external pointer:
+ // 0x2a (offset 0x10, size 0x18)
+ // 0x2b (offset 0x10, no size specified)
+ // 0x37 (offset 0x10, size 0x18)
+ // 0x38 (offset 0x10, size 0x18)
+ }
+}
+
+void mmt_nv_ioctl_pre_clo_init(void)
+{
+ FD_ZERO(&nvidiactl_fds);
+ FD_ZERO(&nvidia0_fds);
+}
diff --git a/mmt/mmt_nv_ioctl.h b/mmt/mmt_nv_ioctl.h
new file mode 100644
index 00000000..5311406f
--- /dev/null
+++ b/mmt/mmt_nv_ioctl.h
@@ -0,0 +1,22 @@
+#ifndef MMT_NVIDIA_IOCTL_H_
+#define MMT_NVIDIA_IOCTL_H_
+
+#include "pub_tool_basics.h"
+
+extern int mmt_trace_nvidia_ioctls;
+extern int mmt_trace_marks;
+
+void mmt_nv_ioctl_fini(void);
+void mmt_nv_ioctl_post_clo_init(void);
+
+void mmt_nv_ioctl_post_open(UWord *args, SysRes res);
+void mmt_nv_ioctl_post_close(UWord *args);
+
+void mmt_nv_ioctl_post_mmap(UWord *args, SysRes res, int offset_unit);
+
+void mmt_nv_ioctl_pre(UWord *args);
+void mmt_nv_ioctl_post(UWord *args);
+
+void mmt_nv_ioctl_pre_clo_init(void);
+
+#endif /* NVIDIA_IOCTL_H_ */