summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mmt/Makefile.am3
-rw-r--r--mmt/mmt_fgl_ioctl.c874
-rw-r--r--mmt/mmt_fgl_ioctl.h22
-rw-r--r--mmt/mmt_instrument.c2
-rw-r--r--mmt/mmt_main.c25
-rw-r--r--mmt/mmt_trace.c103
-rw-r--r--mmt/mmt_trace.h3
7 files changed, 1000 insertions, 32 deletions
diff --git a/mmt/Makefile.am b/mmt/Makefile.am
index d742e66b..e5e7597c 100644
--- a/mmt/Makefile.am
+++ b/mmt/Makefile.am
@@ -5,8 +5,7 @@ if VGCONF_HAVE_PLATFORM_SEC
noinst_PROGRAMS += mmt-@VGCONF_ARCH_SEC@-@VGCONF_OS@
endif
-MMT_SOURCES_COMMON = mmt_main.c mmt_nv_ioctl.c mmt_instrument.c mmt_trace.c \
- mmt_nouveau_ioctl.c
+MMT_SOURCES_COMMON = mmt_main.c mmt_fgl_ioctl.c mmt_instrument.c mmt_trace.c
mmt_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES = \
$(MMT_SOURCES_COMMON)
diff --git a/mmt/mmt_fgl_ioctl.c b/mmt/mmt_fgl_ioctl.c
new file mode 100644
index 00000000..adc74a96
--- /dev/null
+++ b/mmt/mmt_fgl_ioctl.c
@@ -0,0 +1,874 @@
+/*
+ Copyright (C) 2006 Dave Airlie
+ Copyright (C) 2007 Wladimir J. van der Laan
+ Copyright (C) 2009, 2011 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_fgl_ioctl.h"
+#include "mmt_trace.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 "pub_tool_libcassert.h"
+
+#include <stdint.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+static fd_set fglrx_fds;
+static int fglrx_fd;
+
+int mmt_trace_fglrx_ioctls = True;
+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_fgl_ioctl_fini()
+{
+ if (mmt_trace_marks) {
+ VG_(close)(trace_mark_fd);
+ }
+}
+
+void mmt_fgl_ioctl_post_clo_init(void)
+{
+ if (mmt_trace_marks) {
+ SysRes ff;
+ ff = VG_(open)("/sys/kernel/debug/tracing/trace_marker", VKI_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_fgl_mapping(Off64T offset)
+{
+ struct mmt_mmap_data *region;
+
+ region = mmt_find_region_by_fdset_offset(&fglrx_fds, offset);
+ if (region)
+ return region;
+
+ return mmt_add_region(0, 0, 0, offset, 0, 0, 0);
+}
+
+
+static Addr release_fgl_mapping(Off64T offset)
+{
+ struct mmt_mmap_data *region;
+ Addr start;
+
+ region = mmt_find_region_by_fdset_offset(&fglrx_fds, offset);
+ if (!region)
+ return 0;
+
+ start = region->start;
+ mmt_free_region(region);
+
+ return start;
+}
+
+static Addr release_fgl_mapping2(UWord data1, UWord data2)
+{
+ struct mmt_mmap_data *region;
+ Addr start;
+
+ region = mmt_find_region_by_fdset_data(&fglrx_fds, data1, data2);
+ if (!region)
+ return 0;
+
+ start = region->start;
+ mmt_free_region(region);
+
+ return start;
+}
+
+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_fgl_ioctl_post_open(UWord *args, SysRes res)
+{
+ const char *path = (const char *)args[0];
+
+ if (mmt_trace_fglrx_ioctls)
+ {
+ if (VG_(strcmp)(path, "/dev/ati/card0") == 0) {
+ FD_SET(res._val, &fglrx_fds);
+ fglrx_fd = res._val;
+ }
+ }
+}
+
+void mmt_fgl_ioctl_post_close(UWord *args)
+{
+ int fd = (int)args[0];
+
+ if (mmt_trace_fglrx_ioctls)
+ {
+ FD_CLR(fd, &fglrx_fds);
+ }
+}
+
+int mmt_fgl_ioctl_post_mmap(UWord *args, SysRes res, int offset_unit)
+{
+ Addr start = 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];
+ struct mmt_mmap_data *region;
+ struct mmt_mmap_data tmp;
+
+ if (!mmt_trace_fglrx_ioctls)
+ return 0;
+ if (!FD_ISSET(fd, &fglrx_fds))
+ return 0;
+
+ offset *= offset_unit;
+
+#if 0
+ region = mmt_find_region_by_fd_offset(fd, offset);
+ if (!region)
+ return 0;
+
+ tmp = *region;
+
+ mmt_free_region(region);
+#endif
+
+ /* region mapped through mmap are not interesting */
+#if 1
+ start = res._val;
+ region = mmt_add_region(fd, start, start + len, offset, 0, 0, 0);
+
+#if 0
+ VG_(message) (Vg_DebugMsg,
+ "fgl 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);
+#endif
+#endif
+
+ return 1;
+}
+
+#define IOC_NR(x) (((x) >> 0) & ((1 << 8) - 1))
+#define IOC_TYPE(x) (((x) >> 8) & ((1 << 8) - 1))
+#define IOC_SIZE(x) (((x) >> 16) & ((1 << 14) - 1))
+#define IOC_DIR(x) (((x) >> 30) & ((1 << 2) - 1))
+
+struct mmap_info {
+ uint64_t soffset;
+ uint64_t eoffset;
+ uint64_t flags;
+};
+#define MAX_MMAP_INFO 128
+static struct mmap_info mmap_infos[MAX_MMAP_INFO];
+static unsigned mmap_ninfos = 0;
+
+#define MAX_GPU_OFFSET 256
+static uint64_t _know_gpu_offset[MAX_GPU_OFFSET];
+static unsigned _nknow_gpu_offset = 0;
+
+#define MAX_CTX_OFFSET 256
+struct fgl_ctx_offset {
+ uint64_t offset;
+ unsigned ioctl;
+};
+static struct fgl_ctx_offset _ctx_offset[MAX_CTX_OFFSET];
+static unsigned _nctx_offset = 0;
+
+static void mmt_fgl_add_gpu_offset(uint64_t offset)
+{
+ unsigned i;
+
+ for (i = 0; i < _nknow_gpu_offset; i++) {
+ if (_know_gpu_offset[i] == offset) {
+ return;
+ }
+ }
+ if (_nknow_gpu_offset < MAX_GPU_OFFSET) {
+ _know_gpu_offset[_nknow_gpu_offset++] = offset;
+ }
+}
+
+static void mmt_fgl_dump_gpu_offset(void)
+{
+ unsigned i, j;
+ uint64_t *ptr;
+
+ VG_(message)(Vg_DebugMsg, "[GDUMP\n");
+ for (i = 0; i < _nknow_gpu_offset; i++) {
+ ptr = _know_gpu_offset[i];
+ for (j = 0; j < 8; j++) {
+ VG_(message)(Vg_DebugMsg, "gdump [0x%016llx] 0x%08x\n", &ptr[j], ptr[j]);
+ }
+ VG_(message)(Vg_DebugMsg, "--\n");
+ }
+ VG_(message)(Vg_DebugMsg, "GDUMP]\n");
+}
+
+static void mmt_read_line(Int fd, Char *line)
+{
+ unsigned i = 0;
+
+ do {
+ if (VG_(read)(fd, &line[i++], 1) == -1) {
+ line[i - 1] = 0;
+ return;
+ }
+ } while (line[i - 1] != '\n');
+ line[i] = 0;
+}
+
+static void mmt_fgl_update_mmaps(void)
+{
+ Char name[64], line[256];
+ Int fd, pid, added = 0;
+
+ pid = VG_(getpid)();
+ VG_(sprintf)(name, "/proc/%d/maps", pid);
+ fd = VG_(fd_open)(name, O_RDONLY, 0);
+ if (fd == -1) {
+ return;
+ }
+ mmt_fgl_clear_region(fglrx_fd);
+ mmap_ninfos = 0;
+// VG_(message)(Vg_DebugMsg, "MMAPS: *******************************************\n");
+ do {
+ unsigned long saddr;
+ unsigned long eaddr;
+ unsigned long offset;
+ Char *next;
+
+ line[0] = 0;
+ mmt_read_line(fd, line);
+ if (!line[0]) {
+ break;
+ }
+
+ /* parse mmap line */
+ saddr = VG_(strtoull16)(line, &next);
+ next += 1;
+ eaddr = VG_(strtoull16)(next, &next);
+ next += 6;
+ offset = VG_(strtoull16)(next, &next);
+ next += 10;
+ if (*next == 0) {
+// VG_(message)(Vg_DebugMsg, "anon: %s", line);
+ if (mmap_ninfos < MAX_MMAP_INFO) {
+ mmap_infos[mmap_ninfos].soffset = saddr;
+ mmap_infos[mmap_ninfos].eoffset = eaddr;
+ mmap_infos[mmap_ninfos].flags = 0;
+ mmap_ninfos++;
+ }
+ continue;
+ }
+
+// VG_(message)(Vg_DebugMsg, "%s", line);
+ if (line[0] && VG_(strstr)(line, "/dev/ati/card0")) {
+ struct mmt_mmap_data *region, *tmp;
+
+ tmp = mmt_find_region_by_fd_addr(saddr);
+ if (tmp == NULL) {
+#if 0
+ VG_(message)(Vg_DebugMsg, "mmaps: [0x%016llx 0x%016llx] [0x%08x 0x%08x]\n",
+ saddr, eaddr, offset, offset + (eaddr - saddr));
+#endif
+ region = mmt_add_region(fglrx_fd, saddr, eaddr, offset, 0, 1, 0);
+ added++;
+ if (mmap_ninfos < MAX_MMAP_INFO) {
+ mmap_infos[mmap_ninfos].soffset = saddr;
+ mmap_infos[mmap_ninfos].eoffset = eaddr;
+ mmap_infos[mmap_ninfos].flags = 1;
+ mmap_ninfos++;
+ }
+ }
+ }
+ } while(line[0]);
+ VG_(close)(fd);
+ if (added) {
+// mmt_fgl_scan_region(fglrx_fd);
+ }
+}
+
+static const struct mmap_info *mmt_mmap_info(uint64_t addr)
+{
+ unsigned i;
+
+ for (i = 0; i < mmap_ninfos; i++) {
+ if (addr >= mmap_infos[i].soffset && addr < mmap_infos[i].eoffset) {
+ return &mmap_infos[i];
+ }
+ }
+ return NULL;
+}
+
+static void mmt_print_line_grec(void *data, unsigned nqw, char *prefix, int maxrec, int rec, unsigned ioctl)
+{
+ uint32_t *ptr = data;
+ unsigned i;
+ char space[64];
+
+ space[0] = 0;
+ for (i = 0; i < rec; i++) {
+ space[i] = ' ';
+ space[i+1] = 0;
+ }
+ for (i = 0; i < nqw * 2; i++) {
+ VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%08x gdata\n", prefix, ioctl, space, &ptr[i], ptr[i]);
+ }
+}
+
+void fgl_add_ctx_offset(uint64_t offset, unsigned ioctl)
+{
+ unsigned i;
+
+ for (i = 0; i < _nctx_offset; i++) {
+ if (_ctx_offset[i].offset == offset) {
+ return;
+ }
+ }
+ _ctx_offset[_nctx_offset].offset = offset;
+ _ctx_offset[_nctx_offset].ioctl = ioctl;
+ _nctx_offset++;
+}
+
+static void mmt_fgl_dump_ctx_offset(void)
+{
+ unsigned i, j;
+ uint64_t *ptr;
+
+ VG_(message)(Vg_DebugMsg, "[GCTX\n");
+ for (i = 0; i < _nctx_offset; i++) {
+ ptr = _ctx_offset[i].offset;
+ for (j = 0; j < 8; j++) {
+ VG_(message)(Vg_DebugMsg, "gctx ioctl_%02x [0x%016llx] 0x%08x\n", _ctx_offset[i].ioctl, &ptr[j], ptr[j]);
+ }
+ VG_(message)(Vg_DebugMsg, "--\n");
+ }
+ VG_(message)(Vg_DebugMsg, "GCTX]\n");
+}
+
+void fgl_scan_ctx_offset(void *data, unsigned nqw, unsigned ioctl)
+{
+ const struct mmap_info *info;
+ uint64_t *ptr = data;
+ unsigned i;
+
+ for (i = 0; i < nqw; i++) {
+ info = mmt_mmap_info(ptr[i]);
+ if (info && !info->flags) {
+ fgl_add_ctx_offset(ptr[i], ioctl);
+ }
+ }
+}
+
+static void mmt_print_line_rec(void *data, unsigned nqw, char *prefix, int maxrec, int rec, unsigned ioctl)
+{
+ const struct mmap_info *info;
+ uint64_t *ptr = data;
+ unsigned i;
+ char space[64];
+
+ space[0] = 0;
+ for (i = 0; i < rec; i++) {
+ space[i] = ' ';
+ space[i+1] = 0;
+ }
+ for (i = 0; i < nqw; i++) {
+ info = mmt_mmap_info(ptr[i]);
+ if (info) {
+ switch (info->flags) {
+ case 1:
+ mmt_fgl_add_gpu_offset(ptr[i]);
+ VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%016llx gptr\n", prefix, ioctl, space, &ptr[i], ptr[i]);
+ if (rec < maxrec) mmt_print_line_grec(ptr[i], 2, prefix, maxrec, ++rec, ioctl);
+ break;
+ default:
+ VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%016llx aptr\n", prefix, ioctl, space, &ptr[i], ptr[i]);
+// if (rec < maxrec) mmt_print_line_rec(ptr[i], 8, prefix, maxrec, ++rec, ioctl);
+ break;
+ }
+ } else {
+ VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%016llx\n", prefix, ioctl, space, &ptr[i], ptr[i]);
+ }
+ }
+}
+
+static void mmt_print_line(void *data, unsigned nqw, char *prefix, int maxrec, unsigned ioctl)
+{
+ const struct mmap_info *info;
+ uint64_t *ptr = data;
+ unsigned i;
+
+ for (i = 0; i < nqw; i++) {
+ info = mmt_mmap_info(ptr[i]);
+ if (info) {
+ switch (info->flags) {
+ case 1:
+ mmt_fgl_add_gpu_offset(ptr[i]);
+ VG_(message)(Vg_DebugMsg, "%s ioctl_%02x [0x%016llx] 0x%016llx gptr\n", prefix, ioctl, &ptr[i], ptr[i]);
+ if (maxrec) mmt_print_line_grec(ptr[i], 5, prefix, maxrec, 0, ioctl);
+ break;
+ default:
+ VG_(message)(Vg_DebugMsg, "%s ioctl_%02x [0x%016llx] 0x%016llx aptr\n", prefix, ioctl, &ptr[i], ptr[i]);
+ if (maxrec) mmt_print_line_rec(ptr[i], 5, prefix, maxrec, 0, ioctl);
+ break;
+ }
+ } else {
+ VG_(message)(Vg_DebugMsg, "%s ioctl_%02x [0x%016llx] 0x%016llx\n", prefix, ioctl, &ptr[i], ptr[i]);
+ }
+ }
+}
+
+struct fglrx_ioctl_a6 {
+ uint64_t header0;
+ uint64_t args_size;
+ uint64_t *args;
+ uint64_t rets_size;
+ uint64_t *rets;
+};
+
+void mmt_fgl_ioctl_a6(void *data, unsigned size, char *prefix, unsigned post)
+{
+ static uint64_t next_gpu_addr = 0, ib_count = 0;
+ struct fglrx_ioctl_a6 *p_a6 = data;
+ const struct mmap_info *info;
+ unsigned i;
+
+#if 0
+/* header0 | always 0x30
+ * args_size | args size in byte (=0x50 only in clear operation)
+ * args | layout:
+ * [...]
+ * ((u64*)args)[1] always 0x00000002dead0000
+ * [...]
+ * ((u64*)args)[4] if args_size = 0x50 then last fglrx_ioctl_a6.rets[2] aka id1 << 32
+ * if args_size = 0x40 then last fglrx_ioctl_a6.rets[2] aka id1
+ * rets_size | rets size in byte
+ * rets | layout:
+ * ((u64*)rets)[0] unknown
+ * ((u64*)rets)[1] unknown
+ * ((u64*)rets)[2] id1 some kind of id always increasing
+ * ((u64*)rets)[3] id2 some kind of id always increasing same as [2]
+ * ((u64*)rets)[4] user space ptr to ib buffer (mmaped GPU memory)
+ */
+struct fglrx_ioctl_a6 {
+ uint64_t header0;
+ uint64_t args_size;
+ uint64_t *args;
+ uint64_t rets_size;
+ uint64_t *rets;
+};
+#endif
+#if 0
+ mmt_print_line(data, 5 + 7, prefix, 0, 0xa6);
+ mmt_print_line(p_a6->args, p_a6->args_size / 8, " args", 0, 0xa6);
+ VG_(message)(Vg_DebugMsg, "_\n");
+ mmt_print_line(p_a6->rets, p_a6->rets_size / 8, " rets", 1, 0xa6);
+#else
+ if (post && p_a6->args_size == 0x78 && p_a6->rets_size == 0x68) {
+ next_gpu_addr = p_a6->rets[4];
+ }
+ if (!post && p_a6->args_size == 0x78 && p_a6->rets_size == 0x68) {
+ info = mmt_mmap_info(next_gpu_addr);
+ if (info && p_a6->args[2] == 0x1000180200000068) {
+ unsigned ib_size = (p_a6->args[4] >> 32ULL) & 0x0000ffffULL;
+ uint32_t *ptr = next_gpu_addr;
+ VG_(message)(Vg_DebugMsg, "ib size 0x%08x from 0x%016llx\n", ib_size, p_a6->args[4]);
+ for (i = 0; i < ib_size/4; i++) {
+ VG_(message)(Vg_DebugMsg, "[%4d] [%4d] 0x%08x\n", ib_count, i, ptr[i]);
+ }
+ ib_count++;
+ }
+ }
+
+#endif
+}
+
+void mmt_fgl_ioctl_2a(void *data, unsigned size)
+{
+ uint32_t *ptr1 = ((uint64_t*)data)[3];
+ uint32_t *ptr2 = ((uint64_t*)ptr1)[0];
+ uint32_t *ptr3 = ((uint64_t*)ptr1)[1];
+ uint32_t *ptr4 = ((uint64_t*)ptr3)[0];
+ uint32_t *ptr5 = ((uint64_t*)ptr3)[1];
+ unsigned i;
+
+ VG_(message)(Vg_DebugMsg, "IOCTL_2A [0x%016llx]\n", ptr1);
+ for (i = 0; i < 8; i++) {
+ VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr1[i], ptr1[i]);
+ }
+ VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr2 [0x%016llx]\n", ptr2);
+ for (i = 0; i < 8; i++) {
+// VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr2[i], ptr2[i]);
+ }
+ VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr3 [0x%016llx]\n", ptr3);
+ for (i = 0; i < 8; i++) {
+ VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr3[i], ptr3[i]);
+ }
+ VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr4 [0x%016llx]\n", ptr4);
+ for (i = 0; i < 8; i++) {
+// VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr4[i], ptr4[i]);
+ }
+ VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr5 [0x%016llx]\n", ptr5);
+ for (i = 0; i < 8; i++) {
+ VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr5[i], ptr5[i]);
+ }
+}
+
+
+void mmt_fgl_ioctl_pre(UWord *args)
+{
+ int fd = args[0];
+ UInt id = args[1];
+ UInt *data = (UInt *) args[2];
+ unsigned io_nr, io_type, io_size, io_dir;
+ unsigned i, j;
+
+ if (!FD_ISSET(fd, &fglrx_fds))
+ return;
+
+ mmt_fgl_update_mmaps();
+ io_nr = IOC_NR(id);
+ io_type = IOC_TYPE(id);
+ io_size = IOC_SIZE(id);
+ io_dir = IOC_DIR(id);
+
+ 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 1
+// VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12);
+// VG_(message)(Vg_DebugMsg, "pre_ioctl, wrong id:0x%08x (0x%02x, 0x%02x, %4d, 0x%x) [0x%x]\n", id, io_nr, io_type, io_size, io_dir, (unsigned long long) data);
+#if 1
+ switch (io_nr) {
+#if 0
+ case 0x2a:
+ mmt_fgl_ioctl_2a(data, io_size);
+ break;
+#endif
+ case 0xa6:
+ mmt_fgl_ioctl_a6(data, io_size, "pre ", 0);
+ break;
+ default:
+// fgl_scan_ctx_offset(data, io_size/8, io_nr);
+// mmt_print_line(data, (io_size/8), "pre ", 2, io_nr);
+ break;
+ }
+#endif
+#endif
+// mmt_fgl_dump_gpu_offset();
+// mmt_fgl_dump_ctx_offset();
+}
+
+void mmt_fgl_ioctl_post(UWord *args)
+{
+ int fd = args[0];
+ UInt id = args[1];
+ UInt *data = (UInt *) args[2];
+ unsigned io_nr, io_type, io_size, io_dir;
+ unsigned i, j;
+
+ if (!FD_ISSET(fd, &fglrx_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);
+ }
+
+ io_nr = IOC_NR(id);
+ io_type = IOC_TYPE(id);
+ io_size = IOC_SIZE(id);
+ io_dir = IOC_DIR(id);
+#if 1
+// VG_(message)(Vg_DebugMsg, "post_ioctl, wrong id:0x%08x (0x%02x, 0x%02x, %4d, 0x%x) [0x%x]\n", id, io_nr, io_type, io_size, io_dir, (unsigned long long) data);
+#if 1
+ switch (io_nr) {
+#if 0
+ case 0x2a:
+ mmt_fgl_ioctl_2a(data, io_size);
+ break;
+#endif
+ case 0xa6:
+ mmt_fgl_ioctl_a6(data, io_size, "post", 1);
+ break;
+ default:
+// mmt_print_line(data, io_size/8, "post", 2, io_nr);
+ break;
+ }
+#endif
+#endif
+}
+
+void mmt_fgl_ioctl_pre_clo_init(void)
+{
+ FD_ZERO(&fglrx_fds);
+}
+
+/* STORE ********************************************************************/
+/* STORE ********************************************************************/
+/* STORE ********************************************************************/
+/* STORE ********************************************************************/
+/* STORE ********************************************************************/
+/* STORE ********************************************************************/
+
+
+VG_REGPARM(2)
+void mmt_trace_store_1(Addr addr, UWord value)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%02x\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_1_ia(Addr addr, UWord value, Addr inst_addr)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%02x\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_2(Addr addr, UWord value)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%04lx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_2_ia(Addr addr, UWord value, Addr inst_addr)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%04lx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_4(Addr addr, UWord value)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_4_ia(Addr addr, UWord value, Addr inst_addr)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+
+#ifdef MMT_64BIT
+VG_REGPARM(2)
+void mmt_trace_store_8(Addr addr, UWord value)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+VG_REGPARM(2)
+void mmt_trace_store_8_ia(Addr addr, UWord value, Addr inst_addr)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value);
+}
+#endif
+
+VG_REGPARM(2)
+void mmt_trace_store_4_4(Addr addr, UWord value1, UWord value2)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx 0x%08lx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value1, value2);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_4_4_ia(Addr addr, UWord value1, UWord value2, Addr inst_addr)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx 0x%08lx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value1, value2);
+}
+
+#ifdef MMT_64BIT
+VG_REGPARM(2)
+void mmt_trace_store_8_8(Addr addr, UWord value1, UWord value2)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx 0x%016llx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value1, value2);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_8_8_ia(Addr addr, UWord value1, UWord value2, Addr inst_addr)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx 0x%016llx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value1, value2);
+}
+#endif
+
+#ifndef MMT_64BIT
+VG_REGPARM(2)
+void mmt_trace_store_4_4_4_4(Addr addr, UWord value1, UWord value2,
+ UWord value3, UWord value4)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08llx 0x%08llx 0x%08llx 0x%08llx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value1, value2, value3, value4);
+}
+
+VG_REGPARM(2)
+void mmt_trace_store_4_4_4_4_ia(Addr addr, UWord value1, UWord value2,
+ UWord value3, UWord value4, Addr inst_addr)
+{
+ const struct mmap_info *info;
+
+ info = mmt_mmap_info(addr);
+ if (!info) {
+ return;
+ }
+
+ VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08llx 0x%08llx 0x%08llx 0x%08llx\n", info->flags ? 'g' : 'a',
+ info->soffset, info->eoffset, addr, value1, value2, value3, value4);
+}
+#endif
diff --git a/mmt/mmt_fgl_ioctl.h b/mmt/mmt_fgl_ioctl.h
new file mode 100644
index 00000000..b9ffbcf1
--- /dev/null
+++ b/mmt/mmt_fgl_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_fglrx_ioctls;
+extern int mmt_trace_marks;
+
+void mmt_fgl_ioctl_fini(void);
+void mmt_fgl_ioctl_post_clo_init(void);
+
+void mmt_fgl_ioctl_post_open(UWord *args, SysRes res);
+void mmt_fgl_ioctl_post_close(UWord *args);
+
+int mmt_fgl_ioctl_post_mmap(UWord *args, SysRes res, int offset_unit);
+
+void mmt_fgl_ioctl_pre(UWord *args);
+void mmt_fgl_ioctl_post(UWord *args);
+
+void mmt_fgl_ioctl_pre_clo_init(void);
+
+#endif /* NVIDIA_IOCTL_H_ */
diff --git a/mmt/mmt_instrument.c b/mmt/mmt_instrument.c
index a428285b..f6200e86 100644
--- a/mmt/mmt_instrument.c
+++ b/mmt/mmt_instrument.c
@@ -28,7 +28,7 @@
#include "pub_tool_libcprint.h"
#include "pub_tool_libcassert.h"
-int dump_load = True, dump_store = True;
+int dump_load = False, dump_store = False;
static maybe_unused void
__add_trace_load1_ia(IRSB *bb, IRExpr *addr, Int size, Addr inst_addr, IRExpr *val1)
diff --git a/mmt/mmt_main.c b/mmt/mmt_main.c
index 4ae9dc5a..39e9c436 100644
--- a/mmt/mmt_main.c
+++ b/mmt/mmt_main.c
@@ -32,17 +32,15 @@
#include "pub_tool_libcprint.h"
#include "pub_tool_mallocfree.h"
-#include "mmt_nv_ioctl.h"
-#include "mmt_nouveau_ioctl.h"
+#include "mmt_fgl_ioctl.h"
#include "mmt_instrument.h"
#include "mmt_trace.h"
#define TF_OPT "--mmt-trace-file="
-#define TN_OPT "--mmt-trace-nvidia-ioctls"
+#define TN_OPT "--mmt-trace-fglrx-ioctls"
#define TO_OPT "--mmt-trace-all-opens"
#define TA_OPT "--mmt-trace-all-files"
#define TM_OPT "--mmt-trace-marks"
-#define TV_OPT "--mmt-trace-nouveau-ioctls"
static Bool mmt_process_cmd_line_option(Char * arg)
{
@@ -63,7 +61,7 @@ static Bool mmt_process_cmd_line_option(Char * arg)
}
else if (VG_(strcmp)(arg, TN_OPT) == 0)
{
- mmt_trace_nvidia_ioctls = True;
+ mmt_trace_fglrx_ioctls = True;
return True;
}
else if (VG_(strcmp)(arg, TO_OPT) == 0)
@@ -81,11 +79,6 @@ static Bool mmt_process_cmd_line_option(Char * arg)
mmt_trace_marks = True;
return True;
}
- else if (VG_(strcmp)(arg, TV_OPT) == 0)
- {
- mmt_trace_nouveau_ioctls = True;
- return True;
- }
return False;
}
@@ -93,11 +86,10 @@ static Bool mmt_process_cmd_line_option(Char * arg)
static void mmt_print_usage(void)
{
VG_(printf)(" " TF_OPT "path trace loads and stores to memory mapped for\n"
- " this file (e.g. /dev/nvidia0) (you can pass \n"
+ " this file (e.g. /dev/ati/card0) (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 nvidia ioctls on /dev/nvidiactl and /dev/nvidia0\n");
- VG_(printf)(" " TV_OPT " trace nouveau ioctls on /dev/dri/cardX\n");
+ VG_(printf)(" " TN_OPT " trace fglrx ioctls on /dev/ati/card0\n");
VG_(printf)(" " TO_OPT " trace all 'open' syscalls\n");
VG_(printf)(" " TM_OPT " send mmiotrace marks before and after ioctls\n");
}
@@ -108,12 +100,12 @@ static void mmt_print_debug_usage(void)
static void mmt_fini(Int exitcode)
{
- mmt_nv_ioctl_fini();
+ mmt_fgl_ioctl_fini();
}
static void mmt_post_clo_init(void)
{
- mmt_nv_ioctl_post_clo_init();
+ mmt_fgl_ioctl_post_clo_init();
}
static void mmt_pre_clo_init(void)
@@ -137,8 +129,7 @@ static void mmt_pre_clo_init(void)
for (i = 0; i < MMT_MAX_TRACE_FILES; ++i)
FD_ZERO(&mmt_trace_files[i].fds);
- mmt_nv_ioctl_pre_clo_init();
- mmt_nouveau_ioctl_pre_clo_init();
+ mmt_fgl_ioctl_pre_clo_init();
}
VG_DETERMINE_INTERFACE_VERSION(mmt_pre_clo_init)
diff --git a/mmt/mmt_trace.c b/mmt/mmt_trace.c
index e083064d..ec821b51 100644
--- a/mmt/mmt_trace.c
+++ b/mmt/mmt_trace.c
@@ -22,8 +22,7 @@
*/
#include "mmt_trace.h"
-#include "mmt_nv_ioctl.h"
-#include "mmt_nouveau_ioctl.h"
+#include "mmt_fgl_ioctl.h"
#include "pub_tool_libcbase.h"
#include "pub_tool_libcprint.h"
@@ -31,6 +30,8 @@
#include "pub_tool_debuginfo.h"
#include "pub_tool_libcassert.h"
+#include <stdint.h>
+
#define MMT_PRINT_DATA
static struct mmt_mmap_data mmt_mmaps[MMT_MAX_REGIONS];
@@ -400,6 +401,23 @@ struct mmt_mmap_data *mmt_find_region_by_fd_offset(int fd, Off64T offset)
return fd0_region;
}
+
+struct mmt_mmap_data *mmt_find_region_by_fd_addr(Addr addr)
+{
+ int i;
+ struct mmt_mmap_data *fd0_region = NULL;
+
+ for (i = 0; i <= mmt_last_region; ++i)
+ {
+ struct mmt_mmap_data *region = &mmt_mmaps[i];
+ if (addr >= region->start && addr < region->end) {
+ return region;
+ }
+ }
+
+ return fd0_region;
+}
+
struct mmt_mmap_data *mmt_find_region_by_fdset_offset(fd_set *fds, Off64T offset)
{
int i;
@@ -672,6 +690,8 @@ static void mydescribe(Addr inst_addr, char *namestr, int len)
region->id, (unsigned int)(addr - region->start), __VA_ARGS__)
#endif
+#if 0 /* STORE */
+
VG_REGPARM(2)
void mmt_trace_store_1(Addr addr, UWord value)
{
@@ -870,6 +890,12 @@ void mmt_trace_store_4_4_4_4_ia(Addr addr, UWord value1, UWord value2,
}
#endif
+#endif /* STORE */
+
+
+
+
+
VG_REGPARM(2)
void mmt_trace_load_1(Addr addr, UWord value)
{
@@ -1072,8 +1098,7 @@ void mmt_pre_syscall(ThreadId tid, UInt syscallno, UWord *args, UInt nArgs)
{
if (syscallno == __NR_ioctl)
{
- mmt_nv_ioctl_pre(args);
- mmt_nouveau_ioctl_pre(args);
+ mmt_fgl_ioctl_pre(args);
}
}
@@ -1105,8 +1130,7 @@ static void post_open(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
}
}
- mmt_nv_ioctl_post_open(args, res);
- mmt_nouveau_ioctl_post_open(args, res);
+ mmt_fgl_ioctl_post_open(args, res);
}
static void post_close(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
@@ -1124,8 +1148,7 @@ static void post_close(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
}
}
- mmt_nv_ioctl_post_close(args);
- mmt_nouveau_ioctl_post_close(args);
+ mmt_fgl_ioctl_post_close(args);
}
static void post_mmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res, int offset_unit)
@@ -1139,11 +1162,13 @@ static void post_mmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res, int off
int i;
struct mmt_mmap_data *region;
+ start = res._val;
if (res._isError || (int)fd == -1)
return;
- start = res._val;
+//VG_(message)(Vg_DebugMsg, "untracked mmap at %p fd:%ld len: 0x%08lx, offset: 0x%llx\n", (void *)start, fd, len, offset);
+#if 1
if (!mmt_trace_all_files)
{
for(i = 0; i < MMT_MAX_TRACE_FILES; ++i)
@@ -1158,7 +1183,7 @@ static void post_mmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res, int off
}
}
- if (mmt_nv_ioctl_post_mmap(args, res, offset_unit))
+ if (mmt_fgl_ioctl_post_mmap(args, res, offset_unit))
return;
region = mmt_add_region(fd, start, start + len, offset * offset_unit, 0, 0, 0);
@@ -1166,6 +1191,7 @@ static void post_mmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res, int off
VG_(message) (Vg_DebugMsg,
"got new mmap at %p, len: 0x%08lx, offset: 0x%llx, serial: %d\n",
(void *)region->start, len, region->offset, region->id);
+#endif
}
static void post_munmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
@@ -1182,10 +1208,12 @@ static void post_munmap(ThreadId tid, UWord *args, UInt nArgs, SysRes res)
if (!region)
return;
+#if 0
VG_(message) (Vg_DebugMsg,
"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);
+#endif
mmt_free_region(region);
}
@@ -1223,8 +1251,7 @@ void mmt_post_syscall(ThreadId tid, UInt syscallno, UWord *args,
{
if (syscallno == __NR_ioctl)
{
- mmt_nv_ioctl_post(args);
- mmt_nouveau_ioctl_post(args);
+ mmt_fgl_ioctl_post(args);
}
else if (syscallno == __NR_open)
post_open(tid, args, nArgs, res);
@@ -1241,3 +1268,55 @@ void mmt_post_syscall(ThreadId tid, UInt syscallno, UWord *args,
else if (syscallno == __NR_mremap)
post_mremap(tid, args, nArgs, res);
}
+
+void mmt_fgl_clear_region(int fd)
+{
+ struct mmt_mmap_data *fd0_region = NULL;
+ int i;
+
+ for (i = 0; i <= mmt_last_region; ++i) {
+ struct mmt_mmap_data *region = &mmt_mmaps[i];
+
+ if (region->fd == fd && region->data1) {
+ mmt_free_region(region);
+ }
+ }
+}
+
+void mmt_fgl_scan_region(int fd)
+{
+ struct mmt_mmap_data *region = NULL;
+ unsigned i, j, k;
+
+ for (i = 0; i <= mmt_last_region; ++i) {
+ struct mmt_mmap_data *region = &mmt_mmaps[i];
+ if (region->fd == fd && region->data1) {
+ uint32_t *ptr = region->start;
+ unsigned size = (region->end - region->start) / 4;
+ for (j = 0; j < size; j++) {
+ if (ptr[j] == 0xc0004600) {
+ /* looks like cmd buffer */
+#if 1
+ VG_(message)(Vg_DebugMsg, "ib: ---------------------------------------------------------\n");
+ for (k = 0; k < 16; k++) {
+ VG_(message)(Vg_DebugMsg, "IB [0x%016llx 0x%08llx [0x%08x 0x%08x]] 0x%08x\n",
+ &ptr[j + k - 325], region->offset + (j + k - 325) * 4,
+ region->offset, region->offset + size * 4,
+ ptr[j + k - 325]);
+ }
+ VG_(message)(Vg_DebugMsg, "[...]\n");
+#endif
+ for (k = 0; k < 16; k++) {
+ VG_(message)(Vg_DebugMsg, "IB [0x%016llx 0x%08llx [0x%08x 0x%08x]] 0x%08x\n",
+ &ptr[j + k], region->offset + (j + k) * 4,
+ region->offset, region->offset + size * 4,
+ ptr[j + k]);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+
diff --git a/mmt/mmt_trace.h b/mmt/mmt_trace.h
index d29876bd..8f719e49 100644
--- a/mmt/mmt_trace.h
+++ b/mmt/mmt_trace.h
@@ -40,7 +40,10 @@ void mmt_free_region(struct mmt_mmap_data *m);
struct mmt_mmap_data *mmt_add_region(int fd, Addr start, Addr end,
Off64T offset, UInt id, UWord data1, UWord data2);
+void mmt_fgl_clear_region(int fd);
+void mmt_fgl_scan_region(int fd);
struct mmt_mmap_data *mmt_find_region_by_fd_offset(int fd, Off64T offset);
+struct mmt_mmap_data *mmt_find_region_by_fd_addr(Addr addr);
struct mmt_mmap_data *mmt_find_region_by_fdset_offset(fd_set *fds, Off64T offset);
struct mmt_mmap_data *mmt_find_region_by_fdset_data(fd_set *fds, UWord data1, UWord data2);