17ec681f3Smrg/* 27ec681f3Smrg * Copyright (C) 2017-2019 Alyssa Rosenzweig 37ec681f3Smrg * Copyright (C) 2017-2019 Connor Abbott 47ec681f3Smrg * Copyright (C) 2019 Collabora, Ltd. 57ec681f3Smrg * 67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 87ec681f3Smrg * to deal in the Software without restriction, including without limitation 97ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 117ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 127ec681f3Smrg * 137ec681f3Smrg * The above copyright notice and this permission notice (including the next 147ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 157ec681f3Smrg * Software. 167ec681f3Smrg * 177ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 187ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 207ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 217ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 227ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 237ec681f3Smrg * SOFTWARE. 247ec681f3Smrg */ 257ec681f3Smrg 267ec681f3Smrg#include <genxml/gen_macros.h> 277ec681f3Smrg#include <stdio.h> 287ec681f3Smrg#include <stdlib.h> 297ec681f3Smrg#include <memory.h> 307ec681f3Smrg#include <stdbool.h> 317ec681f3Smrg#include <stdarg.h> 327ec681f3Smrg#include <errno.h> 337ec681f3Smrg#include <ctype.h> 347ec681f3Smrg#include "decode.h" 357ec681f3Smrg 367ec681f3Smrg#include "midgard/disassemble.h" 377ec681f3Smrg#include "bifrost/disassemble.h" 387ec681f3Smrg 397ec681f3Smrg#define DUMP_UNPACKED(T, var, ...) { \ 407ec681f3Smrg pandecode_log(__VA_ARGS__); \ 417ec681f3Smrg pan_print(pandecode_dump_stream, T, var, (pandecode_indent + 1) * 2); \ 427ec681f3Smrg} 437ec681f3Smrg 447ec681f3Smrg#define DUMP_CL(T, cl, ...) {\ 457ec681f3Smrg pan_unpack(cl, T, temp); \ 467ec681f3Smrg DUMP_UNPACKED(T, temp, __VA_ARGS__); \ 477ec681f3Smrg} 487ec681f3Smrg 497ec681f3Smrg#define DUMP_SECTION(A, S, cl, ...) { \ 507ec681f3Smrg pan_section_unpack(cl, A, S, temp); \ 517ec681f3Smrg pandecode_log(__VA_ARGS__); \ 527ec681f3Smrg pan_section_print(pandecode_dump_stream, A, S, temp, (pandecode_indent + 1) * 2); \ 537ec681f3Smrg} 547ec681f3Smrg 557ec681f3Smrg#define MAP_ADDR(T, addr, cl) \ 567ec681f3Smrg const uint8_t *cl = 0; \ 577ec681f3Smrg { \ 587ec681f3Smrg struct pandecode_mapped_memory *mapped_mem = pandecode_find_mapped_gpu_mem_containing(addr); \ 597ec681f3Smrg cl = pandecode_fetch_gpu_mem(mapped_mem, addr, pan_size(T)); \ 607ec681f3Smrg } 617ec681f3Smrg 627ec681f3Smrg#define DUMP_ADDR(T, addr, ...) {\ 637ec681f3Smrg MAP_ADDR(T, addr, cl) \ 647ec681f3Smrg DUMP_CL(T, cl, __VA_ARGS__); \ 657ec681f3Smrg} 667ec681f3Smrg 677ec681f3Smrg/* Semantic logging type. 687ec681f3Smrg * 697ec681f3Smrg * Raw: for raw messages to be printed as is. 707ec681f3Smrg * Message: for helpful information to be commented out in replays. 717ec681f3Smrg * 727ec681f3Smrg * Use one of pandecode_log or pandecode_msg as syntax sugar. 737ec681f3Smrg */ 747ec681f3Smrg 757ec681f3Smrgenum pandecode_log_type { 767ec681f3Smrg PANDECODE_RAW, 777ec681f3Smrg PANDECODE_MESSAGE, 787ec681f3Smrg}; 797ec681f3Smrg 807ec681f3Smrg#define pandecode_log(...) pandecode_log_typed(PANDECODE_RAW, __VA_ARGS__) 817ec681f3Smrg#define pandecode_msg(...) pandecode_log_typed(PANDECODE_MESSAGE, __VA_ARGS__) 827ec681f3Smrg 837ec681f3Smrgstatic unsigned pandecode_indent = 0; 847ec681f3Smrg 857ec681f3Smrgstatic void 867ec681f3Smrgpandecode_make_indent(void) 877ec681f3Smrg{ 887ec681f3Smrg for (unsigned i = 0; i < pandecode_indent; ++i) 897ec681f3Smrg fprintf(pandecode_dump_stream, " "); 907ec681f3Smrg} 917ec681f3Smrg 927ec681f3Smrgstatic void PRINTFLIKE(2, 3) 937ec681f3Smrgpandecode_log_typed(enum pandecode_log_type type, const char *format, ...) 947ec681f3Smrg{ 957ec681f3Smrg va_list ap; 967ec681f3Smrg 977ec681f3Smrg pandecode_make_indent(); 987ec681f3Smrg 997ec681f3Smrg if (type == PANDECODE_MESSAGE) 1007ec681f3Smrg fprintf(pandecode_dump_stream, "// "); 1017ec681f3Smrg 1027ec681f3Smrg va_start(ap, format); 1037ec681f3Smrg vfprintf(pandecode_dump_stream, format, ap); 1047ec681f3Smrg va_end(ap); 1057ec681f3Smrg} 1067ec681f3Smrg 1077ec681f3Smrgstatic void 1087ec681f3Smrgpandecode_log_cont(const char *format, ...) 1097ec681f3Smrg{ 1107ec681f3Smrg va_list ap; 1117ec681f3Smrg 1127ec681f3Smrg va_start(ap, format); 1137ec681f3Smrg vfprintf(pandecode_dump_stream, format, ap); 1147ec681f3Smrg va_end(ap); 1157ec681f3Smrg} 1167ec681f3Smrg 1177ec681f3Smrg/* To check for memory safety issues, validates that the given pointer in GPU 1187ec681f3Smrg * memory is valid, containing at least sz bytes. The goal is to eliminate 1197ec681f3Smrg * GPU-side memory bugs (NULL pointer dereferences, buffer overflows, or buffer 1207ec681f3Smrg * overruns) by statically validating pointers. 1217ec681f3Smrg */ 1227ec681f3Smrg 1237ec681f3Smrgstatic void 1247ec681f3Smrgpandecode_validate_buffer(mali_ptr addr, size_t sz) 1257ec681f3Smrg{ 1267ec681f3Smrg if (!addr) { 1277ec681f3Smrg pandecode_msg("XXX: null pointer deref"); 1287ec681f3Smrg return; 1297ec681f3Smrg } 1307ec681f3Smrg 1317ec681f3Smrg /* Find a BO */ 1327ec681f3Smrg 1337ec681f3Smrg struct pandecode_mapped_memory *bo = 1347ec681f3Smrg pandecode_find_mapped_gpu_mem_containing(addr); 1357ec681f3Smrg 1367ec681f3Smrg if (!bo) { 1377ec681f3Smrg pandecode_msg("XXX: invalid memory dereference\n"); 1387ec681f3Smrg return; 1397ec681f3Smrg } 1407ec681f3Smrg 1417ec681f3Smrg /* Bounds check */ 1427ec681f3Smrg 1437ec681f3Smrg unsigned offset = addr - bo->gpu_va; 1447ec681f3Smrg unsigned total = offset + sz; 1457ec681f3Smrg 1467ec681f3Smrg if (total > bo->length) { 1477ec681f3Smrg pandecode_msg("XXX: buffer overrun. " 1487ec681f3Smrg "Chunk of size %zu at offset %d in buffer of size %zu. " 1497ec681f3Smrg "Overrun by %zu bytes. \n", 1507ec681f3Smrg sz, offset, bo->length, total - bo->length); 1517ec681f3Smrg return; 1527ec681f3Smrg } 1537ec681f3Smrg} 1547ec681f3Smrg 1557ec681f3Smrg#if PAN_ARCH <= 5 1567ec681f3Smrg/* Midgard's tiler descriptor is embedded within the 1577ec681f3Smrg * larger FBD */ 1587ec681f3Smrg 1597ec681f3Smrgstatic void 1607ec681f3Smrgpandecode_midgard_tiler_descriptor( 1617ec681f3Smrg const struct mali_tiler_context_packed *tp, 1627ec681f3Smrg const struct mali_tiler_weights_packed *wp) 1637ec681f3Smrg{ 1647ec681f3Smrg pan_unpack(tp, TILER_CONTEXT, t); 1657ec681f3Smrg DUMP_UNPACKED(TILER_CONTEXT, t, "Tiler:\n"); 1667ec681f3Smrg 1677ec681f3Smrg /* We've never seen weights used in practice, but they exist */ 1687ec681f3Smrg pan_unpack(wp, TILER_WEIGHTS, w); 1697ec681f3Smrg bool nonzero_weights = false; 1707ec681f3Smrg 1717ec681f3Smrg nonzero_weights |= w.weight0 != 0x0; 1727ec681f3Smrg nonzero_weights |= w.weight1 != 0x0; 1737ec681f3Smrg nonzero_weights |= w.weight2 != 0x0; 1747ec681f3Smrg nonzero_weights |= w.weight3 != 0x0; 1757ec681f3Smrg nonzero_weights |= w.weight4 != 0x0; 1767ec681f3Smrg nonzero_weights |= w.weight5 != 0x0; 1777ec681f3Smrg nonzero_weights |= w.weight6 != 0x0; 1787ec681f3Smrg nonzero_weights |= w.weight7 != 0x0; 1797ec681f3Smrg 1807ec681f3Smrg if (nonzero_weights) 1817ec681f3Smrg DUMP_UNPACKED(TILER_WEIGHTS, w, "Tiler Weights:\n"); 1827ec681f3Smrg} 1837ec681f3Smrg#endif 1847ec681f3Smrg 1857ec681f3Smrg/* Information about the framebuffer passed back for 1867ec681f3Smrg * additional analysis */ 1877ec681f3Smrg 1887ec681f3Smrgstruct pandecode_fbd { 1897ec681f3Smrg unsigned width; 1907ec681f3Smrg unsigned height; 1917ec681f3Smrg unsigned rt_count; 1927ec681f3Smrg bool has_extra; 1937ec681f3Smrg}; 1947ec681f3Smrg 1957ec681f3Smrg#if PAN_ARCH == 4 1967ec681f3Smrgstatic struct pandecode_fbd 1977ec681f3Smrgpandecode_sfbd(uint64_t gpu_va, int job_no, bool is_fragment, unsigned gpu_id) 1987ec681f3Smrg{ 1997ec681f3Smrg struct pandecode_mapped_memory *mem = pandecode_find_mapped_gpu_mem_containing(gpu_va); 2007ec681f3Smrg const void *PANDECODE_PTR_VAR(s, mem, (mali_ptr) gpu_va); 2017ec681f3Smrg 2027ec681f3Smrg struct pandecode_fbd info = { 2037ec681f3Smrg .has_extra = false, 2047ec681f3Smrg .rt_count = 1 2057ec681f3Smrg }; 2067ec681f3Smrg 2077ec681f3Smrg pandecode_log("Framebuffer:\n"); 2087ec681f3Smrg pandecode_indent++; 2097ec681f3Smrg 2107ec681f3Smrg DUMP_SECTION(FRAMEBUFFER, LOCAL_STORAGE, s, "Local Storage:\n"); 2117ec681f3Smrg pan_section_unpack(s, FRAMEBUFFER, PARAMETERS, p); 2127ec681f3Smrg DUMP_UNPACKED(FRAMEBUFFER_PARAMETERS, p, "Parameters:\n"); 2137ec681f3Smrg 2147ec681f3Smrg const void *t = pan_section_ptr(s, FRAMEBUFFER, TILER); 2157ec681f3Smrg const void *w = pan_section_ptr(s, FRAMEBUFFER, TILER_WEIGHTS); 2167ec681f3Smrg 2177ec681f3Smrg pandecode_midgard_tiler_descriptor(t, w); 2187ec681f3Smrg 2197ec681f3Smrg pandecode_indent--; 2207ec681f3Smrg 2217ec681f3Smrg /* Dummy unpack of the padding section to make sure all words are 0. 2227ec681f3Smrg * No need to call print here since the section is supposed to be empty. 2237ec681f3Smrg */ 2247ec681f3Smrg pan_section_unpack(s, FRAMEBUFFER, PADDING_1, padding1); 2257ec681f3Smrg pan_section_unpack(s, FRAMEBUFFER, PADDING_2, padding2); 2267ec681f3Smrg pandecode_log("\n"); 2277ec681f3Smrg 2287ec681f3Smrg return info; 2297ec681f3Smrg} 2307ec681f3Smrg#endif 2317ec681f3Smrg 2327ec681f3Smrg#if PAN_ARCH >= 5 2337ec681f3Smrgstatic void 2347ec681f3Smrgpandecode_local_storage(uint64_t gpu_va, int job_no) 2357ec681f3Smrg{ 2367ec681f3Smrg struct pandecode_mapped_memory *mem = pandecode_find_mapped_gpu_mem_containing(gpu_va); 2377ec681f3Smrg const struct mali_local_storage_packed *PANDECODE_PTR_VAR(s, mem, (mali_ptr) gpu_va); 2387ec681f3Smrg DUMP_CL(LOCAL_STORAGE, s, "Local Storage:\n"); 2397ec681f3Smrg} 2407ec681f3Smrg 2417ec681f3Smrgstatic void 2427ec681f3Smrgpandecode_render_target(uint64_t gpu_va, unsigned job_no, unsigned gpu_id, 2437ec681f3Smrg const struct MALI_FRAMEBUFFER_PARAMETERS *fb) 2447ec681f3Smrg{ 2457ec681f3Smrg pandecode_log("Color Render Targets:\n"); 2467ec681f3Smrg pandecode_indent++; 2477ec681f3Smrg 2487ec681f3Smrg for (int i = 0; i < (fb->render_target_count); i++) { 2497ec681f3Smrg mali_ptr rt_va = gpu_va + i * pan_size(RENDER_TARGET); 2507ec681f3Smrg struct pandecode_mapped_memory *mem = 2517ec681f3Smrg pandecode_find_mapped_gpu_mem_containing(rt_va); 2527ec681f3Smrg const struct mali_render_target_packed *PANDECODE_PTR_VAR(rtp, mem, (mali_ptr) rt_va); 2537ec681f3Smrg DUMP_CL(RENDER_TARGET, rtp, "Color Render Target %d:\n", i); 2547ec681f3Smrg } 2557ec681f3Smrg 2567ec681f3Smrg pandecode_indent--; 2577ec681f3Smrg pandecode_log("\n"); 2587ec681f3Smrg} 2597ec681f3Smrg#endif 2607ec681f3Smrg 2617ec681f3Smrg#if PAN_ARCH >= 6 2627ec681f3Smrgstatic void 2637ec681f3Smrgpandecode_sample_locations(const void *fb, int job_no) 2647ec681f3Smrg{ 2657ec681f3Smrg pan_section_unpack(fb, FRAMEBUFFER, PARAMETERS, params); 2667ec681f3Smrg 2677ec681f3Smrg struct pandecode_mapped_memory *smem = 2687ec681f3Smrg pandecode_find_mapped_gpu_mem_containing(params.sample_locations); 2697ec681f3Smrg 2707ec681f3Smrg const u16 *PANDECODE_PTR_VAR(samples, smem, params.sample_locations); 2717ec681f3Smrg 2727ec681f3Smrg pandecode_log("Sample locations:\n"); 2737ec681f3Smrg for (int i = 0; i < 33; i++) { 2747ec681f3Smrg pandecode_log(" (%d, %d),\n", 2757ec681f3Smrg samples[2 * i] - 128, 2767ec681f3Smrg samples[2 * i + 1] - 128); 2777ec681f3Smrg } 2787ec681f3Smrg} 2797ec681f3Smrg#endif 2807ec681f3Smrg 2817ec681f3Smrgstatic void 2827ec681f3Smrgpandecode_dcd(const struct MALI_DRAW *p, 2837ec681f3Smrg int job_no, enum mali_job_type job_type, 2847ec681f3Smrg char *suffix, unsigned gpu_id); 2857ec681f3Smrg 2867ec681f3Smrg#if PAN_ARCH >= 5 2877ec681f3Smrgstatic struct pandecode_fbd 2887ec681f3Smrgpandecode_mfbd_bfr(uint64_t gpu_va, int job_no, bool is_fragment, unsigned gpu_id) 2897ec681f3Smrg{ 2907ec681f3Smrg struct pandecode_mapped_memory *mem = pandecode_find_mapped_gpu_mem_containing(gpu_va); 2917ec681f3Smrg const void *PANDECODE_PTR_VAR(fb, mem, (mali_ptr) gpu_va); 2927ec681f3Smrg pan_section_unpack(fb, FRAMEBUFFER, PARAMETERS, params); 2937ec681f3Smrg 2947ec681f3Smrg struct pandecode_fbd info; 2957ec681f3Smrg 2967ec681f3Smrg#if PAN_ARCH >= 6 2977ec681f3Smrg pandecode_sample_locations(fb, job_no); 2987ec681f3Smrg 2997ec681f3Smrg pan_section_unpack(fb, FRAMEBUFFER, PARAMETERS, bparams); 3007ec681f3Smrg unsigned dcd_size = pan_size(DRAW); 3017ec681f3Smrg struct pandecode_mapped_memory *dcdmem = 3027ec681f3Smrg pandecode_find_mapped_gpu_mem_containing(bparams.frame_shader_dcds); 3037ec681f3Smrg 3047ec681f3Smrg if (bparams.pre_frame_0 != MALI_PRE_POST_FRAME_SHADER_MODE_NEVER) { 3057ec681f3Smrg const void *PANDECODE_PTR_VAR(dcd, dcdmem, bparams.frame_shader_dcds + (0 * dcd_size)); 3067ec681f3Smrg pan_unpack(dcd, DRAW, draw); 3077ec681f3Smrg pandecode_log("Pre frame 0:\n"); 3087ec681f3Smrg pandecode_dcd(&draw, job_no, MALI_JOB_TYPE_FRAGMENT, "", gpu_id); 3097ec681f3Smrg } 3107ec681f3Smrg 3117ec681f3Smrg if (bparams.pre_frame_1 != MALI_PRE_POST_FRAME_SHADER_MODE_NEVER) { 3127ec681f3Smrg const void *PANDECODE_PTR_VAR(dcd, dcdmem, bparams.frame_shader_dcds + (1 * dcd_size)); 3137ec681f3Smrg pan_unpack(dcd, DRAW, draw); 3147ec681f3Smrg pandecode_log("Pre frame 1:\n"); 3157ec681f3Smrg pandecode_dcd(&draw, job_no, MALI_JOB_TYPE_FRAGMENT, "", gpu_id); 3167ec681f3Smrg } 3177ec681f3Smrg 3187ec681f3Smrg if (bparams.post_frame != MALI_PRE_POST_FRAME_SHADER_MODE_NEVER) { 3197ec681f3Smrg const void *PANDECODE_PTR_VAR(dcd, dcdmem, bparams.frame_shader_dcds + (2 * dcd_size)); 3207ec681f3Smrg pan_unpack(dcd, DRAW, draw); 3217ec681f3Smrg pandecode_log("Post frame:\n"); 3227ec681f3Smrg pandecode_dcd(&draw, job_no, MALI_JOB_TYPE_FRAGMENT, "", gpu_id); 3237ec681f3Smrg } 3247ec681f3Smrg#endif 3257ec681f3Smrg 3267ec681f3Smrg pandecode_log("Multi-Target Framebuffer:\n"); 3277ec681f3Smrg pandecode_indent++; 3287ec681f3Smrg 3297ec681f3Smrg#if PAN_ARCH <= 5 3307ec681f3Smrg DUMP_SECTION(FRAMEBUFFER, LOCAL_STORAGE, fb, "Local Storage:\n"); 3317ec681f3Smrg#endif 3327ec681f3Smrg 3337ec681f3Smrg info.width = params.width; 3347ec681f3Smrg info.height = params.height; 3357ec681f3Smrg info.rt_count = params.render_target_count; 3367ec681f3Smrg DUMP_UNPACKED(FRAMEBUFFER_PARAMETERS, params, "Parameters:\n"); 3377ec681f3Smrg 3387ec681f3Smrg#if PAN_ARCH <= 5 3397ec681f3Smrg const void *t = pan_section_ptr(fb, FRAMEBUFFER, TILER); 3407ec681f3Smrg const void *w = pan_section_ptr(fb, FRAMEBUFFER, TILER_WEIGHTS); 3417ec681f3Smrg pandecode_midgard_tiler_descriptor(t, w); 3427ec681f3Smrg#endif 3437ec681f3Smrg 3447ec681f3Smrg pandecode_indent--; 3457ec681f3Smrg pandecode_log("\n"); 3467ec681f3Smrg 3477ec681f3Smrg gpu_va += pan_size(FRAMEBUFFER); 3487ec681f3Smrg 3497ec681f3Smrg info.has_extra = params.has_zs_crc_extension; 3507ec681f3Smrg 3517ec681f3Smrg if (info.has_extra) { 3527ec681f3Smrg struct pandecode_mapped_memory *mem = 3537ec681f3Smrg pandecode_find_mapped_gpu_mem_containing(gpu_va); 3547ec681f3Smrg const struct mali_zs_crc_extension_packed *PANDECODE_PTR_VAR(zs_crc, mem, (mali_ptr)gpu_va); 3557ec681f3Smrg DUMP_CL(ZS_CRC_EXTENSION, zs_crc, "ZS CRC Extension:\n"); 3567ec681f3Smrg pandecode_log("\n"); 3577ec681f3Smrg 3587ec681f3Smrg gpu_va += pan_size(ZS_CRC_EXTENSION); 3597ec681f3Smrg } 3607ec681f3Smrg 3617ec681f3Smrg if (is_fragment) 3627ec681f3Smrg pandecode_render_target(gpu_va, job_no, gpu_id, ¶ms); 3637ec681f3Smrg 3647ec681f3Smrg return info; 3657ec681f3Smrg} 3667ec681f3Smrg#endif 3677ec681f3Smrg 3687ec681f3Smrgstatic void 3697ec681f3Smrgpandecode_attributes(const struct pandecode_mapped_memory *mem, 3707ec681f3Smrg mali_ptr addr, int job_no, char *suffix, 3717ec681f3Smrg int count, bool varying, enum mali_job_type job_type) 3727ec681f3Smrg{ 3737ec681f3Smrg char *prefix = varying ? "Varying" : "Attribute"; 3747ec681f3Smrg assert(addr); 3757ec681f3Smrg 3767ec681f3Smrg if (!count) { 3777ec681f3Smrg pandecode_msg("warn: No %s records\n", prefix); 3787ec681f3Smrg return; 3797ec681f3Smrg } 3807ec681f3Smrg 3817ec681f3Smrg MAP_ADDR(ATTRIBUTE_BUFFER, addr, cl); 3827ec681f3Smrg 3837ec681f3Smrg for (int i = 0; i < count; ++i) { 3847ec681f3Smrg pan_unpack(cl + i * pan_size(ATTRIBUTE_BUFFER), ATTRIBUTE_BUFFER, temp); 3857ec681f3Smrg DUMP_UNPACKED(ATTRIBUTE_BUFFER, temp, "%s:\n", prefix); 3867ec681f3Smrg 3877ec681f3Smrg switch (temp.type) { 3887ec681f3Smrg case MALI_ATTRIBUTE_TYPE_1D_NPOT_DIVISOR_WRITE_REDUCTION: 3897ec681f3Smrg case MALI_ATTRIBUTE_TYPE_1D_NPOT_DIVISOR: { 3907ec681f3Smrg pan_unpack(cl + (i + 1) * pan_size(ATTRIBUTE_BUFFER), 3917ec681f3Smrg ATTRIBUTE_BUFFER_CONTINUATION_NPOT, temp2); 3927ec681f3Smrg pan_print(pandecode_dump_stream, ATTRIBUTE_BUFFER_CONTINUATION_NPOT, 3937ec681f3Smrg temp2, (pandecode_indent + 1) * 2); 3947ec681f3Smrg i++; 3957ec681f3Smrg break; 3967ec681f3Smrg } 3977ec681f3Smrg case MALI_ATTRIBUTE_TYPE_3D_LINEAR: 3987ec681f3Smrg case MALI_ATTRIBUTE_TYPE_3D_INTERLEAVED: { 3997ec681f3Smrg pan_unpack(cl + (i + 1) * pan_size(ATTRIBUTE_BUFFER_CONTINUATION_3D), 4007ec681f3Smrg ATTRIBUTE_BUFFER_CONTINUATION_3D, temp2); 4017ec681f3Smrg pan_print(pandecode_dump_stream, ATTRIBUTE_BUFFER_CONTINUATION_3D, 4027ec681f3Smrg temp2, (pandecode_indent + 1) * 2); 4037ec681f3Smrg i++; 4047ec681f3Smrg break; 4057ec681f3Smrg } 4067ec681f3Smrg default: 4077ec681f3Smrg break; 4087ec681f3Smrg } 4097ec681f3Smrg } 4107ec681f3Smrg pandecode_log("\n"); 4117ec681f3Smrg} 4127ec681f3Smrg 4137ec681f3Smrg#if PAN_ARCH >= 6 4147ec681f3Smrg/* Decodes a Bifrost blend constant. See the notes in bifrost_blend_rt */ 4157ec681f3Smrg 4167ec681f3Smrgstatic mali_ptr 4177ec681f3Smrgpandecode_bifrost_blend(void *descs, int job_no, int rt_no, mali_ptr frag_shader) 4187ec681f3Smrg{ 4197ec681f3Smrg pan_unpack(descs + (rt_no * pan_size(BLEND)), BLEND, b); 4207ec681f3Smrg DUMP_UNPACKED(BLEND, b, "Blend RT %d:\n", rt_no); 4217ec681f3Smrg if (b.internal.mode != MALI_BLEND_MODE_SHADER) 4227ec681f3Smrg return 0; 4237ec681f3Smrg 4247ec681f3Smrg return (frag_shader & 0xFFFFFFFF00000000ULL) | b.internal.shader.pc; 4257ec681f3Smrg} 4267ec681f3Smrg#elif PAN_ARCH == 5 4277ec681f3Smrgstatic mali_ptr 4287ec681f3Smrgpandecode_midgard_blend_mrt(void *descs, int job_no, int rt_no) 4297ec681f3Smrg{ 4307ec681f3Smrg pan_unpack(descs + (rt_no * pan_size(BLEND)), BLEND, b); 4317ec681f3Smrg DUMP_UNPACKED(BLEND, b, "Blend RT %d:\n", rt_no); 4327ec681f3Smrg return b.blend_shader ? (b.shader_pc & ~0xf) : 0; 4337ec681f3Smrg} 4347ec681f3Smrg#endif 4357ec681f3Smrg 4367ec681f3Smrgstatic unsigned 4377ec681f3Smrgpandecode_attribute_meta(int count, mali_ptr attribute, bool varying) 4387ec681f3Smrg{ 4397ec681f3Smrg unsigned max = 0; 4407ec681f3Smrg 4417ec681f3Smrg for (int i = 0; i < count; ++i, attribute += pan_size(ATTRIBUTE)) { 4427ec681f3Smrg MAP_ADDR(ATTRIBUTE, attribute, cl); 4437ec681f3Smrg pan_unpack(cl, ATTRIBUTE, a); 4447ec681f3Smrg DUMP_UNPACKED(ATTRIBUTE, a, "%s:\n", varying ? "Varying" : "Attribute"); 4457ec681f3Smrg max = MAX2(max, a.buffer_index); 4467ec681f3Smrg } 4477ec681f3Smrg 4487ec681f3Smrg pandecode_log("\n"); 4497ec681f3Smrg return MIN2(max + 1, 256); 4507ec681f3Smrg} 4517ec681f3Smrg 4527ec681f3Smrg/* return bits [lo, hi) of word */ 4537ec681f3Smrgstatic u32 4547ec681f3Smrgbits(u32 word, u32 lo, u32 hi) 4557ec681f3Smrg{ 4567ec681f3Smrg if (hi - lo >= 32) 4577ec681f3Smrg return word; // avoid undefined behavior with the shift 4587ec681f3Smrg 4597ec681f3Smrg if (lo >= 32) 4607ec681f3Smrg return 0; 4617ec681f3Smrg 4627ec681f3Smrg return (word >> lo) & ((1 << (hi - lo)) - 1); 4637ec681f3Smrg} 4647ec681f3Smrg 4657ec681f3Smrgstatic void 4667ec681f3Smrgpandecode_invocation(const void *i) 4677ec681f3Smrg{ 4687ec681f3Smrg /* Decode invocation_count. See the comment before the definition of 4697ec681f3Smrg * invocation_count for an explanation. 4707ec681f3Smrg */ 4717ec681f3Smrg pan_unpack(i, INVOCATION, invocation); 4727ec681f3Smrg 4737ec681f3Smrg unsigned size_x = bits(invocation.invocations, 0, invocation.size_y_shift) + 1; 4747ec681f3Smrg unsigned size_y = bits(invocation.invocations, invocation.size_y_shift, invocation.size_z_shift) + 1; 4757ec681f3Smrg unsigned size_z = bits(invocation.invocations, invocation.size_z_shift, invocation.workgroups_x_shift) + 1; 4767ec681f3Smrg 4777ec681f3Smrg unsigned groups_x = bits(invocation.invocations, invocation.workgroups_x_shift, invocation.workgroups_y_shift) + 1; 4787ec681f3Smrg unsigned groups_y = bits(invocation.invocations, invocation.workgroups_y_shift, invocation.workgroups_z_shift) + 1; 4797ec681f3Smrg unsigned groups_z = bits(invocation.invocations, invocation.workgroups_z_shift, 32) + 1; 4807ec681f3Smrg 4817ec681f3Smrg pandecode_log("Invocation (%d, %d, %d) x (%d, %d, %d)\n", 4827ec681f3Smrg size_x, size_y, size_z, 4837ec681f3Smrg groups_x, groups_y, groups_z); 4847ec681f3Smrg 4857ec681f3Smrg DUMP_UNPACKED(INVOCATION, invocation, "Invocation:\n") 4867ec681f3Smrg} 4877ec681f3Smrg 4887ec681f3Smrgstatic void 4897ec681f3Smrgpandecode_primitive(const void *p) 4907ec681f3Smrg{ 4917ec681f3Smrg pan_unpack(p, PRIMITIVE, primitive); 4927ec681f3Smrg DUMP_UNPACKED(PRIMITIVE, primitive, "Primitive:\n"); 4937ec681f3Smrg 4947ec681f3Smrg /* Validate an index buffer is present if we need one. TODO: verify 4957ec681f3Smrg * relationship between invocation_count and index_count */ 4967ec681f3Smrg 4977ec681f3Smrg if (primitive.indices) { 4987ec681f3Smrg /* Grab the size */ 4997ec681f3Smrg unsigned size = (primitive.index_type == MALI_INDEX_TYPE_UINT32) ? 5007ec681f3Smrg sizeof(uint32_t) : primitive.index_type; 5017ec681f3Smrg 5027ec681f3Smrg /* Ensure we got a size, and if so, validate the index buffer 5037ec681f3Smrg * is large enough to hold a full set of indices of the given 5047ec681f3Smrg * size */ 5057ec681f3Smrg 5067ec681f3Smrg if (!size) 5077ec681f3Smrg pandecode_msg("XXX: index size missing\n"); 5087ec681f3Smrg else 5097ec681f3Smrg pandecode_validate_buffer(primitive.indices, primitive.index_count * size); 5107ec681f3Smrg } else if (primitive.index_type) 5117ec681f3Smrg pandecode_msg("XXX: unexpected index size\n"); 5127ec681f3Smrg} 5137ec681f3Smrg 5147ec681f3Smrgstatic void 5157ec681f3Smrgpandecode_uniform_buffers(mali_ptr pubufs, int ubufs_count, int job_no) 5167ec681f3Smrg{ 5177ec681f3Smrg struct pandecode_mapped_memory *umem = pandecode_find_mapped_gpu_mem_containing(pubufs); 5187ec681f3Smrg uint64_t *PANDECODE_PTR_VAR(ubufs, umem, pubufs); 5197ec681f3Smrg 5207ec681f3Smrg for (int i = 0; i < ubufs_count; i++) { 5217ec681f3Smrg mali_ptr addr = (ubufs[i] >> 10) << 2; 5227ec681f3Smrg unsigned size = addr ? (((ubufs[i] & ((1 << 10) - 1)) + 1) * 16) : 0; 5237ec681f3Smrg 5247ec681f3Smrg pandecode_validate_buffer(addr, size); 5257ec681f3Smrg 5267ec681f3Smrg char *ptr = pointer_as_memory_reference(addr); 5277ec681f3Smrg pandecode_log("ubuf_%d[%u] = %s;\n", i, size, ptr); 5287ec681f3Smrg free(ptr); 5297ec681f3Smrg } 5307ec681f3Smrg 5317ec681f3Smrg pandecode_log("\n"); 5327ec681f3Smrg} 5337ec681f3Smrg 5347ec681f3Smrgstatic void 5357ec681f3Smrgpandecode_uniforms(mali_ptr uniforms, unsigned uniform_count) 5367ec681f3Smrg{ 5377ec681f3Smrg pandecode_validate_buffer(uniforms, uniform_count * 16); 5387ec681f3Smrg 5397ec681f3Smrg char *ptr = pointer_as_memory_reference(uniforms); 5407ec681f3Smrg pandecode_log("vec4 uniforms[%u] = %s;\n", uniform_count, ptr); 5417ec681f3Smrg free(ptr); 5427ec681f3Smrg pandecode_log("\n"); 5437ec681f3Smrg} 5447ec681f3Smrg 5457ec681f3Smrgstatic const char * 5467ec681f3Smrgshader_type_for_job(unsigned type) 5477ec681f3Smrg{ 5487ec681f3Smrg switch (type) { 5497ec681f3Smrg case MALI_JOB_TYPE_VERTEX: return "VERTEX"; 5507ec681f3Smrg case MALI_JOB_TYPE_TILER: return "FRAGMENT"; 5517ec681f3Smrg case MALI_JOB_TYPE_FRAGMENT: return "FRAGMENT"; 5527ec681f3Smrg case MALI_JOB_TYPE_COMPUTE: return "COMPUTE"; 5537ec681f3Smrg default: return "UNKNOWN"; 5547ec681f3Smrg } 5557ec681f3Smrg} 5567ec681f3Smrg 5577ec681f3Smrgstatic unsigned shader_id = 0; 5587ec681f3Smrg 5597ec681f3Smrgstatic struct midgard_disasm_stats 5607ec681f3Smrgpandecode_shader_disassemble(mali_ptr shader_ptr, int shader_no, int type, 5617ec681f3Smrg unsigned gpu_id) 5627ec681f3Smrg{ 5637ec681f3Smrg struct pandecode_mapped_memory *mem = pandecode_find_mapped_gpu_mem_containing(shader_ptr); 5647ec681f3Smrg uint8_t *PANDECODE_PTR_VAR(code, mem, shader_ptr); 5657ec681f3Smrg 5667ec681f3Smrg /* Compute maximum possible size */ 5677ec681f3Smrg size_t sz = mem->length - (shader_ptr - mem->gpu_va); 5687ec681f3Smrg 5697ec681f3Smrg /* Print some boilerplate to clearly denote the assembly (which doesn't 5707ec681f3Smrg * obey indentation rules), and actually do the disassembly! */ 5717ec681f3Smrg 5727ec681f3Smrg pandecode_log_cont("\n\n"); 5737ec681f3Smrg 5747ec681f3Smrg struct midgard_disasm_stats stats; 5757ec681f3Smrg 5767ec681f3Smrg#if PAN_ARCH >= 6 5777ec681f3Smrg disassemble_bifrost(pandecode_dump_stream, code, sz, true); 5787ec681f3Smrg 5797ec681f3Smrg /* TODO: Extend stats to Bifrost */ 5807ec681f3Smrg stats.texture_count = -128; 5817ec681f3Smrg stats.sampler_count = -128; 5827ec681f3Smrg stats.attribute_count = -128; 5837ec681f3Smrg stats.varying_count = -128; 5847ec681f3Smrg stats.uniform_count = -128; 5857ec681f3Smrg stats.uniform_buffer_count = -128; 5867ec681f3Smrg stats.work_count = -128; 5877ec681f3Smrg 5887ec681f3Smrg stats.instruction_count = 0; 5897ec681f3Smrg stats.bundle_count = 0; 5907ec681f3Smrg stats.quadword_count = 0; 5917ec681f3Smrg stats.helper_invocations = false; 5927ec681f3Smrg#else 5937ec681f3Smrg stats = disassemble_midgard(pandecode_dump_stream, 5947ec681f3Smrg code, sz, gpu_id, true); 5957ec681f3Smrg#endif 5967ec681f3Smrg 5977ec681f3Smrg unsigned nr_threads = 5987ec681f3Smrg (stats.work_count <= 4) ? 4 : 5997ec681f3Smrg (stats.work_count <= 8) ? 2 : 6007ec681f3Smrg 1; 6017ec681f3Smrg 6027ec681f3Smrg pandecode_log_cont("shader%d - MESA_SHADER_%s shader: " 6037ec681f3Smrg "%u inst, %u bundles, %u quadwords, " 6047ec681f3Smrg "%u registers, %u threads, 0 loops, 0:0 spills:fills\n\n\n", 6057ec681f3Smrg shader_id++, 6067ec681f3Smrg shader_type_for_job(type), 6077ec681f3Smrg stats.instruction_count, stats.bundle_count, stats.quadword_count, 6087ec681f3Smrg stats.work_count, nr_threads); 6097ec681f3Smrg 6107ec681f3Smrg return stats; 6117ec681f3Smrg} 6127ec681f3Smrg 6137ec681f3Smrgstatic void 6147ec681f3Smrgpandecode_texture_payload(mali_ptr payload, 6157ec681f3Smrg enum mali_texture_dimension dim, 6167ec681f3Smrg enum mali_texture_layout layout, 6177ec681f3Smrg bool manual_stride, 6187ec681f3Smrg uint8_t levels, 6197ec681f3Smrg uint16_t nr_samples, 6207ec681f3Smrg uint16_t array_size, 6217ec681f3Smrg struct pandecode_mapped_memory *tmem) 6227ec681f3Smrg{ 6237ec681f3Smrg pandecode_log(".payload = {\n"); 6247ec681f3Smrg pandecode_indent++; 6257ec681f3Smrg 6267ec681f3Smrg /* A bunch of bitmap pointers follow. 6277ec681f3Smrg * We work out the correct number, 6287ec681f3Smrg * based on the mipmap/cubemap 6297ec681f3Smrg * properties, but dump extra 6307ec681f3Smrg * possibilities to futureproof */ 6317ec681f3Smrg 6327ec681f3Smrg int bitmap_count = levels; 6337ec681f3Smrg 6347ec681f3Smrg /* Miptree for each face */ 6357ec681f3Smrg if (dim == MALI_TEXTURE_DIMENSION_CUBE) 6367ec681f3Smrg bitmap_count *= 6; 6377ec681f3Smrg 6387ec681f3Smrg /* Array of layers */ 6397ec681f3Smrg bitmap_count *= nr_samples; 6407ec681f3Smrg 6417ec681f3Smrg /* Array of textures */ 6427ec681f3Smrg bitmap_count *= array_size; 6437ec681f3Smrg 6447ec681f3Smrg /* Stride for each element */ 6457ec681f3Smrg if (manual_stride) 6467ec681f3Smrg bitmap_count *= 2; 6477ec681f3Smrg 6487ec681f3Smrg mali_ptr *pointers_and_strides = pandecode_fetch_gpu_mem(tmem, 6497ec681f3Smrg payload, sizeof(mali_ptr) * bitmap_count); 6507ec681f3Smrg for (int i = 0; i < bitmap_count; ++i) { 6517ec681f3Smrg /* How we dump depends if this is a stride or a pointer */ 6527ec681f3Smrg 6537ec681f3Smrg if (manual_stride && (i & 1)) { 6547ec681f3Smrg /* signed 32-bit snuck in as a 64-bit pointer */ 6557ec681f3Smrg uint64_t stride_set = pointers_and_strides[i]; 6567ec681f3Smrg int32_t line_stride = stride_set; 6577ec681f3Smrg int32_t surface_stride = stride_set >> 32; 6587ec681f3Smrg pandecode_log("(mali_ptr) %d /* surface stride */ %d /* line stride */, \n", 6597ec681f3Smrg surface_stride, line_stride); 6607ec681f3Smrg } else { 6617ec681f3Smrg char *a = pointer_as_memory_reference(pointers_and_strides[i]); 6627ec681f3Smrg pandecode_log("%s, \n", a); 6637ec681f3Smrg free(a); 6647ec681f3Smrg } 6657ec681f3Smrg } 6667ec681f3Smrg 6677ec681f3Smrg pandecode_indent--; 6687ec681f3Smrg pandecode_log("},\n"); 6697ec681f3Smrg} 6707ec681f3Smrg 6717ec681f3Smrg#if PAN_ARCH <= 5 6727ec681f3Smrgstatic void 6737ec681f3Smrgpandecode_texture(mali_ptr u, 6747ec681f3Smrg struct pandecode_mapped_memory *tmem, 6757ec681f3Smrg unsigned job_no, unsigned tex) 6767ec681f3Smrg{ 6777ec681f3Smrg struct pandecode_mapped_memory *mapped_mem = pandecode_find_mapped_gpu_mem_containing(u); 6787ec681f3Smrg const uint8_t *cl = pandecode_fetch_gpu_mem(mapped_mem, u, pan_size(TEXTURE)); 6797ec681f3Smrg 6807ec681f3Smrg pan_unpack(cl, TEXTURE, temp); 6817ec681f3Smrg DUMP_UNPACKED(TEXTURE, temp, "Texture:\n") 6827ec681f3Smrg 6837ec681f3Smrg pandecode_indent++; 6847ec681f3Smrg unsigned nr_samples = temp.dimension == MALI_TEXTURE_DIMENSION_3D ? 6857ec681f3Smrg 1 : temp.sample_count; 6867ec681f3Smrg pandecode_texture_payload(u + pan_size(TEXTURE), 6877ec681f3Smrg temp.dimension, temp.texel_ordering, temp.manual_stride, 6887ec681f3Smrg temp.levels, nr_samples, temp.array_size, mapped_mem); 6897ec681f3Smrg pandecode_indent--; 6907ec681f3Smrg} 6917ec681f3Smrg#else 6927ec681f3Smrgstatic void 6937ec681f3Smrgpandecode_bifrost_texture( 6947ec681f3Smrg const void *cl, 6957ec681f3Smrg unsigned job_no, 6967ec681f3Smrg unsigned tex) 6977ec681f3Smrg{ 6987ec681f3Smrg pan_unpack(cl, TEXTURE, temp); 6997ec681f3Smrg DUMP_UNPACKED(TEXTURE, temp, "Texture:\n") 7007ec681f3Smrg 7017ec681f3Smrg struct pandecode_mapped_memory *tmem = pandecode_find_mapped_gpu_mem_containing(temp.surfaces); 7027ec681f3Smrg unsigned nr_samples = temp.dimension == MALI_TEXTURE_DIMENSION_3D ? 7037ec681f3Smrg 1 : temp.sample_count; 7047ec681f3Smrg pandecode_indent++; 7057ec681f3Smrg pandecode_texture_payload(temp.surfaces, temp.dimension, temp.texel_ordering, 7067ec681f3Smrg true, temp.levels, nr_samples, temp.array_size, tmem); 7077ec681f3Smrg pandecode_indent--; 7087ec681f3Smrg} 7097ec681f3Smrg#endif 7107ec681f3Smrg 7117ec681f3Smrgstatic void 7127ec681f3Smrgpandecode_blend_shader_disassemble(mali_ptr shader, int job_no, int job_type, 7137ec681f3Smrg unsigned gpu_id) 7147ec681f3Smrg{ 7157ec681f3Smrg struct midgard_disasm_stats stats = 7167ec681f3Smrg pandecode_shader_disassemble(shader, job_no, job_type, gpu_id); 7177ec681f3Smrg 7187ec681f3Smrg bool has_texture = (stats.texture_count > 0); 7197ec681f3Smrg bool has_sampler = (stats.sampler_count > 0); 7207ec681f3Smrg bool has_attribute = (stats.attribute_count > 0); 7217ec681f3Smrg bool has_varying = (stats.varying_count > 0); 7227ec681f3Smrg bool has_uniform = (stats.uniform_count > 0); 7237ec681f3Smrg bool has_ubo = (stats.uniform_buffer_count > 0); 7247ec681f3Smrg 7257ec681f3Smrg if (has_texture || has_sampler) 7267ec681f3Smrg pandecode_msg("XXX: blend shader accessing textures\n"); 7277ec681f3Smrg 7287ec681f3Smrg if (has_attribute || has_varying) 7297ec681f3Smrg pandecode_msg("XXX: blend shader accessing interstage\n"); 7307ec681f3Smrg 7317ec681f3Smrg if (has_uniform || has_ubo) 7327ec681f3Smrg pandecode_msg("XXX: blend shader accessing uniforms\n"); 7337ec681f3Smrg} 7347ec681f3Smrg 7357ec681f3Smrgstatic void 7367ec681f3Smrgpandecode_textures(mali_ptr textures, unsigned texture_count, int job_no) 7377ec681f3Smrg{ 7387ec681f3Smrg struct pandecode_mapped_memory *mmem = pandecode_find_mapped_gpu_mem_containing(textures); 7397ec681f3Smrg 7407ec681f3Smrg if (!mmem) 7417ec681f3Smrg return; 7427ec681f3Smrg 7437ec681f3Smrg pandecode_log("Textures %"PRIx64"_%d:\n", textures, job_no); 7447ec681f3Smrg pandecode_indent++; 7457ec681f3Smrg 7467ec681f3Smrg#if PAN_ARCH >= 6 7477ec681f3Smrg const void *cl = 7487ec681f3Smrg pandecode_fetch_gpu_mem(mmem, 7497ec681f3Smrg textures, 7507ec681f3Smrg pan_size(TEXTURE) * 7517ec681f3Smrg texture_count); 7527ec681f3Smrg 7537ec681f3Smrg for (unsigned tex = 0; tex < texture_count; ++tex) { 7547ec681f3Smrg pandecode_bifrost_texture(cl + pan_size(TEXTURE) * tex, 7557ec681f3Smrg job_no, tex); 7567ec681f3Smrg } 7577ec681f3Smrg#else 7587ec681f3Smrg mali_ptr *PANDECODE_PTR_VAR(u, mmem, textures); 7597ec681f3Smrg 7607ec681f3Smrg for (int tex = 0; tex < texture_count; ++tex) { 7617ec681f3Smrg mali_ptr *PANDECODE_PTR_VAR(u, mmem, textures + tex * sizeof(mali_ptr)); 7627ec681f3Smrg char *a = pointer_as_memory_reference(*u); 7637ec681f3Smrg pandecode_log("%s,\n", a); 7647ec681f3Smrg free(a); 7657ec681f3Smrg } 7667ec681f3Smrg 7677ec681f3Smrg /* Now, finally, descend down into the texture descriptor */ 7687ec681f3Smrg for (unsigned tex = 0; tex < texture_count; ++tex) { 7697ec681f3Smrg mali_ptr *PANDECODE_PTR_VAR(u, mmem, textures + tex * sizeof(mali_ptr)); 7707ec681f3Smrg struct pandecode_mapped_memory *tmem = pandecode_find_mapped_gpu_mem_containing(*u); 7717ec681f3Smrg if (tmem) 7727ec681f3Smrg pandecode_texture(*u, tmem, job_no, tex); 7737ec681f3Smrg } 7747ec681f3Smrg#endif 7757ec681f3Smrg pandecode_indent--; 7767ec681f3Smrg pandecode_log("\n"); 7777ec681f3Smrg} 7787ec681f3Smrg 7797ec681f3Smrgstatic void 7807ec681f3Smrgpandecode_samplers(mali_ptr samplers, unsigned sampler_count, int job_no) 7817ec681f3Smrg{ 7827ec681f3Smrg pandecode_log("Samplers %"PRIx64"_%d:\n", samplers, job_no); 7837ec681f3Smrg pandecode_indent++; 7847ec681f3Smrg 7857ec681f3Smrg for (int i = 0; i < sampler_count; ++i) 7867ec681f3Smrg DUMP_ADDR(SAMPLER, samplers + (pan_size(SAMPLER) * i), "Sampler %d:\n", i); 7877ec681f3Smrg 7887ec681f3Smrg pandecode_indent--; 7897ec681f3Smrg pandecode_log("\n"); 7907ec681f3Smrg} 7917ec681f3Smrg 7927ec681f3Smrgstatic void 7937ec681f3Smrgpandecode_dcd(const struct MALI_DRAW *p, 7947ec681f3Smrg int job_no, enum mali_job_type job_type, 7957ec681f3Smrg char *suffix, unsigned gpu_id) 7967ec681f3Smrg{ 7977ec681f3Smrg struct pandecode_mapped_memory *attr_mem; 7987ec681f3Smrg 7997ec681f3Smrg#if PAN_ARCH >= 5 8007ec681f3Smrg struct pandecode_fbd fbd_info = { 8017ec681f3Smrg /* Default for Bifrost */ 8027ec681f3Smrg .rt_count = 1 8037ec681f3Smrg }; 8047ec681f3Smrg#endif 8057ec681f3Smrg 8067ec681f3Smrg#if PAN_ARCH >= 6 8077ec681f3Smrg pandecode_local_storage(p->thread_storage & ~1, job_no); 8087ec681f3Smrg#elif PAN_ARCH == 5 8097ec681f3Smrg if (job_type != MALI_JOB_TYPE_TILER) { 8107ec681f3Smrg pandecode_local_storage(p->thread_storage & ~1, job_no); 8117ec681f3Smrg } else { 8127ec681f3Smrg assert(p->fbd & MALI_FBD_TAG_IS_MFBD); 8137ec681f3Smrg fbd_info = pandecode_mfbd_bfr((u64) ((uintptr_t) p->fbd) & ~MALI_FBD_TAG_MASK, 8147ec681f3Smrg job_no, false, gpu_id); 8157ec681f3Smrg } 8167ec681f3Smrg#else 8177ec681f3Smrg pandecode_sfbd((u64) (uintptr_t) p->fbd, job_no, false, gpu_id); 8187ec681f3Smrg#endif 8197ec681f3Smrg 8207ec681f3Smrg int varying_count = 0, attribute_count = 0, uniform_count = 0, uniform_buffer_count = 0; 8217ec681f3Smrg int texture_count = 0, sampler_count = 0; 8227ec681f3Smrg 8237ec681f3Smrg if (p->state) { 8247ec681f3Smrg struct pandecode_mapped_memory *smem = pandecode_find_mapped_gpu_mem_containing(p->state); 8257ec681f3Smrg uint32_t *cl = pandecode_fetch_gpu_mem(smem, p->state, pan_size(RENDERER_STATE)); 8267ec681f3Smrg 8277ec681f3Smrg pan_unpack(cl, RENDERER_STATE, state); 8287ec681f3Smrg 8297ec681f3Smrg if (state.shader.shader & ~0xF) 8307ec681f3Smrg pandecode_shader_disassemble(state.shader.shader & ~0xF, job_no, job_type, gpu_id); 8317ec681f3Smrg 8327ec681f3Smrg#if PAN_ARCH >= 6 8337ec681f3Smrg bool idvs = (job_type == MALI_JOB_TYPE_INDEXED_VERTEX); 8347ec681f3Smrg 8357ec681f3Smrg if (idvs && state.secondary_shader) 8367ec681f3Smrg pandecode_shader_disassemble(state.secondary_shader, job_no, job_type, gpu_id); 8377ec681f3Smrg#endif 8387ec681f3Smrg DUMP_UNPACKED(RENDERER_STATE, state, "State:\n"); 8397ec681f3Smrg pandecode_indent++; 8407ec681f3Smrg 8417ec681f3Smrg /* Save for dumps */ 8427ec681f3Smrg attribute_count = state.shader.attribute_count; 8437ec681f3Smrg varying_count = state.shader.varying_count; 8447ec681f3Smrg texture_count = state.shader.texture_count; 8457ec681f3Smrg sampler_count = state.shader.sampler_count; 8467ec681f3Smrg uniform_buffer_count = state.properties.uniform_buffer_count; 8477ec681f3Smrg 8487ec681f3Smrg#if PAN_ARCH >= 6 8497ec681f3Smrg uniform_count = state.preload.uniform_count; 8507ec681f3Smrg#else 8517ec681f3Smrg uniform_count = state.properties.uniform_count; 8527ec681f3Smrg#endif 8537ec681f3Smrg 8547ec681f3Smrg#if PAN_ARCH >= 6 8557ec681f3Smrg DUMP_UNPACKED(PRELOAD, state.preload, "Preload:\n"); 8567ec681f3Smrg#elif PAN_ARCH == 4 8577ec681f3Smrg mali_ptr shader = state.blend_shader & ~0xF; 8587ec681f3Smrg if (state.multisample_misc.blend_shader && shader) 8597ec681f3Smrg pandecode_blend_shader_disassemble(shader, job_no, job_type, gpu_id); 8607ec681f3Smrg#endif 8617ec681f3Smrg pandecode_indent--; 8627ec681f3Smrg pandecode_log("\n"); 8637ec681f3Smrg 8647ec681f3Smrg /* MRT blend fields are used whenever MFBD is used, with 8657ec681f3Smrg * per-RT descriptors */ 8667ec681f3Smrg 8677ec681f3Smrg#if PAN_ARCH >= 5 8687ec681f3Smrg if ((job_type == MALI_JOB_TYPE_TILER || job_type == MALI_JOB_TYPE_FRAGMENT) && 8697ec681f3Smrg (PAN_ARCH >= 6 || p->thread_storage & MALI_FBD_TAG_IS_MFBD)) { 8707ec681f3Smrg void* blend_base = ((void *) cl) + pan_size(RENDERER_STATE); 8717ec681f3Smrg 8727ec681f3Smrg for (unsigned i = 0; i < fbd_info.rt_count; i++) { 8737ec681f3Smrg mali_ptr shader = 0; 8747ec681f3Smrg 8757ec681f3Smrg#if PAN_ARCH >= 6 8767ec681f3Smrg shader = pandecode_bifrost_blend(blend_base, job_no, i, 8777ec681f3Smrg state.shader.shader); 8787ec681f3Smrg#else 8797ec681f3Smrg shader = pandecode_midgard_blend_mrt(blend_base, job_no, i); 8807ec681f3Smrg#endif 8817ec681f3Smrg if (shader & ~0xF) 8827ec681f3Smrg pandecode_blend_shader_disassemble(shader, job_no, job_type, 8837ec681f3Smrg gpu_id); 8847ec681f3Smrg } 8857ec681f3Smrg } 8867ec681f3Smrg#endif 8877ec681f3Smrg } else 8887ec681f3Smrg pandecode_msg("XXX: missing shader descriptor\n"); 8897ec681f3Smrg 8907ec681f3Smrg if (p->viewport) { 8917ec681f3Smrg DUMP_ADDR(VIEWPORT, p->viewport, "Viewport:\n"); 8927ec681f3Smrg pandecode_log("\n"); 8937ec681f3Smrg } 8947ec681f3Smrg 8957ec681f3Smrg unsigned max_attr_index = 0; 8967ec681f3Smrg 8977ec681f3Smrg if (p->attributes) 8987ec681f3Smrg max_attr_index = pandecode_attribute_meta(attribute_count, p->attributes, false); 8997ec681f3Smrg 9007ec681f3Smrg if (p->attribute_buffers) { 9017ec681f3Smrg attr_mem = pandecode_find_mapped_gpu_mem_containing(p->attribute_buffers); 9027ec681f3Smrg pandecode_attributes(attr_mem, p->attribute_buffers, job_no, suffix, max_attr_index, false, job_type); 9037ec681f3Smrg } 9047ec681f3Smrg 9057ec681f3Smrg if (p->varyings) { 9067ec681f3Smrg varying_count = pandecode_attribute_meta(varying_count, p->varyings, true); 9077ec681f3Smrg } 9087ec681f3Smrg 9097ec681f3Smrg if (p->varying_buffers) { 9107ec681f3Smrg attr_mem = pandecode_find_mapped_gpu_mem_containing(p->varying_buffers); 9117ec681f3Smrg pandecode_attributes(attr_mem, p->varying_buffers, job_no, suffix, varying_count, true, job_type); 9127ec681f3Smrg } 9137ec681f3Smrg 9147ec681f3Smrg if (p->uniform_buffers) { 9157ec681f3Smrg if (uniform_buffer_count) 9167ec681f3Smrg pandecode_uniform_buffers(p->uniform_buffers, uniform_buffer_count, job_no); 9177ec681f3Smrg else 9187ec681f3Smrg pandecode_msg("warn: UBOs specified but not referenced\n"); 9197ec681f3Smrg } else if (uniform_buffer_count) 9207ec681f3Smrg pandecode_msg("XXX: UBOs referenced but not specified\n"); 9217ec681f3Smrg 9227ec681f3Smrg /* We don't want to actually dump uniforms, but we do need to validate 9237ec681f3Smrg * that the counts we were given are sane */ 9247ec681f3Smrg 9257ec681f3Smrg if (p->push_uniforms) { 9267ec681f3Smrg if (uniform_count) 9277ec681f3Smrg pandecode_uniforms(p->push_uniforms, uniform_count); 9287ec681f3Smrg else 9297ec681f3Smrg pandecode_msg("warn: Uniforms specified but not referenced\n"); 9307ec681f3Smrg } else if (uniform_count) 9317ec681f3Smrg pandecode_msg("XXX: Uniforms referenced but not specified\n"); 9327ec681f3Smrg 9337ec681f3Smrg if (p->textures) 9347ec681f3Smrg pandecode_textures(p->textures, texture_count, job_no); 9357ec681f3Smrg 9367ec681f3Smrg if (p->samplers) 9377ec681f3Smrg pandecode_samplers(p->samplers, sampler_count, job_no); 9387ec681f3Smrg} 9397ec681f3Smrg 9407ec681f3Smrgstatic void 9417ec681f3Smrgpandecode_primitive_size(const void *s, bool constant) 9427ec681f3Smrg{ 9437ec681f3Smrg pan_unpack(s, PRIMITIVE_SIZE, ps); 9447ec681f3Smrg if (ps.size_array == 0x0) 9457ec681f3Smrg return; 9467ec681f3Smrg 9477ec681f3Smrg DUMP_UNPACKED(PRIMITIVE_SIZE, ps, "Primitive Size:\n") 9487ec681f3Smrg} 9497ec681f3Smrg 9507ec681f3Smrgstatic void 9517ec681f3Smrgpandecode_vertex_compute_geometry_job(const struct MALI_JOB_HEADER *h, 9527ec681f3Smrg const struct pandecode_mapped_memory *mem, 9537ec681f3Smrg mali_ptr job, int job_no, unsigned gpu_id) 9547ec681f3Smrg{ 9557ec681f3Smrg struct mali_compute_job_packed *PANDECODE_PTR_VAR(p, mem, job); 9567ec681f3Smrg pan_section_unpack(p, COMPUTE_JOB, DRAW, draw); 9577ec681f3Smrg pandecode_dcd(&draw, job_no, h->type, "", gpu_id); 9587ec681f3Smrg 9597ec681f3Smrg pandecode_log("Vertex Job Payload:\n"); 9607ec681f3Smrg pandecode_indent++; 9617ec681f3Smrg pandecode_invocation(pan_section_ptr(p, COMPUTE_JOB, INVOCATION)); 9627ec681f3Smrg DUMP_SECTION(COMPUTE_JOB, PARAMETERS, p, "Vertex Job Parameters:\n"); 9637ec681f3Smrg DUMP_UNPACKED(DRAW, draw, "Draw:\n"); 9647ec681f3Smrg pandecode_indent--; 9657ec681f3Smrg pandecode_log("\n"); 9667ec681f3Smrg} 9677ec681f3Smrg 9687ec681f3Smrg#if PAN_ARCH >= 6 9697ec681f3Smrgstatic void 9707ec681f3Smrgpandecode_bifrost_tiler_heap(mali_ptr gpu_va, int job_no) 9717ec681f3Smrg{ 9727ec681f3Smrg struct pandecode_mapped_memory *mem = pandecode_find_mapped_gpu_mem_containing(gpu_va); 9737ec681f3Smrg pan_unpack(PANDECODE_PTR(mem, gpu_va, void), TILER_HEAP, h); 9747ec681f3Smrg DUMP_UNPACKED(TILER_HEAP, h, "Bifrost Tiler Heap:\n"); 9757ec681f3Smrg} 9767ec681f3Smrg 9777ec681f3Smrgstatic void 9787ec681f3Smrgpandecode_bifrost_tiler(mali_ptr gpu_va, int job_no) 9797ec681f3Smrg{ 9807ec681f3Smrg struct pandecode_mapped_memory *mem = pandecode_find_mapped_gpu_mem_containing(gpu_va); 9817ec681f3Smrg pan_unpack(PANDECODE_PTR(mem, gpu_va, void), TILER_CONTEXT, t); 9827ec681f3Smrg 9837ec681f3Smrg pandecode_bifrost_tiler_heap(t.heap, job_no); 9847ec681f3Smrg 9857ec681f3Smrg DUMP_UNPACKED(TILER_CONTEXT, t, "Bifrost Tiler:\n"); 9867ec681f3Smrg pandecode_indent++; 9877ec681f3Smrg if (t.hierarchy_mask != 0xa && 9887ec681f3Smrg t.hierarchy_mask != 0x14 && 9897ec681f3Smrg t.hierarchy_mask != 0x28 && 9907ec681f3Smrg t.hierarchy_mask != 0x50 && 9917ec681f3Smrg t.hierarchy_mask != 0xa0) 9927ec681f3Smrg pandecode_msg("XXX: Unexpected hierarchy_mask (not 0xa, 0x14, 0x28, 0x50 or 0xa0)!"); 9937ec681f3Smrg 9947ec681f3Smrg pandecode_indent--; 9957ec681f3Smrg} 9967ec681f3Smrg 9977ec681f3Smrgstatic void 9987ec681f3Smrgpandecode_indexed_vertex_job(const struct MALI_JOB_HEADER *h, 9997ec681f3Smrg const struct pandecode_mapped_memory *mem, 10007ec681f3Smrg mali_ptr job, int job_no, unsigned gpu_id) 10017ec681f3Smrg{ 10027ec681f3Smrg struct mali_indexed_vertex_job_packed *PANDECODE_PTR_VAR(p, mem, job); 10037ec681f3Smrg 10047ec681f3Smrg pandecode_log("Vertex:\n"); 10057ec681f3Smrg pan_section_unpack(p, INDEXED_VERTEX_JOB, VERTEX_DRAW, vert_draw); 10067ec681f3Smrg pandecode_dcd(&vert_draw, job_no, h->type, "", gpu_id); 10077ec681f3Smrg DUMP_UNPACKED(DRAW, vert_draw, "Vertex Draw:\n"); 10087ec681f3Smrg 10097ec681f3Smrg pandecode_log("Fragment:\n"); 10107ec681f3Smrg pan_section_unpack(p, INDEXED_VERTEX_JOB, FRAGMENT_DRAW, frag_draw); 10117ec681f3Smrg pandecode_dcd(&frag_draw, job_no, MALI_JOB_TYPE_FRAGMENT, "", gpu_id); 10127ec681f3Smrg DUMP_UNPACKED(DRAW, frag_draw, "Fragment Draw:\n"); 10137ec681f3Smrg 10147ec681f3Smrg pan_section_unpack(p, INDEXED_VERTEX_JOB, TILER, tiler_ptr); 10157ec681f3Smrg pandecode_log("Tiler Job Payload:\n"); 10167ec681f3Smrg pandecode_indent++; 10177ec681f3Smrg pandecode_bifrost_tiler(tiler_ptr.address, job_no); 10187ec681f3Smrg pandecode_indent--; 10197ec681f3Smrg 10207ec681f3Smrg pandecode_invocation(pan_section_ptr(p, INDEXED_VERTEX_JOB, INVOCATION)); 10217ec681f3Smrg pandecode_primitive(pan_section_ptr(p, INDEXED_VERTEX_JOB, PRIMITIVE)); 10227ec681f3Smrg 10237ec681f3Smrg /* TODO: gl_PointSize on Bifrost */ 10247ec681f3Smrg pandecode_primitive_size(pan_section_ptr(p, INDEXED_VERTEX_JOB, PRIMITIVE_SIZE), true); 10257ec681f3Smrg 10267ec681f3Smrg pan_section_unpack(p, INDEXED_VERTEX_JOB, PADDING, padding); 10277ec681f3Smrg} 10287ec681f3Smrg 10297ec681f3Smrgstatic void 10307ec681f3Smrgpandecode_tiler_job_bfr(const struct MALI_JOB_HEADER *h, 10317ec681f3Smrg const struct pandecode_mapped_memory *mem, 10327ec681f3Smrg mali_ptr job, int job_no, unsigned gpu_id) 10337ec681f3Smrg{ 10347ec681f3Smrg struct mali_tiler_job_packed *PANDECODE_PTR_VAR(p, mem, job); 10357ec681f3Smrg pan_section_unpack(p, TILER_JOB, DRAW, draw); 10367ec681f3Smrg pan_section_unpack(p, TILER_JOB, TILER, tiler_ptr); 10377ec681f3Smrg pandecode_dcd(&draw, job_no, h->type, "", gpu_id); 10387ec681f3Smrg 10397ec681f3Smrg pandecode_log("Tiler Job Payload:\n"); 10407ec681f3Smrg pandecode_indent++; 10417ec681f3Smrg pandecode_bifrost_tiler(tiler_ptr.address, job_no); 10427ec681f3Smrg 10437ec681f3Smrg pandecode_invocation(pan_section_ptr(p, TILER_JOB, INVOCATION)); 10447ec681f3Smrg pandecode_primitive(pan_section_ptr(p, TILER_JOB, PRIMITIVE)); 10457ec681f3Smrg 10467ec681f3Smrg /* TODO: gl_PointSize on Bifrost */ 10477ec681f3Smrg pandecode_primitive_size(pan_section_ptr(p, TILER_JOB, PRIMITIVE_SIZE), true); 10487ec681f3Smrg pan_section_unpack(p, TILER_JOB, PADDING, padding); 10497ec681f3Smrg DUMP_UNPACKED(DRAW, draw, "Draw:\n"); 10507ec681f3Smrg pandecode_indent--; 10517ec681f3Smrg pandecode_log("\n"); 10527ec681f3Smrg} 10537ec681f3Smrg#else 10547ec681f3Smrgstatic void 10557ec681f3Smrgpandecode_tiler_job_mdg(const struct MALI_JOB_HEADER *h, 10567ec681f3Smrg const struct pandecode_mapped_memory *mem, 10577ec681f3Smrg mali_ptr job, int job_no, unsigned gpu_id) 10587ec681f3Smrg{ 10597ec681f3Smrg struct mali_tiler_job_packed *PANDECODE_PTR_VAR(p, mem, job); 10607ec681f3Smrg pan_section_unpack(p, TILER_JOB, DRAW, draw); 10617ec681f3Smrg pandecode_dcd(&draw, job_no, h->type, "", gpu_id); 10627ec681f3Smrg 10637ec681f3Smrg pandecode_log("Tiler Job Payload:\n"); 10647ec681f3Smrg pandecode_indent++; 10657ec681f3Smrg pandecode_invocation(pan_section_ptr(p, TILER_JOB, INVOCATION)); 10667ec681f3Smrg pandecode_primitive(pan_section_ptr(p, TILER_JOB, PRIMITIVE)); 10677ec681f3Smrg DUMP_UNPACKED(DRAW, draw, "Draw:\n"); 10687ec681f3Smrg 10697ec681f3Smrg pan_section_unpack(p, TILER_JOB, PRIMITIVE, primitive); 10707ec681f3Smrg pandecode_primitive_size(pan_section_ptr(p, TILER_JOB, PRIMITIVE_SIZE), 10717ec681f3Smrg primitive.point_size_array_format == MALI_POINT_SIZE_ARRAY_FORMAT_NONE); 10727ec681f3Smrg pandecode_indent--; 10737ec681f3Smrg pandecode_log("\n"); 10747ec681f3Smrg} 10757ec681f3Smrg#endif 10767ec681f3Smrg 10777ec681f3Smrgstatic void 10787ec681f3Smrgpandecode_fragment_job(const struct pandecode_mapped_memory *mem, 10797ec681f3Smrg mali_ptr job, int job_no, unsigned gpu_id) 10807ec681f3Smrg{ 10817ec681f3Smrg struct mali_fragment_job_packed *PANDECODE_PTR_VAR(p, mem, job); 10827ec681f3Smrg pan_section_unpack(p, FRAGMENT_JOB, PAYLOAD, s); 10837ec681f3Smrg 10847ec681f3Smrg 10857ec681f3Smrg#if PAN_ARCH == 4 10867ec681f3Smrg pandecode_sfbd(s.framebuffer, job_no, true, gpu_id); 10877ec681f3Smrg#else 10887ec681f3Smrg assert(s.framebuffer & MALI_FBD_TAG_IS_MFBD); 10897ec681f3Smrg 10907ec681f3Smrg struct pandecode_fbd info; 10917ec681f3Smrg 10927ec681f3Smrg info = pandecode_mfbd_bfr(s.framebuffer & ~MALI_FBD_TAG_MASK, job_no, 10937ec681f3Smrg true, gpu_id); 10947ec681f3Smrg#endif 10957ec681f3Smrg 10967ec681f3Smrg#if PAN_ARCH >= 5 10977ec681f3Smrg unsigned expected_tag = 0; 10987ec681f3Smrg 10997ec681f3Smrg /* Compute the tag for the tagged pointer. This contains the type of 11007ec681f3Smrg * FBD (MFBD/SFBD), and in the case of an MFBD, information about which 11017ec681f3Smrg * additional structures follow the MFBD header (an extra payload or 11027ec681f3Smrg * not, as well as a count of render targets) */ 11037ec681f3Smrg 11047ec681f3Smrg expected_tag = MALI_FBD_TAG_IS_MFBD; 11057ec681f3Smrg if (info.has_extra) 11067ec681f3Smrg expected_tag |= MALI_FBD_TAG_HAS_ZS_RT; 11077ec681f3Smrg 11087ec681f3Smrg expected_tag |= MALI_FBD_TAG_IS_MFBD | (MALI_POSITIVE(info.rt_count) << 2); 11097ec681f3Smrg#endif 11107ec681f3Smrg 11117ec681f3Smrg DUMP_UNPACKED(FRAGMENT_JOB_PAYLOAD, s, "Fragment Job Payload:\n"); 11127ec681f3Smrg 11137ec681f3Smrg#if PAN_ARCH >= 5 11147ec681f3Smrg /* The FBD is a tagged pointer */ 11157ec681f3Smrg 11167ec681f3Smrg unsigned tag = (s.framebuffer & MALI_FBD_TAG_MASK); 11177ec681f3Smrg 11187ec681f3Smrg if (tag != expected_tag) 11197ec681f3Smrg pandecode_msg("XXX: expected FBD tag %X but got %X\n", expected_tag, tag); 11207ec681f3Smrg#endif 11217ec681f3Smrg 11227ec681f3Smrg pandecode_log("\n"); 11237ec681f3Smrg} 11247ec681f3Smrg 11257ec681f3Smrgstatic void 11267ec681f3Smrgpandecode_write_value_job(const struct pandecode_mapped_memory *mem, 11277ec681f3Smrg mali_ptr job, int job_no) 11287ec681f3Smrg{ 11297ec681f3Smrg struct mali_write_value_job_packed *PANDECODE_PTR_VAR(p, mem, job); 11307ec681f3Smrg pan_section_unpack(p, WRITE_VALUE_JOB, PAYLOAD, u); 11317ec681f3Smrg DUMP_SECTION(WRITE_VALUE_JOB, PAYLOAD, p, "Write Value Payload:\n"); 11327ec681f3Smrg pandecode_log("\n"); 11337ec681f3Smrg} 11347ec681f3Smrg 11357ec681f3Smrgstatic void 11367ec681f3Smrgpandecode_cache_flush_job(const struct pandecode_mapped_memory *mem, 11377ec681f3Smrg mali_ptr job, int job_no) 11387ec681f3Smrg{ 11397ec681f3Smrg struct mali_cache_flush_job_packed *PANDECODE_PTR_VAR(p, mem, job); 11407ec681f3Smrg pan_section_unpack(p, CACHE_FLUSH_JOB, PAYLOAD, u); 11417ec681f3Smrg DUMP_SECTION(CACHE_FLUSH_JOB, PAYLOAD, p, "Cache Flush Payload:\n"); 11427ec681f3Smrg pandecode_log("\n"); 11437ec681f3Smrg} 11447ec681f3Smrg 11457ec681f3Smrg/* Entrypoint to start tracing. jc_gpu_va is the GPU address for the first job 11467ec681f3Smrg * in the chain; later jobs are found by walking the chain. Bifrost is, well, 11477ec681f3Smrg * if it's bifrost or not. GPU ID is the more finegrained ID (at some point, we 11487ec681f3Smrg * might wish to combine this with the bifrost parameter) because some details 11497ec681f3Smrg * are model-specific even within a particular architecture. */ 11507ec681f3Smrg 11517ec681f3Smrgvoid 11527ec681f3SmrgGENX(pandecode_jc)(mali_ptr jc_gpu_va, unsigned gpu_id) 11537ec681f3Smrg{ 11547ec681f3Smrg pandecode_dump_file_open(); 11557ec681f3Smrg 11567ec681f3Smrg unsigned job_descriptor_number = 0; 11577ec681f3Smrg mali_ptr next_job = 0; 11587ec681f3Smrg 11597ec681f3Smrg do { 11607ec681f3Smrg struct pandecode_mapped_memory *mem = 11617ec681f3Smrg pandecode_find_mapped_gpu_mem_containing(jc_gpu_va); 11627ec681f3Smrg 11637ec681f3Smrg pan_unpack(PANDECODE_PTR(mem, jc_gpu_va, struct mali_job_header_packed), 11647ec681f3Smrg JOB_HEADER, h); 11657ec681f3Smrg next_job = h.next; 11667ec681f3Smrg 11677ec681f3Smrg int job_no = job_descriptor_number++; 11687ec681f3Smrg 11697ec681f3Smrg DUMP_UNPACKED(JOB_HEADER, h, "Job Header:\n"); 11707ec681f3Smrg pandecode_log("\n"); 11717ec681f3Smrg 11727ec681f3Smrg switch (h.type) { 11737ec681f3Smrg case MALI_JOB_TYPE_WRITE_VALUE: 11747ec681f3Smrg pandecode_write_value_job(mem, jc_gpu_va, job_no); 11757ec681f3Smrg break; 11767ec681f3Smrg 11777ec681f3Smrg case MALI_JOB_TYPE_CACHE_FLUSH: 11787ec681f3Smrg pandecode_cache_flush_job(mem, jc_gpu_va, job_no); 11797ec681f3Smrg break; 11807ec681f3Smrg 11817ec681f3Smrg case MALI_JOB_TYPE_TILER: 11827ec681f3Smrg#if PAN_ARCH >= 6 11837ec681f3Smrg pandecode_tiler_job_bfr(&h, mem, jc_gpu_va, job_no, gpu_id); 11847ec681f3Smrg#else 11857ec681f3Smrg pandecode_tiler_job_mdg(&h, mem, jc_gpu_va, job_no, gpu_id); 11867ec681f3Smrg#endif 11877ec681f3Smrg break; 11887ec681f3Smrg 11897ec681f3Smrg case MALI_JOB_TYPE_VERTEX: 11907ec681f3Smrg case MALI_JOB_TYPE_COMPUTE: 11917ec681f3Smrg pandecode_vertex_compute_geometry_job(&h, mem, jc_gpu_va, job_no, gpu_id); 11927ec681f3Smrg break; 11937ec681f3Smrg 11947ec681f3Smrg#if PAN_ARCH >= 6 11957ec681f3Smrg case MALI_JOB_TYPE_INDEXED_VERTEX: 11967ec681f3Smrg pandecode_indexed_vertex_job(&h, mem, jc_gpu_va, job_no, gpu_id); 11977ec681f3Smrg break; 11987ec681f3Smrg#endif 11997ec681f3Smrg 12007ec681f3Smrg case MALI_JOB_TYPE_FRAGMENT: 12017ec681f3Smrg pandecode_fragment_job(mem, jc_gpu_va, job_no, gpu_id); 12027ec681f3Smrg break; 12037ec681f3Smrg 12047ec681f3Smrg default: 12057ec681f3Smrg break; 12067ec681f3Smrg } 12077ec681f3Smrg } while ((jc_gpu_va = next_job)); 12087ec681f3Smrg 12097ec681f3Smrg fflush(pandecode_dump_stream); 12107ec681f3Smrg pandecode_map_read_write(); 12117ec681f3Smrg} 12127ec681f3Smrg 12137ec681f3Smrgvoid 12147ec681f3SmrgGENX(pandecode_abort_on_fault)(mali_ptr jc_gpu_va) 12157ec681f3Smrg{ 12167ec681f3Smrg mali_ptr next_job = 0; 12177ec681f3Smrg 12187ec681f3Smrg do { 12197ec681f3Smrg struct pandecode_mapped_memory *mem = 12207ec681f3Smrg pandecode_find_mapped_gpu_mem_containing(jc_gpu_va); 12217ec681f3Smrg 12227ec681f3Smrg pan_unpack(PANDECODE_PTR(mem, jc_gpu_va, struct mali_job_header_packed), 12237ec681f3Smrg JOB_HEADER, h); 12247ec681f3Smrg next_job = h.next; 12257ec681f3Smrg 12267ec681f3Smrg /* Ensure the job is marked COMPLETE */ 12277ec681f3Smrg if (h.exception_status != 0x1) { 12287ec681f3Smrg fprintf(stderr, "Incomplete job or timeout"); 12297ec681f3Smrg abort(); 12307ec681f3Smrg } 12317ec681f3Smrg } while ((jc_gpu_va = next_job)); 12327ec681f3Smrg 12337ec681f3Smrg pandecode_map_read_write(); 12347ec681f3Smrg} 1235