1/*
2 * Copyright 2015 Advanced Micro Devices, Inc.
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 *      Marek Olšák <maraeo@gmail.com>
25 */
26
27#include "si_pipe.h"
28#include "sid.h"
29#include "sid_tables.h"
30#include "radeon/radeon_elf_util.h"
31#include "ddebug/dd_util.h"
32#include "util/u_memory.h"
33#include "ac_debug.h"
34
35DEBUG_GET_ONCE_OPTION(replace_shaders, "RADEON_REPLACE_SHADERS", NULL)
36
37static void si_dump_shader(struct si_screen *sscreen,
38			   struct si_shader_ctx_state *state, FILE *f)
39{
40	struct si_shader *current = state->current;
41
42	if (!state->cso || !current)
43		return;
44
45	if (current->shader_log)
46		fwrite(current->shader_log, current->shader_log_size, 1, f);
47	else
48		si_shader_dump(sscreen, state->current, NULL,
49			       state->cso->info.processor, f, false);
50}
51
52/**
53 * Shader compiles can be overridden with arbitrary ELF objects by setting
54 * the environment variable RADEON_REPLACE_SHADERS=num1:filename1[;num2:filename2]
55 */
56bool si_replace_shader(unsigned num, struct radeon_shader_binary *binary)
57{
58	const char *p = debug_get_option_replace_shaders();
59	const char *semicolon;
60	char *copy = NULL;
61	FILE *f;
62	long filesize, nread;
63	char *buf = NULL;
64	bool replaced = false;
65
66	if (!p)
67		return false;
68
69	while (*p) {
70		unsigned long i;
71		char *endp;
72		i = strtoul(p, &endp, 0);
73
74		p = endp;
75		if (*p != ':') {
76			fprintf(stderr, "RADEON_REPLACE_SHADERS formatted badly.\n");
77			exit(1);
78		}
79		++p;
80
81		if (i == num)
82			break;
83
84		p = strchr(p, ';');
85		if (!p)
86			return false;
87		++p;
88	}
89	if (!*p)
90		return false;
91
92	semicolon = strchr(p, ';');
93	if (semicolon) {
94		p = copy = strndup(p, semicolon - p);
95		if (!copy) {
96			fprintf(stderr, "out of memory\n");
97			return false;
98		}
99	}
100
101	fprintf(stderr, "radeonsi: replace shader %u by %s\n", num, p);
102
103	f = fopen(p, "r");
104	if (!f) {
105		perror("radeonsi: failed to open file");
106		goto out_free;
107	}
108
109	if (fseek(f, 0, SEEK_END) != 0)
110		goto file_error;
111
112	filesize = ftell(f);
113	if (filesize < 0)
114		goto file_error;
115
116	if (fseek(f, 0, SEEK_SET) != 0)
117		goto file_error;
118
119	buf = MALLOC(filesize);
120	if (!buf) {
121		fprintf(stderr, "out of memory\n");
122		goto out_close;
123	}
124
125	nread = fread(buf, 1, filesize, f);
126	if (nread != filesize)
127		goto file_error;
128
129	radeon_elf_read(buf, filesize, binary);
130	replaced = true;
131
132out_close:
133	fclose(f);
134out_free:
135	FREE(buf);
136	free(copy);
137	return replaced;
138
139file_error:
140	perror("radeonsi: reading shader");
141	goto out_close;
142}
143
144/* Parsed IBs are difficult to read without colors. Use "less -R file" to
145 * read them, or use "aha -b -f file" to convert them to html.
146 */
147#define COLOR_RESET	"\033[0m"
148#define COLOR_RED	"\033[31m"
149#define COLOR_GREEN	"\033[1;32m"
150#define COLOR_YELLOW	"\033[1;33m"
151#define COLOR_CYAN	"\033[1;36m"
152
153static void si_dump_mmapped_reg(struct si_context *sctx, FILE *f,
154				unsigned offset)
155{
156	struct radeon_winsys *ws = sctx->b.ws;
157	uint32_t value;
158
159	if (ws->read_registers(ws, offset, 1, &value))
160		ac_dump_reg(f, offset, value, ~0);
161}
162
163static void si_dump_debug_registers(struct si_context *sctx, FILE *f)
164{
165	if (sctx->screen->b.info.drm_major == 2 &&
166	    sctx->screen->b.info.drm_minor < 42)
167		return; /* no radeon support */
168
169	fprintf(f, "Memory-mapped registers:\n");
170	si_dump_mmapped_reg(sctx, f, R_008010_GRBM_STATUS);
171
172	/* No other registers can be read on DRM < 3.1.0. */
173	if (sctx->screen->b.info.drm_major < 3 ||
174	    sctx->screen->b.info.drm_minor < 1) {
175		fprintf(f, "\n");
176		return;
177	}
178
179	si_dump_mmapped_reg(sctx, f, R_008008_GRBM_STATUS2);
180	si_dump_mmapped_reg(sctx, f, R_008014_GRBM_STATUS_SE0);
181	si_dump_mmapped_reg(sctx, f, R_008018_GRBM_STATUS_SE1);
182	si_dump_mmapped_reg(sctx, f, R_008038_GRBM_STATUS_SE2);
183	si_dump_mmapped_reg(sctx, f, R_00803C_GRBM_STATUS_SE3);
184	si_dump_mmapped_reg(sctx, f, R_00D034_SDMA0_STATUS_REG);
185	si_dump_mmapped_reg(sctx, f, R_00D834_SDMA1_STATUS_REG);
186	si_dump_mmapped_reg(sctx, f, R_000E50_SRBM_STATUS);
187	si_dump_mmapped_reg(sctx, f, R_000E4C_SRBM_STATUS2);
188	si_dump_mmapped_reg(sctx, f, R_000E54_SRBM_STATUS3);
189	si_dump_mmapped_reg(sctx, f, R_008680_CP_STAT);
190	si_dump_mmapped_reg(sctx, f, R_008674_CP_STALLED_STAT1);
191	si_dump_mmapped_reg(sctx, f, R_008678_CP_STALLED_STAT2);
192	si_dump_mmapped_reg(sctx, f, R_008670_CP_STALLED_STAT3);
193	si_dump_mmapped_reg(sctx, f, R_008210_CP_CPC_STATUS);
194	si_dump_mmapped_reg(sctx, f, R_008214_CP_CPC_BUSY_STAT);
195	si_dump_mmapped_reg(sctx, f, R_008218_CP_CPC_STALLED_STAT1);
196	si_dump_mmapped_reg(sctx, f, R_00821C_CP_CPF_STATUS);
197	si_dump_mmapped_reg(sctx, f, R_008220_CP_CPF_BUSY_STAT);
198	si_dump_mmapped_reg(sctx, f, R_008224_CP_CPF_STALLED_STAT1);
199	fprintf(f, "\n");
200}
201
202static void si_dump_last_ib(struct si_context *sctx, FILE *f)
203{
204	int last_trace_id = -1;
205
206	if (!sctx->last_gfx.ib)
207		return;
208
209	if (sctx->last_trace_buf) {
210		/* We are expecting that the ddebug pipe has already
211		 * waited for the context, so this buffer should be idle.
212		 * If the GPU is hung, there is no point in waiting for it.
213		 */
214		uint32_t *map = sctx->b.ws->buffer_map(sctx->last_trace_buf->buf,
215						       NULL,
216						       PIPE_TRANSFER_UNSYNCHRONIZED |
217						       PIPE_TRANSFER_READ);
218		if (map)
219			last_trace_id = *map;
220	}
221
222	if (sctx->init_config)
223		ac_parse_ib(f, sctx->init_config->pm4, sctx->init_config->ndw,
224			    -1, "IB2: Init config", sctx->b.chip_class,
225			    NULL, NULL);
226
227	if (sctx->init_config_gs_rings)
228		ac_parse_ib(f, sctx->init_config_gs_rings->pm4,
229			    sctx->init_config_gs_rings->ndw,
230			    -1, "IB2: Init GS rings", sctx->b.chip_class,
231			    NULL, NULL);
232
233	ac_parse_ib(f, sctx->last_gfx.ib, sctx->last_gfx.num_dw,
234		    last_trace_id, "IB", sctx->b.chip_class,
235		     NULL, NULL);
236}
237
238static const char *priority_to_string(enum radeon_bo_priority priority)
239{
240#define ITEM(x) [RADEON_PRIO_##x] = #x
241	static const char *table[64] = {
242		ITEM(FENCE),
243	        ITEM(TRACE),
244	        ITEM(SO_FILLED_SIZE),
245	        ITEM(QUERY),
246	        ITEM(IB1),
247	        ITEM(IB2),
248	        ITEM(DRAW_INDIRECT),
249	        ITEM(INDEX_BUFFER),
250	        ITEM(VCE),
251	        ITEM(UVD),
252	        ITEM(SDMA_BUFFER),
253	        ITEM(SDMA_TEXTURE),
254		ITEM(CP_DMA),
255	        ITEM(CONST_BUFFER),
256	        ITEM(DESCRIPTORS),
257	        ITEM(BORDER_COLORS),
258	        ITEM(SAMPLER_BUFFER),
259	        ITEM(VERTEX_BUFFER),
260	        ITEM(SHADER_RW_BUFFER),
261	        ITEM(COMPUTE_GLOBAL),
262	        ITEM(SAMPLER_TEXTURE),
263	        ITEM(SHADER_RW_IMAGE),
264	        ITEM(SAMPLER_TEXTURE_MSAA),
265	        ITEM(COLOR_BUFFER),
266	        ITEM(DEPTH_BUFFER),
267	        ITEM(COLOR_BUFFER_MSAA),
268	        ITEM(DEPTH_BUFFER_MSAA),
269	        ITEM(CMASK),
270	        ITEM(DCC),
271	        ITEM(HTILE),
272		ITEM(SHADER_BINARY),
273		ITEM(SHADER_RINGS),
274		ITEM(SCRATCH_BUFFER),
275	};
276#undef ITEM
277
278	assert(priority < ARRAY_SIZE(table));
279	return table[priority];
280}
281
282static int bo_list_compare_va(const struct radeon_bo_list_item *a,
283				   const struct radeon_bo_list_item *b)
284{
285	return a->vm_address < b->vm_address ? -1 :
286	       a->vm_address > b->vm_address ? 1 : 0;
287}
288
289static void si_dump_bo_list(struct si_context *sctx,
290			    const struct radeon_saved_cs *saved, FILE *f)
291{
292	unsigned i,j;
293
294	if (!saved->bo_list)
295		return;
296
297	/* Sort the list according to VM adddresses first. */
298	qsort(saved->bo_list, saved->bo_count,
299	      sizeof(saved->bo_list[0]), (void*)bo_list_compare_va);
300
301	fprintf(f, "Buffer list (in units of pages = 4kB):\n"
302		COLOR_YELLOW "        Size    VM start page         "
303		"VM end page           Usage" COLOR_RESET "\n");
304
305	for (i = 0; i < saved->bo_count; i++) {
306		/* Note: Buffer sizes are expected to be aligned to 4k by the winsys. */
307		const unsigned page_size = sctx->b.screen->info.gart_page_size;
308		uint64_t va = saved->bo_list[i].vm_address;
309		uint64_t size = saved->bo_list[i].bo_size;
310		bool hit = false;
311
312		/* If there's unused virtual memory between 2 buffers, print it. */
313		if (i) {
314			uint64_t previous_va_end = saved->bo_list[i-1].vm_address +
315						   saved->bo_list[i-1].bo_size;
316
317			if (va > previous_va_end) {
318				fprintf(f, "  %10"PRIu64"    -- hole --\n",
319					(va - previous_va_end) / page_size);
320			}
321		}
322
323		/* Print the buffer. */
324		fprintf(f, "  %10"PRIu64"    0x%013"PRIX64"       0x%013"PRIX64"       ",
325			size / page_size, va / page_size, (va + size) / page_size);
326
327		/* Print the usage. */
328		for (j = 0; j < 64; j++) {
329			if (!(saved->bo_list[i].priority_usage & (1llu << j)))
330				continue;
331
332			fprintf(f, "%s%s", !hit ? "" : ", ", priority_to_string(j));
333			hit = true;
334		}
335		fprintf(f, "\n");
336	}
337	fprintf(f, "\nNote: The holes represent memory not used by the IB.\n"
338		   "      Other buffers can still be allocated there.\n\n");
339}
340
341static void si_dump_framebuffer(struct si_context *sctx, FILE *f)
342{
343	struct pipe_framebuffer_state *state = &sctx->framebuffer.state;
344	struct r600_texture *rtex;
345	int i;
346
347	for (i = 0; i < state->nr_cbufs; i++) {
348		if (!state->cbufs[i])
349			continue;
350
351		rtex = (struct r600_texture*)state->cbufs[i]->texture;
352		fprintf(f, COLOR_YELLOW "Color buffer %i:" COLOR_RESET "\n", i);
353		r600_print_texture_info(rtex, f);
354		fprintf(f, "\n");
355	}
356
357	if (state->zsbuf) {
358		rtex = (struct r600_texture*)state->zsbuf->texture;
359		fprintf(f, COLOR_YELLOW "Depth-stencil buffer:" COLOR_RESET "\n");
360		r600_print_texture_info(rtex, f);
361		fprintf(f, "\n");
362	}
363}
364
365static void si_dump_descriptor_list(struct si_descriptors *desc,
366				    const char *shader_name,
367				    const char *elem_name,
368				    unsigned num_elements,
369				    FILE *f)
370{
371	unsigned i, j;
372	uint32_t *cpu_list = desc->list;
373	uint32_t *gpu_list = desc->gpu_list;
374	const char *list_note = "GPU list";
375
376	if (!gpu_list) {
377		gpu_list = cpu_list;
378		list_note = "CPU list";
379	}
380
381	for (i = 0; i < num_elements; i++) {
382		fprintf(f, COLOR_GREEN "%s%s slot %u (%s):" COLOR_RESET "\n",
383			shader_name, elem_name, i, list_note);
384
385		switch (desc->element_dw_size) {
386		case 4:
387			for (j = 0; j < 4; j++)
388				ac_dump_reg(f, R_008F00_SQ_BUF_RSRC_WORD0 + j*4,
389					    gpu_list[j], 0xffffffff);
390			break;
391		case 8:
392			for (j = 0; j < 8; j++)
393				ac_dump_reg(f, R_008F10_SQ_IMG_RSRC_WORD0 + j*4,
394					    gpu_list[j], 0xffffffff);
395
396			fprintf(f, COLOR_CYAN "    Buffer:" COLOR_RESET "\n");
397			for (j = 0; j < 4; j++)
398				ac_dump_reg(f, R_008F00_SQ_BUF_RSRC_WORD0 + j*4,
399					    gpu_list[4+j], 0xffffffff);
400			break;
401		case 16:
402			for (j = 0; j < 8; j++)
403				ac_dump_reg(f, R_008F10_SQ_IMG_RSRC_WORD0 + j*4,
404					    gpu_list[j], 0xffffffff);
405
406			fprintf(f, COLOR_CYAN "    Buffer:" COLOR_RESET "\n");
407			for (j = 0; j < 4; j++)
408				ac_dump_reg(f, R_008F00_SQ_BUF_RSRC_WORD0 + j*4,
409					    gpu_list[4+j], 0xffffffff);
410
411			fprintf(f, COLOR_CYAN "    FMASK:" COLOR_RESET "\n");
412			for (j = 0; j < 8; j++)
413				ac_dump_reg(f, R_008F10_SQ_IMG_RSRC_WORD0 + j*4,
414					    gpu_list[8+j], 0xffffffff);
415
416			fprintf(f, COLOR_CYAN "    Sampler state:" COLOR_RESET "\n");
417			for (j = 0; j < 4; j++)
418				ac_dump_reg(f, R_008F30_SQ_IMG_SAMP_WORD0 + j*4,
419					    gpu_list[12+j], 0xffffffff);
420			break;
421		}
422
423		if (memcmp(gpu_list, cpu_list, desc->element_dw_size * 4) != 0) {
424			fprintf(f, COLOR_RED "!!!!! This slot was corrupted in GPU memory !!!!!"
425				COLOR_RESET "\n");
426		}
427
428		fprintf(f, "\n");
429		gpu_list += desc->element_dw_size;
430		cpu_list += desc->element_dw_size;
431	}
432}
433
434static void si_dump_descriptors(struct si_context *sctx,
435				struct si_shader_ctx_state *state,
436				FILE *f)
437{
438	if (!state->cso || !state->current)
439		return;
440
441	unsigned type = state->cso->type;
442	const struct tgsi_shader_info *info = &state->cso->info;
443	struct si_descriptors *descs =
444		&sctx->descriptors[SI_DESCS_FIRST_SHADER +
445				   type * SI_NUM_SHADER_DESCS];
446	static const char *shader_name[] = {"VS", "PS", "GS", "TCS", "TES", "CS"};
447
448	static const char *elem_name[] = {
449		" - Constant buffer",
450		" - Shader buffer",
451		" - Sampler",
452		" - Image",
453	};
454	unsigned num_elements[] = {
455		util_last_bit(info->const_buffers_declared),
456		util_last_bit(info->shader_buffers_declared),
457		util_last_bit(info->samplers_declared),
458		util_last_bit(info->images_declared),
459	};
460
461	if (type == PIPE_SHADER_VERTEX) {
462		si_dump_descriptor_list(&sctx->vertex_buffers, shader_name[type],
463					" - Vertex buffer", info->num_inputs, f);
464	}
465
466	for (unsigned i = 0; i < SI_NUM_SHADER_DESCS; ++i, ++descs)
467		si_dump_descriptor_list(descs, shader_name[type], elem_name[i],
468					num_elements[i], f);
469}
470
471static void si_dump_debug_state(struct pipe_context *ctx, FILE *f,
472				unsigned flags)
473{
474	struct si_context *sctx = (struct si_context*)ctx;
475
476	if (flags & PIPE_DUMP_DEVICE_STATUS_REGISTERS)
477		si_dump_debug_registers(sctx, f);
478
479	if (flags & PIPE_DUMP_CURRENT_STATES)
480		si_dump_framebuffer(sctx, f);
481
482	if (flags & PIPE_DUMP_CURRENT_SHADERS) {
483		si_dump_shader(sctx->screen, &sctx->vs_shader, f);
484		si_dump_shader(sctx->screen, &sctx->tcs_shader, f);
485		si_dump_shader(sctx->screen, &sctx->tes_shader, f);
486		si_dump_shader(sctx->screen, &sctx->gs_shader, f);
487		si_dump_shader(sctx->screen, &sctx->ps_shader, f);
488
489		si_dump_descriptor_list(&sctx->descriptors[SI_DESCS_RW_BUFFERS],
490					"", "RW buffers", SI_NUM_RW_BUFFERS, f);
491		si_dump_descriptors(sctx, &sctx->vs_shader, f);
492		si_dump_descriptors(sctx, &sctx->tcs_shader, f);
493		si_dump_descriptors(sctx, &sctx->tes_shader, f);
494		si_dump_descriptors(sctx, &sctx->gs_shader, f);
495		si_dump_descriptors(sctx, &sctx->ps_shader, f);
496	}
497
498	if (flags & PIPE_DUMP_LAST_COMMAND_BUFFER) {
499		si_dump_bo_list(sctx, &sctx->last_gfx, f);
500		si_dump_last_ib(sctx, f);
501
502		fprintf(f, "Done.\n");
503
504		/* dump only once */
505		radeon_clear_saved_cs(&sctx->last_gfx);
506		r600_resource_reference(&sctx->last_trace_buf, NULL);
507	}
508}
509
510static void si_dump_dma(struct si_context *sctx,
511			struct radeon_saved_cs *saved, FILE *f)
512{
513	static const char ib_name[] = "sDMA IB";
514	unsigned i;
515
516	si_dump_bo_list(sctx, saved, f);
517
518	fprintf(f, "------------------ %s begin ------------------\n", ib_name);
519
520	for (i = 0; i < saved->num_dw; ++i) {
521		fprintf(f, " %08x\n", saved->ib[i]);
522	}
523
524	fprintf(f, "------------------- %s end -------------------\n", ib_name);
525	fprintf(f, "\n");
526
527	fprintf(f, "SDMA Dump Done.\n");
528}
529
530static bool si_vm_fault_occured(struct si_context *sctx, uint32_t *out_addr)
531{
532	char line[2000];
533	unsigned sec, usec;
534	int progress = 0;
535	uint64_t timestamp = 0;
536	bool fault = false;
537
538	FILE *p = popen("dmesg", "r");
539	if (!p)
540		return false;
541
542	while (fgets(line, sizeof(line), p)) {
543		char *msg, len;
544
545		if (!line[0] || line[0] == '\n')
546			continue;
547
548		/* Get the timestamp. */
549		if (sscanf(line, "[%u.%u]", &sec, &usec) != 2) {
550			static bool hit = false;
551			if (!hit) {
552				fprintf(stderr, "%s: failed to parse line '%s'\n",
553					__func__, line);
554				hit = true;
555			}
556			continue;
557		}
558		timestamp = sec * 1000000llu + usec;
559
560		/* If just updating the timestamp. */
561		if (!out_addr)
562			continue;
563
564		/* Process messages only if the timestamp is newer. */
565		if (timestamp <= sctx->dmesg_timestamp)
566			continue;
567
568		/* Only process the first VM fault. */
569		if (fault)
570			continue;
571
572		/* Remove trailing \n */
573		len = strlen(line);
574		if (len && line[len-1] == '\n')
575			line[len-1] = 0;
576
577		/* Get the message part. */
578		msg = strchr(line, ']');
579		if (!msg) {
580			assert(0);
581			continue;
582		}
583		msg++;
584
585		switch (progress) {
586		case 0:
587			if (strstr(msg, "GPU fault detected:"))
588				progress = 1;
589			break;
590		case 1:
591			msg = strstr(msg, "VM_CONTEXT1_PROTECTION_FAULT_ADDR");
592			if (msg) {
593				msg = strstr(msg, "0x");
594				if (msg) {
595					msg += 2;
596					if (sscanf(msg, "%X", out_addr) == 1)
597						fault = true;
598				}
599			}
600			progress = 0;
601			break;
602		default:
603			progress = 0;
604		}
605	}
606	pclose(p);
607
608	if (timestamp > sctx->dmesg_timestamp)
609		sctx->dmesg_timestamp = timestamp;
610	return fault;
611}
612
613void si_check_vm_faults(struct r600_common_context *ctx,
614			struct radeon_saved_cs *saved, enum ring_type ring)
615{
616	struct si_context *sctx = (struct si_context *)ctx;
617	struct pipe_screen *screen = sctx->b.b.screen;
618	FILE *f;
619	uint32_t addr;
620	char cmd_line[4096];
621
622	if (!si_vm_fault_occured(sctx, &addr))
623		return;
624
625	f = dd_get_debug_file(false);
626	if (!f)
627		return;
628
629	fprintf(f, "VM fault report.\n\n");
630	if (os_get_command_line(cmd_line, sizeof(cmd_line)))
631		fprintf(f, "Command: %s\n", cmd_line);
632	fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
633	fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
634	fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
635	fprintf(f, "Failing VM page: 0x%08x\n\n", addr);
636
637	if (sctx->apitrace_call_number)
638		fprintf(f, "Last apitrace call: %u\n\n",
639			sctx->apitrace_call_number);
640
641	switch (ring) {
642	case RING_GFX:
643		si_dump_debug_state(&sctx->b.b, f,
644				    PIPE_DUMP_CURRENT_STATES |
645				    PIPE_DUMP_CURRENT_SHADERS |
646				    PIPE_DUMP_LAST_COMMAND_BUFFER);
647		break;
648
649	case RING_DMA:
650		si_dump_dma(sctx, saved, f);
651		break;
652
653	default:
654		break;
655	}
656
657	fclose(f);
658
659	fprintf(stderr, "Detected a VM fault, exiting...\n");
660	exit(0);
661}
662
663void si_init_debug_functions(struct si_context *sctx)
664{
665	sctx->b.b.dump_debug_state = si_dump_debug_state;
666	sctx->b.check_vm_faults = si_check_vm_faults;
667
668	/* Set the initial dmesg timestamp for this context, so that
669	 * only new messages will be checked for VM faults.
670	 */
671	if (sctx->screen->b.debug_flags & DBG_CHECK_VM)
672		si_vm_fault_occured(sctx, NULL);
673}
674