xref: /aosp_15_r20/external/mesa3d/src/intel/tools/error2hangdump_xe.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "error2hangdump_xe.h"
7 
8 #include <inttypes.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "error_decode_xe_lib.h"
14 #include "error2hangdump_lib.h"
15 #include "intel/dev/intel_device_info.h"
16 #include "util/macros.h"
17 
18 void
read_xe_data_file(FILE * dump_file,FILE * hang_dump_file,bool verbose)19 read_xe_data_file(FILE *dump_file, FILE *hang_dump_file, bool verbose)
20 {
21    enum  xe_topic xe_topic = XE_TOPIC_INVALID;
22    uint32_t *vm_entry_data = NULL;
23    uint32_t vm_entry_len = 0;
24    struct xe_vm xe_vm;
25    char *line = NULL;
26    size_t line_size;
27    struct {
28       uint64_t *addrs;
29       uint8_t len;
30    } batch_buffers = { .addrs = NULL, .len = 0 };
31    uint32_t i;
32 
33    error_decode_xe_vm_init(&xe_vm);
34 
35    while (getline(&line, &line_size, dump_file) > 0) {
36       if (error_decode_xe_decode_topic(line, &xe_topic))
37          continue;
38 
39       switch (xe_topic) {
40       case XE_TOPIC_JOB: {
41          uint64_t u64_value;
42 
43          if (error_decode_xe_read_u64_hexacimal_parameter(line, "batch_addr[", &u64_value)) {
44             batch_buffers.addrs = realloc(batch_buffers.addrs, sizeof(uint64_t) * (batch_buffers.len + 1));
45             batch_buffers.addrs[batch_buffers.len] = u64_value;
46             batch_buffers.len++;
47          }
48 
49          break;
50       }
51       case XE_TOPIC_GUC_CT: {
52          enum xe_vm_topic_type type;
53          const char *value_ptr;
54          bool is_hw_ctx;
55 
56          type = error_decode_xe_read_hw_sp_or_ctx_line(line, &value_ptr, &is_hw_ctx);
57          if (type == XE_VM_TOPIC_TYPE_UNKNOWN || !is_hw_ctx) {
58             break;
59          }
60 
61          switch (type) {
62          case XE_VM_TOPIC_TYPE_DATA:
63             if (!error_decode_xe_ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len))
64                printf("Failed to parse HWCTX data\n");
65             break;
66          case XE_VM_TOPIC_TYPE_LENGTH: {
67             vm_entry_len = strtoul(value_ptr, NULL, 0);
68             vm_entry_data = calloc(1, vm_entry_len);
69             if (!vm_entry_data) {
70                printf("Out of memory to allocate a buffer to store content of HWCTX\n");
71                break;
72             }
73 
74             error_decode_xe_vm_hw_ctx_set(&xe_vm, vm_entry_len, vm_entry_data);
75             break;
76          }
77          case XE_VM_TOPIC_TYPE_ERROR:
78             printf("HWCTX not present in dump, content will be zeroed: %s\n", line);
79             break;
80          default:
81             printf("Not expected line in HWCTX: %s", line);
82          }
83 
84          break;
85       }
86       case XE_TOPIC_VM: {
87          enum xe_vm_topic_type type;
88          const char *value_ptr;
89          uint64_t address;
90 
91          type = error_decode_xe_read_vm_line(line, &address, &value_ptr);
92          switch (type) {
93          case XE_VM_TOPIC_TYPE_DATA: {
94             if (!error_decode_xe_ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len))
95                printf("Failed to parse VMA 0x%" PRIx64 " data\n", address);
96             break;
97          }
98          case XE_VM_TOPIC_TYPE_LENGTH: {
99             vm_entry_len = strtoul(value_ptr, NULL, 0);
100             vm_entry_data = calloc(1, vm_entry_len);
101             if (!vm_entry_data) {
102                printf("Out of memory to allocate a buffer to store content of VMA 0x%" PRIx64 "\n", address);
103                break;
104             }
105             if (!error_decode_xe_vm_append(&xe_vm, address, vm_entry_len, vm_entry_data)) {
106                printf("xe_vm_append() failed for VMA 0x%" PRIx64 "\n", address);
107             }
108             break;
109          }
110          case XE_VM_TOPIC_TYPE_ERROR:
111             printf("VMA 0x%" PRIx64 " not present in dump, content will be zeroed: %s\n", address, line);
112             break;
113          default:
114             printf("Not expected line in VM state: %s", line);
115          }
116 
117          break;
118       }
119       default:
120          break;
121       }
122    }
123 
124    if (verbose) {
125       fprintf(stdout, "BOs found:\n");
126       for (i = 0; i < xe_vm.entries_len; i++) {
127          struct xe_vm_entry *entry = &xe_vm.entries[i];
128 
129          fprintf(stdout, "\taddr=0x%016" PRIx64 " size=%" PRIu32 "\n", entry->address, entry->length);
130       }
131    }
132 
133    fail_if(!batch_buffers.len, "Failed to find batch buffer.\n");
134    fail_if(!xe_vm.hw_context.length, "Failed to find HW image buffer.\n");
135 
136    for (i = 0; i < xe_vm.entries_len; i++) {
137       struct xe_vm_entry *entry = &xe_vm.entries[i];
138       const char *name = "user";
139       uint32_t j;
140 
141       for (j = 0; j < batch_buffers.len; j++) {
142          if (batch_buffers.addrs[j] == entry->address)
143             name = "batch";
144       }
145 
146       write_buffer(hang_dump_file, entry->address, entry->data, entry->length, name);
147    }
148 
149    fprintf(stderr, "writing image buffer size=0x%016" PRIx32 "\n", xe_vm.hw_context.length);
150    write_hw_image_buffer(hang_dump_file, xe_vm.hw_context.data, xe_vm.hw_context.length);
151 
152    for (i = 0; i < batch_buffers.len; i++) {
153       write_exec(hang_dump_file, batch_buffers.addrs[i]);
154    }
155 
156    free(batch_buffers.addrs);
157    free(line);
158    error_decode_xe_vm_fini(&xe_vm);
159 }
160