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