Subversion Repositories Kolibri OS

Rev

Rev 4245 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4245 Serge 1
/*
2
 * Copyright © 2007-2011 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 * SOFTWARE.
22
 *
23
 * Authors:
24
 *    Eric Anholt 
25
 *
26
 */
27
 
28
#ifdef HAVE_CONFIG_H
29
#include "config.h"
30
#endif
31
 
32
//#include 
33
#include 
34
 
35
#include "sna.h"
36
#include "sna_reg.h"
37
 
38
#include "kgem_debug.h"
39
 
40
struct drm_i915_gem_relocation_entry *
41
kgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset)
42
{
43
	int i;
44
 
45
	offset *= sizeof(uint32_t);
46
 
47
	for (i = 0; i < kgem->nreloc; i++)
48
		if (kgem->reloc[i].offset == offset)
49
			return kgem->reloc+i;
50
 
51
	assert(!"valid relocation entry, unknown batch offset");
52
	return NULL;
53
}
54
 
55
struct kgem_bo *
56
kgem_debug_get_bo_for_reloc_entry(struct kgem *kgem,
57
				  struct drm_i915_gem_relocation_entry *reloc)
58
{
59
	struct kgem_bo *bo;
60
 
61
	if (reloc == NULL)
62
		return NULL;
63
 
64
	list_for_each_entry(bo, &kgem->next_request->buffers, request)
65
		if (bo->target_handle == reloc->target_handle && bo->proxy == NULL)
66
			break;
67
 
68
	assert(&bo->request != &kgem->next_request->buffers);
69
 
70
	return bo;
71
}
72
 
73
static int kgem_debug_handle_is_fenced(struct kgem *kgem, uint32_t handle)
74
{
75
	int i;
76
 
77
	if (kgem->has_handle_lut)
78
		return kgem->exec[handle].flags & EXEC_OBJECT_NEEDS_FENCE;
79
 
80
	for (i = 0; i < kgem->nexec; i++)
81
		if (kgem->exec[i].handle == handle)
82
			return kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE;
83
 
84
	return 0;
85
}
86
 
87
static int kgem_debug_handle_tiling(struct kgem *kgem, uint32_t handle)
88
{
89
	struct kgem_bo *bo;
90
 
91
	list_for_each_entry(bo, &kgem->next_request->buffers, request)
92
		if (bo->target_handle == handle)
93
			return bo->tiling;
94
 
95
	return 0;
96
}
97
 
98
void
99
kgem_debug_print(const uint32_t *data,
100
		 uint32_t offset, unsigned int index,
101
		 const char *fmt, ...)
102
{
103
	va_list va;
104
	char buf[240];
105
	int len;
106
 
107
	len = snprintf(buf, sizeof(buf),
108
		       "0x%08x: 0x%08x: %s",
109
		       (offset + index) * 4,
110
		       data[index],
111
		       index == 0 ? "" : "   ");
112
 
113
	va_start(va, fmt);
114
	vsnprintf(buf + len, sizeof(buf) - len, fmt, va);
115
	va_end(va);
116
 
117
	ErrorF("%s", buf);
118
    delay(1);
119
}
120
 
121
static int
122
decode_nop(struct kgem *kgem, uint32_t offset)
123
{
124
	uint32_t *data = kgem->batch + offset;
125
	kgem_debug_print(data, offset, 0, "UNKNOWN\n");
126
	assert(0);
127
	return 1;
128
}
129
 
