kgem_debug.c revision 428d7b3d
1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 2007-2011 Intel Corporation 3428d7b3dSmrg * 4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"), 6428d7b3dSmrg * to deal in the Software without restriction, including without limitation 7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions: 10428d7b3dSmrg * 11428d7b3dSmrg * The above copyright notice and this permission notice (including the next 12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the 13428d7b3dSmrg * Software. 14428d7b3dSmrg * 15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21428d7b3dSmrg * SOFTWARE. 22428d7b3dSmrg * 23428d7b3dSmrg * Authors: 24428d7b3dSmrg * Eric Anholt <eric@anholt.net> 25428d7b3dSmrg * 26428d7b3dSmrg */ 27428d7b3dSmrg 28428d7b3dSmrg#ifdef HAVE_CONFIG_H 29428d7b3dSmrg#include "config.h" 30428d7b3dSmrg#endif 31428d7b3dSmrg 32428d7b3dSmrg#include <sys/mman.h> 33428d7b3dSmrg#include <assert.h> 34428d7b3dSmrg 35428d7b3dSmrg#include "sna.h" 36428d7b3dSmrg#include "sna_reg.h" 37428d7b3dSmrg 38428d7b3dSmrg#include "kgem_debug.h" 39428d7b3dSmrg 40428d7b3dSmrgstruct drm_i915_gem_relocation_entry * 41428d7b3dSmrgkgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset) 42428d7b3dSmrg{ 43428d7b3dSmrg int i; 44428d7b3dSmrg 45428d7b3dSmrg offset *= sizeof(uint32_t); 46428d7b3dSmrg 47428d7b3dSmrg for (i = 0; i < kgem->nreloc; i++) 48428d7b3dSmrg if (kgem->reloc[i].offset == offset) 49428d7b3dSmrg return kgem->reloc+i; 50428d7b3dSmrg 51428d7b3dSmrg assert(!"valid relocation entry, unknown batch offset"); 52428d7b3dSmrg return NULL; 53428d7b3dSmrg} 54428d7b3dSmrg 55428d7b3dSmrgstruct kgem_bo * 56428d7b3dSmrgkgem_debug_get_bo_for_reloc_entry(struct kgem *kgem, 57428d7b3dSmrg struct drm_i915_gem_relocation_entry *reloc) 58428d7b3dSmrg{ 59428d7b3dSmrg struct kgem_bo *bo; 60428d7b3dSmrg 61428d7b3dSmrg if (reloc == NULL) 62428d7b3dSmrg return NULL; 63428d7b3dSmrg 64428d7b3dSmrg list_for_each_entry(bo, &kgem->next_request->buffers, request) 65428d7b3dSmrg if (bo->target_handle == reloc->target_handle && bo->proxy == NULL) 66428d7b3dSmrg break; 67428d7b3dSmrg 68428d7b3dSmrg assert(&bo->request != &kgem->next_request->buffers); 69428d7b3dSmrg 70428d7b3dSmrg return bo; 71428d7b3dSmrg} 72428d7b3dSmrg 73428d7b3dSmrgstatic int kgem_debug_handle_is_fenced(struct kgem *kgem, uint32_t handle) 74428d7b3dSmrg{ 75428d7b3dSmrg int i; 76428d7b3dSmrg 77428d7b3dSmrg if (kgem->has_handle_lut) 78428d7b3dSmrg return kgem->exec[handle].flags & EXEC_OBJECT_NEEDS_FENCE; 79428d7b3dSmrg 80428d7b3dSmrg for (i = 0; i < kgem->nexec; i++) 81428d7b3dSmrg if (kgem->exec[i].handle == handle) 82428d7b3dSmrg return kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE; 83428d7b3dSmrg 84428d7b3dSmrg return 0; 85428d7b3dSmrg} 86428d7b3dSmrg 87428d7b3dSmrgstatic int kgem_debug_handle_tiling(struct kgem *kgem, uint32_t handle) 88428d7b3dSmrg{ 89428d7b3dSmrg struct kgem_bo *bo; 90428d7b3dSmrg 91428d7b3dSmrg list_for_each_entry(bo, &kgem->next_request->buffers, request) 92428d7b3dSmrg if (bo->target_handle == handle) 93428d7b3dSmrg return bo->tiling; 94428d7b3dSmrg 95428d7b3dSmrg return 0; 96428d7b3dSmrg} 97428d7b3dSmrg 98428d7b3dSmrgvoid 99428d7b3dSmrgkgem_debug_print(const uint32_t *data, 100428d7b3dSmrg uint32_t offset, unsigned int index, 101428d7b3dSmrg const char *fmt, ...) 102428d7b3dSmrg{ 103428d7b3dSmrg va_list va; 104428d7b3dSmrg char buf[240]; 105428d7b3dSmrg int len; 106428d7b3dSmrg 107428d7b3dSmrg len = snprintf(buf, sizeof(buf), 108428d7b3dSmrg "0x%08x: 0x%08x: %s", 109428d7b3dSmrg (offset + index) * 4, 110428d7b3dSmrg data[index], 111428d7b3dSmrg index == 0 ? "" : " "); 112428d7b3dSmrg 113428d7b3dSmrg va_start(va, fmt); 114428d7b3dSmrg vsnprintf(buf + len, sizeof(buf) - len, fmt, va); 115428d7b3dSmrg va_end(va); 116428d7b3dSmrg 117428d7b3dSmrg ErrorF("%s", buf); 118428d7b3dSmrg} 119428d7b3dSmrg 120428d7b3dSmrgstatic int 121428d7b3dSmrgdecode_nop(struct kgem *kgem, uint32_t offset) 122428d7b3dSmrg{ 123428d7b3dSmrg uint32_t *data = kgem->batch + offset; 124428d7b3dSmrg kgem_debug_print(data, offset, 0, "UNKNOWN\n"); 125428d7b3dSmrg assert(0); 126428d7b3dSmrg return 1; 127428d7b3dSmrg} 128428d7b3dSmrg 129428d7b3dSmrgstatic int 130428d7b3dSmrgdecode_mi(struct kgem *kgem, uint32_t offset) 131428d7b3dSmrg{ 132428d7b3dSmrg static const struct { 133428d7b3dSmrg uint32_t opcode; 134428d7b3dSmrg int len_mask; 135428d7b3dSmrg int min_len; 136428d7b3dSmrg int max_len; 137428d7b3dSmrg const char *name; 138428d7b3dSmrg } opcodes[] = { 139428d7b3dSmrg { 0x08, 0, 1, 1, "MI_ARB_ON_OFF" }, 140428d7b3dSmrg { 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" }, 141428d7b3dSmrg { 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" }, 142428d7b3dSmrg { 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" }, 143428d7b3dSmrg { 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" }, 144428d7b3dSmrg { 0x04, 0, 1, 1, "MI_FLUSH" }, 145428d7b3dSmrg { 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" }, 146428d7b3dSmrg { 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" }, 147428d7b3dSmrg { 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" }, 148428d7b3dSmrg { 0x00, 0, 1, 1, "MI_NOOP" }, 149428d7b3dSmrg { 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" }, 150428d7b3dSmrg { 0x07, 0, 1, 1, "MI_REPORT_HEAD" }, 151428d7b3dSmrg { 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" }, 152428d7b3dSmrg { 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" }, 153428d7b3dSmrg { 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" }, 154428d7b3dSmrg { 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" }, 155428d7b3dSmrg { 0x02, 0, 1, 1, "MI_USER_INTERRUPT" }, 156428d7b3dSmrg { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" }, 157428d7b3dSmrg { 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" }, 158428d7b3dSmrg { 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" }, 159428d7b3dSmrg { 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH" }, 160428d7b3dSmrg }; 161428d7b3dSmrg uint32_t *data = kgem->batch + offset; 162428d7b3dSmrg int op; 163428d7b3dSmrg 164428d7b3dSmrg for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 165428d7b3dSmrg if ((data[0] & 0x1f800000) >> 23 == opcodes[op].opcode) { 166428d7b3dSmrg unsigned int len = 1, i; 167428d7b3dSmrg 168428d7b3dSmrg kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 169428d7b3dSmrg if (opcodes[op].max_len > 1) { 170428d7b3dSmrg len = (data[0] & opcodes[op].len_mask) + 2; 171428d7b3dSmrg if (len < opcodes[op].min_len || 172428d7b3dSmrg len > opcodes[op].max_len) 173428d7b3dSmrg { 174428d7b3dSmrg ErrorF("Bad length (%d) in %s, [%d, %d]\n", 175428d7b3dSmrg len, opcodes[op].name, 176428d7b3dSmrg opcodes[op].min_len, 177428d7b3dSmrg opcodes[op].max_len); 178428d7b3dSmrg assert(0); 179428d7b3dSmrg } 180428d7b3dSmrg } 181428d7b3dSmrg 182428d7b3dSmrg for (i = 1; i < len; i++) 183428d7b3dSmrg kgem_debug_print(data, offset, i, "dword %d\n", i); 184428d7b3dSmrg 185428d7b3dSmrg return len; 186428d7b3dSmrg } 187428d7b3dSmrg } 188428d7b3dSmrg 189428d7b3dSmrg kgem_debug_print(data, offset, 0, "MI UNKNOWN\n"); 190428d7b3dSmrg assert(0); 191428d7b3dSmrg return 1; 192428d7b3dSmrg} 193428d7b3dSmrg 194428d7b3dSmrgstatic int 195428d7b3dSmrg__decode_2d(struct kgem *kgem, uint32_t offset) 196428d7b3dSmrg{ 197428d7b3dSmrg static const struct { 198428d7b3dSmrg uint32_t opcode; 199428d7b3dSmrg int min_len; 200428d7b3dSmrg int max_len; 201428d7b3dSmrg const char *name; 202428d7b3dSmrg } opcodes[] = { 203428d7b3dSmrg { 0x40, 5, 5, "COLOR_BLT" }, 204428d7b3dSmrg { 0x43, 6, 6, "SRC_COPY_BLT" }, 205428d7b3dSmrg { 0x01, 8, 8, "XY_SETUP_BLT" }, 206428d7b3dSmrg { 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" }, 207428d7b3dSmrg { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" }, 208428d7b3dSmrg { 0x24, 2, 2, "XY_PIXEL_BLT" }, 209428d7b3dSmrg { 0x25, 3, 3, "XY_SCANLINES_BLT" }, 210428d7b3dSmrg { 0x26, 4, 4, "Y_TEXT_BLT" }, 211428d7b3dSmrg { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" }, 212428d7b3dSmrg { 0x50, 6, 6, "XY_COLOR_BLT" }, 213428d7b3dSmrg { 0x51, 6, 6, "XY_PAT_BLT" }, 214428d7b3dSmrg { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" }, 215428d7b3dSmrg { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" }, 216428d7b3dSmrg { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" }, 217428d7b3dSmrg { 0x52, 9, 9, "XY_MONO_PAT_BLT" }, 218428d7b3dSmrg { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" }, 219428d7b3dSmrg { 0x53, 8, 8, "XY_SRC_COPY_BLT" }, 220428d7b3dSmrg { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" }, 221428d7b3dSmrg { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" }, 222428d7b3dSmrg { 0x55, 9, 9, "XY_FULL_BLT" }, 223428d7b3dSmrg { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" }, 224428d7b3dSmrg { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" }, 225428d7b3dSmrg { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" }, 226428d7b3dSmrg { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" }, 227428d7b3dSmrg { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" }, 228428d7b3dSmrg }; 229428d7b3dSmrg 230428d7b3dSmrg unsigned int op, len; 231428d7b3dSmrg const char *format = NULL; 232428d7b3dSmrg uint32_t *data = kgem->batch + offset; 233428d7b3dSmrg struct drm_i915_gem_relocation_entry *reloc; 234428d7b3dSmrg 235428d7b3dSmrg /* Special case the two most common ops that we detail in full */ 236428d7b3dSmrg switch ((data[0] & 0x1fc00000) >> 22) { 237428d7b3dSmrg case 0x50: 238428d7b3dSmrg kgem_debug_print(data, offset, 0, 239428d7b3dSmrg "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n", 240428d7b3dSmrg (data[0] & (1 << 20)) ? "en" : "dis", 241428d7b3dSmrg (data[0] & (1 << 21)) ? "en" : "dis", 242428d7b3dSmrg (data[0] >> 11) & 1); 243428d7b3dSmrg 244428d7b3dSmrg len = (data[0] & 0x000000ff) + 2; 245428d7b3dSmrg assert(len == 6); 246428d7b3dSmrg 247428d7b3dSmrg switch ((data[1] >> 24) & 0x3) { 248428d7b3dSmrg case 0: 249428d7b3dSmrg format="8"; 250428d7b3dSmrg break; 251428d7b3dSmrg case 1: 252428d7b3dSmrg format="565"; 253428d7b3dSmrg break; 254428d7b3dSmrg case 2: 255428d7b3dSmrg format="1555"; 256428d7b3dSmrg break; 257428d7b3dSmrg case 3: 258428d7b3dSmrg format="8888"; 259428d7b3dSmrg break; 260428d7b3dSmrg } 261428d7b3dSmrg 262428d7b3dSmrg kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, " 263428d7b3dSmrg "clipping %sabled\n", format, 264428d7b3dSmrg (data[1] >> 16) & 0xff, 265428d7b3dSmrg (short)(data[1] & 0xffff), 266428d7b3dSmrg data[1] & (1 << 30) ? "en" : "dis"); 267428d7b3dSmrg kgem_debug_print(data, offset, 2, "(%d,%d)\n", 268428d7b3dSmrg data[2] & 0xffff, data[2] >> 16); 269428d7b3dSmrg kgem_debug_print(data, offset, 3, "(%d,%d)\n", 270428d7b3dSmrg data[3] & 0xffff, data[3] >> 16); 271428d7b3dSmrg reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 272428d7b3dSmrg kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 273428d7b3dSmrg data[4], 274428d7b3dSmrg reloc->target_handle, reloc->delta, 275428d7b3dSmrg reloc->read_domains, reloc->write_domain, 276428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 277428d7b3dSmrg kgem_debug_handle_tiling(kgem, reloc->target_handle)); 278428d7b3dSmrg kgem_debug_print(data, offset, 5, "color\n"); 279428d7b3dSmrg assert(kgem->gen >= 040 || 280428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 281428d7b3dSmrg return len; 282428d7b3dSmrg 283428d7b3dSmrg case 0x53: 284428d7b3dSmrg kgem_debug_print(data, offset, 0, 285428d7b3dSmrg "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, " 286428d7b3dSmrg "src tile %d, dst tile %d)\n", 287428d7b3dSmrg (data[0] & (1 << 20)) ? "en" : "dis", 288428d7b3dSmrg (data[0] & (1 << 21)) ? "en" : "dis", 289428d7b3dSmrg (data[0] >> 15) & 1, 290428d7b3dSmrg (data[0] >> 11) & 1); 291428d7b3dSmrg 292428d7b3dSmrg len = (data[0] & 0x000000ff) + 2; 293428d7b3dSmrg assert(len == 8); 294428d7b3dSmrg 295428d7b3dSmrg switch ((data[1] >> 24) & 0x3) { 296428d7b3dSmrg case 0: 297428d7b3dSmrg format="8"; 298428d7b3dSmrg break; 299428d7b3dSmrg case 1: 300428d7b3dSmrg format="565"; 301428d7b3dSmrg break; 302428d7b3dSmrg case 2: 303428d7b3dSmrg format="1555"; 304428d7b3dSmrg break; 305428d7b3dSmrg case 3: 306428d7b3dSmrg format="8888"; 307428d7b3dSmrg break; 308428d7b3dSmrg } 309428d7b3dSmrg 310428d7b3dSmrg kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, " 311428d7b3dSmrg "clipping %sabled\n", format, 312428d7b3dSmrg (data[1] >> 16) & 0xff, 313428d7b3dSmrg (short)(data[1] & 0xffff), 314428d7b3dSmrg data[1] & (1 << 30) ? "en" : "dis"); 315428d7b3dSmrg kgem_debug_print(data, offset, 2, "dst (%d,%d)\n", 316428d7b3dSmrg data[2] & 0xffff, data[2] >> 16); 317428d7b3dSmrg kgem_debug_print(data, offset, 3, "dst (%d,%d)\n", 318428d7b3dSmrg data[3] & 0xffff, data[3] >> 16); 319428d7b3dSmrg reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 320428d7b3dSmrg assert(reloc); 321428d7b3dSmrg kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n", 322428d7b3dSmrg data[4], 323428d7b3dSmrg reloc->target_handle, reloc->delta, 324428d7b3dSmrg reloc->read_domains, reloc->write_domain, 325428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 326428d7b3dSmrg kgem_debug_handle_tiling(kgem, reloc->target_handle)); 327428d7b3dSmrg assert(kgem->gen >= 040 || 328428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 329428d7b3dSmrg 330428d7b3dSmrg kgem_debug_print(data, offset, 5, "src (%d,%d)\n", 331428d7b3dSmrg data[5] & 0xffff, data[5] >> 16); 332428d7b3dSmrg kgem_debug_print(data, offset, 6, "src pitch %d\n", 333428d7b3dSmrg (short)(data[6] & 0xffff)); 334428d7b3dSmrg reloc = kgem_debug_get_reloc_entry(kgem, offset+7); 335428d7b3dSmrg assert(reloc); 336428d7b3dSmrg kgem_debug_print(data, offset, 7, "src offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 337428d7b3dSmrg data[7], 338428d7b3dSmrg reloc->target_handle, reloc->delta, 339428d7b3dSmrg reloc->read_domains, reloc->write_domain, 340428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 341428d7b3dSmrg kgem_debug_handle_tiling(kgem, reloc->target_handle)); 342428d7b3dSmrg assert(kgem->gen >= 040 || 343428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 344428d7b3dSmrg 345428d7b3dSmrg return len; 346428d7b3dSmrg } 347428d7b3dSmrg 348428d7b3dSmrg for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 349428d7b3dSmrg if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) { 350428d7b3dSmrg unsigned int i; 351428d7b3dSmrg 352428d7b3dSmrg len = 1; 353428d7b3dSmrg kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 354428d7b3dSmrg if (opcodes[op].max_len > 1) { 355428d7b3dSmrg len = (data[0] & 0x000000ff) + 2; 356428d7b3dSmrg assert(len >= opcodes[op].min_len && 357428d7b3dSmrg len <= opcodes[op].max_len); 358428d7b3dSmrg } 359428d7b3dSmrg 360428d7b3dSmrg for (i = 1; i < len; i++) 361428d7b3dSmrg kgem_debug_print(data, offset, i, "dword %d\n", i); 362428d7b3dSmrg 363428d7b3dSmrg return len; 364428d7b3dSmrg } 365428d7b3dSmrg } 366428d7b3dSmrg 367428d7b3dSmrg kgem_debug_print(data, offset, 0, "2D UNKNOWN\n"); 368428d7b3dSmrg assert(0); 369428d7b3dSmrg return 1; 370428d7b3dSmrg} 371428d7b3dSmrg 372428d7b3dSmrgstatic int 373428d7b3dSmrg__decode_2d_gen8(struct kgem *kgem, uint32_t offset) 374428d7b3dSmrg{ 375428d7b3dSmrg static const struct { 376428d7b3dSmrg uint32_t opcode; 377428d7b3dSmrg int min_len; 378428d7b3dSmrg int max_len; 379428d7b3dSmrg const char *name; 380428d7b3dSmrg } opcodes[] = { 381428d7b3dSmrg { 0x43, 8, 8, "SRC_COPY_BLT" }, 382428d7b3dSmrg { 0x01, 8, 8, "XY_SETUP_BLT" }, 383428d7b3dSmrg { 0x11, 10, 10, "XY_SETUP_MONO_PATTERN_SL_BLT" }, 384428d7b3dSmrg { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" }, 385428d7b3dSmrg { 0x24, 2, 2, "XY_PIXEL_BLT" }, 386428d7b3dSmrg { 0x25, 3, 3, "XY_SCANLINES_BLT" }, 387428d7b3dSmrg { 0x26, 4, 4, "Y_TEXT_BLT" }, 388428d7b3dSmrg { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" }, 389428d7b3dSmrg { 0x50, 7, 7, "XY_COLOR_BLT" }, 390428d7b3dSmrg { 0x51, 6, 6, "XY_PAT_BLT" }, 391428d7b3dSmrg { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" }, 392428d7b3dSmrg { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" }, 393428d7b3dSmrg { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" }, 394428d7b3dSmrg { 0x52, 9, 9, "XY_MONO_PAT_BLT" }, 395428d7b3dSmrg { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" }, 396428d7b3dSmrg { 0x53, 8, 8, "XY_SRC_COPY_BLT" }, 397428d7b3dSmrg { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" }, 398428d7b3dSmrg { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" }, 399428d7b3dSmrg { 0x55, 9, 9, "XY_FULL_BLT" }, 400428d7b3dSmrg { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" }, 401428d7b3dSmrg { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" }, 402428d7b3dSmrg { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" }, 403428d7b3dSmrg { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" }, 404428d7b3dSmrg { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" }, 405428d7b3dSmrg }; 406428d7b3dSmrg 407428d7b3dSmrg unsigned int op, len; 408428d7b3dSmrg const char *format = NULL; 409428d7b3dSmrg uint32_t *data = kgem->batch + offset; 410428d7b3dSmrg struct drm_i915_gem_relocation_entry *reloc; 411428d7b3dSmrg 412428d7b3dSmrg /* Special case the two most common ops that we detail in full */ 413428d7b3dSmrg switch ((data[0] & 0x1fc00000) >> 22) { 414428d7b3dSmrg case 0x50: 415428d7b3dSmrg kgem_debug_print(data, offset, 0, 416428d7b3dSmrg "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n", 417428d7b3dSmrg (data[0] & (1 << 20)) ? "en" : "dis", 418428d7b3dSmrg (data[0] & (1 << 21)) ? "en" : "dis", 419428d7b3dSmrg (data[0] >> 11) & 1); 420428d7b3dSmrg 421428d7b3dSmrg len = (data[0] & 0x000000ff) + 2; 422428d7b3dSmrg assert(len == 7); 423428d7b3dSmrg 424428d7b3dSmrg switch ((data[1] >> 24) & 0x3) { 425428d7b3dSmrg case 0: 426428d7b3dSmrg format="8"; 427428d7b3dSmrg break; 428428d7b3dSmrg case 1: 429428d7b3dSmrg format="565"; 430428d7b3dSmrg break; 431428d7b3dSmrg case 2: 432428d7b3dSmrg format="1555"; 433428d7b3dSmrg break; 434428d7b3dSmrg case 3: 435428d7b3dSmrg format="8888"; 436428d7b3dSmrg break; 437428d7b3dSmrg } 438428d7b3dSmrg 439428d7b3dSmrg kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, " 440428d7b3dSmrg "clipping %sabled\n", format, 441428d7b3dSmrg (data[1] >> 16) & 0xff, 442428d7b3dSmrg (short)(data[1] & 0xffff), 443428d7b3dSmrg data[1] & (1 << 30) ? "en" : "dis"); 444428d7b3dSmrg kgem_debug_print(data, offset, 2, "(%d,%d)\n", 445428d7b3dSmrg data[2] & 0xffff, data[2] >> 16); 446428d7b3dSmrg kgem_debug_print(data, offset, 3, "(%d,%d)\n", 447428d7b3dSmrg data[3] & 0xffff, data[3] >> 16); 448428d7b3dSmrg reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 449428d7b3dSmrg kgem_debug_print(data, offset, 4, "dst offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 450428d7b3dSmrg (long long)*(uint64_t *)&data[4], 451428d7b3dSmrg reloc->target_handle, reloc->delta, 452428d7b3dSmrg reloc->read_domains, reloc->write_domain, 453428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 454428d7b3dSmrg kgem_debug_handle_tiling(kgem, reloc->target_handle)); 455428d7b3dSmrg kgem_debug_print(data, offset, 6, "color\n"); 456428d7b3dSmrg return len; 457428d7b3dSmrg 458428d7b3dSmrg case 0x53: 459428d7b3dSmrg kgem_debug_print(data, offset, 0, 460428d7b3dSmrg "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, " 461428d7b3dSmrg "src tile %d, dst tile %d)\n", 462428d7b3dSmrg (data[0] & (1 << 20)) ? "en" : "dis", 463428d7b3dSmrg (data[0] & (1 << 21)) ? "en" : "dis", 464428d7b3dSmrg (data[0] >> 15) & 1, 465428d7b3dSmrg (data[0] >> 11) & 1); 466428d7b3dSmrg 467428d7b3dSmrg len = (data[0] & 0x000000ff) + 2; 468428d7b3dSmrg assert(len == 10); 469428d7b3dSmrg 470428d7b3dSmrg switch ((data[1] >> 24) & 0x3) { 471428d7b3dSmrg case 0: 472428d7b3dSmrg format="8"; 473428d7b3dSmrg break; 474428d7b3dSmrg case 1: 475428d7b3dSmrg format="565"; 476428d7b3dSmrg break; 477428d7b3dSmrg case 2: 478428d7b3dSmrg format="1555"; 479428d7b3dSmrg break; 480428d7b3dSmrg case 3: 481428d7b3dSmrg format="8888"; 482428d7b3dSmrg break; 483428d7b3dSmrg } 484428d7b3dSmrg 485428d7b3dSmrg kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, " 486428d7b3dSmrg "clipping %sabled\n", format, 487428d7b3dSmrg (data[1] >> 16) & 0xff, 488428d7b3dSmrg (short)(data[1] & 0xffff), 489428d7b3dSmrg data[1] & (1 << 30) ? "en" : "dis"); 490428d7b3dSmrg kgem_debug_print(data, offset, 2, "dst (%d,%d)\n", 491428d7b3dSmrg data[2] & 0xffff, data[2] >> 16); 492428d7b3dSmrg kgem_debug_print(data, offset, 3, "dst (%d,%d)\n", 493428d7b3dSmrg data[3] & 0xffff, data[3] >> 16); 494428d7b3dSmrg reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 495428d7b3dSmrg assert(reloc); 496428d7b3dSmrg kgem_debug_print(data, offset, 4, "dst offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n", 497428d7b3dSmrg (long long)*(uint64_t *)&data[4], 498428d7b3dSmrg reloc->target_handle, reloc->delta, 499428d7b3dSmrg reloc->read_domains, reloc->write_domain, 500428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 501428d7b3dSmrg kgem_debug_handle_tiling(kgem, reloc->target_handle)); 502428d7b3dSmrg 503428d7b3dSmrg kgem_debug_print(data, offset, 6, "src (%d,%d)\n", 504428d7b3dSmrg data[6] & 0xffff, data[6] >> 16); 505428d7b3dSmrg kgem_debug_print(data, offset, 7, "src pitch %d\n", 506428d7b3dSmrg (short)(data[7] & 0xffff)); 507428d7b3dSmrg reloc = kgem_debug_get_reloc_entry(kgem, offset+8); 508428d7b3dSmrg assert(reloc); 509428d7b3dSmrg kgem_debug_print(data, offset, 8, "src offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 510428d7b3dSmrg (long long)*(uint64_t *)&data[8], 511428d7b3dSmrg reloc->target_handle, reloc->delta, 512428d7b3dSmrg reloc->read_domains, reloc->write_domain, 513428d7b3dSmrg kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 514428d7b3dSmrg kgem_debug_handle_tiling(kgem, reloc->target_handle)); 515428d7b3dSmrg 516428d7b3dSmrg return len; 517428d7b3dSmrg } 518428d7b3dSmrg 519428d7b3dSmrg for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 520428d7b3dSmrg if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) { 521428d7b3dSmrg unsigned int i; 522428d7b3dSmrg 523428d7b3dSmrg len = 1; 524428d7b3dSmrg kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 525428d7b3dSmrg if (opcodes[op].max_len > 1) { 526428d7b3dSmrg len = (data[0] & 0x000000ff) + 2; 527428d7b3dSmrg assert(len >= opcodes[op].min_len && 528428d7b3dSmrg len <= opcodes[op].max_len); 529428d7b3dSmrg } 530428d7b3dSmrg 531428d7b3dSmrg for (i = 1; i < len; i++) 532428d7b3dSmrg kgem_debug_print(data, offset, i, "dword %d\n", i); 533428d7b3dSmrg 534428d7b3dSmrg return len; 535428d7b3dSmrg } 536428d7b3dSmrg } 537428d7b3dSmrg 538428d7b3dSmrg kgem_debug_print(data, offset, 0, "2D UNKNOWN\n"); 539428d7b3dSmrg assert(0); 540428d7b3dSmrg return 1; 541428d7b3dSmrg} 542428d7b3dSmrg 543428d7b3dSmrgstatic int (*decode_2d(int gen))(struct kgem*, uint32_t) 544428d7b3dSmrg{ 545428d7b3dSmrg if (gen >= 0100) 546428d7b3dSmrg return __decode_2d_gen8; 547428d7b3dSmrg else 548428d7b3dSmrg return __decode_2d; 549428d7b3dSmrg} 550428d7b3dSmrg 551428d7b3dSmrgstatic int kgem_nop_decode_3d(struct kgem *kgem, uint32_t offset) 552428d7b3dSmrg{ 553428d7b3dSmrg uint32_t *data = kgem->batch + offset; 554428d7b3dSmrg return (data[0] & 0xf) + 2; 555428d7b3dSmrg} 556428d7b3dSmrg 557428d7b3dSmrgstatic void kgem_nop_finish_state(struct kgem *kgem) 558428d7b3dSmrg{ 559428d7b3dSmrg} 560428d7b3dSmrg 561428d7b3dSmrgstatic int (*decode_3d(int gen))(struct kgem*, uint32_t) 562428d7b3dSmrg{ 563428d7b3dSmrg if (gen >= 0100) { 564428d7b3dSmrg return kgem_nop_decode_3d; 565428d7b3dSmrg } else if (gen >= 070) { 566428d7b3dSmrg return kgem_gen7_decode_3d; 567428d7b3dSmrg } else if (gen >= 060) { 568428d7b3dSmrg return kgem_gen6_decode_3d; 569428d7b3dSmrg } else if (gen >= 050) { 570428d7b3dSmrg return kgem_gen5_decode_3d; 571428d7b3dSmrg } else if (gen >= 040) { 572428d7b3dSmrg return kgem_gen4_decode_3d; 573428d7b3dSmrg } else if (gen >= 030) { 574428d7b3dSmrg return kgem_gen3_decode_3d; 575428d7b3dSmrg } else if (gen >= 020) { 576428d7b3dSmrg return kgem_gen2_decode_3d; 577428d7b3dSmrg } 578428d7b3dSmrg assert(0); 579428d7b3dSmrg} 580428d7b3dSmrg 581428d7b3dSmrgstatic void (*finish_state(int gen))(struct kgem*) 582428d7b3dSmrg{ 583428d7b3dSmrg if (gen >= 0100) { 584428d7b3dSmrg return kgem_nop_finish_state; 585428d7b3dSmrg } else if (gen >= 070) { 586428d7b3dSmrg return kgem_gen7_finish_state; 587428d7b3dSmrg } else if (gen >= 060) { 588428d7b3dSmrg return kgem_gen6_finish_state; 589428d7b3dSmrg } else if (gen >= 050) { 590428d7b3dSmrg return kgem_gen5_finish_state; 591428d7b3dSmrg } else if (gen >= 040) { 592428d7b3dSmrg return kgem_gen4_finish_state; 593428d7b3dSmrg } else if (gen >= 030) { 594428d7b3dSmrg return kgem_gen3_finish_state; 595428d7b3dSmrg } else if (gen >= 020) { 596428d7b3dSmrg return kgem_gen2_finish_state; 597428d7b3dSmrg } 598428d7b3dSmrg assert(0); 599428d7b3dSmrg} 600428d7b3dSmrg 601428d7b3dSmrgvoid __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch) 602428d7b3dSmrg{ 603428d7b3dSmrg int (*const decode[])(struct kgem *, uint32_t) = { 604428d7b3dSmrg decode_mi, 605428d7b3dSmrg decode_nop, 606428d7b3dSmrg decode_2d(kgem->gen), 607428d7b3dSmrg decode_3d(kgem->gen), 608428d7b3dSmrg }; 609428d7b3dSmrg uint32_t offset = 0; 610428d7b3dSmrg 611428d7b3dSmrg while (offset < nbatch) { 612428d7b3dSmrg int class = (kgem->batch[offset] & 0xe0000000) >> 29; 613428d7b3dSmrg assert(class < ARRAY_SIZE(decode)); 614428d7b3dSmrg offset += decode[class](kgem, offset); 615428d7b3dSmrg } 616428d7b3dSmrg 617428d7b3dSmrg finish_state(kgem->gen)(kgem); 618428d7b3dSmrg} 619