51b2472e7fdbd6e808ad069eee65ebf5459332bd
[chai.git] / src / ktrace.c
1 /*
2  *
3  * Copyright (C) 2017 Cafe Beverage. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15
16 static void formatted_hex_dump(char *array, uint8_t *buffer, size_t s) 
17 {
18         if (!buffer) return;
19
20         print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS, 16, 1, buffer, s, true);
21 }
22
23 /* Dump CPU memory by address. */
24
25 #define CPU_DUMP_SIZE 256
26
27 static void *kbase_fetch_cpu(struct kbase_context *kctx, void __user *cpu_addr, size_t *size_o, size_t size_i)
28 {
29         uint8_t *buffer;
30
31         if (!cpu_addr) return NULL;
32
33         if (!size_i) size_i = CPU_DUMP_SIZE;
34         if (size_o) *size_o = size_i;
35
36         buffer = kmalloc(size_i, GFP_KERNEL);
37
38         if (!buffer) {
39                 return NULL;
40         }
41
42         if (copy_from_user(buffer, cpu_addr, size_i) != 0) {
43                 kfree(buffer);
44                 return NULL;
45         }
46
47         return buffer;
48 }
49
50 /* Dump GPU memory by address.
51  * See mali_kbase_debug_mem_view.c for more information */
52
53 int kbase_jd_umm_map(struct kbase_context *kctx, struct kbase_va_region *reg);
54 void kbase_jd_umm_unmap(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc);
55
56 static void *kbase_fetch_gpu(struct kbase_context *kctx, u64 gpu_addr, size_t *size_o, size_t size_i)
57 {
58         struct kbase_va_region *reg;
59         struct kbase_mem_phy_alloc *alloc;
60         uint8_t *buffer;
61         uint8_t *buffer_on;
62         int p;
63         pgprot_t prot = PAGE_KERNEL;
64         uint64_t offset;
65
66         reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr);
67
68         if (!reg) {
69                 printk("Region not found!");
70                 return NULL;
71         }
72
73         if (!reg->gpu_alloc) {
74                 printk("No alloc!\n");
75                 return NULL;
76         }
77
78         offset = gpu_addr - (reg->start_pfn << PAGE_SHIFT);
79
80         if (offset < 0) {
81                 printk("What?\n");
82                 printk("GPU addr: %LX", gpu_addr);
83                 printk("start_pfn: %LX", reg->start_pfn);
84                 return NULL;
85         }
86
87         alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc);
88
89         if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) {
90                 kbase_jd_umm_map(kctx, reg);
91         }
92
93         if (!alloc->nents) {
94                 printk("Unbacked buffer %LX\n", gpu_addr);
95                 printk("Type: %d\n", alloc->type);
96
97                 return NULL;
98         }
99
100         if (!size_i) size_i = (alloc->nents << PAGE_SHIFT) - offset;
101         if (size_o) *size_o = size_i;
102
103         if (!(reg->flags & KBASE_REG_CPU_CACHED))
104                 prot = pgprot_writecombine(prot);
105
106         buffer = kmalloc(alloc->nents << PAGE_SHIFT, GFP_KERNEL);
107
108         if (!buffer) {
109                 printk("Bad alloc");
110                 return NULL;
111         }
112
113         for (p = 0; p < alloc->nents; ++p) {
114                 struct page *page = pfn_to_page(PFN_DOWN(alloc->pages[p]));
115                 uint8_t *mapping = vmap(&page, 1, VM_MAP, prot);
116
117                 if (!mapping) {
118                         printk("Bad mapping");
119                         kfree(buffer);
120                         return NULL;
121                 }
122
123                 memcpy(buffer + (p << PAGE_SHIFT), mapping, PAGE_SIZE);
124
125                 vunmap(mapping);
126         }
127
128         if (offset) {
129                 buffer_on = kmalloc(size_i, GFP_KERNEL);
130                 memcpy(buffer_on, buffer + offset, size_i);
131                 kfree(buffer);
132
133                 return buffer_on;
134         }
135
136         if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) {
137                 kbase_jd_umm_unmap(kctx, alloc);
138         }
139
140         return buffer;
141 }
142
143 static void kbase_push_gpu(struct kbase_context *kctx, void *buffer, u64 gpu_addr, size_t s)
144 {
145         struct kbase_va_region *reg;
146         struct kbase_mem_phy_alloc *alloc;
147         int p;
148         pgprot_t prot = PAGE_KERNEL;
149         uint64_t offset;
150         uint32_t buffer_offset = 0;
151         bool first_page = true;
152
153         printk("Pushing %d bytes from %p to %LX", s, buffer, gpu_addr);
154
155         reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr);
156
157         if (!reg) {
158                 printk("Region not found!");
159                 return;
160         }
161
162         if (!reg->gpu_alloc) {
163                 printk("No alloc!\n");
164                 return;
165         }
166
167         offset = gpu_addr - (reg->start_pfn << PAGE_SHIFT);
168
169         printk("Offset: %LX", offset);
170
171         if (offset < 0) {
172                 printk("What?\n");
173                 printk("GPU addr: %LX", gpu_addr);
174                 printk("start_pfn: %LX", reg->start_pfn);
175                 return;
176         }
177
178         alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc);
179
180         if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) {
181                 kbase_jd_umm_map(kctx, reg);
182         }
183
184         if (!alloc->nents) {
185                 printk("Unbacked buffer %LX\n", gpu_addr);
186                 printk("Type: %d\n", alloc->type);
187                 return;
188         }
189
190         if (!(reg->flags & KBASE_REG_CPU_CACHED))
191                 prot = pgprot_writecombine(prot);
192
193         /* Copy page-by-page */
194
195         for (p = offset >> PAGE_SHIFT; p < ((offset + s + PAGE_SIZE - 1) >> PAGE_SHIFT); ++p) {
196                 struct page *page;
197                 uint8_t *mapping;
198
199                 int copy_offset = p << PAGE_SHIFT, copy_quant = PAGE_SIZE;
200
201                 page = pfn_to_page(PFN_DOWN(alloc->pages[p]));
202                 mapping = vmap(&page, 1, VM_MAP, prot);
203
204                 if (!mapping) {
205                         printk("Bad mapping");
206                         return;
207                 }
208
209                 if(first_page) {
210                         copy_offset += offset & ~PAGE_MASK;
211                         copy_quant = PAGE_SIZE - copy_offset;
212
213                         first_page = false;
214                 }
215
216                 if(buffer_offset + copy_quant > s) {
217                         copy_quant = s - buffer_offset;
218                 }
219
220                 printk("Copying %d bytes to offset %d from offset %d",
221                                 copy_quant, copy_offset, buffer_offset);
222
223                 memcpy(mapping + copy_offset,
224                                 buffer + buffer_offset,
225                                 copy_quant);
226
227                 buffer_offset += copy_quant;
228
229                 vunmap(mapping);
230         }
231
232         if (alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) {
233                 kbase_jd_umm_unmap(kctx, alloc);
234         }
235 }
236
237 /* Assert that synthesised command stream is bit-identical with trace */
238
239 static void assert_gpu_same(struct kbase_context *kctx, uint64_t addr, size_t s, uint8_t *synth) 
240 {
241         uint8_t *buffer = kbase_fetch_gpu(kctx, addr, NULL, s);
242         int i;
243
244         if (!buffer) {
245                 printk("Bad allocation in assert %LX", addr);
246                 return;
247         }
248
249         for (i = 0; i < s; ++i) {
250                 if (buffer[i] != synth[i]) {
251                         printk("At %LX, expected:", addr);
252                         formatted_hex_dump("b", synth, s);
253                         printk("Instead got:");
254                         formatted_hex_dump("b", buffer, s);
255
256                         break;
257                 }
258         }
259
260         kfree(buffer);
261 }
262
263 static void assert_gpu_zeroes(struct kbase_context *kctx, uint64_t addr, size_t s) 
264 {
265         char *zero = kzalloc(s, GFP_KERNEL);
266
267         assert_gpu_same(kctx, addr, s, zero);
268         kfree(zero);
269 }
270
271 static void quick_dump_gpu(struct kbase_context *kctx, uint64_t addr, size_t s)
272 {
273         uint8_t *buf;
274
275         if(!addr) {
276                 printk("Null quick dump");
277                 return;
278         }
279
280         buf = kbase_fetch_gpu(kctx, addr, NULL, s);
281
282         printk("Quick GPU dump (%LX)", addr);
283
284         if(!buf) {
285                 printk("Not found");
286                 return;
287         }
288
289         formatted_hex_dump("a", buf, s);
290         kfree(buf);
291 }
292
293 #include "chai-notes.h"
294
295 #define DEFINE_CASE(label) case label: return #label;
296
297 static char *kbase_job_type_name(int type)
298 {
299         switch (type) {
300                 DEFINE_CASE(JOB_NOT_STARTED)
301                 DEFINE_CASE(JOB_TYPE_NULL)
302                 DEFINE_CASE(JOB_TYPE_SET_VALUE)
303                 DEFINE_CASE(JOB_TYPE_CACHE_FLUSH)
304                 DEFINE_CASE(JOB_TYPE_COMPUTE)
305                 DEFINE_CASE(JOB_TYPE_VERTEX)
306                 DEFINE_CASE(JOB_TYPE_TILER)
307                 DEFINE_CASE(JOB_TYPE_FUSED)
308                 DEFINE_CASE(JOB_TYPE_FRAGMENT)
309
310                 default:
311                         printk("Requested job type %X", type);
312                         return "UNKNOWN";
313         }
314 }
315
316 static char* kbase_gl_mode_name(uint8_t b) 
317 {
318         switch (b) {
319                 DEFINE_CASE(CHAI_POINTS)
320                 DEFINE_CASE(CHAI_LINES)
321                 DEFINE_CASE(CHAI_TRIANGLES)
322                 DEFINE_CASE(CHAI_TRIANGLE_STRIP)
323                 DEFINE_CASE(CHAI_TRIANGLE_FAN)
324
325                 default:
326                         printk("Unknown mode %X", b);
327                         return "GL_UNKNOWN";
328         }
329 }
330
331 /* TODO: Figure out what "fbd" means */
332 /* TODO: Corresponding SFBD decode (don't assume MFBD) */
333
334 static void kbase_trace_fbd(struct kbase_context *kctx, uint32_t fbd)
335 {
336         struct tentative_mfbd *mfbd = (struct tentative_mfbd *) kbase_fetch_gpu(kctx, (uint64_t) (uint32_t) fbd & FBD_POINTER_MASK, NULL, sizeof(struct tentative_mfbd));
337         uint8_t *buf;
338         uint32_t *buf32;
339
340         printk("MFBD @ %X (%X)", fbd & FBD_POINTER_MASK, fbd & ~FBD_POINTER_MASK);
341         printk("MFBD flags %X, heap free address %LX",
342                         mfbd->flags, mfbd->heap_free_address);
343
344         formatted_hex_dump("Block 1", (uint8_t *) mfbd->block1, sizeof(mfbd->block1));
345
346         printk("unk2");
347         buf = kbase_fetch_gpu(kctx, mfbd->unknown2, NULL, 64);
348         formatted_hex_dump("B", buf, 64);
349         kfree(buf);
350
351         assert_gpu_zeroes(kctx, mfbd->block2[0], 64);
352         assert_gpu_zeroes(kctx, mfbd->block2[1], 64);
353         assert_gpu_zeroes(kctx, mfbd->ugaT, 64);
354         assert_gpu_zeroes(kctx, mfbd->unknown_gpu_address, 64);
355
356         /* Somehow maybe sort of kind of framebufferish?
357          * It changes predictably in the same way as the FB.
358          * Unclear what exactly it is, though.
359          *
360          * Where the framebuffer is: 1A 33 00 00
361          * This is: 71 B3 03 71 6C 4D 87 46
362          * Where the framebuffer is: 1A 33 1A 00
363          * This is: AB E4 43 9C E8 D6 D1 25
364          *
365          * It repeats, too, but everything 8 bytes rather than 4.
366          *
367          * It is a function of the colour painted. But the exact details
368          * are elusive.
369          *
370          * Also, this is an output, not an input.
371          * Assuming the framebuffer works as intended, RE may be
372          * pointless.
373          */
374
375         printk("ugaT %LX, uga %LX", mfbd->ugaT, mfbd->unknown_gpu_address);
376         printk("ugan %LX", mfbd->unknown_gpu_addressN);
377         buf = kbase_fetch_gpu(kctx, mfbd->unknown_gpu_addressN, NULL, 64);
378         formatted_hex_dump("B", buf, 64);
379         kfree(buf);
380
381         printk("unk1 %X, b1 %LX, b2 %LX, unk2 %LX, unk3 %LX, blah %LX",
382                         mfbd->unknown1,
383                         mfbd->block2[0],
384                         mfbd->block2[1],
385                         mfbd->unknown2,
386                         mfbd->unknown3,
387                         mfbd->blah);
388
389         printk("Weights [ %X, %X, %X, %X, %X, %X, %X, %X ]",
390                         mfbd->weights[0], mfbd->weights[1],
391                         mfbd->weights[2], mfbd->weights[3],
392                         mfbd->weights[4], mfbd->weights[5],
393                         mfbd->weights[6], mfbd->weights[7]);
394
395         formatted_hex_dump("Block 3", (uint8_t *) mfbd->block3, sizeof(mfbd->block3));
396         printk("---");
397         formatted_hex_dump("Block 4", (uint8_t *) mfbd->block4, sizeof(mfbd->block4));
398
399         printk("--- (seriously though) --- %X", mfbd->block3[4]);
400         buf32 = kbase_fetch_gpu(kctx, mfbd->block3[4], NULL, 128);
401         
402         if(buf32) {
403                 formatted_hex_dump("a", (uint8_t*) buf32, 128);
404
405                 quick_dump_gpu(kctx, buf32[6], 64);
406                 quick_dump_gpu(kctx, buf32[20], 64);
407                 quick_dump_gpu(kctx, buf32[23], 64);
408                 quick_dump_gpu(kctx, buf32[24], 64);
409                 quick_dump_gpu(kctx, buf32[25], 64);
410                 quick_dump_gpu(kctx, buf32[26], 64);
411                 quick_dump_gpu(kctx, buf32[27], 64);
412                 quick_dump_gpu(kctx, buf32[28], 64);
413                 quick_dump_gpu(kctx, buf32[31], 64);
414
415                 kfree(buf32);
416         }
417
418         quick_dump_gpu(kctx, mfbd->block3[16], 128);
419
420         kfree(mfbd);
421 }
422
423 static void kbase_trace_vertices(struct kbase_context *kctx, uint64_t address)
424 {
425         uint64_t raw, flags;
426         int vertex_count;
427         uint32_t *v;
428         int i;
429
430         struct vertex_buffer *vb =
431                 (struct vertex_buffer *) kbase_fetch_gpu(
432                                 kctx, address,
433                                 NULL, sizeof(struct vertex_buffer));
434         if (!vb) return;
435
436         raw = vb->vertices & ~3;
437         flags = vb->vertices ^ raw;
438
439         v = kbase_fetch_gpu(kctx, raw, NULL, vb->size);
440
441         if (vb->vertex_size != 3 * sizeof(float)) {
442                 printk("Bad vertex size %x", vb->vertex_size);
443                 return;
444         }
445
446         vertex_count = vb->size / vb->vertex_size;
447
448         kfree(vb);
449
450         printk("Vertices at %LX (flag %LX):", raw, flags);
451
452         for (i = 0; i < vertex_count * 3; i += 3) {
453                 printk("<%X, %X, %X>", v[i], v[i + 1], v[i + 2]);
454
455                 /* Interfere for fun */
456                 if(i == 3) {
457                         printk("Interfering for fun");
458                         v[i + 0] = v[i + 1] = 0x3F800000;
459                 }
460         }
461
462         kbase_push_gpu(kctx, v, raw, vb->size);
463 }
464
465 static void kbase_trace_hw_chain(struct kbase_context *kctx, uint64_t chain)
466 {
467         struct job_descriptor_header *h;
468         uint8_t *gen_pay;
469         u64 next;
470         u64 payload;
471
472         /* Trace descriptor */
473         h = kbase_fetch_gpu(kctx, chain, NULL, sizeof(*h));
474
475         printk("%s job, %d-bit, status %X, incomplete %X, fault %LX, barrier %d, index %hX, dependencies (%hX, %hX)",
476                         kbase_job_type_name(h->job_type),
477                         h->job_descriptor_size ? 64 : 32,
478                         h->exception_status,
479                         h->first_incomplete_task,
480                         h->fault_pointer,
481                         h->job_barrier,
482                         h->job_index,
483                         h->job_dependency_index_1,
484                         h->job_dependency_index_2);
485
486         payload = chain + sizeof(*h);
487
488         switch (h->job_type) {
489         case JOB_TYPE_SET_VALUE: {
490                 struct payload_set_value *s;
491
492                 s = kbase_fetch_gpu(kctx, payload, NULL, sizeof(*s));
493                 printk("set value -> %LX (%LX)", s->out, s->unknown);
494                 kfree(s);
495                 break;
496         }
497
498         case JOB_TYPE_VERTEX:
499         case JOB_TYPE_TILER: {
500                 struct payload_vertex_tiler32 *v;
501                 int addr = 0;
502                 uint64_t *i_shader;
503                 uint8_t *shader;
504
505                 v = kbase_fetch_gpu(kctx, payload, NULL, sizeof(*v));
506
507                 if ((v->shader & 0xFFF00000) == 0x5AB00000) {
508                         printk("Job sabotaged");
509                         break;
510                 }
511
512                 /* Mask out lower 128-bit (instruction word) for flags.
513                  *
514                  * TODO: Decode flags.
515                  *
516                  * TODO: Link with cwabbotts-open-gpu-tools to
517                  * disassemble on the fly.
518                  */
519
520                 i_shader = kbase_fetch_gpu(kctx, v->shader, NULL, sizeof(u64));
521
522                 printk("%s shader @ %LX (flags %LX)\n",
523                         h->job_type == JOB_TYPE_VERTEX ? "Vertex" : "Fragment",
524                         *i_shader & ~15,
525                         *i_shader & 15);
526
527                 shader = kbase_fetch_gpu(kctx, *i_shader & ~15, NULL, 0x880 - 0x540);
528                 formatted_hex_dump("s", shader, 0x880 - 0x540);
529                 kfree(shader);
530                 kfree(i_shader);
531
532                 kbase_trace_vertices(kctx, v->vertices);
533
534                 if (h->job_type == JOB_TYPE_TILER)
535                         printk("Drawing in %s", kbase_gl_mode_name(((uint8_t *) v->block1)[8]));
536
537                 assert_gpu_zeroes(kctx, v->zeroes, 64);
538
539                 if (v->null1 | v->null2 | v->null4)
540                         printk("Null tripped?");
541
542                 printk("%cFBD", v->fbd & FBD_TYPE ? 'M' : 'S');
543                 kbase_trace_fbd(kctx, v->fbd);
544
545                 formatted_hex_dump("Block 1", (uint8_t *) v->block1, sizeof(v->block1));
546
547                 for (addr = 0; addr < 14; ++addr) {
548                         uint32_t address = ((uint32_t *) &(v->zeroes))[addr];
549                         uint8_t *buf;
550                         size_t sz = 64;
551
552                         /* Structure known. Skip hex dump */
553                         if (addr == 2) continue;
554                         if (addr == 3) continue;
555                         //if (addr == 6) continue;
556                         if (addr == 10 && h->job_type == JOB_TYPE_VERTEX) continue;
557                         if (addr == 11) continue;
558                         if (addr == 12) continue;
559
560                         /* Size known exactly but not structure; cull */
561                         if (addr == 0) sz = 0x100;
562                         if (addr == 1) sz = 0x10;
563                         if (addr == 4) sz = 0x40;
564                         if (addr == 5) sz = 0x20;
565                         if (addr == 7) sz = 0x10;
566                         if (addr == 8) sz = 0x20;
567
568                         if (addr == 6) sz = 0x80;
569
570                         printk("Addr %d %X", addr, address);
571
572                         if (!address) continue;
573
574                         if (addr == 0) {
575                                 buf = kbase_fetch_cpu(kctx, (void *) (uint32_t) address, NULL, sz);
576                         } else {
577                                 buf = kbase_fetch_gpu(kctx, address, NULL, sz);
578                         }
579
580                         formatted_hex_dump("B", buf, sz);
581
582                         if (addr == 8) {
583                                 uint32_t sub = *((uint32_t *) buf) & 0xFFFFFFFE;
584                                 uint8_t *sbuf = kbase_fetch_gpu(kctx, sub, NULL, 64);
585
586                                 printk("---");
587                                 formatted_hex_dump("S", sbuf, 64);
588                                 kfree(sbuf);
589                         }
590
591                         if (addr == 1) {
592                                 uint64_t sub = *((uint64_t*) buf) >> 8;
593                                 uint8_t *sbuf = kbase_fetch_gpu(kctx, sub, NULL, 64);
594
595                                 printk("--- %LX", sub);
596                                 formatted_hex_dump("S", sbuf, 64);
597                                 kfree(sbuf);
598                         }
599
600                         kfree(buf);
601                 }
602
603                 formatted_hex_dump("Block 2", (uint8_t *) v->block2, sizeof(v->block2));
604
605                 kfree(v);
606                 break;
607         }
608
609         case JOB_TYPE_FRAGMENT: {
610                 struct payload_fragment *f;
611
612                 f = kbase_fetch_gpu(kctx, payload, NULL, sizeof(*f));
613
614                 /* Bit 31 of max_tile_coord clear on the first frame.
615                  * Set after.
616                  * TODO: Research.
617                  */
618
619                 printk("frag %X %X (%d, %d) -> (%d, %d), fbd type %cFBD at %LX (%LX) \n",
620                                 f->min_tile_coord, f->max_tile_coord,
621                                 TILE_COORD_X(f->min_tile_coord),
622                                 TILE_COORD_Y(f->min_tile_coord),
623                                 TILE_COORD_X(f->max_tile_coord),
624                                 TILE_COORD_Y(f->max_tile_coord),
625                                 f->fragment_fbd & FBD_TYPE ? 'M' : 'S',
626                                 f->fragment_fbd,
627                                 f->fragment_fbd & FBD_POINTER_MASK);
628
629                 kbase_trace_fbd(kctx, f->fragment_fbd);
630
631                 kfree(f);
632                 break;
633         }
634
635         default: {
636                 printk("Dumping payload %LX for job type %s",
637                                 payload,
638                                 kbase_job_type_name(h->job_type));
639
640                 gen_pay = kbase_fetch_gpu(kctx, payload, NULL, 256);
641                 formatted_hex_dump("pl", gen_pay, 256);
642                 kfree(gen_pay);
643         }
644         }
645
646         next = h->job_descriptor_size
647                 ? h->next_job._64
648                 : h->next_job._32;
649
650         kfree(h);
651
652         /* Traverse the job chain */
653         if (next)
654                 kbase_trace_hw_chain(kctx, next);
655 }
656
657 static void kbase_trace_ext_resources(
658                 struct kbase_context *kctx,
659                 int n,
660                 union kbase_pointer rsrc)
661 {
662         int i;
663         u64 *lst = kbase_fetch_cpu(kctx, rsrc.value, NULL, sizeof(u64) * n);
664
665         for (i = 0; i < n; ++i) {
666                 u64 link = lst[i];
667                 u64 addr = link & ~BASE_EXT_RES_ACCESS_EXCLUSIVE;
668                 void *rs = kbase_fetch_gpu(kctx, addr, NULL, 0);
669
670                 printk("Resource %d: %LX %s",
671                         i,
672                         addr,
673                         link & BASE_EXT_RES_ACCESS_EXCLUSIVE
674                                 ? "(exclusive)" : "(shared)");
675
676                 /* Framebuffer in fragment jobs */
677
678                 formatted_hex_dump("fb", rs, 48);
679                 kfree(rs);
680         }
681
682         kfree(lst);
683 }
684
685 extern const char *kbasep_map_core_reqs_to_string(base_jd_core_req);
686
687 static void kbase_trace_special_base_jd_atom_v2(
688                 struct kbase_context *kctx,
689                 struct base_jd_atom_v2 *v)
690 {
691         printk("%s", kbasep_map_core_reqs_to_string(v->core_req));
692
693         kbase_trace_ext_resources(kctx, v->nr_extres, v->extres_list);
694
695         if (v->core_req & BASE_JD_REQ_SOFT_JOB) {
696                 if (v->core_req & BASE_JD_REQ_SOFT_REPLAY) {
697                         struct base_jd_replay_payload *payload;
698
699                         payload = (struct base_jd_replay_payload *)
700                                 kbase_fetch_gpu(kctx, v->jc, NULL, sizeof(*payload));
701
702                         printk("tiler_jc_list = %LX, fragment_jc = %LX, "
703                                 "tiler_heap_free = %LX, fragment hierarchy mask = %hX, "
704                                 "tiler hierachy mask = %hX, hierarchy def weight %X, "
705                                 "tiler core_req = %X, fragment core_req = %X",
706                                 payload->tiler_jc_list,
707                                 payload->fragment_jc,
708                                 payload->tiler_heap_free,
709                                 payload->fragment_hierarchy_mask,
710                                 payload->tiler_hierarchy_mask,
711                                 payload->hierarchy_default_weight,
712                                 payload->tiler_core_req,
713                                 payload->fragment_core_req);
714
715                         kfree(payload);
716                 } else  {
717                         /* TODO: Soft job decoding */
718                         printk("Unknown soft job");
719                 }
720         } else {
721                 kbase_trace_hw_chain(kctx, v->jc);
722         }
723 }
724
725 /* The ioctl tracer is automatically generated by black */
726 #include "black-output-trace.c"