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 handle_nvrm_ioctl_vspace_unmap(uint32_t fd, struct nvrm_ioctl_vspace_unmap *s) { if (s->status != NVRM_STATUS_SUCCESS) return; check_cid(s->cid); struct gpu_object *obj = gpu_object_find(s->cid, s->handle); if (!obj) { mmt_error("nvrm_ioctl_vspace_unmap: cannot find object 0x%08x 0x%08x\n", s->cid, s->handle); return; } struct gpu_mapping *gpu_mapping; for (gpu_mapping = obj->gpu_mappings; gpu_mapping != NULL; gpu_mapping = gpu_mapping->next) if (gpu_mapping->address == s->addr) { gpu_mapping->address = 0; gpu_mapping_destroy(gpu_mapping); return; } mmt_error("can't find matching gpu_mappings%s\n", ""); demmt_abort(); }
static void handle_nvrm_ioctl_host_map(uint32_t fd, struct nvrm_ioctl_host_map *s) { if (s->status != NVRM_STATUS_SUCCESS) return; check_cid(s->cid); struct gpu_object *obj = gpu_object_find(s->cid, s->handle); if (!obj) { mmt_error("nvrm_ioctl_host_map: cannot find object 0x%08x 0x%08x\n", s->cid, s->handle); return; } // NOTE: s->subdev may not be object's parent and may not even be an ancestor of its parent /* if (obj->parent != s->subdev) { struct gpu_object *subdev = find_object(s->cid, s->subdev); while (subdev && subdev->handle != obj->parent) subdev = subdev->parent_object; if (!subdev) { mmt_error("nvrm_ioctl_host_map: subdev 0x%08x is not an ancestor of object's parent (0x%08x)\n", s->subdev, obj->parent); return; } }*/ host_map(obj, fd, s->foffset, s->base, s->limit + 1, s->subdev, -1); }
static void handle_nvrm_ioctl_vspace_map(uint32_t fd, struct nvrm_ioctl_vspace_map *s) { if (s->status != NVRM_STATUS_SUCCESS) return; check_cid(s->cid); struct gpu_object *obj = gpu_object_find(s->cid, s->handle); if (!obj) { mmt_error("nvrm_ioctl_vspace_map: cannot find object 0x%08x 0x%08x\n", s->cid, s->handle); return; } struct gpu_mapping *mapping = calloc(sizeof(struct gpu_mapping), 1); mapping->fd = fd; mapping->dev = s->dev; mapping->vspace = s->vspace; mapping->address = s->addr; mapping->object_offset = s->base; mapping->length = s->size; if (s->size > obj->length) { obj->data = realloc(obj->data, s->size); memset(obj->data + obj->length, 0, s->size - obj->length); obj->length = s->size; } mapping->object = obj; mapping->next = obj->gpu_mappings; obj->gpu_mappings = mapping; }
static void handle_nvrm_ioctl_host_unmap(uint32_t fd, struct nvrm_ioctl_host_unmap *s) { if (s->status != NVRM_STATUS_SUCCESS) return; check_cid(s->cid); struct gpu_object *obj = gpu_object_find(s->cid, s->handle); if (!obj) { mmt_error("nvrm_ioctl_host_unmap: cannot find object 0x%08x 0x%08x\n", s->cid, s->handle); return; } struct cpu_mapping *cpu_mapping; for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) if (cpu_mapping->mmap_offset == (s->foffset & ~0xfffUL)) { cpu_mapping->mmap_offset = 0; disconnect_cpu_mapping_from_gpu_object(cpu_mapping); return; } // weird, host_unmap accepts cpu addresses in foffset field for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) if (cpu_mapping->cpu_addr == (s->foffset & ~0xfffUL)) { //mmt_error("host_unmap with cpu address as offset, wtf?%s\n", ""); cpu_mapping->mmap_offset = 0; disconnect_cpu_mapping_from_gpu_object(cpu_mapping); return; } mmt_error("can't find matching mapping%s\n", ""); demmt_abort(); }
static void check_cid(uint32_t cid) { if (cid_not_found && gpu_object_find(cid, cid) == NULL) { nvrm_add_object(-1, cid, cid, cid, 0x0041); cid_not_found--; } }
static void handle_nvrm_ioctl_call(struct nvrm_ioctl_call *s, struct mmt_memory_dump *args, int argc) { struct mmt_buf *data = find_ptr(s->ptr, args, argc); if (!data) return; if (s->mthd == NVRM_MTHD_FIFO_IB_OBJECT_INFO || s->mthd == NVRM_MTHD_FIFO_IB_OBJECT_INFO2) { struct nvrm_mthd_fifo_ib_object_info *mthd_data = (void *) data->data; struct gpu_object *obj = gpu_object_find(s->cid, s->handle); pushbuf_add_object_name(mthd_data->handle, mthd_data->name, obj); } else if (s->mthd == NVRM_MTHD_SUBDEVICE_GET_CHIPSET) { struct nvrm_mthd_subdevice_get_chipset *mthd_data = (void *) data->data; struct gpu_object *obj = gpu_object_find(s->cid, s->handle); if (obj) obj = nvrm_get_device(obj); if (obj) nvrm_device_set_chipset(obj, mthd_data->major | mthd_data->minor); } }
static void handle_nvrm_ioctl_host_map56(uint32_t fd, struct nvrm_ioctl_host_map56 *s) { if (s->status != NVRM_STATUS_SUCCESS) return; check_cid(s->cid); struct gpu_object *obj = gpu_object_find(s->cid, s->handle); if (!obj) { mmt_error("nvrm_ioctl_host_map56: cannot find object 0x%08x 0x%08x\n", s->cid, s->handle); return; } host_map(obj, fd, s->foffset, 0, s->length, s->subdev, s->map_id); }
static void handle_nvrm_ioctl_host_unmap(uint32_t fd, struct nvrm_ioctl_host_unmap *s) { if (s->status != NVRM_STATUS_SUCCESS) return; check_cid(s->cid); struct gpu_object *obj = gpu_object_find(s->cid, s->handle); if (!obj) { mmt_error("nvrm_ioctl_host_unmap: cannot find object 0x%08x 0x%08x\n", s->cid, s->handle); return; } struct cpu_mapping *cpu_mapping; /* it seems, depending on blob version, foffset have different meaning :/ */ for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) if (cpu_mapping->map_id == s->foffset) { cpu_mapping->mmap_offset = -1; cpu_mapping->map_id = -1; disconnect_cpu_mapping_from_gpu_object(cpu_mapping); return; } for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) if (cpu_mapping->mmap_offset == (s->foffset & ~0xfffUL)) { cpu_mapping->mmap_offset = -1; cpu_mapping->map_id = -1; disconnect_cpu_mapping_from_gpu_object(cpu_mapping); return; } for (cpu_mapping = obj->cpu_mappings; cpu_mapping != NULL; cpu_mapping = cpu_mapping->next) if (cpu_mapping->cpu_addr == (s->foffset & ~0xfffUL)) { //mmt_error("host_unmap with cpu address as offset, wtf?%s\n", ""); cpu_mapping->mmap_offset = -1; cpu_mapping->map_id = -1; disconnect_cpu_mapping_from_gpu_object(cpu_mapping); return; } mmt_error("can't find matching mapping%s\n", ""); demmt_abort(); }
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); }