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