• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "error_decode_xe_lib.h"
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "error_decode_lib.h"
12 #include "util/macros.h"
13 
14 static const char *
read_parameter_helper(const char * line,const char * parameter)15 read_parameter_helper(const char *line, const char *parameter)
16 {
17    if (!strstr(line, parameter))
18       return NULL;
19 
20    while (*line != ':')
21       line++;
22    /* skip ':' and ' ' */
23    line += 2;
24 
25    return line;
26 }
27 
28 /* parse lines like 'batch_addr[0]: 0x0000effeffff5000 */
29 bool
error_decode_xe_read_u64_hexacimal_parameter(const char * line,const char * parameter,uint64_t * value)30 error_decode_xe_read_u64_hexacimal_parameter(const char *line, const char *parameter, uint64_t *value)
31 {
32    line = read_parameter_helper(line, parameter);
33    if (!line)
34       return false;
35 
36    *value = (uint64_t)strtoull(line, NULL, 0);
37    return true;
38 }
39 
40 /* parse lines like 'PCI ID: 0x9a49' */
41 bool
error_decode_xe_read_hexacimal_parameter(const char * line,const char * parameter,uint32_t * value)42 error_decode_xe_read_hexacimal_parameter(const char *line, const char *parameter, uint32_t *value)
43 {
44    line = read_parameter_helper(line, parameter);
45    if (!line)
46       return false;
47 
48    *value = (int)strtoul(line, NULL, 0);
49    return true;
50 }
51 
52 /* parse lines like 'rcs0 (physical), logical instance=0' */
53 bool
error_decode_xe_read_engine_name(const char * line,char * ring_name)54 error_decode_xe_read_engine_name(const char *line, char *ring_name)
55 {
56    int i;
57 
58    if (!strstr(line, " (physical), logical instance="))
59       return false;
60 
61    i = 0;
62    for (i = 0; *line != ' '; i++, line++)
63       ring_name[i] = *line;
64 
65    ring_name[i] = 0;
66    return true;
67 }
68 
69 /*
70  * when a topic string is parsed it sets new_topic and returns true, otherwise
71  * does nothing.
72  */
73 bool
error_decode_xe_decode_topic(const char * line,enum xe_topic * new_topic)74 error_decode_xe_decode_topic(const char *line, enum xe_topic *new_topic)
75 {
76    static const char *xe_topic_strings[] = {
77       "**** Xe Device Coredump ****",
78       "**** GuC CT ****",
79       "**** Job ****",
80       "**** HW Engines ****",
81       "**** VM state ****",
82       "**** Contexts ****",
83    };
84    bool topic_changed = false;
85 
86    for (int i = 0; i < ARRAY_SIZE(xe_topic_strings); i++) {
87       if (strncmp(xe_topic_strings[i], line, strlen(xe_topic_strings[i])) == 0) {
88          topic_changed = true;
89          *new_topic = i;
90          break;
91       }
92    }
93 
94    return topic_changed;
95 }
96 
97 /* return type of VM topic lines like '[200000].data: x...' and points
98  * value_ptr to first char of data of topic type
99  */
100 enum xe_vm_topic_type
error_decode_xe_read_vm_line(const char * line,uint64_t * address,const char ** value_ptr)101 error_decode_xe_read_vm_line(const char *line, uint64_t *address, const char **value_ptr)
102 {
103    enum xe_vm_topic_type type;
104    char text_addr[64];
105    int i;
106 
107    if (*line != '[')
108       return XE_VM_TOPIC_TYPE_UNKNOWN;
109 
110    for (i = 0, line++; *line != ']'; i++, line++)
111       text_addr[i] = *line;
112 
113    text_addr[i] = 0;
114    *address = (uint64_t)strtoull(text_addr, NULL, 16);
115 
116    /* at this point line points to last address digit so +3 to point to type */
117    line += 2;
118    switch (*line) {
119    case 'd':
120       type = XE_VM_TOPIC_TYPE_DATA;
121       break;
122    case 'l':
123       type = XE_VM_TOPIC_TYPE_LENGTH;
124       break;
125    case 'e':
126       type = XE_VM_TOPIC_TYPE_ERROR;
127       break;
128    default:
129       printf("type char: %c\n", *line);
130       return XE_VM_TOPIC_TYPE_UNKNOWN;
131    }
132 
133    for (; *line != ':'; line++);
134 
135    *value_ptr = line + 2;
136    return type;
137 }
138 
139 /*
140  * similar to read_xe_vm_line() but it parses '[HWCTX].data: ...'
141  */
142 enum xe_vm_topic_type
error_decode_xe_read_hw_sp_or_ctx_line(const char * line,const char ** value_ptr,bool * is_hw_ctx)143 error_decode_xe_read_hw_sp_or_ctx_line(const char *line, const char **value_ptr, bool *is_hw_ctx)
144 {
145    enum xe_vm_topic_type type;
146    char text_addr[64];
147    bool is_hw_sp;
148    int i;
149 
150    if (*line != '\t')
151       return XE_VM_TOPIC_TYPE_UNKNOWN;
152 
153    line++;
154    if (*line != '[')
155       return XE_VM_TOPIC_TYPE_UNKNOWN;
156 
157    for (i = 0, line++; *line != ']'; i++, line++)
158       text_addr[i] = *line;
159 
160    text_addr[i] = 0;
161    *is_hw_ctx = strncmp(text_addr, "HWCTX", strlen("HWCTX")) == 0;
162    is_hw_sp =  strncmp(text_addr, "HWSP", strlen("HWSP")) == 0;
163    if (*is_hw_ctx == false && is_hw_sp == false)
164          return XE_VM_TOPIC_TYPE_UNKNOWN;
165 
166    /* at this point line points to last address digit so +3 to point to type */
167    line += 2;
168    switch (*line) {
169    case 'd':
170       type = XE_VM_TOPIC_TYPE_DATA;
171       break;
172    case 'l':
173       type = XE_VM_TOPIC_TYPE_LENGTH;
174       break;
175    case 'e':
176       type = XE_VM_TOPIC_TYPE_ERROR;
177       break;
178    default:
179       printf("type char: %c\n", *line);
180       return XE_VM_TOPIC_TYPE_UNKNOWN;
181    }
182 
183    for (; *line != ':'; line++);
184 
185    *value_ptr = line + 2;
186    return type;
187 }
188 
error_decode_xe_vm_init(struct xe_vm * xe_vm)189 void error_decode_xe_vm_init(struct xe_vm *xe_vm)
190 {
191    xe_vm->entries = NULL;
192    xe_vm->entries_len = 0;
193    memset(&xe_vm->hw_context, 0, sizeof(xe_vm->hw_context));
194 }
195 
error_decode_xe_vm_fini(struct xe_vm * xe_vm)196 void error_decode_xe_vm_fini(struct xe_vm *xe_vm)
197 {
198    uint32_t i;
199 
200    for (i = 0; i < xe_vm->entries_len; i++)
201       free((uint32_t *)xe_vm->entries[i].data);
202 
203    free((uint32_t *)xe_vm->hw_context.data);
204    free(xe_vm->entries);
205 }
206 
207 static void
xe_vm_entry_set(struct xe_vm_entry * entry,const uint64_t address,const uint32_t length,const uint32_t * data)208 xe_vm_entry_set(struct xe_vm_entry *entry, const uint64_t address,
209                 const uint32_t length, const uint32_t *data)
210 {
211    entry->address = address;
212    entry->length = length;
213    entry->data = data;
214 }
215 
216 void
error_decode_xe_vm_hw_ctx_set(struct xe_vm * xe_vm,const uint32_t length,const uint32_t * data)217 error_decode_xe_vm_hw_ctx_set(struct xe_vm *xe_vm, const uint32_t length,
218                               const uint32_t *data)
219 {
220    xe_vm_entry_set(&xe_vm->hw_context, 0, length, data);
221 }
222 
223 /*
224  * error_decode_xe_vm_fini() will take care to free data
225  */
226 bool
error_decode_xe_vm_append(struct xe_vm * xe_vm,const uint64_t address,const uint32_t length,const uint32_t * data)227 error_decode_xe_vm_append(struct xe_vm *xe_vm, const uint64_t address,
228                           const uint32_t length, const uint32_t *data)
229 {
230    size_t len = sizeof(*xe_vm->entries) * (xe_vm->entries_len + 1);
231 
232    xe_vm->entries = realloc(xe_vm->entries, len);
233    if (!xe_vm->entries)
234       return false;
235 
236    xe_vm_entry_set(&xe_vm->entries[xe_vm->entries_len], address, length, data);
237    xe_vm->entries_len++;
238    return true;
239 }
240 
241 const struct xe_vm_entry *
error_decode_xe_vm_entry_get(struct xe_vm * xe_vm,const uint64_t address)242 error_decode_xe_vm_entry_get(struct xe_vm *xe_vm, const uint64_t address)
243 {
244    uint32_t i;
245 
246    for (i = 0; i < xe_vm->entries_len; i++) {
247       struct xe_vm_entry *entry = &xe_vm->entries[i];
248 
249       if (entry->address == address)
250          return entry;
251 
252       if (address > entry->address &&
253           address < (entry->address + entry->length))
254          return entry;
255    }
256 
257    return NULL;
258 }
259 
260 uint32_t *
error_decode_xe_vm_entry_address_get_data(const struct xe_vm_entry * entry,const uint64_t address)261 error_decode_xe_vm_entry_address_get_data(const struct xe_vm_entry *entry,
262                                           const uint64_t address)
263 {
264    uint32_t offset = (address - entry->address) / sizeof(uint32_t);
265    return (uint32_t *)&entry->data[offset];
266 }
267 
268 uint32_t
error_decode_xe_vm_entry_address_get_len(const struct xe_vm_entry * entry,const uint64_t address)269 error_decode_xe_vm_entry_address_get_len(const struct xe_vm_entry *entry,
270                                          const uint64_t address)
271 {
272    return entry->length - (address - entry->address);
273 }
274 
275 bool
error_decode_xe_ascii85_decode_allocated(const char * in,uint32_t * out,uint32_t vm_entry_bytes_len)276 error_decode_xe_ascii85_decode_allocated(const char *in, uint32_t *out, uint32_t vm_entry_bytes_len)
277 {
278    const uint32_t dword_len = vm_entry_bytes_len / sizeof(uint32_t);
279    uint32_t i;
280 
281    for (i = 0; (*in >= '!') && (*in <= 'z') && (i < dword_len); i++)
282       in = ascii85_decode_char(in, &out[i]);
283 
284    if (dword_len != i)
285       printf("mismatch dword_len=%u i=%u\n", dword_len, i);
286 
287    return dword_len == i && (*in < '!' || *in > 'z');
288 }
289