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