103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 2007-2011 Intel Corporation 303b705cfSriastradh * 403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a 503b705cfSriastradh * copy of this software and associated documentation files (the "Software"), 603b705cfSriastradh * to deal in the Software without restriction, including without limitation 703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the 903b705cfSriastradh * Software is furnished to do so, subject to the following conditions: 1003b705cfSriastradh * 1103b705cfSriastradh * The above copyright notice and this permission notice (including the next 1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the 1303b705cfSriastradh * Software. 1403b705cfSriastradh * 1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2103b705cfSriastradh * SOFTWARE. 2203b705cfSriastradh * 2303b705cfSriastradh * Authors: 2403b705cfSriastradh * Eric Anholt <eric@anholt.net> 2503b705cfSriastradh * 2603b705cfSriastradh */ 2703b705cfSriastradh 2803b705cfSriastradh#ifdef HAVE_CONFIG_H 2903b705cfSriastradh#include "config.h" 3003b705cfSriastradh#endif 3103b705cfSriastradh 3203b705cfSriastradh#include <sys/mman.h> 3303b705cfSriastradh#include <assert.h> 3403b705cfSriastradh 3503b705cfSriastradh#include "sna.h" 3603b705cfSriastradh#include "sna_reg.h" 3703b705cfSriastradh 3803b705cfSriastradh#include "kgem_debug.h" 3903b705cfSriastradh 4003b705cfSriastradhstruct drm_i915_gem_relocation_entry * 4103b705cfSriastradhkgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset) 4203b705cfSriastradh{ 4303b705cfSriastradh int i; 4403b705cfSriastradh 4503b705cfSriastradh offset *= sizeof(uint32_t); 4603b705cfSriastradh 4703b705cfSriastradh for (i = 0; i < kgem->nreloc; i++) 4803b705cfSriastradh if (kgem->reloc[i].offset == offset) 4903b705cfSriastradh return kgem->reloc+i; 5003b705cfSriastradh 5103b705cfSriastradh assert(!"valid relocation entry, unknown batch offset"); 5203b705cfSriastradh return NULL; 5303b705cfSriastradh} 5403b705cfSriastradh 5503b705cfSriastradhstruct kgem_bo * 5603b705cfSriastradhkgem_debug_get_bo_for_reloc_entry(struct kgem *kgem, 5703b705cfSriastradh struct drm_i915_gem_relocation_entry *reloc) 5803b705cfSriastradh{ 5903b705cfSriastradh struct kgem_bo *bo; 6003b705cfSriastradh 6103b705cfSriastradh if (reloc == NULL) 6203b705cfSriastradh return NULL; 6303b705cfSriastradh 6403b705cfSriastradh list_for_each_entry(bo, &kgem->next_request->buffers, request) 6503b705cfSriastradh if (bo->target_handle == reloc->target_handle && bo->proxy == NULL) 6603b705cfSriastradh break; 6703b705cfSriastradh 6803b705cfSriastradh assert(&bo->request != &kgem->next_request->buffers); 6903b705cfSriastradh 7003b705cfSriastradh return bo; 7103b705cfSriastradh} 7203b705cfSriastradh 7303b705cfSriastradhstatic int kgem_debug_handle_is_fenced(struct kgem *kgem, uint32_t handle) 7403b705cfSriastradh{ 7503b705cfSriastradh int i; 7603b705cfSriastradh 7703b705cfSriastradh if (kgem->has_handle_lut) 7803b705cfSriastradh return kgem->exec[handle].flags & EXEC_OBJECT_NEEDS_FENCE; 7903b705cfSriastradh 8003b705cfSriastradh for (i = 0; i < kgem->nexec; i++) 8103b705cfSriastradh if (kgem->exec[i].handle == handle) 8203b705cfSriastradh return kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE; 8303b705cfSriastradh 8403b705cfSriastradh return 0; 8503b705cfSriastradh} 8603b705cfSriastradh 8703b705cfSriastradhstatic int kgem_debug_handle_tiling(struct kgem *kgem, uint32_t handle) 8803b705cfSriastradh{ 8903b705cfSriastradh struct kgem_bo *bo; 9003b705cfSriastradh 9103b705cfSriastradh list_for_each_entry(bo, &kgem->next_request->buffers, request) 9203b705cfSriastradh if (bo->target_handle == handle) 9303b705cfSriastradh return bo->tiling; 9403b705cfSriastradh 9503b705cfSriastradh return 0; 9603b705cfSriastradh} 9703b705cfSriastradh 9803b705cfSriastradhvoid 9903b705cfSriastradhkgem_debug_print(const uint32_t *data, 10003b705cfSriastradh uint32_t offset, unsigned int index, 10103b705cfSriastradh const char *fmt, ...) 10203b705cfSriastradh{ 10303b705cfSriastradh va_list va; 10403b705cfSriastradh char buf[240]; 10503b705cfSriastradh int len; 10603b705cfSriastradh 10703b705cfSriastradh len = snprintf(buf, sizeof(buf), 10803b705cfSriastradh "0x%08x: 0x%08x: %s", 10903b705cfSriastradh (offset + index) * 4, 11003b705cfSriastradh data[index], 11103b705cfSriastradh index == 0 ? "" : " "); 11203b705cfSriastradh 11303b705cfSriastradh va_start(va, fmt); 11403b705cfSriastradh vsnprintf(buf + len, sizeof(buf) - len, fmt, va); 11503b705cfSriastradh va_end(va); 11603b705cfSriastradh 11703b705cfSriastradh ErrorF("%s", buf); 11803b705cfSriastradh} 11903b705cfSriastradh 12003b705cfSriastradhstatic int 12103b705cfSriastradhdecode_nop(struct kgem *kgem, uint32_t offset) 12203b705cfSriastradh{ 12303b705cfSriastradh uint32_t *data = kgem->batch + offset; 12403b705cfSriastradh kgem_debug_print(data, offset, 0, "UNKNOWN\n"); 12503b705cfSriastradh assert(0); 12603b705cfSriastradh return 1; 12703b705cfSriastradh} 12803b705cfSriastradh 12903b705cfSriastradhstatic int 13003b705cfSriastradhdecode_mi(struct kgem *kgem, uint32_t offset) 13103b705cfSriastradh{ 13203b705cfSriastradh static const struct { 13303b705cfSriastradh uint32_t opcode; 13403b705cfSriastradh int len_mask; 13503b705cfSriastradh int min_len; 13603b705cfSriastradh int max_len; 13703b705cfSriastradh const char *name; 13803b705cfSriastradh } opcodes[] = { 13903b705cfSriastradh { 0x08, 0, 1, 1, "MI_ARB_ON_OFF" }, 14003b705cfSriastradh { 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" }, 14103b705cfSriastradh { 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" }, 14203b705cfSriastradh { 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" }, 14303b705cfSriastradh { 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" }, 14403b705cfSriastradh { 0x04, 0, 1, 1, "MI_FLUSH" }, 14503b705cfSriastradh { 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" }, 14603b705cfSriastradh { 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" }, 14703b705cfSriastradh { 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" }, 14803b705cfSriastradh { 0x00, 0, 1, 1, "MI_NOOP" }, 14903b705cfSriastradh { 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" }, 15003b705cfSriastradh { 0x07, 0, 1, 1, "MI_REPORT_HEAD" }, 15103b705cfSriastradh { 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" }, 15203b705cfSriastradh { 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" }, 15303b705cfSriastradh { 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" }, 15403b705cfSriastradh { 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" }, 15503b705cfSriastradh { 0x02, 0, 1, 1, "MI_USER_INTERRUPT" }, 15603b705cfSriastradh { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" }, 15703b705cfSriastradh { 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" }, 15803b705cfSriastradh { 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" }, 15903b705cfSriastradh { 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH" }, 16003b705cfSriastradh }; 16103b705cfSriastradh uint32_t *data = kgem->batch + offset; 16203b705cfSriastradh int op; 16303b705cfSriastradh 16403b705cfSriastradh for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 16503b705cfSriastradh if ((data[0] & 0x1f800000) >> 23 == opcodes[op].opcode) { 16603b705cfSriastradh unsigned int len = 1, i; 16703b705cfSriastradh 16803b705cfSriastradh kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 16903b705cfSriastradh if (opcodes[op].max_len > 1) { 17003b705cfSriastradh len = (data[0] & opcodes[op].len_mask) + 2; 17103b705cfSriastradh if (len < opcodes[op].min_len || 17203b705cfSriastradh len > opcodes[op].max_len) 17303b705cfSriastradh { 17403b705cfSriastradh ErrorF("Bad length (%d) in %s, [%d, %d]\n", 17503b705cfSriastradh len, opcodes[op].name, 17603b705cfSriastradh opcodes[op].min_len, 17703b705cfSriastradh opcodes[op].max_len); 17803b705cfSriastradh assert(0); 17903b705cfSriastradh } 18003b705cfSriastradh } 18103b705cfSriastradh 18203b705cfSriastradh for (i = 1; i < len; i++) 18303b705cfSriastradh kgem_debug_print(data, offset, i, "dword %d\n", i); 18403b705cfSriastradh 18503b705cfSriastradh return len; 18603b705cfSriastradh } 18703b705cfSriastradh } 18803b705cfSriastradh 18903b705cfSriastradh kgem_debug_print(data, offset, 0, "MI UNKNOWN\n"); 19003b705cfSriastradh assert(0); 19103b705cfSriastradh return 1; 19203b705cfSriastradh} 19303b705cfSriastradh 19403b705cfSriastradhstatic int 19542542f5fSchristos__decode_2d(struct kgem *kgem, uint32_t offset) 19603b705cfSriastradh{ 19703b705cfSriastradh static const struct { 19803b705cfSriastradh uint32_t opcode; 19903b705cfSriastradh int min_len; 20003b705cfSriastradh int max_len; 20103b705cfSriastradh const char *name; 20203b705cfSriastradh } opcodes[] = { 20303b705cfSriastradh { 0x40, 5, 5, "COLOR_BLT" }, 20403b705cfSriastradh { 0x43, 6, 6, "SRC_COPY_BLT" }, 20503b705cfSriastradh { 0x01, 8, 8, "XY_SETUP_BLT" }, 20603b705cfSriastradh { 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" }, 20703b705cfSriastradh { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" }, 20803b705cfSriastradh { 0x24, 2, 2, "XY_PIXEL_BLT" }, 20903b705cfSriastradh { 0x25, 3, 3, "XY_SCANLINES_BLT" }, 21003b705cfSriastradh { 0x26, 4, 4, "Y_TEXT_BLT" }, 21103b705cfSriastradh { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" }, 21203b705cfSriastradh { 0x50, 6, 6, "XY_COLOR_BLT" }, 21303b705cfSriastradh { 0x51, 6, 6, "XY_PAT_BLT" }, 21403b705cfSriastradh { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" }, 21503b705cfSriastradh { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" }, 21603b705cfSriastradh { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" }, 21703b705cfSriastradh { 0x52, 9, 9, "XY_MONO_PAT_BLT" }, 21803b705cfSriastradh { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" }, 21903b705cfSriastradh { 0x53, 8, 8, "XY_SRC_COPY_BLT" }, 22003b705cfSriastradh { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" }, 22103b705cfSriastradh { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" }, 22203b705cfSriastradh { 0x55, 9, 9, "XY_FULL_BLT" }, 22303b705cfSriastradh { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" }, 22403b705cfSriastradh { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" }, 22503b705cfSriastradh { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" }, 22603b705cfSriastradh { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" }, 22703b705cfSriastradh { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" }, 22803b705cfSriastradh }; 22903b705cfSriastradh 23003b705cfSriastradh unsigned int op, len; 23103b705cfSriastradh const char *format = NULL; 23203b705cfSriastradh uint32_t *data = kgem->batch + offset; 23303b705cfSriastradh struct drm_i915_gem_relocation_entry *reloc; 23403b705cfSriastradh 23503b705cfSriastradh /* Special case the two most common ops that we detail in full */ 23603b705cfSriastradh switch ((data[0] & 0x1fc00000) >> 22) { 23703b705cfSriastradh case 0x50: 23803b705cfSriastradh kgem_debug_print(data, offset, 0, 23903b705cfSriastradh "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n", 24003b705cfSriastradh (data[0] & (1 << 20)) ? "en" : "dis", 24103b705cfSriastradh (data[0] & (1 << 21)) ? "en" : "dis", 24203b705cfSriastradh (data[0] >> 11) & 1); 24303b705cfSriastradh 24403b705cfSriastradh len = (data[0] & 0x000000ff) + 2; 24503b705cfSriastradh assert(len == 6); 24603b705cfSriastradh 24703b705cfSriastradh switch ((data[1] >> 24) & 0x3) { 24803b705cfSriastradh case 0: 24903b705cfSriastradh format="8"; 25003b705cfSriastradh break; 25103b705cfSriastradh case 1: 25203b705cfSriastradh format="565"; 25303b705cfSriastradh break; 25403b705cfSriastradh case 2: 25503b705cfSriastradh format="1555"; 25603b705cfSriastradh break; 25703b705cfSriastradh case 3: 25803b705cfSriastradh format="8888"; 25903b705cfSriastradh break; 26003b705cfSriastradh } 26103b705cfSriastradh 26203b705cfSriastradh kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, " 26303b705cfSriastradh "clipping %sabled\n", format, 26403b705cfSriastradh (data[1] >> 16) & 0xff, 26503b705cfSriastradh (short)(data[1] & 0xffff), 26603b705cfSriastradh data[1] & (1 << 30) ? "en" : "dis"); 26703b705cfSriastradh kgem_debug_print(data, offset, 2, "(%d,%d)\n", 26803b705cfSriastradh data[2] & 0xffff, data[2] >> 16); 26903b705cfSriastradh kgem_debug_print(data, offset, 3, "(%d,%d)\n", 27003b705cfSriastradh data[3] & 0xffff, data[3] >> 16); 27103b705cfSriastradh reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 27203b705cfSriastradh kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 27303b705cfSriastradh data[4], 27403b705cfSriastradh reloc->target_handle, reloc->delta, 27503b705cfSriastradh reloc->read_domains, reloc->write_domain, 27603b705cfSriastradh kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 27703b705cfSriastradh kgem_debug_handle_tiling(kgem, reloc->target_handle)); 27803b705cfSriastradh kgem_debug_print(data, offset, 5, "color\n"); 27903b705cfSriastradh assert(kgem->gen >= 040 || 28003b705cfSriastradh kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 28103b705cfSriastradh return len; 28203b705cfSriastradh 28303b705cfSriastradh case 0x53: 28403b705cfSriastradh kgem_debug_print(data, offset, 0, 28503b705cfSriastradh "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, " 28603b705cfSriastradh "src tile %d, dst tile %d)\n", 28703b705cfSriastradh (data[0] & (1 << 20)) ? "en" : "dis", 28803b705cfSriastradh (data[0] & (1 << 21)) ? "en" : "dis", 28903b705cfSriastradh (data[0] >> 15) & 1, 29003b705cfSriastradh (data[0] >> 11) & 1); 29103b705cfSriastradh 29203b705cfSriastradh len = (data[0] & 0x000000ff) + 2; 29303b705cfSriastradh assert(len == 8); 29403b705cfSriastradh 29503b705cfSriastradh switch ((data[1] >> 24) & 0x3) { 29603b705cfSriastradh case 0: 29703b705cfSriastradh format="8"; 29803b705cfSriastradh break; 29903b705cfSriastradh case 1: 30003b705cfSriastradh format="565"; 30103b705cfSriastradh break; 30203b705cfSriastradh case 2: 30303b705cfSriastradh format="1555"; 30403b705cfSriastradh break; 30503b705cfSriastradh case 3: 30603b705cfSriastradh format="8888"; 30703b705cfSriastradh break; 30803b705cfSriastradh } 30903b705cfSriastradh 31003b705cfSriastradh kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, " 31103b705cfSriastradh "clipping %sabled\n", format, 31203b705cfSriastradh (data[1] >> 16) & 0xff, 31303b705cfSriastradh (short)(data[1] & 0xffff), 31403b705cfSriastradh data[1] & (1 << 30) ? "en" : "dis"); 31503b705cfSriastradh kgem_debug_print(data, offset, 2, "dst (%d,%d)\n", 31603b705cfSriastradh data[2] & 0xffff, data[2] >> 16); 31703b705cfSriastradh kgem_debug_print(data, offset, 3, "dst (%d,%d)\n", 31803b705cfSriastradh data[3] & 0xffff, data[3] >> 16); 31903b705cfSriastradh reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 32003b705cfSriastradh assert(reloc); 32103b705cfSriastradh kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n", 32203b705cfSriastradh data[4], 32303b705cfSriastradh reloc->target_handle, reloc->delta, 32403b705cfSriastradh reloc->read_domains, reloc->write_domain, 32503b705cfSriastradh kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 32603b705cfSriastradh kgem_debug_handle_tiling(kgem, reloc->target_handle)); 32703b705cfSriastradh assert(kgem->gen >= 040 || 32803b705cfSriastradh kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 32903b705cfSriastradh 33003b705cfSriastradh kgem_debug_print(data, offset, 5, "src (%d,%d)\n", 33103b705cfSriastradh data[5] & 0xffff, data[5] >> 16); 33203b705cfSriastradh kgem_debug_print(data, offset, 6, "src pitch %d\n", 33303b705cfSriastradh (short)(data[6] & 0xffff)); 33403b705cfSriastradh reloc = kgem_debug_get_reloc_entry(kgem, offset+7); 33503b705cfSriastradh assert(reloc); 33603b705cfSriastradh kgem_debug_print(data, offset, 7, "src offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 33703b705cfSriastradh data[7], 33803b705cfSriastradh reloc->target_handle, reloc->delta, 33903b705cfSriastradh reloc->read_domains, reloc->write_domain, 34003b705cfSriastradh kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 34103b705cfSriastradh kgem_debug_handle_tiling(kgem, reloc->target_handle)); 34203b705cfSriastradh assert(kgem->gen >= 040 || 34303b705cfSriastradh kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 34403b705cfSriastradh 34503b705cfSriastradh return len; 34603b705cfSriastradh } 34703b705cfSriastradh 34803b705cfSriastradh for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 34903b705cfSriastradh if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) { 35003b705cfSriastradh unsigned int i; 35103b705cfSriastradh 35203b705cfSriastradh len = 1; 35303b705cfSriastradh kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 35403b705cfSriastradh if (opcodes[op].max_len > 1) { 35503b705cfSriastradh len = (data[0] & 0x000000ff) + 2; 35603b705cfSriastradh assert(len >= opcodes[op].min_len && 35703b705cfSriastradh len <= opcodes[op].max_len); 35803b705cfSriastradh } 35903b705cfSriastradh 36003b705cfSriastradh for (i = 1; i < len; i++) 36103b705cfSriastradh kgem_debug_print(data, offset, i, "dword %d\n", i); 36203b705cfSriastradh 36303b705cfSriastradh return len; 36403b705cfSriastradh } 36503b705cfSriastradh } 36603b705cfSriastradh 36703b705cfSriastradh kgem_debug_print(data, offset, 0, "2D UNKNOWN\n"); 36803b705cfSriastradh assert(0); 36903b705cfSriastradh return 1; 37003b705cfSriastradh} 37103b705cfSriastradh 37242542f5fSchristosstatic int 37342542f5fSchristos__decode_2d_gen8(struct kgem *kgem, uint32_t offset) 37442542f5fSchristos{ 37542542f5fSchristos static const struct { 37642542f5fSchristos uint32_t opcode; 37742542f5fSchristos int min_len; 37842542f5fSchristos int max_len; 37942542f5fSchristos const char *name; 38042542f5fSchristos } opcodes[] = { 38142542f5fSchristos { 0x43, 8, 8, "SRC_COPY_BLT" }, 38242542f5fSchristos { 0x01, 8, 8, "XY_SETUP_BLT" }, 38342542f5fSchristos { 0x11, 10, 10, "XY_SETUP_MONO_PATTERN_SL_BLT" }, 38442542f5fSchristos { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" }, 38542542f5fSchristos { 0x24, 2, 2, "XY_PIXEL_BLT" }, 38642542f5fSchristos { 0x25, 3, 3, "XY_SCANLINES_BLT" }, 38742542f5fSchristos { 0x26, 4, 4, "Y_TEXT_BLT" }, 38842542f5fSchristos { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" }, 38942542f5fSchristos { 0x50, 7, 7, "XY_COLOR_BLT" }, 39042542f5fSchristos { 0x51, 6, 6, "XY_PAT_BLT" }, 39142542f5fSchristos { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" }, 39242542f5fSchristos { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" }, 39342542f5fSchristos { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" }, 39442542f5fSchristos { 0x52, 9, 9, "XY_MONO_PAT_BLT" }, 39542542f5fSchristos { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" }, 39642542f5fSchristos { 0x53, 8, 8, "XY_SRC_COPY_BLT" }, 39742542f5fSchristos { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" }, 39842542f5fSchristos { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" }, 39942542f5fSchristos { 0x55, 9, 9, "XY_FULL_BLT" }, 40042542f5fSchristos { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" }, 40142542f5fSchristos { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" }, 40242542f5fSchristos { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" }, 40342542f5fSchristos { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" }, 40442542f5fSchristos { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" }, 40542542f5fSchristos }; 40642542f5fSchristos 40742542f5fSchristos unsigned int op, len; 40842542f5fSchristos const char *format = NULL; 40942542f5fSchristos uint32_t *data = kgem->batch + offset; 41042542f5fSchristos struct drm_i915_gem_relocation_entry *reloc; 41142542f5fSchristos 41242542f5fSchristos /* Special case the two most common ops that we detail in full */ 41342542f5fSchristos switch ((data[0] & 0x1fc00000) >> 22) { 41442542f5fSchristos case 0x50: 41542542f5fSchristos kgem_debug_print(data, offset, 0, 41642542f5fSchristos "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n", 41742542f5fSchristos (data[0] & (1 << 20)) ? "en" : "dis", 41842542f5fSchristos (data[0] & (1 << 21)) ? "en" : "dis", 41942542f5fSchristos (data[0] >> 11) & 1); 42042542f5fSchristos 42142542f5fSchristos len = (data[0] & 0x000000ff) + 2; 42242542f5fSchristos assert(len == 7); 42342542f5fSchristos 42442542f5fSchristos switch ((data[1] >> 24) & 0x3) { 42542542f5fSchristos case 0: 42642542f5fSchristos format="8"; 42742542f5fSchristos break; 42842542f5fSchristos case 1: 42942542f5fSchristos format="565"; 43042542f5fSchristos break; 43142542f5fSchristos case 2: 43242542f5fSchristos format="1555"; 43342542f5fSchristos break; 43442542f5fSchristos case 3: 43542542f5fSchristos format="8888"; 43642542f5fSchristos break; 43742542f5fSchristos } 43842542f5fSchristos 43942542f5fSchristos kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, " 44042542f5fSchristos "clipping %sabled\n", format, 44142542f5fSchristos (data[1] >> 16) & 0xff, 44242542f5fSchristos (short)(data[1] & 0xffff), 44342542f5fSchristos data[1] & (1 << 30) ? "en" : "dis"); 44442542f5fSchristos kgem_debug_print(data, offset, 2, "(%d,%d)\n", 44542542f5fSchristos data[2] & 0xffff, data[2] >> 16); 44642542f5fSchristos kgem_debug_print(data, offset, 3, "(%d,%d)\n", 44742542f5fSchristos data[3] & 0xffff, data[3] >> 16); 44842542f5fSchristos reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 44942542f5fSchristos kgem_debug_print(data, offset, 4, "dst offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 45042542f5fSchristos (long long)*(uint64_t *)&data[4], 45142542f5fSchristos reloc->target_handle, reloc->delta, 45242542f5fSchristos reloc->read_domains, reloc->write_domain, 45342542f5fSchristos kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 45442542f5fSchristos kgem_debug_handle_tiling(kgem, reloc->target_handle)); 45542542f5fSchristos kgem_debug_print(data, offset, 6, "color\n"); 45642542f5fSchristos return len; 45742542f5fSchristos 45842542f5fSchristos case 0x53: 45942542f5fSchristos kgem_debug_print(data, offset, 0, 46042542f5fSchristos "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, " 46142542f5fSchristos "src tile %d, dst tile %d)\n", 46242542f5fSchristos (data[0] & (1 << 20)) ? "en" : "dis", 46342542f5fSchristos (data[0] & (1 << 21)) ? "en" : "dis", 46442542f5fSchristos (data[0] >> 15) & 1, 46542542f5fSchristos (data[0] >> 11) & 1); 46642542f5fSchristos 46742542f5fSchristos len = (data[0] & 0x000000ff) + 2; 46842542f5fSchristos assert(len == 10); 46942542f5fSchristos 47042542f5fSchristos switch ((data[1] >> 24) & 0x3) { 47142542f5fSchristos case 0: 47242542f5fSchristos format="8"; 47342542f5fSchristos break; 47442542f5fSchristos case 1: 47542542f5fSchristos format="565"; 47642542f5fSchristos break; 47742542f5fSchristos case 2: 47842542f5fSchristos format="1555"; 47942542f5fSchristos break; 48042542f5fSchristos case 3: 48142542f5fSchristos format="8888"; 48242542f5fSchristos break; 48342542f5fSchristos } 48442542f5fSchristos 48542542f5fSchristos kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, " 48642542f5fSchristos "clipping %sabled\n", format, 48742542f5fSchristos (data[1] >> 16) & 0xff, 48842542f5fSchristos (short)(data[1] & 0xffff), 48942542f5fSchristos data[1] & (1 << 30) ? "en" : "dis"); 49042542f5fSchristos kgem_debug_print(data, offset, 2, "dst (%d,%d)\n", 49142542f5fSchristos data[2] & 0xffff, data[2] >> 16); 49242542f5fSchristos kgem_debug_print(data, offset, 3, "dst (%d,%d)\n", 49342542f5fSchristos data[3] & 0xffff, data[3] >> 16); 49442542f5fSchristos reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 49542542f5fSchristos assert(reloc); 49642542f5fSchristos kgem_debug_print(data, offset, 4, "dst offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n", 49742542f5fSchristos (long long)*(uint64_t *)&data[4], 49842542f5fSchristos reloc->target_handle, reloc->delta, 49942542f5fSchristos reloc->read_domains, reloc->write_domain, 50042542f5fSchristos kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 50142542f5fSchristos kgem_debug_handle_tiling(kgem, reloc->target_handle)); 50242542f5fSchristos 50342542f5fSchristos kgem_debug_print(data, offset, 6, "src (%d,%d)\n", 50442542f5fSchristos data[6] & 0xffff, data[6] >> 16); 50542542f5fSchristos kgem_debug_print(data, offset, 7, "src pitch %d\n", 50642542f5fSchristos (short)(data[7] & 0xffff)); 50742542f5fSchristos reloc = kgem_debug_get_reloc_entry(kgem, offset+8); 50842542f5fSchristos assert(reloc); 50942542f5fSchristos kgem_debug_print(data, offset, 8, "src offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 51042542f5fSchristos (long long)*(uint64_t *)&data[8], 51142542f5fSchristos reloc->target_handle, reloc->delta, 51242542f5fSchristos reloc->read_domains, reloc->write_domain, 51342542f5fSchristos kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 51442542f5fSchristos kgem_debug_handle_tiling(kgem, reloc->target_handle)); 51542542f5fSchristos 51642542f5fSchristos return len; 51742542f5fSchristos } 51842542f5fSchristos 51942542f5fSchristos for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 52042542f5fSchristos if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) { 52142542f5fSchristos unsigned int i; 52242542f5fSchristos 52342542f5fSchristos len = 1; 52442542f5fSchristos kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 52542542f5fSchristos if (opcodes[op].max_len > 1) { 52642542f5fSchristos len = (data[0] & 0x000000ff) + 2; 52742542f5fSchristos assert(len >= opcodes[op].min_len && 52842542f5fSchristos len <= opcodes[op].max_len); 52942542f5fSchristos } 53042542f5fSchristos 53142542f5fSchristos for (i = 1; i < len; i++) 53242542f5fSchristos kgem_debug_print(data, offset, i, "dword %d\n", i); 53342542f5fSchristos 53442542f5fSchristos return len; 53542542f5fSchristos } 53642542f5fSchristos } 53742542f5fSchristos 53842542f5fSchristos kgem_debug_print(data, offset, 0, "2D UNKNOWN\n"); 53942542f5fSchristos assert(0); 54042542f5fSchristos return 1; 54142542f5fSchristos} 54242542f5fSchristos 54342542f5fSchristosstatic int (*decode_2d(int gen))(struct kgem*, uint32_t) 54442542f5fSchristos{ 54542542f5fSchristos if (gen >= 0100) 54642542f5fSchristos return __decode_2d_gen8; 54742542f5fSchristos else 54842542f5fSchristos return __decode_2d; 54942542f5fSchristos} 55042542f5fSchristos 55142542f5fSchristosstatic int kgem_nop_decode_3d(struct kgem *kgem, uint32_t offset) 55242542f5fSchristos{ 55342542f5fSchristos uint32_t *data = kgem->batch + offset; 55442542f5fSchristos return (data[0] & 0xf) + 2; 55542542f5fSchristos} 55642542f5fSchristos 55742542f5fSchristosstatic void kgem_nop_finish_state(struct kgem *kgem) 55842542f5fSchristos{ 55942542f5fSchristos} 56042542f5fSchristos 56103b705cfSriastradhstatic int (*decode_3d(int gen))(struct kgem*, uint32_t) 56203b705cfSriastradh{ 56303b705cfSriastradh if (gen >= 0100) { 56442542f5fSchristos return kgem_nop_decode_3d; 56503b705cfSriastradh } else if (gen >= 070) { 56603b705cfSriastradh return kgem_gen7_decode_3d; 56703b705cfSriastradh } else if (gen >= 060) { 56803b705cfSriastradh return kgem_gen6_decode_3d; 56903b705cfSriastradh } else if (gen >= 050) { 57003b705cfSriastradh return kgem_gen5_decode_3d; 57103b705cfSriastradh } else if (gen >= 040) { 57203b705cfSriastradh return kgem_gen4_decode_3d; 57303b705cfSriastradh } else if (gen >= 030) { 57403b705cfSriastradh return kgem_gen3_decode_3d; 57503b705cfSriastradh } else if (gen >= 020) { 57603b705cfSriastradh return kgem_gen2_decode_3d; 57703b705cfSriastradh } 57803b705cfSriastradh assert(0); 57903b705cfSriastradh} 58003b705cfSriastradh 58103b705cfSriastradhstatic void (*finish_state(int gen))(struct kgem*) 58203b705cfSriastradh{ 58303b705cfSriastradh if (gen >= 0100) { 58442542f5fSchristos return kgem_nop_finish_state; 58503b705cfSriastradh } else if (gen >= 070) { 58603b705cfSriastradh return kgem_gen7_finish_state; 58703b705cfSriastradh } else if (gen >= 060) { 58803b705cfSriastradh return kgem_gen6_finish_state; 58903b705cfSriastradh } else if (gen >= 050) { 59003b705cfSriastradh return kgem_gen5_finish_state; 59103b705cfSriastradh } else if (gen >= 040) { 59203b705cfSriastradh return kgem_gen4_finish_state; 59303b705cfSriastradh } else if (gen >= 030) { 59403b705cfSriastradh return kgem_gen3_finish_state; 59503b705cfSriastradh } else if (gen >= 020) { 59603b705cfSriastradh return kgem_gen2_finish_state; 59703b705cfSriastradh } 59803b705cfSriastradh assert(0); 59903b705cfSriastradh} 60003b705cfSriastradh 60103b705cfSriastradhvoid __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch) 60203b705cfSriastradh{ 60303b705cfSriastradh int (*const decode[])(struct kgem *, uint32_t) = { 60403b705cfSriastradh decode_mi, 60503b705cfSriastradh decode_nop, 60642542f5fSchristos decode_2d(kgem->gen), 60703b705cfSriastradh decode_3d(kgem->gen), 60803b705cfSriastradh }; 60903b705cfSriastradh uint32_t offset = 0; 61003b705cfSriastradh 61103b705cfSriastradh while (offset < nbatch) { 61203b705cfSriastradh int class = (kgem->batch[offset] & 0xe0000000) >> 29; 61303b705cfSriastradh assert(class < ARRAY_SIZE(decode)); 61403b705cfSriastradh offset += decode[class](kgem, offset); 61503b705cfSriastradh } 61603b705cfSriastradh 61703b705cfSriastradh finish_state(kgem->gen)(kgem); 61803b705cfSriastradh} 619