1 /*
2 * Copyright © 2021 Google, Inc.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "util/macros.h"
7 #include "crashdec.h"
8
9 static const char *hfi_msg_name(unsigned msgid);
10
11 /*
12 * Decode HFI queues
13 */
14
15 /* HFI message types */
16
17 #define HFI_MSG_CMD 0
18 #define HFI_MSG_ACK 1
19 #define HFI_MSG_ACK_V1 2
20
21 #define HFI_HEADER_ID(msg) ((msg) & 0xff)
22 /* Note that header size includes the header itself: */
23 #define HFI_HEADER_SIZE(msg) (((msg) >> 8) & 0xff)
24 #define HFI_HEADER_TYPE(msg) (((msg) >> 16) & 0xf)
25 #define HFI_HEADER_SEQNUM(msg) (((msg) >> 20) & 0xfff)
26
27 struct a6xx_hfi_queue_header {
28 uint32_t status;
29 uint32_t iova;
30 uint32_t type;
31 uint32_t size;
32 uint32_t msg_size;
33 uint32_t dropped;
34 uint32_t rx_watermark;
35 uint32_t tx_watermark;
36 uint32_t rx_request;
37 uint32_t tx_request;
38 uint32_t read_index;
39 uint32_t write_index;
40 };
41
42 struct a6xx_hfi_queue_table_header {
43 uint32_t version;
44 uint32_t size; /* Size of the queue table in dwords */
45 uint32_t qhdr0_offset; /* Offset of the first queue header */
46 uint32_t qhdr_size; /* Size of the queue headers */
47 uint32_t num_queues; /* Number of total queues */
48 uint32_t active_queues; /* Number of active queues */
49 struct a6xx_hfi_queue_header queue[];
50 };
51
52 /*
53 * HFI message definitions:
54 */
55
56 #define HFI_F2H_MSG_ACK 126
57
58 struct a6xx_hfi_msg_response {
59 uint32_t header;
60 uint32_t ret_header;
61 uint32_t error;
62 uint32_t payload[16];
63 };
64
65 static void
decode_F2H_MSG_ACK(struct a6xx_hfi_msg_response * msg)66 decode_F2H_MSG_ACK(struct a6xx_hfi_msg_response *msg)
67 {
68 unsigned msgid = HFI_HEADER_ID(msg->ret_header);
69
70 printf("\t\t\t\tret_header: %s (id=%u, size=%u, type=%u, seqnum=%u)\n",
71 hfi_msg_name(msgid), msgid, HFI_HEADER_SIZE(msg->ret_header),
72 HFI_HEADER_TYPE(msg->ret_header), HFI_HEADER_SEQNUM(msg->ret_header));
73 printf("\t\t\t\terror: %u\n", msg->error);
74 }
75
76 #define HFI_F2H_MSG_ERROR 100
77
78 struct a6xx_hfi_msg_error {
79 uint32_t header;
80 uint32_t code;
81 uint32_t payload[2];
82 };
83
84 static void
decode_F2H_MSG_ERROR(struct a6xx_hfi_msg_error * msg)85 decode_F2H_MSG_ERROR(struct a6xx_hfi_msg_error *msg)
86 {
87 printf("\t\t\t\tcode: %u\n", msg->code);
88 }
89
90 #define HFI_H2F_MSG_INIT 0
91
92 struct a6xx_hfi_msg_gmu_init_cmd {
93 uint32_t header;
94 uint32_t seg_id;
95 uint32_t dbg_buffer_addr;
96 uint32_t dbg_buffer_size;
97 uint32_t boot_state;
98 };
99
100 static void
decode_H2F_MSG_INIT(struct a6xx_hfi_msg_gmu_init_cmd * msg)101 decode_H2F_MSG_INIT(struct a6xx_hfi_msg_gmu_init_cmd *msg)
102 {
103 printf("\t\t\t\tseg_id: %u\n", msg->seg_id);
104 printf("\t\t\t\tdbg_buffer_addr: 0x%08x\n", msg->dbg_buffer_addr);
105 printf("\t\t\t\tdbg_buffer_size: %u\n", msg->dbg_buffer_size);
106 printf("\t\t\t\tboot_state: %u\n", msg->boot_state);
107 }
108
109 #define HFI_H2F_MSG_FW_VERSION 1
110
111 struct a6xx_hfi_msg_fw_version {
112 uint32_t header;
113 uint32_t supported_version;
114 };
115
116 static void
decode_H2F_MSG_FW_VERSION(struct a6xx_hfi_msg_fw_version * msg)117 decode_H2F_MSG_FW_VERSION(struct a6xx_hfi_msg_fw_version *msg)
118 {
119 printf("\t\t\t\tsupported_version: 0x%x\n", msg->supported_version);
120 }
121
122 #define HFI_H2F_MSG_PERF_TABLE 4
123
124 struct perf_level {
125 uint32_t vote;
126 uint32_t freq;
127 };
128
129 struct perf_gx_level {
130 uint32_t vote;
131 uint32_t acd;
132 uint32_t freq;
133 };
134
135 struct a6xx_hfi_msg_perf_table_v1 {
136 uint32_t header;
137 uint32_t num_gpu_levels;
138 uint32_t num_gmu_levels;
139
140 struct perf_level gx_votes[16];
141 struct perf_level cx_votes[4];
142 };
143
144 struct a6xx_hfi_msg_perf_table {
145 uint32_t header;
146 uint32_t num_gpu_levels;
147 uint32_t num_gmu_levels;
148
149 struct perf_gx_level gx_votes[16];
150 struct perf_level cx_votes[4];
151 };
152
153 static void
decode_H2F_MSG_PERF_TABLE(void * _msg)154 decode_H2F_MSG_PERF_TABLE(void *_msg)
155 {
156 if (is_gmu_legacy()) {
157 struct a6xx_hfi_msg_perf_table_v1 *msg = _msg;
158 unsigned i;
159
160 printf("\t\t\t\tnum_gpu_levels: %u\n", msg->num_gpu_levels);
161 printf("\t\t\t\tnum_gmu_levels: %u\n", msg->num_gmu_levels);
162
163 assert(msg->num_gpu_levels <= ARRAY_SIZE(msg->gx_votes));
164 for (i = 0; i < msg->num_gpu_levels; i++) {
165 printf("\t\t\t\tgx_vote[%u]: vote=%u, freq=%u\n", i,
166 msg->gx_votes[i].vote, msg->gx_votes[i].freq);
167 }
168
169 for (; i < ARRAY_SIZE(msg->gx_votes); i++) {
170 assert(!msg->gx_votes[i].vote);
171 assert(!msg->gx_votes[i].freq);
172 }
173
174 assert(msg->num_gmu_levels <= ARRAY_SIZE(msg->cx_votes));
175 for (i = 0; i < msg->num_gmu_levels; i++) {
176 printf("\t\t\t\tcx_vote[%u]: vote=%u, freq=%u\n", i,
177 msg->cx_votes[i].vote, msg->cx_votes[i].freq);
178 }
179
180 for (; i < ARRAY_SIZE(msg->cx_votes); i++) {
181 assert(!msg->cx_votes[i].vote);
182 assert(!msg->cx_votes[i].freq);
183 }
184 } else {
185 struct a6xx_hfi_msg_perf_table *msg = _msg;
186 unsigned i;
187
188 printf("\t\t\t\tnum_gpu_levels: %u\n", msg->num_gpu_levels);
189 printf("\t\t\t\tnum_gmu_levels: %u\n", msg->num_gmu_levels);
190
191 assert(msg->num_gpu_levels <= ARRAY_SIZE(msg->gx_votes));
192 for (i = 0; i < msg->num_gpu_levels; i++) {
193 printf("\t\t\t\tgx_vote[%u]: vote=%u, acd=%u, freq=%u\n", i,
194 msg->gx_votes[i].vote, msg->gx_votes[i].acd,
195 msg->gx_votes[i].freq);
196 }
197
198 for (; i < ARRAY_SIZE(msg->gx_votes); i++) {
199 assert(!msg->gx_votes[i].vote);
200 assert(!msg->gx_votes[i].acd);
201 assert(!msg->gx_votes[i].freq);
202 }
203
204 assert(msg->num_gmu_levels <= ARRAY_SIZE(msg->cx_votes));
205 for (i = 0; i < msg->num_gmu_levels; i++) {
206 printf("\t\t\t\tcx_vote[%u]: vote=%u, freq=%u\n", i,
207 msg->cx_votes[i].vote, msg->cx_votes[i].freq);
208 }
209
210 for (; i < ARRAY_SIZE(msg->cx_votes); i++) {
211 assert(!msg->cx_votes[i].vote);
212 assert(!msg->cx_votes[i].freq);
213 }
214 }
215 }
216
217 #define HFI_H2F_MSG_BW_TABLE 3
218
219 struct a6xx_hfi_msg_bw_table {
220 uint32_t header;
221 uint32_t bw_level_num;
222 uint32_t cnoc_cmds_num;
223 uint32_t ddr_cmds_num;
224 uint32_t cnoc_wait_bitmask;
225 uint32_t ddr_wait_bitmask;
226 uint32_t cnoc_cmds_addrs[6];
227 uint32_t cnoc_cmds_data[2][6];
228 uint32_t ddr_cmds_addrs[8];
229 uint32_t ddr_cmds_data[16][8];
230 };
231
232 static void
decode_H2F_MSG_BW_TABLE(struct a6xx_hfi_msg_bw_table * msg)233 decode_H2F_MSG_BW_TABLE(struct a6xx_hfi_msg_bw_table *msg)
234 {
235 printf("\t\t\t\tbw_level_num: %u\n", msg->bw_level_num);
236 printf("\t\t\t\tcnoc_cmds_num: %u\n", msg->cnoc_cmds_num);
237 printf("\t\t\t\tddr_cmds_num: %u\n", msg->ddr_cmds_num);
238 printf("\t\t\t\tcnoc_wait_bitmask: 0x%x\n", msg->cnoc_wait_bitmask);
239 printf("\t\t\t\tddr_wait_bitmask: 0x%x\n", msg->ddr_wait_bitmask);
240 printf("\t\t\t\tcnoc_cmds_addrs: %08x %08x %08x %08x %08x %08x\n",
241 msg->cnoc_cmds_addrs[0], msg->cnoc_cmds_addrs[1], msg->cnoc_cmds_addrs[2],
242 msg->cnoc_cmds_addrs[3], msg->cnoc_cmds_addrs[4], msg->cnoc_cmds_addrs[5]);
243 for (unsigned i = 0; i < ARRAY_SIZE(msg->cnoc_cmds_data); i++) {
244 printf("\t\t\t\tcnoc_cmds_data[%u]: %08x %08x %08x %08x %08x %08x\n", i,
245 msg->cnoc_cmds_data[i][0], msg->cnoc_cmds_data[i][1], msg->cnoc_cmds_data[i][2],
246 msg->cnoc_cmds_data[i][3], msg->cnoc_cmds_data[i][4], msg->cnoc_cmds_data[i][5]);
247 }
248 printf("\t\t\t\tddr_cmds_addrs: %08x %08x %08x %08x %08x %08x %08x %08x\n",
249 msg->ddr_cmds_addrs[0], msg->ddr_cmds_addrs[1], msg->ddr_cmds_addrs[2],
250 msg->ddr_cmds_addrs[3], msg->ddr_cmds_addrs[4], msg->ddr_cmds_addrs[5],
251 msg->ddr_cmds_addrs[6], msg->ddr_cmds_addrs[7]);
252 for (unsigned i = 0; i < ARRAY_SIZE(msg->ddr_cmds_data); i++) {
253 printf("\t\t\t\tddr_cmds_data[%u]: %08x %08x %08x %08x %08x %08x %08x %08x\n", i,
254 msg->ddr_cmds_data[i][0], msg->ddr_cmds_data[i][1], msg->ddr_cmds_data[i][2],
255 msg->ddr_cmds_data[i][3], msg->ddr_cmds_data[i][4], msg->ddr_cmds_data[i][5],
256 msg->ddr_cmds_data[i][6], msg->ddr_cmds_data[i][7]);
257 }
258 }
259
260 #define HFI_H2F_MSG_TEST 5
261
262 struct a6xx_hfi_msg_test {
263 uint32_t header;
264 };
265
266 static void
decode_H2F_MSG_TEST(struct a6xx_hfi_msg_test * msg)267 decode_H2F_MSG_TEST(struct a6xx_hfi_msg_test *msg)
268 {
269 }
270
271 #define HFI_H2F_MSG_START 10
272
273 struct a6xx_hfi_msg_start {
274 uint32_t header;
275 };
276
277 static void
decode_H2F_MSG_START(struct a6xx_hfi_msg_start * msg)278 decode_H2F_MSG_START(struct a6xx_hfi_msg_start *msg)
279 {
280 }
281
282 #define HFI_H2F_MSG_CORE_FW_START 14
283
284 struct a6xx_hfi_msg_core_fw_start {
285 uint32_t header;
286 uint32_t handle;
287 };
288
289 static void
decode_H2F_MSG_CORE_FW_START(struct a6xx_hfi_msg_core_fw_start * msg)290 decode_H2F_MSG_CORE_FW_START(struct a6xx_hfi_msg_core_fw_start *msg)
291 {
292 printf("\t\t\t\thandle: %u\n", msg->handle);
293 }
294
295 #define HFI_H2F_MSG_GX_BW_PERF_VOTE 30
296
297 struct a6xx_hfi_gx_bw_perf_vote_cmd {
298 uint32_t header;
299 uint32_t ack_type;
300 uint32_t freq;
301 uint32_t bw;
302 };
303
304 static void
decode_H2F_MSG_GX_BW_PERF_VOTE(struct a6xx_hfi_gx_bw_perf_vote_cmd * msg)305 decode_H2F_MSG_GX_BW_PERF_VOTE(struct a6xx_hfi_gx_bw_perf_vote_cmd *msg)
306 {
307 printf("\t\t\t\tack_type: %u\n", msg->ack_type);
308 printf("\t\t\t\tfreq: %u\n", msg->freq);
309 printf("\t\t\t\tbw: %u\n", msg->bw);
310 }
311
312 #define HFI_H2F_MSG_PREPARE_SLUMBER 33
313
314 struct a6xx_hfi_prep_slumber_cmd {
315 uint32_t header;
316 uint32_t bw;
317 uint32_t freq;
318 };
319
320 static void
decode_H2F_MSG_PREPARE_SLUMBER(struct a6xx_hfi_prep_slumber_cmd * msg)321 decode_H2F_MSG_PREPARE_SLUMBER(struct a6xx_hfi_prep_slumber_cmd *msg)
322 {
323 printf("\t\t\t\tbw: %u\n", msg->bw);
324 printf("\t\t\t\tfreq: %u\n", msg->freq);
325 }
326
327 static struct {
328 const char *name;
329 void (*decode)(void *);
330 } hfi_msgs[] = {
331 #define HFI_MSG(name) [HFI_ ## name] = { #name, (void (*)(void *))decode_ ## name }
332 HFI_MSG(F2H_MSG_ACK),
333 HFI_MSG(F2H_MSG_ERROR),
334 HFI_MSG(H2F_MSG_INIT),
335 HFI_MSG(H2F_MSG_FW_VERSION),
336 HFI_MSG(H2F_MSG_PERF_TABLE),
337 HFI_MSG(H2F_MSG_BW_TABLE),
338 HFI_MSG(H2F_MSG_TEST),
339 HFI_MSG(H2F_MSG_START),
340 HFI_MSG(H2F_MSG_CORE_FW_START),
341 HFI_MSG(H2F_MSG_GX_BW_PERF_VOTE),
342 HFI_MSG(H2F_MSG_PREPARE_SLUMBER),
343 };
344
345 static bool
is_valid_msg_type(unsigned type)346 is_valid_msg_type(unsigned type)
347 {
348 switch (type) {
349 case HFI_MSG_CMD:
350 case HFI_MSG_ACK:
351 case HFI_MSG_ACK_V1:
352 return true;
353 default:
354 return false;
355 }
356 }
357
358 static const char *
hfi_msg_name(unsigned msgid)359 hfi_msg_name(unsigned msgid)
360 {
361 if (msgid < ARRAY_SIZE(hfi_msgs))
362 return hfi_msgs[msgid].name;
363 return NULL;
364 }
365
366 static bool
is_valid_decode_start(struct a6xx_hfi_state * hfi,unsigned qidx,int32_t read_index)367 is_valid_decode_start(struct a6xx_hfi_state *hfi, unsigned qidx, int32_t read_index)
368 {
369 struct a6xx_hfi_queue_table_header *table = hfi->buf;
370 struct a6xx_hfi_queue_header *queue = &table->queue[qidx];
371 uint32_t offset = queue->iova - hfi->iova;
372 uint32_t *dw = (uint32_t *)(((uint8_t *)hfi->buf) + offset);
373 int last_seqno = -1;
374
375 if (read_index < 0)
376 return false;
377
378 while (read_index != queue->write_index) {
379 uint32_t hdr = dw[read_index];
380
381 if (!is_valid_msg_type(HFI_HEADER_TYPE(hdr)))
382 return false;
383
384 if (!hfi_msg_name(HFI_HEADER_ID(hdr)))
385 return false;
386
387 /* Header size should be at least 1, and not extend past the write_index: */
388 unsigned sz = HFI_HEADER_SIZE(hdr);
389 if (!is_gmu_legacy())
390 sz = ALIGN_POT(sz, 4);
391 int remaining = ((read_index + sz) + (queue->size - 1) -
392 queue->write_index) % queue->size;
393 if ((sz == 0) || (remaining < 0))
394 return false;
395
396 /* Seqno should be one more than previous seqno: */
397 unsigned seqno = HFI_HEADER_SEQNUM(hdr);
398 if ((last_seqno != -1) && (((last_seqno + 1) & 0xfff) != seqno))
399 return false;
400
401 last_seqno = seqno;
402
403 read_index = (read_index + sz) % queue->size;
404 }
405
406 return true;
407 }
408
409 static void
decode_hfi(struct a6xx_hfi_state * hfi,unsigned qidx,int32_t read_index)410 decode_hfi(struct a6xx_hfi_state *hfi, unsigned qidx, int32_t read_index)
411 {
412 struct a6xx_hfi_queue_table_header *table = hfi->buf;
413 struct a6xx_hfi_queue_header *queue = &table->queue[qidx];
414 uint32_t offset = queue->iova - hfi->iova;
415 uint32_t *dw = (uint32_t *)(((uint8_t *)hfi->buf) + offset);
416
417 while (read_index != queue->write_index) {
418 uint32_t hdr = dw[read_index];
419 unsigned msgid = HFI_HEADER_ID(hdr);
420 unsigned sz = HFI_HEADER_SIZE(hdr);
421 unsigned type = HFI_HEADER_TYPE(hdr);
422 unsigned seqno = HFI_HEADER_SEQNUM(hdr);
423
424 assert(is_valid_msg_type(type));
425 assert(hfi_msg_name(msgid));
426
427 printf("\t\t\t------ %s (id=%u, size=%u, type=%u, seqnum=%u)\n",
428 hfi_msg_name(msgid), msgid, sz, type, seqno);
429
430 if (!is_gmu_legacy())
431 sz = ALIGN_POT(sz, 4);
432
433 uint32_t buf[sz];
434 for (unsigned i = 0; i < sz; i++) {
435 buf[i] = dw[(read_index + i) % queue->size];
436 }
437
438 if (type == HFI_MSG_CMD)
439 hfi_msgs[msgid].decode(buf);
440
441 dump_hex_ascii(buf, sz*4, 4);
442
443 read_index = (read_index + sz) % queue->size;
444 }
445 }
446
447 /* Search backwards from the most recent (last) history entry to try to
448 * find start of the oldest HFI message which has not been overwritten
449 * due to ringbuffer wraparound.
450 */
451 static int32_t
find_decode_start(struct a6xx_hfi_state * hfi,unsigned qidx)452 find_decode_start(struct a6xx_hfi_state *hfi, unsigned qidx)
453 {
454 int i;
455
456 for (i = ARRAY_SIZE(hfi->history[qidx]) - 1; i >= 0; i--) {
457 if (!is_valid_decode_start(hfi, qidx, hfi->history[qidx][i]))
458 break;
459 }
460
461 /* Last entry was invalid, or we decremented below zero, so advance
462 * the index by one:
463 */
464 i++;
465
466 if (i >= ARRAY_SIZE(hfi->history[qidx]))
467 return -1;
468
469 return hfi->history[qidx][i];
470 }
471
472 void
dump_gmu_hfi(struct a6xx_hfi_state * hfi)473 dump_gmu_hfi(struct a6xx_hfi_state *hfi)
474 {
475 struct a6xx_hfi_queue_table_header *table = hfi->buf;
476
477 printf("\tversion: %u\n", table->version);
478 printf("\tsize: %u\n", table->size);
479 printf("\tqhdr0_offset: %u\n", table->qhdr0_offset);
480 printf("\tqhdr_size: %u\n", table->qhdr_size);
481 printf("\tnum_queues: %u\n", table->num_queues);
482 printf("\tactive_queues: %u\n", table->active_queues);
483
484 for (unsigned i = 0; i < table->num_queues; i++) {
485 struct a6xx_hfi_queue_header *queue = &table->queue[i];
486
487 printf("\tqueue[%u]:\n", i);
488 printf("\t\tstatus: 0x%x\n", queue->status);
489 printf("\t\tiova: 0x%x\n", queue->iova);
490 printf("\t\ttype: 0x%x\n", queue->type);
491 printf("\t\tsize: %u\n", queue->size);
492 printf("\t\tmsg_size: %u\n", queue->msg_size);
493 printf("\t\tdropped: %u\n", queue->dropped);
494 printf("\t\trx_watermark: 0x%x\n", queue->rx_watermark);
495 printf("\t\ttx_watermark: 0x%x\n", queue->tx_watermark);
496 printf("\t\trx_request: 0x%x\n", queue->rx_request);
497 printf("\t\ttx_request: 0x%x\n", queue->tx_request);
498 printf("\t\tread_index: %u\n", queue->read_index);
499 printf("\t\twrite_index: %u\n", queue->write_index);
500
501 int32_t read_index = find_decode_start(hfi, i);
502 if (read_index >= 0)
503 decode_hfi(hfi, i, read_index);
504 }
505 }
506