summaryrefslogtreecommitdiff
path: root/ring.c
diff options
context:
space:
mode:
Diffstat (limited to 'ring.c')
-rw-r--r--ring.c770
1 files changed, 770 insertions, 0 deletions
diff --git a/ring.c b/ring.c
new file mode 100644
index 0000000..45fecba
--- /dev/null
+++ b/ring.c
@@ -0,0 +1,770 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include "main.h"
+
+/* from Linux kernel file: intel_lrc.c */
+#define CTX_LRI_HEADER_0 0x01
+#define CTX_CONTEXT_CONTROL 0x02
+#define CTX_RING_HEAD 0x04
+#define CTX_RING_TAIL 0x06
+#define CTX_RING_BUFFER_START 0x08
+#define CTX_RING_BUFFER_CONTROL 0x0a
+#define CTX_BB_HEAD_U 0x0c
+#define CTX_BB_HEAD_L 0x0e
+#define CTX_BB_STATE 0x10
+#define CTX_SECOND_BB_HEAD_U 0x12
+#define CTX_SECOND_BB_HEAD_L 0x14
+#define CTX_SECOND_BB_STATE 0x16
+#define CTX_BB_PER_CTX_PTR 0x18
+#define CTX_RCS_INDIRECT_CTX 0x1a
+#define CTX_RCS_INDIRECT_CTX_OFFSET 0x1c
+#define CTX_LRI_HEADER_1 0x21
+#define CTX_CTX_TIMESTAMP 0x22
+#define CTX_PDP3_UDW 0x24
+#define CTX_PDP3_LDW 0x26
+#define CTX_PDP2_UDW 0x28
+#define CTX_PDP2_LDW 0x2a
+#define CTX_PDP1_UDW 0x2c
+#define CTX_PDP1_LDW 0x2e
+#define CTX_PDP0_UDW 0x30
+#define CTX_PDP0_LDW 0x32
+#define CTX_LRI_HEADER_2 0x41
+#define CTX_R_PWR_CLK_STATE 0x42
+#define CTX_GPGPU_CSR_BASE_ADDRESS 0x44
+
+
+static int process_dumpbb(int indent, unsigned int stat_addr, unsigned int bb_addr, int id);
+static int process_dumpbb2(int indent, unsigned int stat_addr, unsigned int bb_addr, int id);
+
+static char *uint_to_char(uint32_t tmp)
+{
+ static char uint_char_buf[33];
+ uint32_t i=0, n=tmp;
+
+ memset(uint_char_buf,(int)'0',32);
+ uint_char_buf[32]='\0';
+ do {
+ uint_char_buf[i++] = (n&1)+'0';
+ n/=2;
+ } while(n);
+
+ return uint_char_buf;
+}
+
+#define printf_indent(indent, format, args...) \
+ do { \
+ int abc; \
+ for (abc=0; abc<indent; abc++) \
+ printf("\t"); \
+ if (indent != 0) \
+ printf("BB-L%d: ", indent); \
+ printf(format, ##args); \
+ } while (0)
+
+static int print_inst_mi(int indent, unsigned int stat_addr, uint32_t cmd_header,
+ int offset, uint32_t *cmd_ptr, int render_cs)
+{
+ int i, size;
+ unsigned int opcode = (cmd_header>>23) & 0x3f;
+ char *buf = uint_to_char(cmd_header);
+ int dump_bb = 0;
+ struct mi_inst {
+ uint32_t opcode;
+ uint32_t size;
+ const char *name;
+ } mi_insts[] = {
+ {0x00, 1, "MI_NOOP"},
+ {0x01, 1, "MI_SET_PREDICATE"},
+ {0x02, 1, "MI_USER_INTERRUPT"},
+ {0x03, 1, "MI_WAIT_FOR_EVENT"},
+ {0x05, 1, "MI_ARB_CHECK"},
+ {0x06, 1, "MI_RS_CONTROL"},
+ {0x07, 1, "MI_REPORT_HEAD"},
+ {0x08, 1, "MI_ARB_ON_OFF"},
+ {0x09, 1, "MI_URB_ATOMIC_ALLOC"},
+ {0x0A, 1, "MI_BATCH_BUFFER_END"},
+ {0x0B, 1, "MI_SUSPEND_FLUSH"},
+ {0x0C, 1, "MI_PREDICATE"},
+ {0x0D, 1, "MI_TOPOLOGY_FILTER"},
+ {0x0E, 1, "MI_SET_APPID"},
+ {0x0F, 1, "MI_RS_CONTEXT"},
+ //2+ DWord
+ {0x10, 0, "Reserved"},
+ {0x14, 0, "MI_DISPLAY_FLIP"},
+ {0x15, 0, "Reserved"},
+ {0x16, 0, "MI_SEMAPHORE_MBOX"},
+ {0x17, 0, "Reserved"},
+ {0x18, 0, "MI_SET_CONTEXT"},
+ {0x19, 0, "MI_URB_CLEAR"},
+ {0x1A, 0, "MI_MATH"},
+ {0x1B, 0, "MI_SEMAPHORE_SIGNAL"},
+ {0x1C, 0, "MI_SEMAPHORE_WAIT"},
+ //Store "Data"
+ {0x20, 0, "MI_STORE_DATA_IMM"},
+ {0x21, 0, "MI_STORE_DATA_INDEX"},
+ {0x22, 0, "MI_LOAD_REGISTER_IMM"},
+ {0x23, 0, "MI_UPDATE_GTT"},
+ {0x24, 0, "MI_STORE_REGISTER_MEM"},
+ {0x26, 0, "MI_FLUSH_DW"},
+ {0x27, 0, "MI_CLFLUSH"},
+ {0x28, 0, "MI_REPORT_PERF_COUNT"},
+ {0x29, 0, "MI_LOAD_REGISTER_MEM"},
+ {0x2A, 0, "MI_LOAD_REGISTER_REG"},
+ {0x2B, 0, "MI_RS_STORE_DATA_IMM"},
+ {0x2C, 0, "MI_LOAD_URB_MEM"},
+ {0x2D, 0, "MI_STORE_URB_MEM"},
+ {0x2E, 0, "MI_MEM_TO_MEM"},
+ {0x2F, 0, "MI_ATOMIC"},
+ {0x30, 0, "Reserved"},
+ //Ring/batch buffer
+ {0x31, 3, "MI_BATCH_BUFFER_START"},
+ {0x36, 1, "MI_CONDITIONAL_BATCH_BUFFER_END"},
+ {0xff, 0, "TBD"},
+ }, *mi_current = NULL;
+
+ int mi_size = sizeof(mi_insts) / sizeof(mi_insts[0]);
+
+ for (i=0; i<mi_size; i++) {
+ if (opcode == mi_insts[i].opcode)
+ break;
+ }
+ if (i==mi_size)
+ mi_current = &mi_insts[mi_size -1];
+ else
+ mi_current = &mi_insts[i];
+
+ printf_indent(indent,"0x%04x:0x%08x (%s)", offset, cmd_header, mi_current->name);
+ if (strcmp(mi_current->name, "MI_BATCH_BUFFER_START") == 0) {
+ if ((cmd_header & 0x100) != 0) {
+ dump_bb = 1;
+ printf("(BB in PPGTT)\n");
+ } else {
+ /* the instructions in GGTT is the initialization code filled in Kernel */
+ dump_bb = 0;
+ printf("(BB in GGTT)\n");
+ }
+ } else
+ printf("\n");
+
+ printf_indent(indent,"\t");
+ printf("31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00\n");
+ printf_indent(indent,"\t");
+ printf("|%c%c%c| ",buf[31],buf[30],buf[29]);
+ printf("|%c%c%c%c%c%c| ",buf[28],buf[27],buf[26],buf[25],buf[24],buf[23]);
+ printf("|%c%c%c| ",buf[22],buf[21],buf[20]);
+#define print_four_bits(from) printf("|%c%c%c%c| ",buf[from],buf[from-1],buf[from-2],buf[from-3])
+ for (i=19;i>=3;i=i-4)
+ print_four_bits(i);
+
+ printf("\n");
+
+ //if ((opcode == 0x20) ||(opcode == 0x21)||(opcode == 0x22))
+ if (mi_current->size == 0)
+ size = (cmd_header & 0x3f) + 2;
+ else if (opcode == 0x0a) /* MI_BATCH_BUFFER_END */
+ size = 0;
+ else
+ size = mi_current->size;
+
+ for (i=1; i<size; i++)
+ printf_indent(indent,"0x%04x:0x%08x (data)\n", offset+i*4, *(cmd_ptr+i));
+
+ printf("\n");
+
+ if (dump_bb == 0)
+ return size;
+
+ uint32_t bb_addr = *(cmd_ptr+1);
+
+ indent++;
+ printf_indent(indent,">>>>>>>>>>>>BB @ 0x%08x Begin>>>>>>>>>>>>>\n", bb_addr);
+ if (dump_bb == 1) {
+ if (render_cs)
+ process_dumpbb(indent, stat_addr, bb_addr, RCS);
+ else
+ process_dumpbb(indent, stat_addr, bb_addr, VCS);
+ } else if (dump_bb == 2) {
+ if (render_cs)
+ process_dumpbb2(indent, stat_addr, bb_addr, RCS);
+ else
+ process_dumpbb2(indent, stat_addr, bb_addr, VCS);
+ }
+ printf_indent(indent,"<<<<<<<<<<<BB @ 0x%08x End<<<<<<<<<<<<<<<<<\n\n", bb_addr);
+
+ return size;
+}
+
+
+static int print_inst_rendercs(int indent, uint32_t cmd_header, int offset, uint32_t *cmd_ptr)
+{
+ int i, size;
+ unsigned int opcode_bit28_27 = (cmd_header>>27) & 0x3;
+ unsigned int opcode_bit26_24 = (cmd_header>>24) & 0x7;
+ unsigned int opcode_bit23_16 = (cmd_header>>16) & 0xff;
+ char *buf = uint_to_char(cmd_header);
+ struct render_inst {
+ uint32_t opcode_bit28_27;
+ uint32_t opcode_bit26_24;
+ uint32_t opcode_bit23_16;
+ uint32_t size;
+ const char *name;
+ } render_insts[] = {
+ { 0, 1, 0x1, 0, "STATE_BASE_ADDRESS" },
+ { 1, 1, 0x4, 1, "PIPELINE_SELECT"},
+
+ { 2, 0, 0x0, 0, "MEDIA_VFE_STATE" },
+ { 2, 0, 0x1, 0, "MEDIA_CURBE_LOAD" },
+ { 2, 0, 0x2, 0, "MEDIA_INTERFACE_DESCRIPTOR_LOAD" },
+ { 2, 0, 0x3, 0, "CMD_MEDIA_GATEWAY_STATE" },
+ { 2, 0, 0x4, 0, "MEDIA_STATE_FLUSH" },
+ { 2, 1, 0x0, 0, "MEDIA_OBJECT" },
+ { 2, 1, 0x2, 0, "MEDIA_OBJECT_PTR" },
+ { 2, 1, 0x3, 0, "MEDIA_OBJECT_WALKER" },
+
+ { 3, 0, 0x04, 0, "3DSTATE_CLEAR_PARAMS" },
+ { 3, 0, 0x05, 0, "3DSTATE_DEPTH_BUFFER" },
+ { 3, 0, 0x06, 0, "3DSTATE_STENCIL_BUFFER" },
+ { 3, 0, 0x07, 0, "3DSTATE_HIER_DEPTH_BUFFER" },
+ { 3, 0, 0x08, 0, "3DSTATE_VERTEX_BUFFERS" },
+ { 3, 0, 0x09, 0, "3DSTATE_VERTEX_ELEMENTS" },
+ { 3, 0, 0x0A, 0, "3DSTATE_INDEX_BUFFER" },
+ { 3, 0, 0x0B, 0, "3DSTATE_VF_STATISTICS" },
+ { 3, 0, 0x0D, 0, "3DSTATE_VIEWPORT_STATE_POINTERS" },
+ { 3, 0, 0x0E, 0, "3DSTATE_CC_STATE_POINTERS" },
+ { 3, 0, 0x10, 0, "3DSTATE_VS" },
+ { 3, 0, 0x11, 0, "3DSTATE_GS" },
+ { 3, 0, 0x12, 0, "3DSTATE_CLIP" },
+ { 3, 0, 0x13, 0, "3DSTATE_SF" },
+ { 3, 0, 0x14, 0, "3DSTATE_WM" },
+ { 3, 0, 0x15, 0, "3DSTATE_CONSTANT_VS" },
+ { 3, 0, 0x16, 0, "3DSTATE_CONSTANT_GS" },
+ { 3, 0, 0x17, 0, "3DSTATE_CONSTANT_PS" },
+ { 3, 0, 0x18, 0, "3DSTATE_SAMPLE_MASK" },
+ { 3, 0, 0x19, 0, "3DSTATE_CONSTANT_HS" },
+ { 3, 0, 0x1A, 0, "3DSTATE_CONSTANT_DS" },
+ { 3, 0, 0x1B, 0, "3DSTATE_HS" },
+ { 3, 0, 0x1C, 0, "3DSTATE_TE" },
+ { 3, 0, 0x1D, 0, "3DSTATE_DS" },
+ { 3, 0, 0x1E, 0, "3DSTATE_STREAMOUT" },
+ { 3, 0, 0x1F, 0, "3DSTATE_SBE" },
+ { 3, 0, 0x20, 0, "3DSTATE_PS" },
+ { 3, 0, 0x21, 0, "3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP" },
+ { 3, 0, 0x23, 0, "3DSTATE_VIEWPORT_STATE_POINTERS_CC" },
+ { 3, 0, 0x24, 0, "3DSTATE_BLEND_STATE_POINTERS" },
+ { 3, 0, 0x25, 0, "3DSTATE_DEPTH_STENCIL_STATE_POINTERS" },
+ { 3, 0, 0x26, 0, "3DSTATE_BINDING_TABLE_POINTERS_VS" },
+ { 3, 0, 0x27, 0, "3DSTATE_BINDING_TABLE_POINTERS_HS" },
+ { 3, 0, 0x28, 0, "3DSTATE_BINDING_TABLE_POINTERS_DS" },
+ { 3, 0, 0x29, 0, "3DSTATE_BINDING_TABLE_POINTERS_GS" },
+ { 3, 0, 0x2A, 0, "3DSTATE_BINDING_TABLE_POINTERS_PS" },
+ { 3, 0, 0x2B, 0, "3DSTATE_SAMPLER_STATE_POINTERS_VS" },
+ { 3, 0, 0x2C, 0, "3DSTATE_SAMPLER_STATE_POINTERS_HS" },
+ { 3, 0, 0x2D, 0, "3DSTATE_SAMPLER_STATE_POINTERS_DS" },
+ { 3, 0, 0x2E, 0, "3DSTATE_SAMPLER_STATE_POINTERS_GS" },
+ { 3, 0, 0x30, 0, "3DSTATE_URB_VS" },
+ { 3, 0, 0x31, 0, "3DSTATE_URB_HS" },
+ { 3, 0, 0x32, 0, "3DSTATE_URB_DS" },
+ { 3, 0, 0x33, 0, "3DSTATE_URB_GS" },
+ { 3, 0, 0x34, 0, "3DSTATE_GATHER_CONSTANT_VS" },
+ { 3, 0, 0x35, 0, "3DSTATE_GATHER_CONSTANT_GS" },
+ { 3, 0, 0x36, 0, "3DSTATE_GATHER_CONSTANT_HS" },
+ { 3, 0, 0x37, 0, "3DSTATE_GATHER_CONSTANT_DS" },
+ { 3, 0, 0x38, 0, "3DSTATE_GATHER_CONSTANT_PS" },
+ { 3, 0, 0x39, 0, "3DSTATE_DX9_CONSTANTF_VS" },
+ { 3, 0, 0x3A, 0, "3DSTATE_DX9_CONSTANTF_PS" },
+ { 3, 0, 0x3B, 0, "3DSTATE_DX9_CONSTANTI_VS" },
+ { 3, 0, 0x3C, 0, "3DSTATE_DX9_CONSTANTI_PS" },
+ { 3, 0, 0x3D, 0, "3DSTATE_DX9_CONSTANTB_VS" },
+ { 3, 0, 0x3E, 0, "3DSTATE_DX9_CONSTANTB_PS" },
+ { 3, 0, 0x3F, 0, "3DSTATE_DX9_LOCAL_VALID_VS" },
+ { 3, 0, 0x40, 0, "3DSTATE_DX9_LOCAL_VALID_PS" },
+ { 3, 0, 0x41, 0, "3DSTATE_DX9_GENERATE_ACTIVE_VS" },
+ { 3, 0, 0x42, 0, "3DSTATE_DX9_GENERATE_ACTIVE_PS" },
+ { 3, 0, 0x43, 0, "3DSTATE_BINDING_TABLE_EDIT_VS" },
+ { 3, 0, 0x44, 0, "3DSTATE_BINDING_TABLE_EDIT_GS" },
+ { 3, 0, 0x45, 0, "3DSTATE_BINDING_TABLE_EDIT_HS" },
+ { 3, 0, 0x46, 0, "3DSTATE_BINDING_TABLE_EDIT_DS" },
+ { 3, 0, 0x47, 0, "3DSTATE_BINDING_TABLE_EDIT_PS" },
+ { 3, 0, 0x48, 0, "3DSTATE_VF_HASHING" },
+ { 3, 0, 0x49, 0, "3DSTATE_VF_INSTANCING" },
+ { 3, 0, 0x4A, 0, "3DSTATE_VF_SGVS" },
+ { 3, 0, 0x4B, 0, "3DSTATE_VF_TOPOLOGY" },
+ { 3, 0, 0x4C, 0, "3DSTATE_WM_CHROMA_KEY" },
+ { 3, 0, 0x4D, 0, "3DSTATE_PS_BLEND" },
+ { 3, 0, 0x4E, 0, "3DSTATE_WM_DEPTH_STENCIL" },
+ { 3, 0, 0x4F, 0, "3DSTATE_PS_EXTRA" },
+ { 3, 0, 0x50, 0, "3DSTATE_RASTER" },
+ { 3, 0, 0x51, 0, "3DSTATE_SBE_SWIZ" },
+ { 3, 0, 0x52, 0, "3DSTATE_WM_HZ_OP" },
+ { 3, 0, 0x53, 0, "3DSTATE_INT" },
+ { 3, 1, 0x00, 0, "3DSTATE_DRAWING_RECTANGLE" },
+ { 3, 1, 0x02, 0, "3DSTATE_SAMPLER_PALETTE_LOAD0" },
+ { 3, 1, 0x04, 0, "3DSTATE_CHROMA_KEY" },
+ { 3, 1, 0x06, 0, "3DSTATE_POLY_STIPPLE_OFFSET" },
+ { 3, 1, 0x07, 0, "3DSTATE_POLY_STIPPLE_PATTERN" },
+ { 3, 1, 0x08, 0, "3DSTATE_LINE_STIPPLE" },
+ { 3, 1, 0x0A, 0, "3DSTATE_AA_LINE_PARAMS" },
+ { 3, 1, 0x0B, 0, "3DSTATE_GS_SVB_INDEX" },
+ { 3, 1, 0x0C, 0, "3DSTATE_SAMPLER_PALETTE_LOAD1" },
+ { 3, 1, 0x0D, 0, "3DSTATE_MULTISAMPLE" },
+ { 3, 1, 0x0E, 0, "3DSTATE_STENCIL_BUFFER" },
+ { 3, 1, 0x0F, 0, "3DSTATE_HIER_DEPTH_BUFFER" },
+ { 3, 1, 0x10, 0, "3DSTATE_CLEAR_PARAMS" },
+ { 3, 1, 0x11, 0, "3DSTATE_MONOFILTER_SIZE" },
+ { 3, 1, 0x12, 0, "3DSTATE_PUSH_CONSTANT_ALLOC_VS" },
+ { 3, 1, 0x13, 0, "3DSTATE_PUSH_CONSTANT_ALLOC_HS" },
+ { 3, 1, 0x14, 0, "3DSTATE_PUSH_CONSTANT_ALLOC_DS" },
+ { 3, 1, 0x15, 0, "3DSTATE_PUSH_CONSTANT_ALLOC_GS" },
+ { 3, 1, 0x16, 0, "3DSTATE_PUSH_CONSTANT_ALLOC_PS" },
+ { 3, 1, 0x17, 0, "3DSTATE_SO_DECL_LIST" },
+ { 3, 1, 0x18, 0, "3DSTATE_SO_BUFFER" },
+ { 3, 1, 0x19, 0, "3DSTATE_BINDING_TABLE_POOL_ALLOC" },
+ { 3, 1, 0x1A, 0, "3DSTATE_GATHER_POOL_ALLOC" },
+ { 3, 1, 0x1B, 0, "3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC" },
+ { 3, 1, 0x1C, 0, "3DSTATE_SAMPLE_PATTERN" },
+ { 3, 1, 0x1D, 0, "3DSTATE_URB_CLEAR" },
+ { 3, 2, 0x00, 0, "PIPE_CONTROL" },
+ { 3, 3, 0x00, 0, "3DPRIMITIVE" },
+ { 3, 7, 0xff, 0, "TBD"},
+ }, *render_current = NULL;
+
+ int render_size = sizeof(render_insts) / sizeof(render_insts[0]);
+
+ for (i=0; i<render_size; i++) {
+ if ((opcode_bit28_27 == render_insts[i].opcode_bit28_27)
+ && (opcode_bit26_24 == render_insts[i].opcode_bit26_24)
+ && (opcode_bit23_16 == render_insts[i].opcode_bit23_16))
+ break;
+ }
+ if (i==render_size)
+ render_current = &render_insts[render_size -1];
+ else
+ render_current = &render_insts[i];
+
+ printf_indent(indent,"0x%04x:0x%08x (%s)\n", offset, cmd_header, render_current->name);
+
+ printf_indent(indent,"\t");
+ printf("31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00\n");
+ printf_indent(indent,"\t");
+ printf("|%c%c%c| ",buf[31],buf[30],buf[29]);
+ printf("|%c%c| ",buf[28],buf[27]);
+ printf("|%c%c%c| ", buf[26],buf[25],buf[24]);
+ printf("|%c%c%c| ", buf[23],buf[22],buf[21]);
+ printf("|%c%c%c%c%c| ", buf[20],buf[19],buf[18],buf[17],buf[16]);
+#define print_four_bits(from) printf("|%c%c%c%c| ",buf[from],buf[from-1],buf[from-2],buf[from-3])
+ for (i=15;i>=3;i=i-4)
+ print_four_bits(i);
+
+ printf("\n");
+ /*
+ if ((strcmp(render_current->name, "MFX_PIPE_MODE_SELECT") == 0)
+ || (strcmp(render_current->name, "MFX_SURFACE_STATE") == 0)
+ || (strcmp(render_current->name, "MFX_PIPE_BUF_ADDR_STATE") == 0))
+ */
+ if (render_current->size == 0)
+ size = (cmd_header & 0xfff) + 2;
+ else
+ size = render_current->size;
+ for (i=1; i<size; i++)
+ printf_indent(indent,"0x%04x:0x%08x (data)\n", offset+i*4, *(cmd_ptr+i));
+
+ printf("\n");
+
+ return size;
+}
+
+
+static int print_inst_mfxcs(int indent, uint32_t cmd_header, int offset, uint32_t *cmd_ptr)
+{
+ int i, size;
+ unsigned int opcode_bit28_27 = (cmd_header>>27) & 0x3;
+ unsigned int opcode_bit26_24 = (cmd_header>>24) & 0x7;
+ unsigned int opcode_bit23_21 = (cmd_header>>21) & 0x7;
+ unsigned int opcode_bit20_16 = (cmd_header>>16) & 0x1f;
+ char *buf = uint_to_char(cmd_header);
+ struct mfx_inst {
+ uint32_t opcode_bit28_27;
+ uint32_t opcode_bit26_24;
+ uint32_t opcode_bit23_21;
+ uint32_t opcode_bit20_16;
+ uint32_t size;
+ const char *name;
+ } mfx_insts[] = {
+ {1, 0, 0, 0, 1, "MFX_WAIT"},
+ {2, 0, 0, 0, 0, "MFX_PIPE_MODE_SELECT"},
+ {2, 0, 0, 1, 0, "MFX_SURFACE_STATE"},
+ {2, 0, 0, 2, 0, "MFX_PIPE_BUF_ADDR_STATE"},
+ {2, 0, 0, 3, 0, "MFX_IND_OBJ_BASE_ADDR_STATE"},
+ {2, 0, 0, 4, 0, "MFX_BSP_BUF_BASE_ADDR_STATE"},
+ {2, 0, 0, 5, 0, "MFX_AES_STATE"},
+ {2, 0, 0, 6, 0, "MFX_STATE_POINTER"},
+ {2, 0, 0, 7, 0, "MFX_QM_STATE"},
+ {2, 0, 0, 8, 0, "MFX_FQM_STATE"},
+ {2, 0, 1, 9, 0, "MFD_IT_OBJECT"},
+ {2, 0, 2, 8, 0, "MFX_INSERT_OBJECT"},
+ {2, 1, 0, 0, 0, "MFX_AVC_IMG_STATE"},
+ {2, 1, 0, 1, 0, "MFX_AVC_QM_STATE"},
+ {2, 1, 0, 2, 0, "MFX_AVC_DIRECTMODE_STATE"},
+ {2, 1, 0, 3, 0, "MFX_AVC_SLICE_STATE"},
+ {2, 1, 0, 4, 0, "MFX_AVC_REF_IDX_STATE"},
+ {2, 1, 0, 5, 0, "MFX_AVC_WEIGHTOFFSET_STATE"},
+ {2, 1, 1, 5, 0, "MFD_AVC_PICID_STATE"},
+ {2, 1, 1, 8, 0, "MFD_AVC_BSD_OBJECT"},
+ {2, 1, 2, 2, 0, "MFC_AVC_FQM_STATE"},
+ {2, 1, 2, 8, 0, "MFC_AVC_PAK_INSERT_OBJECT"},
+ {2, 1, 2, 9, 0, "MFC_AVC_PAK_OBJECT"},
+ {2, 2, 0, 0, 0, "MFX_VC1_PIC_STATE"},
+ {2, 2, 0, 1, 0, "MFX_VC1_PRED_PIPE_STATE"},
+ {2, 2, 0, 2, 0, "MFX_VC1_DIRECTMODE_STATE"},
+ {2, 2, 1, 0, 0, "MFD_VC1_SHORT_PIC_STATE"},
+ {2, 2, 1, 1, 0, "MFD_VC1_LONG_PIC_STATE"},
+ {2, 2, 1, 8, 0, "MFD_VC1_BSD_OBJECT"},
+ {2, 3, 0, 0, 0, "MFX_MPEG2_PIC_STATE"},
+ {2, 3, 0, 1, 0, "MFX_MPEG2_QM_STATE"},
+ {2, 3, 1, 8, 0, "MFD_MPEG2_BSD_OBJECT"},
+ {2, 3, 2, 3, 0, "MFC_MPEG2_PAK_OBJECT"},
+ {2, 3, 2, 9, 0, "MFC_MPEG2_SLICEGROUP_STATE"},
+ {2, 4, 0, 0, 0, "MFX_VP8_PIC_STATE"},
+ {2, 4, 1, 8, 0, "MFD_VP8_BSD_OBJECT"},
+ {2, 4, 2, 1, 0, "MFX_VP8_ENCODER_CFG"},
+ {2, 4, 2, 3, 0, "MFX_VP8_BSP_BUF_BASE_ADDR_STATE"},
+ {2, 4, 2, 9, 0, "MFX_VP8_PAK_OBJECT"},
+ {2, 7, 0, 0, 0, "MFX_JPEG_PIC_STATE"},
+ {2, 7, 0, 2, 0, "MFX_JPEG_HUFF_TABLE_STATE"},
+ {2, 7, 0, 0, 0, "MFX_JPEG_PIC_STATE"},
+ {2, 7, 0, 2, 0, "MFX_JPEG_HUFF_TABLE_STATE"},
+ {2, 7, 1, 8, 0, "MFD_JPEG_BSD_OBJECT"},
+ {2, 7, 2, 9, 0, "MFC_JPEG_SCAN_OBJECT"},
+ {2, 7, 2, 3, 0, "MFC_JPEG_HUFF_TABLE_STATE"},
+ {3, 4, 0, 0, 0, "VEB_SURFACE_STATE"},
+ {3, 4, 0, 2, 0, "VEB_STATE"},
+ {3, 4, 0, 3, 0, "VEB_DNDI_IECP_STATE"},
+ {3, 2, 7, 0, 0, "HCP_PIPE_MODE_SELECT"},
+ {3, 2, 7, 1, 0, "HCP_SURFACE_STATE"},
+
+ {2, 7, 7, 0x1f, 0, "TBD"},
+ }, *mfx_current = NULL;
+
+ int mfx_size = sizeof(mfx_insts) / sizeof(mfx_insts[0]);
+
+ for (i=0; i<mfx_size; i++) {
+ if ((opcode_bit28_27 == mfx_insts[i].opcode_bit28_27)
+ && (opcode_bit26_24 == mfx_insts[i].opcode_bit26_24)
+ && (opcode_bit23_21 == mfx_insts[i].opcode_bit23_21)
+ && (opcode_bit20_16 == mfx_insts[i].opcode_bit20_16))
+ break;
+ }
+ if (i==mfx_size)
+ mfx_current = &mfx_insts[mfx_size -1];
+ else
+ mfx_current = &mfx_insts[i];
+
+ printf_indent(indent,"0x%04x:0x%08x (%s)\n", offset, cmd_header, mfx_current->name);
+
+ printf_indent(indent,"\t");
+ printf("31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00\n");
+ printf_indent(indent,"\t");
+ printf("|%c%c%c| ",buf[31],buf[30],buf[29]);
+ printf("|%c%c| ",buf[28],buf[27]);
+ printf("|%c%c%c| ", buf[26],buf[25],buf[24]);
+ printf("|%c%c%c| ", buf[23],buf[22],buf[21]);
+ printf("|%c%c%c%c%c| ", buf[20],buf[19],buf[18],buf[17],buf[16]);
+#define print_four_bits(from) printf("|%c%c%c%c| ",buf[from],buf[from-1],buf[from-2],buf[from-3])
+ for (i=15;i>=3;i=i-4)
+ print_four_bits(i);
+
+ printf("\n");
+ if (mfx_current->size == 0)
+ size = (cmd_header & 0xfff) + 2;
+ else
+ size = mfx_current->size;
+ for (i=1; i<size; i++)
+ printf_indent(indent,"0x%04x:0x%08x (data)\n", offset+i*4, *(cmd_ptr+i));
+
+ printf("\n");
+
+ return size;
+}
+
+int process_dumpring(char *cmdhdr,unsigned int stat_addr, unsigned int head, unsigned int tail)
+{
+ uint32_t *ring_ptr, i, dw_count;
+ uint32_t ring_addr;
+ /* render CS has PIPE_CONTROL, use it to differentiate render and video... */
+ int render_cs = 0;
+
+ if (is_gen7) {
+ printf("Execlist/Logica ring is not supported on GEN7\n");
+ return 0;
+ }
+ CHECK_STRICT_DEVMEM;
+
+ if (tail <= head) {
+ printf("Invalid tail=%d/head=%d\n", tail, head);
+ return 0;
+ }
+ ring_addr = get_ring(stat_addr);
+
+ dw_count = (tail - head)/4;
+ printf("Ring buffer address 0x%08x(%dM+%dK), head =%d(0x%x), tail=%d(0x%x), %d instructions \n",
+ ring_addr, ring_addr>>20, (ring_addr>>10) & 0x3ff,
+ head, head, tail, tail, dw_count);
+
+ printf("************************************************************************\n");
+
+ ring_ptr = (uint32_t *)((unsigned char *)linear_fb + ring_addr + head);
+ for (i=0; i<dw_count;) {
+ uint32_t cmd_header = *ring_ptr;
+ uint32_t type = (cmd_header>>29)&0x7;
+ uint32_t dw_cmdpkg = 1;
+
+ if (type == 0)
+ dw_cmdpkg = print_inst_mi(0, stat_addr, cmd_header, head+i*4, ring_ptr, render_cs);
+ else if (type == 3) {
+ render_cs = 1;
+ dw_cmdpkg = print_inst_rendercs(0, cmd_header, head+i*4, ring_ptr);
+ } else
+ printf("Unknow instructions 0x%08x\n", cmd_header);
+
+ ring_ptr += dw_cmdpkg;
+
+ i = i + dw_cmdpkg;
+ }
+
+ return 0;
+}
+
+#define BB_MAX_PAGE 10
+#define BB_MAX_CMDS (BB_MAX_PAGE*4096/4)
+static int dumpbb_help(int indent, unsigned int stat_addr, uint32_t *bb_ptr, int id)
+{
+ uint32_t cmd_header, type;
+ uint32_t dw_count, dw_cmdpkg=0;
+
+ /* Parse all BB commands */
+ dw_count = 0;
+ while (1) {
+ cmd_header = *bb_ptr;
+ type = (cmd_header>>29)&0x7;
+
+ if (type == 0)
+ dw_cmdpkg = print_inst_mi(indent, stat_addr, cmd_header, dw_count*4, bb_ptr, id == RCS);
+ else if (type == 3) {
+ if (id == RCS)
+ dw_cmdpkg = print_inst_rendercs(indent, cmd_header, dw_count*4, bb_ptr);
+ else if (id == VCS)
+ dw_cmdpkg = print_inst_mfxcs(indent, cmd_header, dw_count*4, bb_ptr);
+ } else {
+ printf_indent(indent,"Unknow instructions 0x%08x\n", cmd_header);
+ print_bin_fmt(cmd_header, 8);
+
+ dw_cmdpkg = 1;
+ }
+
+ if (dw_cmdpkg == 0) /*MI_BATCH_BUFFER_END*/
+ break;
+
+ dw_count = dw_count + dw_cmdpkg;
+ bb_ptr += dw_cmdpkg;
+
+ if (dw_count >= BB_MAX_CMDS) {
+ printf_indent(indent,"The batch buffer is still not ended, bugs? Break the loop\n");
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int process_dumpbb2(int indent, unsigned int stat_addr, unsigned int bb_addr, int id)
+{
+ uint32_t *bb_ptr;
+
+ /*
+ printf("Render ring batch buffer address in GGTT 0x%08x(%dM+%dK, offset in page %d)\n",
+ bb_addr, bb_addr>>20, (bb_addr>>10) & 0x3ff, bb_addr & 0xfff);
+ */
+
+ /* Parse all BB commands */
+ bb_ptr = (uint32_t *)((unsigned char *)linear_fb + bb_addr);
+ dumpbb_help(indent, stat_addr, bb_ptr, id);
+
+ return 0;
+}
+
+static int process_dumpbb(int indent, unsigned int stat_addr, unsigned int bb_addr, int id)
+{
+ uint32_t bb_addr_aligned, bb_addr_offset;
+ uint32_t i, *bb_ptr;
+ unsigned char *ten_pages;
+
+ uint32_t ppgtt_addr = get_ppgtt(stat_addr);
+
+ bb_addr_aligned = bb_addr & 0xfffff000;;
+ bb_addr_offset = bb_addr & 0xfff;
+
+ /*
+ printf("Render ring batch buffer address in PPGTT 0x%08x(%dM+%dK, offset in page %d)\n",
+ bb_addr, bb_addr>>20, (bb_addr>>10) & 0x3ff, bb_addr_offset);
+ printf("Read ten pages from PPGTT mapping (physical address 0x%08x)\n", ppgtt_addr);
+ */
+ /* Read maximum pages to avoid one command package
+ * wrapping on two pages. It is for simplicity
+ */
+ ten_pages = malloc(BB_MAX_PAGE * 4096);
+ for (i=0; i<BB_MAX_PAGE; i++)
+ get_ppgtt_page(ppgtt_addr, bb_addr_aligned + i * 4096, ten_pages + i * 4096);
+
+ /* Parse all BB commands */
+ bb_ptr = (uint32_t *)(ten_pages + bb_addr_offset);
+ dumpbb_help(indent, stat_addr, bb_ptr, id);
+
+ return 0;
+}
+
+uint32_t get_ppgtt(unsigned int stat_addr)
+{
+ uint32_t *reg_state = (uint32_t *)(linear_fb+stat_addr + 4096);
+
+ /*
+ printf("Stat buffer: reg_state[CTX_PDP0_LDW+1] = 0x%x (page directory physical address)\n",
+ reg_state[CTX_PDP0_LDW+1]);
+ */
+ return reg_state[CTX_PDP0_LDW+1];
+}
+
+uint32_t get_ring(unsigned int stat_addr)
+{
+ uint32_t *reg_state = (uint32_t *)(linear_fb+stat_addr + 4096);
+
+ /*
+ printf("Stat buffer: reg_state[CTX_RING_BUFFER_START+1] = 0x%x (ring address)\n",
+ reg_state[CTX_RING_BUFFER_START+1]);
+ */
+ return reg_state[CTX_RING_BUFFER_START+1];
+}
+
+
+int process_dumpstat(char *cmdhdr,unsigned int stat_addr)
+{
+ /* The second page of the context object contains some fields which must
+ * be set up prior to the first execution.
+ */
+ uint32_t *reg_state = (uint32_t *)(linear_fb+stat_addr + 4096);
+ int id = RCS; /* ignore it currently */
+
+ if (is_gen7) {
+ printf("Execlist/logical ring is not supported on GEN7\n");
+ return 0;
+ }
+ CHECK_STRICT_DEVMEM;
+
+ /* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM
+ * commands followed by (reg, value) pairs. The values we are setting here are
+ * only for the first context restore: on a subsequent save, the GPU will
+ * recreate this batchbuffer with new values (including all the missing
+ * MI_LOAD_REGISTER_IMM commands that we are not initializing here). */
+ printf("reg_state[CTX_LRI_HEADER_0]=0x%x\n", reg_state[CTX_LRI_HEADER_0]);
+ printf("reg_state[CTX_CONTEXT_CONTROL]=0x%x\n", reg_state[CTX_CONTEXT_CONTROL]);
+ printf("reg_state[CTX_CONTEXT_CONTROL+1]=0x%x\n", reg_state[CTX_CONTEXT_CONTROL+1]);
+ printf("reg_state[CTX_RING_HEAD]=0x%x(mmio base+0x34)\n", reg_state[CTX_RING_HEAD]);
+ printf("reg_state[CTX_RING_HEAD+1]=0x%x\n", reg_state[CTX_RING_HEAD+1]);
+ printf("reg_state[CTX_RING_TAIL]=0x%x(mmio base+0x30)\n", reg_state[CTX_RING_TAIL]);
+ printf("reg_state[CTX_RING_TAIL+1]=0x%x\n", reg_state[CTX_RING_TAIL+1]);
+ /* Ring buffer start address is not known until the buffer is pinned.
+ * It is written to the context image in execlists_update_context()
+ */
+ printf("reg_state[CTX_RING_BUFFER_START]=0x%x(mmio base+0x38)\n", reg_state[CTX_RING_BUFFER_START]);
+ printf("reg_state[CTX_RING_BUFFER_START+1]=0x%x(mmio base+0x38+4)\n", reg_state[CTX_RING_BUFFER_START+1]);
+ printf("reg_state[CTX_RING_BUFFER_CONTROL]=0x%x(mmio base+0x3c)\n", reg_state[CTX_RING_BUFFER_CONTROL]);
+ printf("reg_state[CTX_RING_BUFFER_CONTROL+1]=0x%x\n", reg_state[CTX_RING_BUFFER_CONTROL+1]);
+ printf("reg_state[CTX_BB_HEAD_U]=0x%x(mmio base+0x168)\n", reg_state[CTX_BB_HEAD_U]);
+ printf("reg_state[CTX_BB_HEAD_U+1]=0x%x\n", reg_state[CTX_BB_HEAD_U+1]);
+ printf("reg_state[CTX_BB_HEAD_L]=0x%x(mmio base+0x140)\n", reg_state[CTX_BB_HEAD_L]);
+ printf("reg_state[CTX_BB_HEAD_L+1]=0x%x\n", reg_state[CTX_BB_HEAD_L+1]);
+ printf("reg_state[CTX_BB_STATE]=0x%x(mmio base+0x110)\n", reg_state[CTX_BB_STATE]);
+ printf("reg_state[CTX_BB_STATE+1]=0x%x\n", reg_state[CTX_BB_STATE+1]);
+ printf("reg_state[CTX_SECOND_BB_HEAD_U]=0x%x(mmio base+0x11c)\n", reg_state[CTX_SECOND_BB_HEAD_U]);
+ printf("reg_state[CTX_SECOND_BB_HEAD_U+1]=0x%x\n", reg_state[CTX_SECOND_BB_HEAD_U+1]);
+ printf("reg_state[CTX_SECOND_BB_HEAD_L]=0x%x(mmio base+0x114)\n", reg_state[CTX_SECOND_BB_HEAD_L]);
+ printf("reg_state[CTX_SECOND_BB_HEAD_L+1]=0x%x\n", reg_state[CTX_SECOND_BB_HEAD_L+1]);
+ printf("reg_state[CTX_SECOND_BB_STATE]=0x%x(mmio base+0x118)\n", reg_state[CTX_SECOND_BB_STATE]);
+ printf("reg_state[CTX_SECOND_BB_STATE+1]=0x%x\n", reg_state[CTX_SECOND_BB_STATE+1]);
+
+ if (id == RCS) {
+ printf("reg_state[CTX_BB_PER_CTX_PTR]=0x%x\n", reg_state[CTX_BB_PER_CTX_PTR]);
+ printf("reg_state[CTX_BB_PER_CTX_PTR+1]=0x%x\n", reg_state[CTX_BB_PER_CTX_PTR+1]);
+ printf("reg_state[CTX_RCS_INDIRECT_CTX]=0x%x\n", reg_state[CTX_RCS_INDIRECT_CTX]);
+ printf("reg_state[CTX_RCS_INDIRECT_CTX+1]=0x%x\n", reg_state[CTX_RCS_INDIRECT_CTX+1]);
+ printf("reg_state[CTX_RCS_INDIRECT_CTX_OFFSET]=0x%x\n", reg_state[CTX_RCS_INDIRECT_CTX_OFFSET]);
+ printf("reg_state[CTX_RCS_INDIRECT_CTX_OFFSET+1]=0x%x\n", reg_state[CTX_RCS_INDIRECT_CTX_OFFSET+1]);
+ }
+
+ printf("reg_state[CTX_LRI_HEADER_1]=0x%x\n", reg_state[CTX_LRI_HEADER_1]);
+ printf("reg_state[CTX_LRI_HEADER_1]=0x%x\n", reg_state[CTX_LRI_HEADER_1]);
+ printf("reg_state[CTX_CTX_TIMESTAMP]=0x%x\n", reg_state[CTX_CTX_TIMESTAMP]);
+ printf("reg_state[CTX_CTX_TIMESTAMP+1]=0x%x\n", reg_state[CTX_CTX_TIMESTAMP+1]);
+ printf("reg_state[CTX_PDP3_UDW]=0x%x(mmio base+0x270+(3*8)+4)\n", reg_state[CTX_PDP3_UDW]);
+ printf("reg_state[CTX_PDP3_LDW]=0x%x(mmio base+0x270+(3*8))\n", reg_state[CTX_PDP3_LDW]);
+ printf("reg_state[CTX_PDP2_UDW]=0x%x(mmio base+0x270+(2*8)+4)\n", reg_state[CTX_PDP2_UDW]);
+ printf("reg_state[CTX_PDP2_LDW]=0x%x(mmio base+0x270+(3*8))\n", reg_state[CTX_PDP2_LDW]);
+ printf("reg_state[CTX_PDP1_UDW]=0x%x(mmio base+0x270+(1*8)+4)\n", reg_state[CTX_PDP1_UDW]);
+ printf("reg_state[CTX_PDP1_LDW]=0x%x(mmio base+0x270+(3*8))\n", reg_state[CTX_PDP1_LDW]);
+ printf("reg_state[CTX_PDP0_UDW]=0x%x(mmio base+0x270+(0*8)+4)\n", reg_state[CTX_PDP0_UDW]);
+ printf("reg_state[CTX_PDP0_LDW]=0x%x(mmio base+0x270+(3*8))\n", reg_state[CTX_PDP0_LDW]);
+ printf("reg_state[CTX_PDP3_UDW+1]=0x%x\n", reg_state[CTX_PDP3_UDW+1]);
+ printf("reg_state[CTX_PDP3_LDW+1]=0x%x(pd 3 phyaddr)\n", reg_state[CTX_PDP3_LDW+1]);
+ printf("reg_state[CTX_PDP2_UDW+1]=0x%x\n", reg_state[CTX_PDP2_UDW+1]);
+ printf("reg_state[CTX_PDP2_LDW+1]=0x%x(pd 2 phyaddr)\n", reg_state[CTX_PDP2_LDW+1]);
+ printf("reg_state[CTX_PDP1_UDW+1]=0x%x\n", reg_state[CTX_PDP1_UDW+1]);
+ printf("reg_state[CTX_PDP1_LDW+1]=0x%x(pd 1 phyaddr)\n", reg_state[CTX_PDP1_LDW+1]);
+ printf("reg_state[CTX_PDP0_UDW+1]=0x%x\n", reg_state[CTX_PDP0_UDW+1]);
+ printf("reg_state[CTX_PDP0_LDW+1]=0x%x(pd 0 phyaddr)\n", reg_state[CTX_PDP0_LDW+1]);
+
+ if (id == RCS) {
+ printf("reg_state[CTX_LRI_HEADER_2]=0x%x\n", reg_state[CTX_LRI_HEADER_2]);
+ printf("reg_state[CTX_R_PWR_CLK_STATE]=0x%x\n", reg_state[CTX_R_PWR_CLK_STATE]);
+ printf("reg_state[CTX_R_PWR_CLK_STATE+1]=0x%x\n", reg_state[CTX_R_PWR_CLK_STATE+1]);
+ }
+
+ printf("*****************************************************************\n");
+ printf("reg_state[CTX_RING_BUFFER_START+1] = 0x%x (ring buffer gtt address)\n",
+ reg_state[CTX_RING_BUFFER_START+1]);
+ printf("reg_state[CTX_PDP0_LDW+1] = 0x%x (page directory physical address)\n",
+ reg_state[CTX_PDP0_LDW+1]);
+ //printf("Render Ring [%d..%d); Video Ring [%d..%d)\n",
+ // INREG(linear_mmio, 0x2034), INREG(linear_mmio, 0x2030),
+ // INREG(linear_mmio, 0x12034), INREG(linear_mmio, 0x12030));
+ printf("*****************************************************************\n");
+
+ return 0;
+}