예제 #1
0
파일: nvrm.c 프로젝트: jhol/envytools
static void handle_nvrm_ioctl_vspace_unmap(struct nvrm_ioctl_vspace_unmap *s)
{
	struct buffer *buf;
	int found = 0;
	for (buf = buffers_list; buf != NULL; buf = buf->next)
		if (buf->data1 == s->dev && buf->data2 == s->handle &&
				buf->gpu_start == s->addr)
		{
			mmt_debug("clearing gpu address for buffer %d (was: 0x%08lx)\n", buf->id, buf->gpu_start);
			buf->gpu_start = 0;

			found = 1;
			break;
		}

	if (!found)
	{
		for (buf = gpu_only_buffers_list; buf != NULL; buf = buf->next)
		{
			if (buf->data1 == s->dev && buf->data2 == s->handle && buf->gpu_start == s->addr)
			{
				mmt_debug("deregistering gpu only buffer of size %ld\n", buf->length);
				buffer_free(buf);

				found = 1;
				break;
			}
		}

		if (!found)
			mmt_log("gpu only buffer not found%s\n", "");
	}
}
예제 #2
0
void decode_gf100_m2mf_verbose(struct gpu_object *obj, struct pushbuf_decode_state *pstate)
{
	int mthd = pstate->mthd;
	uint32_t data = pstate->mthd_data;
	struct gf100_m2mf_data *objdata = obj->class_data;

	if (check_addresses_verbose(pstate, objdata->addresses))
	{ }
	else if (mthd == 0x0300) // EXEC
	{
		int flags_ok = (data & 0x111) == 0x111 ? 1 : 0;
		mmt_debug("m2mf exec: 0x%08x push&linear: %d\n", data, flags_ok);

		if (!flags_ok || objdata->offset_out.gpu_mapping == NULL)
		{
			objdata->offset_out.address = 0;
			objdata->offset_out.gpu_mapping = NULL;
		}
	}
	else if (mthd == 0x0304) // DATA
	{
		mmt_debug("m2mf data: 0x%08x\n", data);
		if (objdata->offset_out.gpu_mapping)
		{
			gpu_mapping_register_write(objdata->offset_out.gpu_mapping,
					objdata->offset_out.address + objdata->data_offset, 4, &data);
			objdata->data_offset += 4;
		}
	}
}
예제 #3
0
static void maybe_merge_with_previous(struct region *cur, struct regions *parent)
{
	// previous exists?
	if (!cur->prev)
		return;

	// previous ends before start of this one?
	if (cur->prev->end < cur->start)
		return;

	// now previous ends within this one

	// previous starts within this one?
	if (cur->prev->start >= cur->start)
	{
		// just drop previous entry
		drop_region(cur->prev, parent);

		// and see if previous^2 should be merged
		maybe_merge_with_previous(cur, parent);
	}
	else
	{
		// now previous starts before this one

		// extend current start
		mmt_debug("extending entry <0x%08x, 0x%08x> left to 0x%08x\n",
				cur->start, cur->end, cur->prev->start);
		cur->start = cur->prev->start;

		// and drop previous entry
		drop_region(cur->prev, parent);
	}
}
예제 #4
0
파일: nvrm.c 프로젝트: jhol/envytools
static void handle_nvrm_ioctl_vspace_map(struct nvrm_ioctl_vspace_map *s)
{
	struct buffer *buf;
	int found = 0;
	for (buf = buffers_list; buf != NULL; buf = buf->next)
		if (buf->data1 == s->dev && buf->data2 == s->handle && buf->length == s->size)
		{
			buf->gpu_start = s->addr;
			mmt_debug("setting gpu address for buffer %d to 0x%08lx\n", buf->id, buf->gpu_start);

			found = 1;
			break;
		}

	if (!found)
	{
		struct unk_map *tmp;
		for (tmp = unk_maps; tmp != NULL; tmp = tmp->next)
		{
			if (tmp->data1 == s->dev && tmp->data2 == s->handle)
			{
				mmt_log("TODO: unk buffer found, demmt_nv_gpu_map needs to be updated!%s\n", "");
				break;
			}
		}

		register_gpu_only_buffer(s->addr, s->size, 0, s->dev, s->handle);
	}
}
예제 #5
0
static void maybe_merge_with_next(struct region *cur, struct regions *parent)
{
	// next exists?
	if (!cur->next)
		return;

	// next starts after this one?
	if (cur->next->start > cur->end)
		return;

	// now next starts within this one

	// next ends within this one?
	if (cur->next->end <= cur->end)
	{
		// drop next one
		drop_region(cur->next, parent);

		// and see if next^2 should be merged
		maybe_merge_with_next(cur, parent);
	}
	else
	{
		// now next ends after this one

		// extend current end
		mmt_debug("extending entry <0x%08x, 0x%08x> right to 0x%08x\n",
				cur->start, cur->end, cur->next->end);
		cur->end = cur->next->end;

		// and drop next entry
		drop_region(cur->next, parent);
	}
}
예제 #6
0
static void g80_3d_disassemble(struct buffer *buf, const char *mode, uint32_t start_id)
{
	if (!buf)
		return;

	mmt_debug("%s_start id 0x%08x\n", mode, start_id);
	struct region *reg;
	for (reg = buf->written_regions.head; reg != NULL; reg = reg->next)
	{
		if (reg->start != start_id)
			continue;

		if (MMT_DEBUG)
		{
			uint32_t x;
			mmt_debug("CODE: %s", "");
			for (x = reg->start; x < reg->end; x += 4)
				mmt_debug_cont("0x%08x ", *(uint32_t *)(buf->data + x));
			mmt_debug_cont("%s\n", "");
		}

		if (!isa_g80)
			isa_g80 = ed_getisa("g80");

		struct varinfo *var = varinfo_new(isa_g80->vardata);

		if (chipset == 0x50)
			varinfo_set_variant(var, "g80");
		else if (chipset >= 0x84 && chipset <= 0x98)
			varinfo_set_variant(var, "g84");
		else if (chipset == 0xa0)
			varinfo_set_variant(var, "g200");
		else if (chipset >= 0xaa && chipset <= 0xac)
			varinfo_set_variant(var, "mcp77");
		else if ((chipset >= 0xa3 && chipset <= 0xa8) || chipset == 0xaf)
			varinfo_set_variant(var, "gt215");

		varinfo_set_mode(var, mode);

		envydis(isa_g80, stdout, buf->data + reg->start, 0,
				reg->end - reg->start, var, 0, NULL, 0, colors);
		varinfo_del(var);
		break;
	}
}
예제 #7
0
void decode_g80_3d_verbose(struct pushbuf_decode_state *pstate)
{
	int mthd = pstate->mthd;
	uint32_t data = pstate->mthd_data;

	if (check_addresses_verbose(pstate, g80_3d_addresses))
	{ }
	else if (mthd == 0x140c && dump_vp) // VP_START_ID
		g80_3d_disassemble(g80_3d.vp.buffer, "vp", data);
	else if (mthd == 0x1414 && dump_fp) // FP_START_ID
		g80_3d_disassemble(g80_3d.fp.buffer, "fp", data);
	else if (mthd == 0x1410 && dump_gp) // GP_START_ID
		g80_3d_disassemble(g80_3d.gp.buffer, "gp", data);
	else if (mthd >= 0x1444 && mthd < 0x1448 + 0x8 * 3)
	{
		int i;
		for (i = 0; i < 3; ++i)
		{
			if (dump_tsc && g80_3d.tsc.buffer && mthd == 0x1444 + i * 0x8) // BIND_TSC[i]
			{
				int j, tsc = (data >> 12) & 0xff;
				mmt_debug("bind tsc[%d]: 0x%08x\n", i, tsc);
				uint32_t *tsc_data = (uint32_t *)&g80_3d.tsc.buffer->data[8 * tsc];

				for (j = 0; j < 8; ++j)
					decode_tsc(tsc, j, tsc_data);

				break;
			}
			if (dump_tic && g80_3d.tic.buffer && mthd == 0x1448 + i * 0x8) // BIND_TIC[i]
			{
				int j, tic = (data >> 9) & 0x1ffff;
				mmt_debug("bind tic[%d]: 0x%08x\n", i, tic);
				uint32_t *tic_data = (uint32_t *)&g80_3d.tic.buffer->data[8 * tic];

				for (j = 0; j < 8; ++j)
					decode_tic(tic, j, tic_data);

				break;
			}
예제 #8
0
static void drop_region(struct region *reg, struct regions *parent)
{
	struct region *prev = reg->prev;
	struct region *next = reg->next;
	mmt_debug("dropping entry <0x%08x, 0x%08x>\n", reg->start, reg->end);
	free(reg);
	if (prev)
		prev->next = next;
	else
	{
		mmt_debug("new head is at <0x%08x, 0x%08x>\n", next->start, next->end);
		parent->head = next;
	}

	if (next)
		next->prev = prev;
	else
	{
		mmt_debug("new last is at <0x%08x, 0x%08x>\n", prev->start, prev->end);
		parent->last = prev;
	}
}
예제 #9
0
int check_addresses_verbose(struct pushbuf_decode_state *pstate, struct mthd2addr *addresses)
{
	int mthd = pstate->mthd;
	struct mthd2addr *tmp = addresses;
	while (tmp->high)
	{
		if (tmp->low == mthd)
		{
			mmt_debug("buffer found: %d\n", tmp->buf->buffer ? 1 : 0);
			return 1;
		}
		tmp++;
	}
	return 0;
}
예제 #10
0
파일: nvrm.c 프로젝트: jhol/envytools
static void handle_nvrm_ioctl_host_map(struct nvrm_ioctl_host_map *s)
{
	struct buffer *buf;
	int found = 0;
	for (buf = buffers_list; buf != NULL; buf = buf->next)
		if (buf->mmap_offset == s->foffset)
		{
			buf->data1 = s->subdev;
			buf->data2 = s->handle;

			found = 1;
			break;
		}

	if (!found)
	{
		for (buf = gpu_only_buffers_list; buf != NULL; buf = buf->next)
		{
			if (buf->data1 == s->subdev && buf->data2 == s->handle)
			{
				if (buf->mmap_offset != s->foffset)
				{
					mmt_debug("gpu only buffer found (0x%016lx), merging mmap_offset\n", buf->gpu_start);
					buf->mmap_offset = s->foffset;
				}

				found = 1;
				break;
			}
		}

		if (!found)
		{
			struct unk_map *m = malloc(sizeof(struct unk_map));
			m->data1 = s->subdev;
			m->data2 = s->handle;
			m->mmap_offset = s->foffset;
			m->next = unk_maps;
			unk_maps = m;
		}
	}
}
예제 #11
0
static void __regions_add_range(struct regions *regions, uint32_t start, uint32_t len)
{
	struct region *cur = regions->head;

	if (cur == NULL)
	{
		regions->head = cur = malloc(sizeof(struct region));
		cur->start = start;
		cur->end = start + len;
		cur->prev = NULL;
		cur->next = NULL;
		regions->last = cur;
		return;
	}

	struct region *last_reg = regions->last;
	if (start == last_reg->end)
	{
		mmt_debug("extending last entry <0x%08x, 0x%08x> right by %d\n",
				last_reg->start, last_reg->end, len);
		last_reg->end += len;
		return;
	}

	if (start > last_reg->end)
	{
		mmt_debug("adding last entry <0x%08x, 0x%08x> after <0x%08x, 0x%08x>\n",
				start, start + len, last_reg->start, last_reg->end);
		cur = malloc(sizeof(struct region));
		cur->start = start;
		cur->end = start + len;
		cur->prev = last_reg;
		cur->next = NULL;
		last_reg->next = cur;
		regions->last = cur;
		return;
	}

	if (start + len > last_reg->end)
	{
		mmt_debug("extending last entry <0x%08x, 0x%08x> right to 0x%08x\n",
				last_reg->start, last_reg->end, start + len);
		last_reg->end = start + len;
		if (start < last_reg->start)
		{
			mmt_debug("... and extending last entry <0x%08x, 0x%08x> left to 0x%08x\n",
					last_reg->start, last_reg->end, start);
			last_reg->start = start;
			maybe_merge_with_previous(last_reg, regions);
		}
		return;
	}


	while (start + len > cur->end) // if we will ever crash on cur being NULL then it means we screwed up earlier
	{
		if (cur->end == start) // optimization
		{
			mmt_debug("extending entry <0x%08x, 0x%08x> by %d\n", cur->start, cur->end, len);
			cur->end += len;
			maybe_merge_with_next(cur, regions);
			return;
		}
		cur = cur->next;
	}

	// now it ends before end of current

	// does it start in this one?
	if (start >= cur->start)
		return;

	// does it end before start of current one?
	if (start + len < cur->start)
	{
		mmt_debug("adding new entry <0x%08x, 0x%08x> before <0x%08x, 0x%08x>\n",
				start, start + len, cur->start, cur->end);
		struct region *tmp = malloc(sizeof(struct region));
		tmp->start = start;
		tmp->end = start + len;
		tmp->prev = cur->prev;
		tmp->next = cur;
		if (cur->prev)
			cur->prev->next = tmp;
		else
			regions->head = tmp;
		cur->prev = tmp;
		maybe_merge_with_previous(tmp, regions);
		return;
	}

	// now it ends in current and starts before
	cur->start = start;
	maybe_merge_with_previous(cur, regions);
}