diff options
author | John Doe <glisse@dhcp-189-215.bos.redhat.com> | 2012-07-02 22:40:02 -0400 |
---|---|---|
committer | John Doe <glisse@dhcp-189-215.bos.redhat.com> | 2012-07-02 22:40:02 -0400 |
commit | 7d0316c1f46e6bde913d2bf5395f4fa8d36684c5 (patch) | |
tree | c0646f5537dd07ccccd567dfd1129c02fd0c33b5 | |
parent | 7992d6429f5a1c685c932189fbb5807669bde35b (diff) |
-rw-r--r-- | mmt/Makefile.am | 3 | ||||
-rw-r--r-- | mmt/mmt_fgl_ioctl.c | 874 | ||||
-rw-r--r-- | mmt/mmt_fgl_ioctl.h | 22 | ||||
-rw-r--r-- | mmt/mmt_instrument.c | 2 | ||||
-rw-r--r-- | mmt/mmt_main.c | 25 | ||||
-rw-r--r-- | mmt/mmt_trace.c | 103 | ||||
-rw-r--r-- | mmt/mmt_trace.h | 3 |
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); |