130
static int
131
decode_mi(struct kgem *kgem, uint32_t offset)
132
{
133
	static const struct {
134
		uint32_t opcode;
135
		int len_mask;
136
		int min_len;
137
		int max_len;
138
		const char *name;
139
	} opcodes[] = {
140
		{ 0x08, 0, 1, 1, "MI_ARB_ON_OFF" },
141
		{ 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" },
142
		{ 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" },
143
		{ 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" },
144
		{ 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" },
145
		{ 0x04, 0, 1, 1, "MI_FLUSH" },
146
		{ 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" },
147
		{ 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" },
148
		{ 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" },
149
		{ 0x00, 0, 1, 1, "MI_NOOP" },
150
		{ 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" },
151
		{ 0x07, 0, 1, 1, "MI_REPORT_HEAD" },
152
		{ 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" },
153
		{ 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" },
154
		{ 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" },
155
		{ 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" },
156
		{ 0x02, 0, 1, 1, "MI_USER_INTERRUPT" },
157
		{ 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" },
158
		{ 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" },
159
		{ 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" },
160
		{ 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH" },
161
	};
162
	uint32_t *data = kgem->batch + offset;
163
	int op;
164
 
165
	for (op = 0; op < ARRAY_SIZE(opcodes); op++) {
166
		if ((data[0] & 0x1f800000) >> 23 == opcodes[op].opcode) {
167
			unsigned int len = 1, i;
168
 
169
			kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name);
170
			if (opcodes[op].max_len > 1) {
171
				len = (data[0] & opcodes[op].len_mask) + 2;
172
				if (len < opcodes[op].min_len ||
173
				    len > opcodes[op].max_len)
174
				{
175
					ErrorF("Bad length (%d) in %s, [%d, %d]\n",
176
					       len, opcodes[op].name,
177
					       opcodes[op].min_len,
178
					       opcodes[op].max_len);
179
					assert(0);
180
				}
181
			}
182
 
183
			for (i = 1; i < len; i++)
184
				kgem_debug_print(data, offset, i, "dword %d\n", i);
185
 
186
			return len;
187
		}
188
	}
189
 
190
	kgem_debug_print(data, offset, 0, "MI UNKNOWN\n");
191
	assert(0);
192
	return 1;
193
}
194
 
195
static int
196
decode_2d(struct kgem *kgem, uint32_t offset)
197
{
198
	static const struct {
199
		uint32_t opcode;
200
		int min_len;
201
		int max_len;
202
		const char *name;
203
	} opcodes[] = {
204
		{ 0x40, 5, 5, "COLOR_BLT" },
205
		{ 0x43, 6, 6, "SRC_COPY_BLT" },
206
		{ 0x01, 8, 8, "XY_SETUP_BLT" },
207
		{ 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" },
208
		{ 0x03, 3, 3, "XY_SETUP_CLIP_BLT" },
209
		{ 0x24, 2, 2, "XY_PIXEL_BLT" },
210
		{ 0x25, 3, 3, "XY_SCANLINES_BLT" },
211
		{ 0x26, 4, 4, "Y_TEXT_BLT" },
212
		{ 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" },
213
		{ 0x50, 6, 6, "XY_COLOR_BLT" },
214
		{ 0x51, 6, 6, "XY_PAT_BLT" },
215
		{ 0x76, 8, 8, "XY_PAT_CHROMA_BLT" },
216
		{ 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" },
217
		{ 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" },
218
		{ 0x52, 9, 9, "XY_MONO_PAT_BLT" },
219
		{ 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" },
220
		{ 0x53, 8, 8, "XY_SRC_COPY_BLT" },
221
		{ 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" },
222
		{ 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" },
223
		{ 0x55, 9, 9, "XY_FULL_BLT" },
224
		{ 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" },
225
		{ 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" },
226
		{ 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" },
227
		{ 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" },
228
		{ 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" },
229
	};
230
 
231
	unsigned int op, len;
232
	const char *format = NULL;
233
	uint32_t *data = kgem->batch + offset;
234
	struct drm_i915_gem_relocation_entry *reloc;
235
 
236
	/* Special case the two most common ops that we detail in full */
237
	switch ((data[0] & 0x1fc00000) >> 22) {
238
	case 0x50:
239
		kgem_debug_print(data, offset, 0,
240
			  "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n",
241
			  (data[0] & (1 << 20)) ? "en" : "dis",
242
			  (data[0] & (1 << 21)) ? "en" : "dis",
243
			  (data[0] >> 11) & 1);
244
 
245
		len = (data[0] & 0x000000ff) + 2;
246
		assert(len == 6);
247
 
248
		switch ((data[1] >> 24) & 0x3) {
249
		case 0:
250
			format="8";
251
			break;
252
		case 1:
253
			format="565";
254
			break;
255
		case 2:
256
			format="1555";
257
			break;
258
		case 3:
259
			format="8888";
260
			break;
261
		}
262
 
263
		kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, "
264
			  "clipping %sabled\n", format,
265
			  (data[1] >> 16) & 0xff,
266
			  (short)(data[1] & 0xffff),
267
			  data[1] & (1 << 30) ? "en" : "dis");
268
		kgem_debug_print(data, offset, 2, "(%d,%d)\n",
269
			  data[2] & 0xffff, data[2] >> 16);
270
		kgem_debug_print(data, offset, 3, "(%d,%d)\n",
271
			  data[3] & 0xffff, data[3] >> 16);
272
		reloc = kgem_debug_get_reloc_entry(kgem, offset+4);
273
		kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n",
274
				 data[4],
275
				 reloc->target_handle, reloc->delta,
276
				 reloc->read_domains, reloc->write_domain,
277
				 kgem_debug_handle_is_fenced(kgem, reloc->target_handle),
278
				 kgem_debug_handle_tiling(kgem, reloc->target_handle));
279
		kgem_debug_print(data, offset, 5, "color\n");
280
		assert(kgem->gen >= 040 ||
281
		       kgem_debug_handle_is_fenced(kgem, reloc->target_handle));
282
		return len;
283
 
284
	case 0x53:
285
		kgem_debug_print(data, offset, 0,
286
			  "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, "
287
			  "src tile %d, dst tile %d)\n",
288
			  (data[0] & (1 << 20)) ? "en" : "dis",
289
			  (data[0] & (1 << 21)) ? "en" : "dis",
290
			  (data[0] >> 15) & 1,
291
			  (data[0] >> 11) & 1);
292
 
293
		len = (data[0] & 0x000000ff) + 2;
294
		assert(len == 8);
295
 
296
		switch ((data[1] >> 24) & 0x3) {
297
		case 0:
298
			format="8";
299
			break;
300
		case 1:
301
			format="565";
302
			break;
303
		case 2:
304
			format="1555";
305
			break;
306
		case 3:
307
			format="8888";
308
			break;
309
		}
310
 
311
		kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, "
312
				 "clipping %sabled\n", format,
313
				 (data[1] >> 16) & 0xff,
314
				 (short)(data[1] & 0xffff),
315
				 data[1] & (1 << 30) ? "en" : "dis");
316
		kgem_debug_print(data, offset, 2, "dst (%d,%d)\n",
317
				 data[2] & 0xffff, data[2] >> 16);
318
		kgem_debug_print(data, offset, 3, "dst (%d,%d)\n",
319
				 data[3] & 0xffff, data[3] >> 16);
320
		reloc = kgem_debug_get_reloc_entry(kgem, offset+4);
321
		assert(reloc);
322
		kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n",
323
				 data[4],
324
				 reloc->target_handle, reloc->delta,
325
				 reloc->read_domains, reloc->write_domain,
326
				 kgem_debug_handle_is_fenced(kgem, reloc->target_handle),
327
				 kgem_debug_handle_tiling(kgem, reloc->target_handle));
328
		assert(kgem->gen >= 040 ||
329
		       kgem_debug_handle_is_fenced(kgem, reloc->target_handle));
330
 
331
		kgem_debug_print(data, offset, 5, "src (%d,%d)\n",
332
				 data[5] & 0xffff, data[5] >> 16);
333
		kgem_debug_print(data, offset, 6, "src pitch %d\n",
334
				 (short)(data[6] & 0xffff));
335
		reloc = kgem_debug_get_reloc_entry(kgem, offset+7);
336
		assert(reloc);
337
		kgem_debug_print(data, offset, 7, "src offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n",
338
				 data[7],
339
				 reloc->target_handle, reloc->delta,
340
				 reloc->read_domains, reloc->write_domain,
341
				 kgem_debug_handle_is_fenced(kgem, reloc->target_handle),
342
				 kgem_debug_handle_tiling(kgem, reloc->target_handle));
343
		assert(kgem->gen >= 040 ||
344
		       kgem_debug_handle_is_fenced(kgem, reloc->target_handle));
345
 
346
		return len;
347
	}
348
 
349
	for (op = 0; op < ARRAY_SIZE(opcodes); op++) {
350
		if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) {
351
			unsigned int i;
352
 
353
			len = 1;
354
			kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name);
355
			if (opcodes[op].max_len > 1) {
356
				len = (data[0] & 0x000000ff) + 2;
357
				assert(len >= opcodes[op].min_len &&
358
				       len <= opcodes[op].max_len);
359
			}
360
 
361
			for (i = 1; i < len; i++)
362
				kgem_debug_print(data, offset, i, "dword %d\n", i);
363
 
364
			return len;
365
		}
366
	}
367
 
368
	kgem_debug_print(data, offset, 0, "2D UNKNOWN\n");
369
	assert(0);
370
	return 1;
371
}
372
 
373
static int (*decode_3d(int gen))(struct kgem*, uint32_t)
374
{
375
	if (gen >= 0100) {
376
	} else if (gen >= 070) {
377
		return kgem_gen7_decode_3d;
378
	} else if (gen >= 060) {
379
		return kgem_gen6_decode_3d;
380
	} else if (gen >= 050) {
381
		return kgem_gen5_decode_3d;
382
	} else if (gen >= 040) {
383
		return kgem_gen4_decode_3d;
384
	} else if (gen >= 030) {
385
		return kgem_gen3_decode_3d;
386
	}
387
	assert(0);
388
}
389
 
390
static void (*finish_state(int gen))(struct kgem*)
391
{
392
	if (gen >= 0100) {
393
	} else if (gen >= 070) {
394
		return kgem_gen7_finish_state;
395
	} else if (gen >= 060) {
396
		return kgem_gen6_finish_state;
397
	} else if (gen >= 050) {
398
		return kgem_gen5_finish_state;
399
	} else if (gen >= 040) {
400
		return kgem_gen4_finish_state;
401
	} else if (gen >= 030) {
402
		return kgem_gen3_finish_state;
403
	}
404
	assert(0);
405
}
406
 
407
void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch)
408
{
409
	int (*const decode[])(struct kgem *, uint32_t) = {
410
		decode_mi,
411
		decode_nop,
412
		decode_2d,
413
		decode_3d(kgem->gen),
414
	};
415
	uint32_t offset = 0;
416
 
417
	while (offset < nbatch) {
418
		int class = (kgem->batch[offset] & 0xe0000000) >> 29;
419
		assert(class < ARRAY_SIZE(decode));
420
		offset += decode[class](kgem, offset);
421
	}
422
 
423
	finish_state(kgem->gen)(kgem);
424
}