- char line[2000];
- unsigned sec, usec;
- int progress = 0;
- uint64_t timestamp = 0;
- bool fault = false;
-
- FILE *p = popen("dmesg", "r");
- if (!p)
- return false;
-
- while (fgets(line, sizeof(line), p)) {
- char *msg, len;
-
- if (!line[0] || line[0] == '\n')
- continue;
-
- /* Get the timestamp. */
- if (sscanf(line, "[%u.%u]", &sec, &usec) != 2) {
- static bool hit = false;
- if (!hit) {
- fprintf(stderr, "%s: failed to parse line '%s'\n",
- __func__, line);
- hit = true;
- }
- continue;
- }
- timestamp = sec * 1000000ull + usec;
-
- /* If just updating the timestamp. */
- if (!out_addr)
- continue;
-
- /* Process messages only if the timestamp is newer. */
- if (timestamp <= sctx->dmesg_timestamp)
- continue;
-
- /* Only process the first VM fault. */
- if (fault)
- continue;
-
- /* Remove trailing \n */
- len = strlen(line);
- if (len && line[len-1] == '\n')
- line[len-1] = 0;
-
- /* Get the message part. */
- msg = strchr(line, ']');
- if (!msg) {
- assert(0);
- continue;
- }
- msg++;
-
- const char *header_line, *addr_line_prefix, *addr_line_format;
-
- if (sctx->b.chip_class >= GFX9) {
- /* Match this:
- * ..: [gfxhub] VMC page fault (src_id:0 ring:158 vm_id:2 pas_id:0)
- * ..: at page 0x0000000219f8f000 from 27
- * ..: VM_L2_PROTECTION_FAULT_STATUS:0x0020113C
- */
- header_line = "VMC page fault";
- addr_line_prefix = " at page";
- addr_line_format = "%"PRIx64;
- } else {
- header_line = "GPU fault detected:";
- addr_line_prefix = "VM_CONTEXT1_PROTECTION_FAULT_ADDR";
- addr_line_format = "%"PRIX64;
- }
-
- switch (progress) {
- case 0:
- if (strstr(msg, header_line))
- progress = 1;
- break;
- case 1:
- msg = strstr(msg, addr_line_prefix);
- if (msg) {
- msg = strstr(msg, "0x");
- if (msg) {
- msg += 2;
- if (sscanf(msg, addr_line_format, out_addr) == 1)
- fault = true;
- }
- }
- progress = 0;
- break;
- default:
- progress = 0;
- }
- }
- pclose(p);
-
- if (timestamp > sctx->dmesg_timestamp)
- sctx->dmesg_timestamp = timestamp;
- return fault;
-}
-
-void si_check_vm_faults(struct r600_common_context *ctx,
- struct radeon_saved_cs *saved, enum ring_type ring)
-{
- struct si_context *sctx = (struct si_context *)ctx;
- struct pipe_screen *screen = sctx->b.b.screen;
- FILE *f;
- uint64_t addr;
- char cmd_line[4096];
-
- if (!si_vm_fault_occured(sctx, &addr))
- return;
-
- f = dd_get_debug_file(false);
- if (!f)
- return;
-
- fprintf(f, "VM fault report.\n\n");
- if (os_get_command_line(cmd_line, sizeof(cmd_line)))
- fprintf(f, "Command: %s\n", cmd_line);
- fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
- fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
- fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
- fprintf(f, "Failing VM page: 0x%08"PRIx64"\n\n", addr);
-
- if (sctx->apitrace_call_number)
- fprintf(f, "Last apitrace call: %u\n\n",
- sctx->apitrace_call_number);
-
- switch (ring) {
- case RING_GFX: {
- struct u_log_context log;
- u_log_context_init(&log);
-
- si_log_draw_state(sctx, &log);
- si_log_compute_state(sctx, &log);
-
- u_log_new_page_print(&log, f);
- u_log_context_destroy(&log);
- break;
- }
- case RING_DMA:
- si_dump_dma(sctx, saved, f);
- break;
-
- default:
- break;
- }
-
- fclose(f);
-
- fprintf(stderr, "Detected a VM fault, exiting...\n");
- exit(0);
+ struct pipe_screen *screen = sctx->b.screen;
+ FILE *f;
+ uint64_t addr;
+ char cmd_line[4096];
+
+ if (!ac_vm_fault_occured(sctx->chip_class, &sctx->dmesg_timestamp, &addr))
+ return;
+
+ f = dd_get_debug_file(false);
+ if (!f)
+ return;
+
+ fprintf(f, "VM fault report.\n\n");
+ if (os_get_command_line(cmd_line, sizeof(cmd_line)))
+ fprintf(f, "Command: %s\n", cmd_line);
+ fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
+ fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
+ fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
+ fprintf(f, "Failing VM page: 0x%08" PRIx64 "\n\n", addr);
+
+ if (sctx->apitrace_call_number)
+ fprintf(f, "Last apitrace call: %u\n\n", sctx->apitrace_call_number);
+
+ switch (ring) {
+ case RING_GFX: {
+ struct u_log_context log;
+ u_log_context_init(&log);
+
+ si_log_draw_state(sctx, &log);
+ si_log_compute_state(sctx, &log);
+ si_log_cs(sctx, &log, true);
+
+ u_log_new_page_print(&log, f);
+ u_log_context_destroy(&log);
+ break;
+ }
+ case RING_DMA:
+ si_dump_dma(sctx, saved, f);
+ break;
+
+ default:
+ break;
+ }
+
+ fclose(f);
+
+ fprintf(stderr, "Detected a VM fault, exiting...\n");
+ exit(0);