void nvrm_device_set_pb_pointer_found(struct gpu_object *obj, bool pb_pointer_found) { struct gpu_object *dev = nvrm_get_device(obj); assert(dev); struct nvrm_device *ndev = nvrm_dev(dev); if (!ndev) { nvrm_get_chipset(obj); ndev = nvrm_dev(dev); } assert(ndev); ndev->pb_pointer_found = pb_pointer_found; }
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); }
bool nvrm_get_pb_pointer_found(struct gpu_object *obj) { struct gpu_object *dev = nvrm_get_device(obj); assert(dev); struct nvrm_device *ndev = nvrm_dev(dev); assert(ndev); if (!ndev) return false; return ndev->pb_pointer_found; }
int nvrm_get_chipset(struct gpu_object *obj) { struct gpu_object *dev = nvrm_get_device(obj); if (dev && dev->class_data) return nvrm_dev(dev)->chipset; if (chipset) return chipset; mmt_error("Can't detect chipset, you need to use -m option or regenerate trace with newer mmt (> Sep 7 2014)%s\n", ""); demmt_abort(); }
void nvrm_device_set_chipset(struct gpu_object *dev, int chipset) { struct nvrm_device *d = nvrm_dev(dev); if (!d) { d = dev->class_data = calloc(1, sizeof(*d)); dev->class_data_destroy = device_destroy; } if (chipset != d->chipset) { d->chipset = chipset; mmt_log("Chipset: NV%02X\n", chipset); } }
static struct gpu_object *nvrm_add_object(uint32_t fd, uint32_t cid, uint32_t parent, uint32_t handle, uint32_t class_) { struct gpu_object *obj = gpu_object_add(fd, cid, parent, handle, class_); if (dump_object_tree_on_create_destroy) { mmt_log("Object tree after create: %s\n", ""); dump_object_trees(obj); } if (is_fifo_ib_class(class_) || is_fifo_dma_class(class_)) { struct gpu_object *dev = nvrm_get_device(obj); if (dev && dev->class_data) nvrm_dev(dev)->fifos++; } return obj; }
static void nvrm_destroy_gpu_object(uint32_t fd, uint32_t cid, uint32_t parent, uint32_t handle) { struct gpu_object *obj = gpu_object_find(cid, handle); if (obj == NULL) { uint16_t cl = handle & 0xffff; // userspace deletes objects which it didn't create and kernel returns SUCCESS :/ // just ignore known offenders switch (cl) { case 0x0014: case 0x0202: case 0x0301: case 0x0308: case 0x0360: case 0x0371: case 0x1e00: case 0x1e01: case 0x1e10: case 0x1e20: break; default: mmt_error("trying to destroy object 0x%08x / 0x%08x which does not exist!\n", cid, handle); } return; } if (dump_object_tree_on_create_destroy) { mmt_log("Object tree before destroy: %s\n", ""); dump_object_trees(obj); } if (is_fifo_ib_class(obj->class_) || is_fifo_dma_class(obj->class_)) { struct gpu_object *dev = nvrm_get_device(obj); if (dev && dev->class_data) nvrm_dev(dev)->fifos--; } gpu_object_destroy(obj); }
struct gpu_object *nvrm_get_fifo(struct gpu_object *obj, uint64_t gpu_addr, int strict) { struct gpu_object *last = NULL; while (obj) { if (is_fifo(obj, 0)) last = obj; if (is_fifo_and_addr_belongs(obj, gpu_addr)) return obj; if (obj->class_ == NVRM_DEVICE_0) { struct gpu_object *fifo = nvrm_find_object_by_func(obj, is_fifo_and_addr_belongs, gpu_addr); if (!fifo && !strict) // fallback, for traces without ioctl_create args { fifo = nvrm_find_object_by_func(obj, is_fifo, 0); struct gpu_object *dev = nvrm_get_device(obj); int fifos = 0; if (dev && dev->class_data) fifos = nvrm_dev(dev)->fifos; static int warned = 0; if (fifos > 1 && !warned) { int chipset = nvrm_get_chipset(dev); if (chipset > 0x80 || chipset == 0x50) mmt_error("This trace may not be decoded accurately because there are multiple fifo objects " "and ioctl_creates for some of them were not captured with argument data%s\n", ""); else mmt_error("This trace may not be decoded accurately because there are multiple fifo objects " "and USER buffer detection is not implemented yet%s\n", ""); warned = 1; } } return fifo; } obj = obj->parent_object; } return last; }