Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/broadcom/clif/clif_dump.c
4560 views
1
/*
2
* Copyright © 2016 Broadcom
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
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include "drm-uapi/v3d_drm.h"
28
#include "clif_dump.h"
29
#include "clif_private.h"
30
#include "util/list.h"
31
#include "util/ralloc.h"
32
33
#include "broadcom/cle/v3d_decoder.h"
34
35
struct reloc_worklist_entry *
36
clif_dump_add_address_to_worklist(struct clif_dump *clif,
37
enum reloc_worklist_type type,
38
uint32_t addr)
39
{
40
struct reloc_worklist_entry *entry =
41
rzalloc(clif, struct reloc_worklist_entry);
42
if (!entry)
43
return NULL;
44
45
entry->type = type;
46
entry->addr = addr;
47
48
list_addtail(&entry->link, &clif->worklist);
49
50
return entry;
51
}
52
53
struct clif_dump *
54
clif_dump_init(const struct v3d_device_info *devinfo,
55
FILE *out, bool pretty)
56
{
57
struct clif_dump *clif = rzalloc(NULL, struct clif_dump);
58
59
clif->devinfo = devinfo;
60
clif->out = out;
61
clif->spec = v3d_spec_load(devinfo);
62
clif->pretty = pretty;
63
64
list_inithead(&clif->worklist);
65
66
return clif;
67
}
68
69
void
70
clif_dump_destroy(struct clif_dump *clif)
71
{
72
ralloc_free(clif);
73
}
74
75
struct clif_bo *
76
clif_lookup_bo(struct clif_dump *clif, uint32_t addr)
77
{
78
for (int i = 0; i < clif->bo_count; i++) {
79
struct clif_bo *bo = &clif->bo[i];
80
81
if (addr >= bo->offset &&
82
addr < bo->offset + bo->size) {
83
return bo;
84
}
85
}
86
87
return NULL;
88
}
89
90
static bool
91
clif_lookup_vaddr(struct clif_dump *clif, uint32_t addr, void **vaddr)
92
{
93
struct clif_bo *bo = clif_lookup_bo(clif, addr);
94
if (!bo)
95
return false;
96
97
*vaddr = bo->vaddr + addr - bo->offset;
98
return true;
99
}
100
101
#define out_uint(_clif, field) out(_clif, " /* %s = */ %u\n", \
102
#field, values-> field);
103
104
static bool
105
clif_dump_packet(struct clif_dump *clif, uint32_t offset, const uint8_t *cl,
106
uint32_t *size, bool reloc_mode)
107
{
108
if (clif->devinfo->ver >= 42)
109
return v3d42_clif_dump_packet(clif, offset, cl, size, reloc_mode);
110
else if (clif->devinfo->ver >= 41)
111
return v3d41_clif_dump_packet(clif, offset, cl, size, reloc_mode);
112
else
113
return v3d33_clif_dump_packet(clif, offset, cl, size, reloc_mode);
114
}
115
116
static uint32_t
117
clif_dump_cl(struct clif_dump *clif, uint32_t start, uint32_t end,
118
bool reloc_mode)
119
{
120
struct clif_bo *bo = clif_lookup_bo(clif, start);
121
if (!bo) {
122
out(clif, "Failed to look up address 0x%08x\n",
123
start);
124
return 0;
125
}
126
127
void *start_vaddr = bo->vaddr + start - bo->offset;
128
129
/* The end address is optional (for example, a BRANCH instruction
130
* won't set an end), but is used for BCL/RCL termination.
131
*/
132
void *end_vaddr = NULL;
133
if (end && !clif_lookup_vaddr(clif, end, &end_vaddr)) {
134
out(clif, "Failed to look up address 0x%08x\n",
135
end);
136
return 0;
137
}
138
139
if (!reloc_mode)
140
out(clif, "@format ctrllist /* [%s+0x%08x] */\n",
141
bo->name, start - bo->offset);
142
143
uint32_t size;
144
uint8_t *cl = start_vaddr;
145
while (clif_dump_packet(clif, start, cl, &size, reloc_mode)) {
146
cl += size;
147
start += size;
148
149
if (cl == end_vaddr)
150
break;
151
}
152
153
return (void *)cl - bo->vaddr;
154
}
155
156
/* Walks the worklist, parsing the relocs for any memory regions that might
157
* themselves have additional relocations.
158
*/
159
static uint32_t
160
clif_dump_gl_shader_state_record(struct clif_dump *clif,
161
struct reloc_worklist_entry *reloc,
162
void *vaddr)
163
{
164
struct v3d_group *state = v3d_spec_find_struct(clif->spec,
165
"GL Shader State Record");
166
struct v3d_group *attr = v3d_spec_find_struct(clif->spec,
167
"GL Shader State Attribute Record");
168
assert(state);
169
assert(attr);
170
uint32_t offset = 0;
171
172
out(clif, "@format shadrec_gl_main\n");
173
v3d_print_group(clif, state, 0, vaddr + offset);
174
offset += v3d_group_get_length(state);
175
176
for (int i = 0; i < reloc->shader_state.num_attrs; i++) {
177
out(clif, "@format shadrec_gl_attr /* %d */\n", i);
178
v3d_print_group(clif, attr, 0, vaddr + offset);
179
offset += v3d_group_get_length(attr);
180
}
181
182
return offset;
183
}
184
185
static void
186
clif_process_worklist(struct clif_dump *clif)
187
{
188
list_for_each_entry_safe(struct reloc_worklist_entry, reloc,
189
&clif->worklist, link) {
190
void *vaddr;
191
if (!clif_lookup_vaddr(clif, reloc->addr, &vaddr)) {
192
out(clif, "Failed to look up address 0x%08x\n",
193
reloc->addr);
194
continue;
195
}
196
197
switch (reloc->type) {
198
case reloc_cl:
199
clif_dump_cl(clif, reloc->addr, reloc->cl.end, true);
200
break;
201
202
case reloc_gl_shader_state:
203
break;
204
case reloc_generic_tile_list:
205
clif_dump_cl(clif, reloc->addr,
206
reloc->generic_tile_list.end, true);
207
break;
208
}
209
}
210
}
211
212
static int
213
worklist_entry_compare(const void *a, const void *b)
214
{
215
return ((*(struct reloc_worklist_entry **)a)->addr -
216
(*(struct reloc_worklist_entry **)b)->addr);
217
}
218
219
static bool
220
clif_dump_if_blank(struct clif_dump *clif, struct clif_bo *bo,
221
uint32_t start, uint32_t end)
222
{
223
for (int i = start; i < end; i++) {
224
if (((uint8_t *)bo->vaddr)[i] != 0)
225
return false;
226
}
227
228
out(clif, "\n");
229
out(clif, "@format blank %d /* [%s+0x%08x..0x%08x] */\n", end - start,
230
bo->name, start, end - 1);
231
return true;
232
}
233
234
/* Dumps the binary data in the BO from start to end (relative to the start of
235
* the BO).
236
*/
237
static void
238
clif_dump_binary(struct clif_dump *clif, struct clif_bo *bo,
239
uint32_t start, uint32_t end)
240
{
241
if (start == end)
242
return;
243
244
if (clif_dump_if_blank(clif, bo, start, end))
245
return;
246
247
out(clif, "@format binary /* [%s+0x%08x] */\n",
248
bo->name, start);
249
250
uint32_t offset = start;
251
int dumped_in_line = 0;
252
while (offset < end) {
253
if (clif_dump_if_blank(clif, bo, offset, end))
254
return;
255
256
if (end - offset >= 4) {
257
out(clif, "0x%08x ", *(uint32_t *)(bo->vaddr + offset));
258
offset += 4;
259
} else {
260
out(clif, "0x%02x ", *(uint8_t *)(bo->vaddr + offset));
261
offset++;
262
}
263
264
if (++dumped_in_line == 8) {
265
out(clif, "\n");
266
dumped_in_line = 0;
267
}
268
}
269
if (dumped_in_line)
270
out(clif, "\n");
271
}
272
273
/* Walks the list of relocations, dumping each buffer's contents (using our
274
* codegenned dump routines for pretty printing, and most importantly proper
275
* address references so that the CLIF parser can relocate buffers).
276
*/
277
static void
278
clif_dump_buffers(struct clif_dump *clif)
279
{
280
int num_relocs = 0;
281
list_for_each_entry(struct reloc_worklist_entry, reloc,
282
&clif->worklist, link) {
283
num_relocs++;
284
}
285
struct reloc_worklist_entry **relocs =
286
ralloc_array(clif, struct reloc_worklist_entry *, num_relocs);
287
int i = 0;
288
list_for_each_entry(struct reloc_worklist_entry, reloc,
289
&clif->worklist, link) {
290
relocs[i++] = reloc;
291
}
292
qsort(relocs, num_relocs, sizeof(*relocs), worklist_entry_compare);
293
294
struct clif_bo *bo = NULL;
295
uint32_t offset = 0;
296
297
for (i = 0; i < num_relocs; i++) {
298
struct reloc_worklist_entry *reloc = relocs[i];
299
struct clif_bo *new_bo = clif_lookup_bo(clif, reloc->addr);
300
301
if (!new_bo) {
302
out(clif, "Failed to look up address 0x%08x\n",
303
reloc->addr);
304
continue;
305
}
306
307
if (new_bo != bo) {
308
if (bo) {
309
/* Finish out the last of the last BO. */
310
clif_dump_binary(clif, bo,
311
offset,
312
bo->size);
313
}
314
315
out(clif, "\n");
316
out(clif, "@buffer %s\n", new_bo->name);
317
bo = new_bo;
318
offset = 0;
319
bo->dumped = true;
320
}
321
322
int reloc_offset = reloc->addr - bo->offset;
323
if (offset != reloc_offset)
324
clif_dump_binary(clif, bo, offset, reloc_offset);
325
offset = reloc_offset;
326
327
switch (reloc->type) {
328
case reloc_cl:
329
offset = clif_dump_cl(clif, reloc->addr, reloc->cl.end,
330
false);
331
out(clif, "\n");
332
break;
333
334
case reloc_gl_shader_state:
335
offset += clif_dump_gl_shader_state_record(clif,
336
reloc,
337
bo->vaddr +
338
offset);
339
break;
340
case reloc_generic_tile_list:
341
offset = clif_dump_cl(clif, reloc->addr,
342
reloc->generic_tile_list.end,
343
false);
344
break;
345
}
346
out(clif, "\n");
347
}
348
349
if (bo) {
350
clif_dump_binary(clif, bo, offset, bo->size);
351
}
352
353
/* For any BOs that didn't have relocations, just dump them raw. */
354
for (int i = 0; i < clif->bo_count; i++) {
355
bo = &clif->bo[i];
356
if (bo->dumped)
357
continue;
358
out(clif, "@buffer %s\n", bo->name);
359
clif_dump_binary(clif, bo, 0, bo->size);
360
out(clif, "\n");
361
}
362
}
363
364
void
365
clif_dump_add_cl(struct clif_dump *clif, uint32_t start, uint32_t end)
366
{
367
struct reloc_worklist_entry *entry =
368
clif_dump_add_address_to_worklist(clif, reloc_cl, start);
369
370
entry->cl.end = end;
371
}
372
373
static int
374
clif_bo_offset_compare(const void *a, const void *b)
375
{
376
return ((struct clif_bo *)a)->offset - ((struct clif_bo *)b)->offset;
377
}
378
379
void
380
clif_dump(struct clif_dump *clif, const struct drm_v3d_submit_cl *submit)
381
{
382
clif_dump_add_cl(clif, submit->bcl_start, submit->bcl_end);
383
clif_dump_add_cl(clif, submit->rcl_start, submit->rcl_end);
384
385
qsort(clif->bo, clif->bo_count, sizeof(clif->bo[0]),
386
clif_bo_offset_compare);
387
388
/* A buffer needs to be defined before we can emit a CLIF address
389
* referencing it, so emit them all now.
390
*/
391
for (int i = 0; i < clif->bo_count; i++) {
392
out(clif, "@createbuf_aligned 4096 %s\n", clif->bo[i].name);
393
}
394
395
/* Walk the worklist figuring out the locations of structs based on
396
* the CL contents.
397
*/
398
clif_process_worklist(clif);
399
400
/* Dump the contents of the buffers using the relocations we found to
401
* pretty-print structures.
402
*/
403
clif_dump_buffers(clif);
404
405
out(clif, "@add_bin 0\n ");
406
out_address(clif, submit->bcl_start);
407
out(clif, "\n ");
408
out_address(clif, submit->bcl_end);
409
out(clif, "\n ");
410
out_address(clif, submit->qma);
411
out(clif, "\n %d\n ", submit->qms);
412
out_address(clif, submit->qts);
413
out(clif, "\n");
414
out(clif, "@wait_bin_all_cores\n");
415
416
out(clif, "@add_render 0\n ");
417
out_address(clif, submit->rcl_start);
418
out(clif, "\n ");
419
out_address(clif, submit->rcl_end);
420
out(clif, "\n ");
421
out_address(clif, submit->qma);
422
out(clif, "\n");
423
out(clif, "@wait_render_all_cores\n");
424
}
425
426
void
427
clif_dump_add_bo(struct clif_dump *clif, const char *name,
428
uint32_t offset, uint32_t size, void *vaddr)
429
{
430
if (clif->bo_count >= clif->bo_array_size) {
431
clif->bo_array_size = MAX2(4, clif->bo_array_size * 2);
432
clif->bo = reralloc(clif, clif->bo, struct clif_bo,
433
clif->bo_array_size);
434
}
435
436
/* CLIF relocs use the buffer name, so make sure they're unique. */
437
for (int i = 0; i < clif->bo_count; i++)
438
assert(strcmp(clif->bo[i].name, name) != 0);
439
440
clif->bo[clif->bo_count].name = ralloc_strdup(clif, name);
441
clif->bo[clif->bo_count].offset = offset;
442
clif->bo[clif->bo_count].size = size;
443
clif->bo[clif->bo_count].vaddr = vaddr;
444
clif->bo[clif->bo_count].dumped = false;
445
clif->bo_count++;
446
}
447
448