• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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          /*
53           * Workaround bug in the kernel that would put the exec queue dump
54           * in the wrong place, under "GuC CT" topic.
55           */
56       case XE_TOPIC_CONTEXT: {
57          enum xe_vm_topic_type type;
58          const char *value_ptr;
59          bool is_hw_ctx;
60 
61          type = error_decode_xe_read_hw_sp_or_ctx_line(line, &value_ptr, &is_hw_ctx);
62          if (type == XE_VM_TOPIC_TYPE_UNKNOWN || !is_hw_ctx) {
63             break;
64          }
65 
66          switch (type) {
67          case XE_VM_TOPIC_TYPE_DATA:
68             if (!error_decode_xe_ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len))
69                printf("Failed to parse HWCTX data\n");
70             break;
71          case XE_VM_TOPIC_TYPE_LENGTH: {
72             vm_entry_len = strtoul(value_ptr, NULL, 0);
73             vm_entry_data = calloc(1, vm_entry_len);
74             if (!vm_entry_data) {
75                printf("Out of memory to allocate a buffer to store content of HWCTX\n");
76                break;
77             }
78 
79             error_decode_xe_vm_hw_ctx_set(&xe_vm, vm_entry_len, vm_entry_data);
80             break;
81          }
82          case XE_VM_TOPIC_TYPE_ERROR:
83             printf("HWCTX not present in dump, content will be zeroed: %s\n", line);
84             break;
85          default:
86             printf("Not expected line in HWCTX: %s", line);
87          }
88 
89          break;
90       }
91       case XE_TOPIC_VM: {
92          enum xe_vm_topic_type type;
93          const char *value_ptr;
94          uint64_t address;
95 
96          type = error_decode_xe_read_vm_line(line, &address, &value_ptr);
97          switch (type) {
98          case XE_VM_TOPIC_TYPE_DATA: {
99             if (!error_decode_xe_ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len))
100                printf("Failed to parse VMA 0x%" PRIx64 " data\n", address);
101             break;
102          }
103          case XE_VM_TOPIC_TYPE_LENGTH: {
104             vm_entry_len = strtoul(value_ptr, NULL, 0);
105             vm_entry_data = calloc(1, vm_entry_len);
106             if (!vm_entry_data) {
107                printf("Out of memory to allocate a buffer to store content of VMA 0x%" PRIx64 "\n", address);
108                break;
109             }
110             if (!error_decode_xe_vm_append(&xe_vm, address, vm_entry_len, vm_entry_data)) {
111                printf("xe_vm_append() failed for VMA 0x%" PRIx64 "\n", address);
112             }
113             break;
114          }
115          case XE_VM_TOPIC_TYPE_ERROR:
116             printf("VMA 0x%" PRIx64 " not present in dump, content will be zeroed: %s\n", address, line);
117             break;
118          default:
119             printf("Not expected line in VM state: %s", line);
120          }
121 
122          break;
123       }
124       default:
125          break;
126       }
127    }
128 
129    if (verbose) {
130       fprintf(stdout, "BOs found:\n");
131       for (i = 0; i < xe_vm.entries_len; i++) {
132          struct xe_vm_entry *entry = &xe_vm.entries[i];
133 
134          fprintf(stdout, "\taddr=0x%016" PRIx64 " size=%" PRIu32 "\n", entry->address, entry->length);
135       }
136    }
137 
138    fail_if(!batch_buffers.len, "Failed to find batch buffer.\n");
139    fail_if(!xe_vm.hw_context.length, "Failed to find HW image buffer.\n");
140 
141    for (i = 0; i < xe_vm.entries_len; i++) {
142       struct xe_vm_entry *entry = &xe_vm.entries[i];
143       const char *name = "user";
144       uint32_t j;
145 
146       for (j = 0; j < batch_buffers.len; j++) {
147          if (batch_buffers.addrs[j] == entry->address)
148             name = "batch";
149       }
150 
151       write_buffer(hang_dump_file, entry->address, entry->data, entry->length, name);
152    }
153 
154    fprintf(stderr, "writing image buffer size=0x%016" PRIx32 "\n", xe_vm.hw_context.length);
155    write_hw_image_buffer(hang_dump_file, xe_vm.hw_context.data, xe_vm.hw_context.length);
156 
157    for (i = 0; i < batch_buffers.len; i++) {
158       write_exec(hang_dump_file, batch_buffers.addrs[i]);
159    }
160 
161    free(batch_buffers.addrs);
162    free(line);
163    error_decode_xe_vm_fini(&xe_vm);
164 }
165