1 /*
2 * Copyright (C) 2017-2019 Lyude Paul
3 * Copyright (C) 2017-2019 Alyssa Rosenzweig
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 */
25
26 #ifndef __PAN_DECODE_H__
27 #define __PAN_DECODE_H__
28
29 #include "genxml/gen_macros.h"
30 #include "util/rb_tree.h"
31 #include "util/simple_mtx.h"
32 #include "util/u_dynarray.h"
33
34 #include "wrap.h"
35
36 struct pandecode_context {
37 int id; /* only used for the filename */
38 FILE *dump_stream;
39 unsigned indent;
40 struct rb_tree mmap_tree;
41 struct util_dynarray ro_mappings;
42 int dump_frame_count;
43 simple_mtx_t lock;
44
45 /* On CSF context, set to true if the root CS ring buffer
46 * is managed in userspace. The blob does that, and mesa might use
47 * usermode queues too at some point.
48 */
49 bool usermode_queue;
50 };
51
52 void pandecode_dump_file_open(struct pandecode_context *ctx);
53
54 struct pandecode_mapped_memory {
55 struct rb_node node;
56 size_t length;
57 void *addr;
58 uint64_t gpu_va;
59 bool ro;
60 char name[32];
61 };
62
63 char *pointer_as_memory_reference(struct pandecode_context *ctx, uint64_t ptr);
64
65 struct pandecode_mapped_memory *
66 pandecode_find_mapped_gpu_mem_containing(struct pandecode_context *ctx,
67 uint64_t addr);
68
69 void pandecode_map_read_write(struct pandecode_context *ctx);
70
71 void pandecode_dump_mappings(struct pandecode_context *ctx);
72
73 static inline void *
__pandecode_fetch_gpu_mem(struct pandecode_context * ctx,uint64_t gpu_va,size_t size,int line,const char * filename)74 __pandecode_fetch_gpu_mem(struct pandecode_context *ctx, uint64_t gpu_va,
75 size_t size, int line, const char *filename)
76 {
77 const struct pandecode_mapped_memory *mem =
78 pandecode_find_mapped_gpu_mem_containing(ctx, gpu_va);
79
80 if (!mem) {
81 fprintf(stderr, "Access to unknown memory %" PRIx64 " in %s:%d\n", gpu_va,
82 filename, line);
83 fflush(ctx->dump_stream);
84 assert(0);
85 }
86
87 assert(size + (gpu_va - mem->gpu_va) <= mem->length);
88
89 return mem->addr + gpu_va - mem->gpu_va;
90 }
91
92 #define pandecode_fetch_gpu_mem(ctx, gpu_va, size) \
93 __pandecode_fetch_gpu_mem(ctx, gpu_va, size, __LINE__, __FILE__)
94
95 /* Returns a validated pointer to mapped GPU memory with the given pointer type,
96 * size automatically determined from the pointer type
97 */
98 #define PANDECODE_PTR(ctx, gpu_va, type) \
99 ((type *)(__pandecode_fetch_gpu_mem(ctx, gpu_va, sizeof(type), __LINE__, \
100 __FILE__)))
101
102 /* Usage: <variable type> PANDECODE_PTR_VAR(name, gpu_va) */
103 #define PANDECODE_PTR_VAR(ctx, name, gpu_va) \
104 name = __pandecode_fetch_gpu_mem(ctx, gpu_va, sizeof(*name), __LINE__, \
105 __FILE__)
106
107 void pandecode_validate_buffer(struct pandecode_context *ctx, uint64_t addr,
108 size_t sz);
109
110 /* Forward declare for all supported gens to permit thunking */
111 void pandecode_jc_v4(struct pandecode_context *ctx, uint64_t jc_gpu_va,
112 unsigned gpu_id);
113 void pandecode_jc_v5(struct pandecode_context *ctx, uint64_t jc_gpu_va,
114 unsigned gpu_id);
115 void pandecode_jc_v6(struct pandecode_context *ctx, uint64_t jc_gpu_va,
116 unsigned gpu_id);
117 void pandecode_jc_v7(struct pandecode_context *ctx, uint64_t jc_gpu_va,
118 unsigned gpu_id);
119 void pandecode_jc_v9(struct pandecode_context *ctx, uint64_t jc_gpu_va,
120 unsigned gpu_id);
121
122 void pandecode_abort_on_fault_v4(struct pandecode_context *ctx,
123 uint64_t jc_gpu_va);
124 void pandecode_abort_on_fault_v5(struct pandecode_context *ctx,
125 uint64_t jc_gpu_va);
126 void pandecode_abort_on_fault_v6(struct pandecode_context *ctx,
127 uint64_t jc_gpu_va);
128 void pandecode_abort_on_fault_v7(struct pandecode_context *ctx,
129 uint64_t jc_gpu_va);
130 void pandecode_abort_on_fault_v9(struct pandecode_context *ctx,
131 uint64_t jc_gpu_va);
132
133 void pandecode_interpret_cs_v10(struct pandecode_context *ctx, uint64_t queue,
134 uint32_t size, unsigned gpu_id, uint32_t *regs);
135 void pandecode_cs_binary_v10(struct pandecode_context *ctx, uint64_t bin,
136 uint32_t bin_size, unsigned gpu_id);
137 void pandecode_cs_trace_v10(struct pandecode_context *ctx, uint64_t trace,
138 uint32_t trace_size, unsigned gpu_id);
139
140 /* Logging infrastructure */
141 static void
pandecode_make_indent(struct pandecode_context * ctx)142 pandecode_make_indent(struct pandecode_context *ctx)
143 {
144 for (unsigned i = 0; i < ctx->indent; ++i)
145 fprintf(ctx->dump_stream, " ");
146 }
147
148 static inline void PRINTFLIKE(2, 3)
pandecode_log(struct pandecode_context * ctx,const char * format,...)149 pandecode_log(struct pandecode_context *ctx, const char *format, ...)
150 {
151 va_list ap;
152
153 pandecode_make_indent(ctx);
154 va_start(ap, format);
155 vfprintf(ctx->dump_stream, format, ap);
156 va_end(ap);
157 }
158
159 static inline void PRINTFLIKE(2, 3)
pandecode_user_msg(struct pandecode_context * ctx,const char * format,...)160 pandecode_user_msg(struct pandecode_context *ctx, const char *format, ...)
161 {
162 va_list ap;
163
164 simple_mtx_lock(&ctx->lock);
165 pandecode_dump_file_open(ctx);
166 pandecode_make_indent(ctx);
167 va_start(ap, format);
168 vfprintf(ctx->dump_stream, format, ap);
169 va_end(ap);
170 simple_mtx_unlock(&ctx->lock);
171 }
172
173 static inline void
pandecode_log_cont(struct pandecode_context * ctx,const char * format,...)174 pandecode_log_cont(struct pandecode_context *ctx, const char *format, ...)
175 {
176 va_list ap;
177
178 va_start(ap, format);
179 vfprintf(ctx->dump_stream, format, ap);
180 va_end(ap);
181 }
182
183 /* Convenience methods */
184 #define DUMP_UNPACKED(ctx, T, var, ...) \
185 { \
186 pandecode_log(ctx, __VA_ARGS__); \
187 pan_print(ctx->dump_stream, T, var, (ctx->indent + 1) * 2); \
188 }
189
190 #define DUMP_CL(ctx, T, cl, ...) \
191 { \
192 pan_unpack((MALI_##T##_PACKED_T *)(cl), T, temp); \
193 DUMP_UNPACKED(ctx, T, temp, __VA_ARGS__); \
194 }
195
196 #define DUMP_SECTION(ctx, A, S, cl, ...) \
197 { \
198 pan_section_unpack(cl, A, S, temp); \
199 pandecode_log(ctx, __VA_ARGS__); \
200 pan_section_print(ctx->dump_stream, A, S, temp, (ctx->indent + 1) * 2); \
201 }
202
203 #define MAP_ADDR(ctx, T, addr, cl) \
204 const MALI_##T##_PACKED_T *cl = \
205 pandecode_fetch_gpu_mem(ctx, addr, pan_size(T));
206
207 #define DUMP_ADDR(ctx, T, addr, ...) \
208 { \
209 MAP_ADDR(ctx, T, addr, cl) \
210 DUMP_CL(ctx, T, cl, __VA_ARGS__); \
211 }
212
213 void pandecode_shader_disassemble(struct pandecode_context *ctx,
214 uint64_t shader_ptr, unsigned gpu_id);
215
216 #ifdef PAN_ARCH
217
218 /* Information about the framebuffer passed back for additional analysis */
219 struct pandecode_fbd {
220 unsigned rt_count;
221 bool has_extra;
222 };
223
224 struct pandecode_fbd GENX(pandecode_fbd)(struct pandecode_context *ctx,
225 uint64_t gpu_va, bool is_fragment,
226 unsigned gpu_id);
227
228 #if PAN_ARCH >= 9
229 void GENX(pandecode_dcd)(struct pandecode_context *ctx,
230 const struct MALI_DRAW *p, unsigned unused,
231 unsigned gpu_id);
232 #else
233 void GENX(pandecode_dcd)(struct pandecode_context *ctx,
234 const struct MALI_DRAW *p, enum mali_job_type job_type,
235 unsigned gpu_id);
236 #endif
237
238 #if PAN_ARCH <= 5
239 void GENX(pandecode_texture)(struct pandecode_context *ctx, uint64_t u,
240 unsigned tex);
241 #else
242 void GENX(pandecode_texture)(struct pandecode_context *ctx,
243 const struct mali_texture_packed *cl,
244 unsigned tex);
245 #endif
246
247 #if PAN_ARCH >= 5
248 uint64_t GENX(pandecode_blend)(struct pandecode_context *ctx,
249 struct mali_blend_packed *descs, int rt_no,
250 uint64_t frag_shader);
251 #endif
252
253 #if PAN_ARCH >= 6
254 void GENX(pandecode_tiler)(struct pandecode_context *ctx, uint64_t gpu_va,
255 unsigned gpu_id);
256 #endif
257
258 #if PAN_ARCH >= 9
259 void GENX(pandecode_shader_environment)(struct pandecode_context *ctx,
260 const struct MALI_SHADER_ENVIRONMENT *p,
261 unsigned gpu_id);
262
263 void GENX(pandecode_resource_tables)(struct pandecode_context *ctx,
264 uint64_t addr, const char *label);
265
266 void GENX(pandecode_fau)(struct pandecode_context *ctx, uint64_t addr,
267 unsigned count, const char *name);
268
269 uint64_t GENX(pandecode_shader)(struct pandecode_context *ctx, uint64_t addr,
270 const char *label, unsigned gpu_id);
271
272 void GENX(pandecode_blend_descs)(struct pandecode_context *ctx, uint64_t blend,
273 unsigned count, uint64_t frag_shader,
274 unsigned gpu_id);
275
276 void GENX(pandecode_depth_stencil)(struct pandecode_context *ctx,
277 uint64_t addr);
278 #endif
279
280 #endif
281
282 #endif /* __MMAP_TRACE_H__ */
283