static void dump_object_tree(struct gpu_object *obj, int level, struct gpu_object *highlight) { int i, indent_level = level * 4 + 2; mmt_log("%s", ""); if (obj == highlight) { mmt_log_cont("%s", "*"); indent_level--; } for (i = 0; i < indent_level; ++i) mmt_log_cont("%s", " "); // mmt_log_cont("cid: 0x%08x, ", obj->cid); mmt_log_cont("handle: 0x%08x", obj->handle); describe_nvrm_object(obj->cid, obj->handle, ""); if (obj->class_ == NVRM_DEVICE_0) { struct nvrm_device *d = nvrm_dev(obj); if (d) mmt_log_cont(", chipset: 0x%x", d->chipset); } mmt_log_cont("%s\n", ""); for (i = 0; i < obj->children_space; ++i) if (obj->children_objects[i]) dump_object_tree(obj->children_objects[i], level + 1, highlight); }
void describe_nvrm_object(uint32_t cid, uint32_t handle, const char *field_name) { if (!nvrm_describe_handles) return; struct gpu_object *obj = gpu_object_find(cid, handle); if (!obj || strcmp(field_name, "cid") == 0) return; if (obj->cid == obj->handle) { mmt_log_cont(" [cid]%s", ""); return; } if (obj->class_ == 0xffffffff) { mmt_log_cont(" [class: ?%s]", ""); return; } const char *name = nvrm_get_class_name(obj->class_); if (name) mmt_log_cont(" [class: 0x%04x %s]", obj->class_, name); else mmt_log_cont(" [class: 0x%04x]", obj->class_); }
static void __demmt_ioctl_post(uint32_t fd, uint32_t id, struct mmt_buf *data, uint64_t ret, uint64_t err, void *state, struct mmt_memory_dump *args, int argc) { uint8_t dir, type, nr; uint16_t size; decode_ioctl_id(id, &dir, &type, &nr, &size); int print_raw = 0; enum mmt_fd_type fdtype = demmt_get_fdtype(fd); if (fdtype == FDDRM) print_raw = demmt_drm_ioctl_post(fd, id, dir, nr, size, data, ret, err, state, args, argc); else if (fdtype == FDNVIDIA) print_raw = nvrm_ioctl_post(fd, id, dir, nr, size, data, ret, err, state, args, argc); else if (fdtype == FDFGLRX) print_raw = fglrx_ioctl_post(fd, id, dir, nr, size, data, ret, err, state, args, argc); else mmt_error("ioctl 0x%x called for unknown type of file [%d, %d]\n", id, fd, fdtype); print_raw = print_raw || dump_raw_ioctl_data; if (print_raw) { mmt_log("ioctl post 0x%02x (0x%08x), fd: %d, dir: %2s, size: %4d", nr, id, fd, dir_desc[dir], size); if (ret) mmt_log_cont(", ret: 0x%" PRIx64 "", ret); if (err) mmt_log_cont(", err: 0x%" PRIx64 "", err); if (size != data->len) mmt_log_cont(", data.len: %d", data->len); ioctl_data_print(data); mmt_log_cont_nl(); } }
void demmt_memory_dump(struct mmt_memory_dump_prefix *d, struct mmt_buf *b, void *state) { // dead code, because memory dumps are passed to ioctl_pre / ioctl_post handlers int i; mmt_log("memory dump, addr: 0x%016lx, txt: \"%s\", data.len: %d, data:", d->addr, d->str.data, b->len); for (i = 0; i < b->len / 4; ++i) mmt_log_cont(" 0x%08x", ((uint32_t *)b->data)[i]); mmt_log_cont("%s", "\n"); }
static void ioctl_data_print(struct mmt_buf *data) { uint32_t i; if (!dump_raw_ioctl_data) return; mmt_log_cont(", data:%s", ""); for (i = 0; i < data->len / 4; ++i) mmt_log_cont(" 0x%08x", ((uint32_t *)data->data)[i]); }
void nvrm_munmap(uint32_t id, uint64_t mmap_addr, uint64_t len, uint64_t mmap_offset) { struct gpu_object *obj; struct cpu_mapping *cpu_mapping; for (obj = gpu_objects; obj != NULL; obj = obj->next) for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) if (cpu_mapping->cpu_addr == mmap_addr) { if (dump_sys_munmap) { if (cpu_mapping->fdtype == FDNVIDIA) { mmt_log_cont(", cid: 0x%08x, handle: 0x%08x", obj->cid, obj->handle); describe_nvrm_object(obj->cid, obj->handle, ""); } } disconnect_cpu_mapping_from_gpu_object(cpu_mapping); break; } if (dump_sys_munmap) mmt_log_cont_nl(); buffer_munmap(id); }
void nvrm_mmap(uint32_t id, uint32_t fd, uint64_t mmap_addr, uint64_t len, uint64_t mmap_offset) { struct gpu_object *obj; struct cpu_mapping *cpu_mapping; for (obj = gpu_objects; obj != NULL; obj = obj->next) for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) //can't validate fd if (cpu_mapping->mmap_offset == mmap_offset) { cpu_mapping->cpu_addr = mmap_addr; cpu_mapping->id = id; set_cpu_mapping(id, cpu_mapping); if (dump_sys_mmap) { if (cpu_mapping->fdtype == FDNVIDIA) { mmt_log_cont(", cid: 0x%08x, handle: 0x%08x", obj->cid, obj->handle); describe_nvrm_object(obj->cid, obj->handle, ""); } mmt_log_cont_nl(); } return; } if (dump_sys_mmap) mmt_log_cont_nl(); if (demmt_get_fdtype(fd) == FDNVIDIA) mmt_error("nvrm_mmap: couldn't find object/space offset: 0x%016" PRIx64 "\n", mmap_offset); buffer_mmap(id, fd, mmap_addr, len, mmap_offset); }
void __demmt_mmap2(uint64_t start, uint64_t len, uint32_t id, uint64_t offset, uint32_t fd, uint32_t prot, uint32_t flags, void *state) { if (dump_sys_mmap) { mmt_log("mmap: address: 0x%" PRIx64 ", length: 0x%08" PRIx64 ", id: %d, offset: 0x%08" PRIx64 ", fd: %d", start, len, id, offset, fd); if (dump_sys_mmap_details || prot != (PROT_READ | PROT_WRITE)) { mmt_log_cont(", prot: %s", ""); decode_mmap_prot(prot); } if (dump_sys_mmap_details || flags != MAP_SHARED) { mmt_log_cont(", flags: %s", ""); decode_mmap_flags(flags); } } nvrm_mmap(id, fd, start, len, offset); }
void decode_bitfield(uint32_t data, struct bitfield_desc *bfdesc) { uint32_t data_ = data; int printed = 0; if (!data) mmt_log_cont("%s", "NONE"); while (data && bfdesc->name) { if (data & bfdesc->mask) { mmt_log_cont("%s%s", printed ? ", " : "", bfdesc->name); data &= ~bfdesc->mask; printed = 1; } bfdesc++; } if (data) mmt_log_cont("%sUNK%x", printed ? ", " : "", data); mmt_log_cont(" (0x%x)", data_); }
void nvrm_mmap(uint32_t id, uint32_t fd, uint64_t mmap_addr, uint64_t len, uint64_t mmap_offset) { struct gpu_object *obj; struct cpu_mapping *cpu_mapping; for (obj = gpu_objects; obj != NULL; obj = obj->next) for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) //can't validate fd if (cpu_mapping->mmap_offset == mmap_offset) { cpu_mapping->cpu_addr = mmap_addr; uint32_t old_id = cpu_mapping->id; cpu_mapping->id = id; set_cpu_mapping(id, cpu_mapping); if (dump_sys_mmap) { if (cpu_mapping->fdtype == FDNVIDIA) { mmt_log_cont(", cid: 0x%08x, handle: 0x%08x", obj->cid, obj->handle); describe_nvrm_object(obj->cid, obj->handle, ""); } mmt_log_cont_nl(); } if (old_id) mmt_error("%d -> %d, mapping reuse, expect crash soon\n", old_id, id); /* * On newer blob, where mmap_offset is 0 for * all mappings (WTF?), clobber the value to * prevent the next nvrm_mmap from finding this * mapping. */ if (cpu_mapping->mmap_offset == 0) cpu_mapping->mmap_offset = -1; return; } if (dump_sys_mmap) mmt_log_cont_nl(); if (demmt_get_fdtype(fd) == FDNVIDIA) mmt_error("nvrm_mmap: couldn't find object/space offset: 0x%016" PRIx64 "\n", mmap_offset); buffer_mmap(id, fd, mmap_addr, len, mmap_offset); }
static void __demmt_ioctl_pre(uint32_t fd, uint32_t id, struct mmt_buf *data, void *state, struct mmt_memory_dump *args, int argc) { uint8_t dir, type, nr; uint16_t size; decode_ioctl_id(id, &dir, &type, &nr, &size); int print_raw = 1; enum mmt_fd_type fdtype = demmt_get_fdtype(fd); if (fdtype == FDUNK) { if (type == 0x64) // DRM fdtype = undetected_fdtype = FDDRM; else if (type == 0x46) // nvidia fdtype = undetected_fdtype = FDNVIDIA; } if (fdtype == FDDRM) print_raw = demmt_drm_ioctl_pre(fd, id, dir, nr, size, data, state, args, argc); else if (fdtype == FDNVIDIA) print_raw = nvrm_ioctl_pre(fd, id, dir, nr, size, data, state, args, argc); else if (fdtype == FDFGLRX) print_raw = fglrx_ioctl_pre(fd, id, dir, nr, size, data, state, args, argc); else mmt_error("ioctl 0x%x called for unknown type of file [%d, %d]\n", id, fd, fdtype); print_raw = print_raw || dump_raw_ioctl_data; if (print_raw) { mmt_log("ioctl pre 0x%02x (0x%08x), fd: %d, dir: %2s, size: %4d", nr, id, fd, dir_desc[dir], size); if (size != data->len) mmt_log_cont(", data.len: %d", data->len); ioctl_data_print(data); mmt_log_cont_nl(); } }
static void decode_nvrm_ioctl_env_info(struct nvrm_ioctl_env_info *s) { mmt_log_cont("pat_supported: %d\n", s->pat_supported); }
static void decode_nvrm_ioctl_check_version_str(struct nvrm_ioctl_check_version_str *s) { mmt_log_cont("cmd: %d, reply: %d, vernum: %s\n", s->cmd, s->reply, s->vernum); }