fb4b4ffcfc6ce0262b8709a452973be0d9154115
2 * Copyright © 2018 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
35 #include "aub_write.h"
37 #include "intel_aub.h"
39 static void __attribute__ ((format(__printf__
, 2, 3)))
40 fail_if(int cond
, const char *format
, ...)
47 va_start(args
, format
);
48 vfprintf(stderr
, format
, args
);
54 #define fail(...) fail_if(true, __VA_ARGS__)
56 static int zlib_inflate(uint32_t **ptr
, int len
)
58 struct z_stream_s zstream
;
60 const uint32_t out_size
= 128*4096; /* approximate obj size */
62 memset(&zstream
, 0, sizeof(zstream
));
64 zstream
.next_in
= (unsigned char *)*ptr
;
65 zstream
.avail_in
= 4*len
;
67 if (inflateInit(&zstream
) != Z_OK
)
70 out
= malloc(out_size
);
71 zstream
.next_out
= out
;
72 zstream
.avail_out
= out_size
;
75 switch (inflate(&zstream
, Z_SYNC_FLUSH
)) {
85 if (zstream
.avail_out
)
88 out
= realloc(out
, 2*zstream
.total_out
);
94 zstream
.next_out
= (unsigned char *)out
+ zstream
.total_out
;
95 zstream
.avail_out
= zstream
.total_out
;
101 return zstream
.total_out
/ 4;
104 static int ascii85_decode(const char *in
, uint32_t **out
, bool inflate
)
106 int len
= 0, size
= 1024;
108 *out
= realloc(*out
, sizeof(uint32_t)*size
);
112 while (*in
>= '!' && *in
<= 'z') {
117 *out
= realloc(*out
, sizeof(uint32_t)*size
);
125 v
+= in
[0] - 33; v
*= 85;
126 v
+= in
[1] - 33; v
*= 85;
127 v
+= in
[2] - 33; v
*= 85;
128 v
+= in
[3] - 33; v
*= 85;
138 return zlib_inflate(out
, len
);
142 print_help(const char *progname
, FILE *file
)
145 "Usage: %s [OPTION]... [FILE]\n"
146 "Convert an Intel GPU i915 error state to an aub file.\n"
147 " -h, --help display this help and exit\n"
148 " -o, --output=FILE the output aub file (default FILE.aub)\n",
153 main(int argc
, char *argv
[])
157 char *out_filename
= NULL
, *in_filename
= NULL
;
158 const struct option aubinator_opts
[] = {
159 { "help", no_argument
, NULL
, 'h' },
160 { "output", required_argument
, NULL
, 'o' },
165 while ((c
= getopt_long(argc
, argv
, "ho:", aubinator_opts
, &i
)) != -1) {
171 out_filename
= strdup(optarg
);
179 in_filename
= argv
[optind
++];
181 if (help
|| argc
== 1 || !in_filename
) {
182 print_help(argv
[0], stderr
);
183 return in_filename
? EXIT_SUCCESS
: EXIT_FAILURE
;
186 if (out_filename
== NULL
) {
187 int out_filename_size
= strlen(in_filename
) + 5;
188 out_filename
= malloc(out_filename_size
);
189 snprintf(out_filename
, out_filename_size
, "%s.aub", in_filename
);
192 FILE *err_file
= fopen(in_filename
, "r");
193 fail_if(!err_file
, "Failed to open error file \"%s\": %m\n", in_filename
);
195 FILE *aub_file
= fopen(out_filename
, "w");
196 fail_if(!aub_file
, "Failed to open aub file \"%s\": %m\n", in_filename
);
198 struct aub_file aub
= {};
200 uint32_t active_ring
= 0;
201 int num_ring_bos
= 0;
203 uint64_t batch_addr
= 0;
209 } bo_type
= BO_TYPE_UNKNOWN
;
210 uint64_t bo_addr
= 0;
214 while (getline(&line
, &line_size
, err_file
) > 0) {
215 const char *pci_id_start
= strstr(line
, "PCI ID");
218 int matched
= sscanf(line
, "PCI ID: 0x%04x\n", &pci_id
);
219 fail_if(!matched
, "Invalid error state file!\n");
221 aub_file_init(&aub
, aub_file
, pci_id
);
222 fail_if(!aub_use_execlists(&aub
),
223 "%s currently only works on gen8+\n", argv
[0]);
225 aub_write_header(&aub
, "error state");
229 const char *active_start
= "Active (";
230 if (strncmp(line
, active_start
, strlen(active_start
)) == 0) {
231 fail_if(active_ring
!= 0, "TODO: Handle multiple active rings\n");
233 char *ring
= line
+ strlen(active_start
);
239 { "rcs", I915_EXEC_RENDER
},
240 { "vcs", I915_EXEC_VEBOX
},
241 { "bcs", I915_EXEC_BLT
},
242 { NULL
, BO_TYPE_UNKNOWN
},
245 for (r
= rings
; r
->match
; r
++) {
246 if (strncasecmp(ring
, r
->match
, strlen(r
->match
)) == 0) {
247 active_ring
= r
->ring
;
252 char *count
= strchr(ring
, '[');
253 fail_if(!count
|| sscanf(count
, "[%d]:", &num_ring_bos
) < 1,
254 "Failed to parse BO table header\n");
258 if (num_ring_bos
> 0) {
259 unsigned hi
, lo
, size
;
260 if (sscanf(line
, " %x_%x %d", &hi
, &lo
, &size
) == 3) {
261 assert(aub_use_execlists(&aub
));
262 aub_map_ppgtt(&aub
, ((uint64_t)hi
) << 32 | lo
, size
);
265 fail("Not enough BO entries in the active table\n");
270 if (line
[0] == ':' || line
[0] == '~') {
271 if (bo_type
== BO_TYPE_UNKNOWN
)
274 uint32_t *data
= NULL
;
275 int count
= ascii85_decode(line
+1, &data
, line
[0] == ':');
276 fail_if(count
== 0, "ASCII85 decode failed.\n");
277 uint64_t bo_size
= count
* 4;
279 if (bo_type
== BO_TYPE_BATCH
) {
280 aub_write_trace_block(&aub
, AUB_TRACE_TYPE_BATCH
,
281 data
, bo_size
, bo_addr
);
282 batch_addr
= bo_addr
;
284 assert(bo_type
== BO_TYPE_USER
);
285 aub_write_trace_block(&aub
, AUB_TRACE_TYPE_NOTYPE
,
286 data
, bo_size
, bo_addr
);
292 char *dashes
= strstr(line
, "---");
300 { "gtt_offset", BO_TYPE_BATCH
},
301 { "user", BO_TYPE_USER
},
302 { NULL
, BO_TYPE_UNKNOWN
},
305 bo_type
= BO_TYPE_UNKNOWN
;
306 for (b
= bo_types
; b
->match
; b
++) {
307 if (strncasecmp(dashes
, b
->match
, strlen(b
->match
)) == 0) {
313 if (bo_type
!= BO_TYPE_UNKNOWN
) {
315 dashes
= strchr(dashes
, '=');
316 if (dashes
&& sscanf(dashes
, "= 0x%08x %08x\n", &hi
, &lo
) == 2) {
317 bo_addr
= ((uint64_t) hi
) << 32 | lo
;
319 fail("User BO does not have an address\n");
326 fail_if(!batch_addr
, "Failed to find batch buffer.\n");
328 aub_write_exec(&aub
, batch_addr
, aub_gtt_size(&aub
), I915_EXEC_RENDER
);
336 aub_file_finish(&aub
);
337 } else if(aub_file
) {
343 /* vim: set ts=8 sw=8 tw=0 cino=:0,(0 noet :*/