• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2012 Rob Clark <robdclark@gmail.com>
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #ifndef __CFFDEC_H__
7 #define __CFFDEC_H__
8 
9 #include <stdbool.h>
10 
11 #include "freedreno_pm4.h"
12 #include "freedreno_dev_info.h"
13 
14 enum query_mode {
15    /* default mode, dump all queried regs on each draw: */
16    QUERY_ALL = 0,
17 
18    /* only dump if any of the queried regs were written
19     * since last draw:
20     */
21    QUERY_WRITTEN,
22 
23    /* only dump if any of the queried regs changed since
24     * last draw:
25     */
26    QUERY_DELTA,
27 };
28 
29 struct cffdec_options {
30    struct fd_dev_id dev_id;
31    const struct fd_dev_info *info;
32    int draw_filter;
33    int color;
34    int dump_shaders;
35    int summary;
36    int allregs;
37    int dump_textures;
38    int dump_bindless;
39    int decode_markers;
40    char *script;
41 
42    int query_compare; /* binning vs SYSMEM/GMEM compare mode */
43    int query_mode;    /* enum query_mode */
44    char **querystrs;
45    int nquery;
46 
47    /* In "once" mode, only decode a cmdstream buffer once (per draw
48     * mode, in the case of a6xx+ where a single cmdstream buffer can
49     * be used for both binning and draw pass), rather than each time
50     * encountered (ie. once per tile/bin in GMEM draw passes)
51     */
52    int once;
53 
54    /* In unit_test mode, suppress pathnames in output so that we can have references
55     * independent of the build dir.
56     */
57    int unit_test;
58 
59    /* for crashdec, where we know CP_IBx_REM_SIZE, we can use this
60     * to highlight the cmdstream not parsed yet, to make it easier
61     * to see how far along the CP is.
62     */
63    struct {
64       uint64_t base;
65       uint32_t rem;
66       bool crash_found : 1;
67    } ibs[4];
68 };
69 
70 /**
71  * A helper to deal with 64b registers by accumulating the lo/hi 32b
72  * dwords.  Example usage:
73  *
74  *    struct regacc r = regacc(rnn);
75  *
76  *    for (dword in dwords) {
77  *       if (regacc_push(&r, regbase, dword)) {
78  *          printf("\t%08x"PRIx64", r.value);
79  *          dump_register_val(r.regbase, r.value, 0);
80  *       }
81  *       regbase++;
82  *    }
83  *
84  * It is expected that 64b regs will come in pairs of <lo, hi>.
85  */
86 struct regacc {
87    uint32_t regbase;
88    uint64_t value;
89 
90    /* private: */
91    struct rnn *rnn;
92    bool has_dword_lo;
93 };
94 struct regacc regacc(struct rnn *rnn);
95 bool regacc_push(struct regacc *regacc, uint32_t regbase, uint32_t dword);
96 
97 void printl(int lvl, const char *fmt, ...);
98 const char *pktname(unsigned opc);
99 uint32_t regbase(const char *name);
100 const char *regname(uint32_t regbase, int color);
101 bool reg_written(uint32_t regbase);
102 uint32_t reg_lastval(uint32_t regbase);
103 uint32_t reg_val(uint32_t regbase);
104 void reg_set(uint32_t regbase, uint32_t val);
105 uint32_t * parse_cp_indirect(uint32_t *dwords, uint32_t sizedwords,
106                              uint64_t *ibaddr, uint32_t *ibsize);
107 void reset_regs(void);
108 void cffdec_init(const struct cffdec_options *options);
109 void dump_register_val(struct regacc *r, int level);
110 void dump_commands(uint32_t *dwords, uint32_t sizedwords, int level);
111 
112 /*
113  * Packets (mostly) fall into two categories, "write one or more registers"
114  * (type0 or type4 depending on generation) or "packet with opcode and
115  * opcode specific payload" (type3 or type7).  These helpers deal with
116  * the type0+type3 vs type4+type7 differences (a2xx-a4xx vs a5xx+).
117  */
118 
119 static inline bool
pkt_is_regwrite(uint32_t dword,uint32_t * offset,uint32_t * size)120 pkt_is_regwrite(uint32_t dword, uint32_t *offset, uint32_t *size)
121 {
122    if (pkt_is_type0(dword)) {
123       *size = type0_pkt_size(dword) + 1;
124       *offset = type0_pkt_offset(dword);
125       return true;
126    } if (pkt_is_type4(dword)) {
127       *size = type4_pkt_size(dword) + 1;
128       *offset = type4_pkt_offset(dword);
129       return true;
130    }
131    return false;
132 }
133 
134 static inline bool
pkt_is_opcode(uint32_t dword,uint32_t * opcode,uint32_t * size)135 pkt_is_opcode(uint32_t dword, uint32_t *opcode, uint32_t *size)
136 {
137    if (pkt_is_type3(dword)) {
138       *size = type3_pkt_size(dword) + 1;
139       *opcode = cp_type3_opcode(dword);
140       return true;
141    } else if (pkt_is_type7(dword)) {
142       *size = type7_pkt_size(dword) + 1;
143       *opcode = cp_type7_opcode(dword);
144      return true;
145    }
146    return false;
147 }
148 
149 /**
150  * For a5xx+ we can detect valid packet headers vs random other noise, and
151  * can use this to "re-sync" to the start of the next valid packet.  So that
152  * the same cmdstream corruption that confused the GPU doesn't confuse us!
153  */
154 static inline uint32_t
find_next_packet(uint32_t * dwords,uint32_t sizedwords)155 find_next_packet(uint32_t *dwords, uint32_t sizedwords)
156 {
157    for (uint32_t c = 0; c < sizedwords; c++) {
158       if (pkt_is_type7(dwords[c]) || pkt_is_type4(dwords[c]))
159          return c;
160    }
161    return sizedwords;
162 }
163 
164 
165 #endif /* __CFFDEC_H__ */
166