diff options
author | Austin Yuan <shengquan.yuan@intel.com> | 2015-05-20 13:26:26 +0800 |
---|---|---|
committer | Austin Yuan <shengquan.yuan@intel.com> | 2015-05-20 13:26:26 +0800 |
commit | 23bd23703b9e23491935d4657ad9472305c10409 (patch) | |
tree | c96f5623fea47cde99e7e803087bb43c59dd6347 /reg.c |
Signed-off-by: Austin Yuan <shengquan.yuan@intel.com>
Diffstat (limited to 'reg.c')
-rw-r--r-- | reg.c | 446 |
1 files changed, 446 insertions, 0 deletions
@@ -0,0 +1,446 @@ +/* + * 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/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdint.h> +#include <errno.h> +#include <sys/time.h> + +#include "i915_reg.h" +#include "main.h" + +int process_regread(char *cmdhdr,unsigned int reg) +{ + uint32_t value=INREG(linear_mmio,reg); + + printf("read register 0x%x,value is 0x%08x\n",reg,value); + + print_bin_fmt(value,15); + + return 0; +} + +int process_regwrite(char *cmdhdr,unsigned int reg, unsigned int value) +{ + printf("Write register 0x%x with value 0x%x\n",reg,value); + OUTREG(linear_mmio,reg,value); + + return 0; +} + + +static uint64_t now_us() +{ + struct timeval tv; + if (gettimeofday(&tv, NULL)) + return 0; + return tv.tv_usec + tv.tv_sec*1000*1000; +} + +static int current_render(uint32_t delta_ms, uint32_t delta_us); +static int current_video(uint32_t delta_ms, uint32_t delta_us); + +#define I915_GEM_HWS_INDEX 0x20 + + +/* Linux kernle file i915_irq.c */ +#define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which))) +#define GEN8_BCS_IRQ_SHIFT 16 +#define GEN8_RCS_IRQ_SHIFT 0 +#define GEN8_VCS2_IRQ_SHIFT 16 +#define GEN8_VCS1_IRQ_SHIFT 0 +#define GEN8_VECS_IRQ_SHIFT 0 +#define GEN8_OACS_IRQ_SHIFT 19 +int process_irq(char *cmdhdr,unsigned int seconds) +{ + uint64_t start = now_us(); + uint64_t expected_end = start + 1000 * 1000 * seconds; + unsigned int render_iir=0, video_iir=0; + uint32_t *render_seqno, *video_seqno, last_render_seqno=0, last_video_seqno=0; + uint32_t *blit_seqno, *video2_seqno, last_blit_seqno=0, last_video2_seqno=0; + uint32_t render_hws, video_hws, blit_hws, video2_hws; + + if (is_gen7) { + printf("IRQ sample tbd on GEN7\n"); + return 0; + } + render_hws = INREG(linear_mmio, 0x2080); + video_hws = INREG(linear_mmio, 0x12080); + blit_hws = INREG(linear_mmio, 0x1a080); + video2_hws = INREG(linear_mmio, 0x1c080); + + printf("Sample IRQ for %d seconds....It is not accurate, just rough view\n", seconds); + printf("Render HWS_PGA=0x%08x, Video HWS_PGA=0x%08x\n", render_hws, video_hws); + + render_seqno = (uint32_t *)((unsigned char *)linear_fb + render_hws) + I915_GEM_HWS_INDEX; + video_seqno = (uint32_t *)((unsigned char *)linear_fb + video_hws) + I915_GEM_HWS_INDEX; + blit_seqno = (uint32_t *)((unsigned char *)linear_fb + blit_hws) + I915_GEM_HWS_INDEX; + video2_seqno = (uint32_t *)((unsigned char *)linear_fb + video2_hws) + I915_GEM_HWS_INDEX; + + while (1) { + uint64_t now = now_us(); + int64_t test = now - expected_end; + + //printf("now=%u, expected end=%u, test = %d\n", now, expected_end, test); + if (test > 0) + break; + + uint64_t delta = now - start; + uint32_t delta_ms = (uint32_t)(delta/1000); + uint32_t delta_us = (uint32_t)(delta%1000); + + uint32_t tmp = INREG(linear_mmio, GEN8_GT_IIR(0)); + uint32_t tmp1 = INREG(linear_mmio, GEN8_GT_IIR(1)); + + while (render_iir != tmp) { + uint32_t rcs = tmp >> GEN8_RCS_IRQ_SHIFT; + uint32_t bcs = tmp >> GEN8_BCS_IRQ_SHIFT; + int has_irq; + + render_iir = tmp; + + has_irq = (rcs|bcs) & (GT_RENDER_USER_INTERRUPT|GT_CONTEXT_SWITCH_INTERRUPT); + if (has_irq) { + printf("T%d.%03d:iir=0x%08x\n", delta_ms, delta_us, tmp); + //print_bin_fmt(tmp, 8); + } else + break; + + if ((rcs & GT_RENDER_USER_INTERRUPT) + && (last_render_seqno != *render_seqno)) { + printf("\tRCS:GT_USER_INTERRUPT (seqno=0x%08x)\n", *render_seqno); + last_render_seqno = *render_seqno; + } + + if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) { + printf("\tRCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *render_seqno); + if (verbose) + current_render(delta_ms, delta_us); + } + + if ((bcs & GT_RENDER_USER_INTERRUPT) + && (last_blit_seqno != *blit_seqno)) { + last_blit_seqno = *blit_seqno; + printf("\tBCS:GT_USER_INTERRUPT (seqno=0x%08x)\n", *blit_seqno); + } + + if (bcs & GT_CONTEXT_SWITCH_INTERRUPT) + printf("\tBCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *render_seqno); + + + break; + } + + while (video_iir != tmp1) { + /* video engine */ + uint32_t vcs = tmp1 >> GEN8_VCS1_IRQ_SHIFT; + uint32_t vcs2 = tmp1 >> GEN8_VCS2_IRQ_SHIFT; + int has_irq; + + video_iir = tmp1; + + has_irq = (vcs|vcs2) & (GT_RENDER_USER_INTERRUPT|GT_CONTEXT_SWITCH_INTERRUPT); + if (has_irq) { + printf("T%d.%03d:iir=0x%08x\n", delta_ms, delta_us, tmp1); + //print_bin_fmt(tmp, 8); + } else + break; + + if ((vcs & GT_RENDER_USER_INTERRUPT) + && (last_video_seqno != *video_seqno)) { + last_video_seqno = *video_seqno; + printf("\tVCS:GT_USER_INTERRUPT (seqno=0x%08x)\n", *video_seqno); + } + + if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) { + printf("\tVCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *video_seqno); + if (verbose) + current_video(delta_ms, delta_us); + } + + if ((vcs2 & GT_RENDER_USER_INTERRUPT) + && (last_video2_seqno != *video2_seqno)) { + last_video2_seqno = *video2_seqno; + printf("\tVCS2:GT_USER_INTERRUPT (seqno=0x%08x)\n", *video2_seqno); + } + + if (vcs2 & GT_CONTEXT_SWITCH_INTERRUPT) + printf("\tVCS2:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x%08x)\n", *video_seqno); + + break; + } + } + + return 0; +} + + +static void print_estatus(uint32_t estatus) +{ + uint32_t tmp; + + printf("\tExeclist 0 Active = %d\n", (estatus>>18) & 0x1); + printf("\tExeclist 1 Active = %d\n", (estatus>>18) & 0x1); + + tmp = (estatus>>14) & 0x2; + printf("\tCurrent Active Element Status = %d", tmp); + if (tmp == 0) + printf("(No Active Element being executed)\n"); + else if (tmp == 1) + printf("(Element0 of current execlist being executed)\n"); + else if (tmp == 2) + printf("(Element1 of current execlist being executed)\n"); + + tmp = (estatus>>5) & 0x1ff; + printf("\tLast Context Switch Reason = 0x%x\n", tmp); + if (tmp & 1) + printf("\t\tIDLE to ACTIVE\n"); + if (tmp & 2) + printf("\t\tPreempted\n"); + if (tmp & 4) + printf("\t\tElement Switch: from element0 to element1 in the current execlist\n"); + if (tmp & 8) + printf("\t\tACTIVE to IDLE\n"); + if (tmp & 0x10) + printf("\t\tContext Complete:Element is completely processed\n"); + if (tmp & 0x1e0) + printf("\t\tWait on display\n"); + + printf("\tExeclist 0 Valid = %d\n", (estatus>>4) & 0x1); + printf("\tExeclist 1 Valid = %d\n", (estatus>>3) & 0x1); +} + +int process_estatus(char *cmdhdr,unsigned int seconds) +{ + uint64_t start = now_us(); + uint64_t expected_end = start + 1000 * 1000 * seconds; + uint32_t previous_r_eid = 0, previous_r_estatus = 0; + uint32_t previous_v_eid = 0, previous_v_estatus = 0; + + if (is_gen7) { + printf("Execlist is not supported on GEN7\n"); + return 0; + } + + printf("Sample ExecList Status for %d seconds....\n", seconds); + printf("It is not accurate, just for a rough view\n"); + + while (1) { + uint64_t now = now_us(); + int64_t test = now - expected_end; + + if (test > 0) + break; + + uint64_t delta = now - start; + uint32_t delta_ms = (uint32_t)(delta/1000); + uint32_t delta_us = (uint32_t)(delta%1000); + + uint32_t r_estatus = INREG(linear_mmio, 0x2234); + uint32_t r_eid = INREG(linear_mmio, 0x2238); + + uint32_t v_estatus = INREG(linear_mmio, 0x12234); + uint32_t v_eid = INREG(linear_mmio, 0x12238); + + if ((r_eid !=0) && (r_estatus != 0) + && ((previous_r_eid != r_eid) || (previous_r_estatus!= r_estatus))) { + printf("----------------------------------Render---------------------------------\n"); + printf("T%d.%03d:context id=0x%08x, status=0x%08x\n", + delta_ms, delta_us, r_eid, r_estatus); + + print_estatus(r_estatus); + + previous_r_eid = r_eid; + previous_r_estatus = r_estatus; + } + + if ((v_eid !=0) && (v_estatus != 0) + && ((previous_v_eid != v_eid) || (previous_v_estatus!= v_estatus))) { + + printf("----------------------------------Video---------------------------------\n"); + printf("T%d.%03d:context id=0x%08x, status=0x%08x\n", + delta_ms, delta_us, v_eid, v_estatus); + + print_estatus(v_estatus); + + previous_v_eid = v_eid; + previous_v_estatus = v_estatus; + } + } + + return 0; +} + +static void print_cstatus(uint32_t ldw, uint32_t udw) +{ + uint32_t tmp; + + printf("\tContext id=0x%08x\n", udw); + printf("\tContext status = 0x%08x\n", ldw); + + printf("\t\tWait display plane = 0x%04x\n", (ldw>>16) & 0xf); + printf("\t\tLite restore = %d\n", (ldw>>15)&1); + printf("\t\tWait display plane = 0x%03x\n", (ldw>>12) & 0x3); + printf("\t\tSemaphore wait mode = %d\n", (ldw>>11)&1); + + tmp = ldw & 0x1ff; + printf("\t\tLast Context Switch Reason = 0x%x\n", tmp); + if (tmp & 1) + printf("\t\t\tIDLE to ACTIVE\n"); + if (tmp & 2) + printf("\t\t\tPreempted\n"); + if (tmp & 4) + printf("\t\t\tElement Switch: from element0 to element1 in the current execlist\n"); + if (tmp & 8) + printf("\t\t\tACTIVE to IDLE\n"); + if (tmp & 0x10) + printf("\t\t\tContext Complete:Element is completely processed\n"); + if (tmp & 0x1e0) + printf("\t\t\tWait on display\n"); +} + +static struct context_status_t { + uint32_t udw; + uint32_t ldw; +} render[6], video[6]; +static int render_wp, video_wp, last_render_wp, last_video_wp; + +static int current_render(uint32_t delta_ms, uint32_t delta_us) +{ + uint32_t mmio_addr; + + render_wp = INREG(linear_mmio, 0x23a0) % 6; + if (render_wp == last_render_wp) + return 0; + + last_render_wp = render_wp; + + if (render_wp == 0) + render_wp = 5; + else + render_wp--; + + mmio_addr = 0x2370; + render[render_wp].ldw = INREG(linear_mmio, mmio_addr + render_wp*8); + render[render_wp].udw = INREG(linear_mmio, mmio_addr + render_wp*8 + 4); + + if (render[render_wp].udw != 0) { + printf("-----------------------------------------------\n"); + printf("T%d.%03d:Render Context Info(write ponter = %d)\n", delta_ms, delta_us, render_wp); + print_cstatus(render[render_wp].ldw, render[render_wp].udw); + printf("-----------------------------------------------\n"); + } + + return 0; +} + +static int current_video(uint32_t delta_ms, uint32_t delta_us) +{ + uint32_t mmio_addr; + + video_wp = INREG(linear_mmio, 0x123a0) % 6; + if (video_wp == last_video_wp) + return 0; + last_video_wp = video_wp; + + if (video_wp == 0) + video_wp = 5; + else + video_wp--; + + mmio_addr = 0x12370; + video[video_wp].ldw = INREG(linear_mmio, mmio_addr + video_wp*8); + video[video_wp].udw = INREG(linear_mmio, mmio_addr + video_wp*8 + 4); + if (video[video_wp].udw != 0) { + printf("-----------------------------------------------\n"); + printf("T%d.%03d:Video Context Info (write ponter = %d)\n", delta_ms, delta_us, video_wp); + print_cstatus(video[video_wp].ldw, video[video_wp].udw); + printf("-----------------------------------------------\n"); + } + + return 0; +} + +int process_cstatus(char *cmdhdr,unsigned int seconds) +{ + uint64_t start = now_us(); + uint64_t expected_end = start + 1000 * 1000 * seconds; + + if (is_gen7) { + printf("Execlist is not supported on GEN7\n"); + return 0; + } + + printf("Sample Context Status for %d seconds....\n", seconds); + printf("It is not accurate, just for rough view\n"); + + while (1) { + uint64_t now = now_us(); + int64_t test = now - expected_end; + + if (test > 0) + break; + + uint64_t delta = now - start; + uint32_t delta_ms = (uint32_t)(delta/1000); + uint32_t delta_us = (uint32_t)(delta%1000); + + current_render(delta_ms, delta_us); + current_video(delta_ms, delta_us); + } + + return 0; +} + +int process_msgread(char *cmdhdr,unsigned int port,unsigned int reg) +{ + unsigned int value = 0; + + //value = MSG_READ32(port, reg) + printf("read MSG port 0x%x, reg 0x%x, value=0x%08x\n",port, reg, value); + print_bin_fmt(value,15); + + return 0; +} + +int process_msgwrite(char *cmdhdr,unsigned int port, unsigned int reg, unsigned int new_value) +{ + unsigned int value = 0; + + //value = MSG_READ32(port, reg); + printf("Read MSG port 0x%x, reg 0x%x, value 0x%08x,try to write 0x%08x\n",port, reg, value, new_value); + + //MSG_WRITE32(port,reg,new_value); + + //value = MSG_READ32(port, reg); + printf("After write, MSG port 0x%x, reg 0x%x, new value=0x%08x\n",port, reg, value); + + return 0; +} |