igdbg: i915 kernel driver tool Content: 1. Introduction 2. Implementation overview 3. Command summary 4. Command details 5. Reference 1. Introduction igdbg is a standalone user mode tool that can run on a Linux system with proper configuration. The primary purpose of this tool is to learn and understand i915 GPU driver which is in linux kernel "drivers/gpu/drm/i915" folder. It might be also helpful for developers to check or dump GPU states. The tool must be invoked by root. Usage: igdbg [ -v -d -c ] is the device that the tool uses to access GPU resources, by default it is /dev/mem is the command to be executed. Without it, the tool enters into interactive mode so that user can type a command later The tool till now is only tested on a GEN8 based Android device. It only adds a few device IDs in the support list, thus it might not work or might get different result on other devices. 2. Implementation overview The tool opens /dev/mem to "mmap" device memory. The memory includes GPU mmio space, gtt space and frame buffer. It is the way that the tool dumps registers/gtt and frame buffer content. There are some GPU resources that are in system memory including PPGTT tables, ring buffers, etc. For them, the tool uses "read/write" to access them. There are two Linux kernel configurations that may forbid "mmap" and "read/write" on /dev/mem: CONFIG_X86_PAT and CONFIG_STRICT_DEVMEM. PAT can be flagged on or off by "nopat" kernel boot parameter. Check bellow table if there are some problems to run the tool: CONFIG_STRICT_DEVMEM | Y | N ---------------------+---------------------+------------------------- Allow "mmap" | Usually it is Yes, but may get issue on some on device memory? | systems. Try to add "nopat" if it is the case ---------------------+---------------------+------------------------- Allow "read/write" | No | Yes on system RAM? | | ---------------------+---------------------+------------------------- Sub-folder linux/imem.c is a kernel module of char device. It derives from linux kernel "driver/char/mem.c". The difference is that it removes the restrictions of CONFIG_STRICT_DEVMEM. When load it into kernel, it registers a char device with major number 999. The tool can use this char device instead of /dev/mem to "mmap" and "read/write" by command line parameter "-d ". It is for the people that don't want to rebuild the kernel to disable STRICT_DEVMEM configuration. 3. Command summary As mentioned above, "mmap" is used to access mmio/gtt space and frame buffer content, and "read/write" is used to access the resources in system memory. From this perspective, there are two types of commands: A. Commands that are supported by "mmap" /dev/mem Command | Introduction -----------+--------------------------------------------------- regread | Read a register -----------+--------------------------------------------------- regwrite | Write a register -----------+--------------------------------------------------- dumpgtt | Dump GGTT mappings -----------+--------------------------------------------------- stolen | Dump stolen memory mappings -----------+--------------------------------------------------- dumpfb | Dump frame buffer -----------+--------------------------------------------------- dumpfbl | Dump frame buffer with a fence register, | thus it is linear mode -----------+--------------------------------------------------- fillfb | Fill frame buffer -----------+--------------------------------------------------- fillfbl | Fill frame buffer with a fence register, | thus it is linear mode -----------+--------------------------------------------------- irq | Sample IRQ status -----------+--------------------------------------------------- cstatus | Sample execlist context status -----------+--------------------------------------------------- B. Commands that are supported by "read/write" /dev/mem Command | Introduction -----------+--------------------------------------------------- dumpstat | Dump context stat -----------+--------------------------------------------------- dumppgtt | Dump PPGTT mappins -----------+--------------------------------------------------- dumpring | Dump ring buffer and the chained batch buffer -----------+--------------------------------------------------- 4. Command details 4.1 regread/regwrite regread regwrite 4.2 dumpgtt GTT table usually shares the PCI BAR0 with mmio space. It locates at the half bottom of the space. The real memory behind it actually resides in system RAM whose address can be read out from a register dumpgtt Example: igdbg -c "dumpgtt 2<<20 40<<10" >>>>>> GTT size = 4096K (Can map 2048M memory), location at 0x7c900000 (1993M) -----------------------------002M FB------------------------------ FB:0x0200000|002M+0000K|GTT offset:0x01000(entry 0x00200): 007cf00001 FB:0x0201000|002M+0004K|GTT offset:0x01008(entry 0x00201): 007cf01001 FB:0x0202000|002M+0008K|GTT offset:0x01010(entry 0x00202): 007cf02001 FB:0x0203000|002M+0012K|GTT offset:0x01018(entry 0x00203): 007cf03001 FB:0x0204000|002M+0016K|GTT offset:0x01020(entry 0x00204): 007cf04001 FB:0x0205000|002M+0020K|GTT offset:0x01028(entry 0x00205): 007cf05001 FB:0x0206000|002M+0024K|GTT offset:0x01030(entry 0x00206): 007cf06001 FB:0x0207000|002M+0028K|GTT offset:0x01038(entry 0x00207): 007cf07001 FB:0x0208000|002M+0032K|GTT offset:0x01040(entry 0x00208): 007cf08001 FB:0x0209000|002M+0036K|GTT offset:0x01048(entry 0x00209): 007cf09001 <<<<<< It dumps the mapping of 40 pages (40K) starting from 2M of frame buffer. 4.3 stolen Dump the mysterious stolen memory mappings in GTT stolen Example: igdbg -c "stolen" >>>>>> Stolen size =32768K (physical base=[0x7cd00000~0x7ed00000](1997M~2029M)) -----------------------------000M+0000K FB------------------------------ FB:0x0000000|000M+0000K|GTT offset:0x00000(entry 0x00000): 007cd00001 FB:0x0001000|000M+0004K|GTT offset:0x00008(entry 0x00001): 007cd01001 FB:0x0002000|000M+0008K|GTT offset:0x00010(entry 0x00002): 007cd02001 ...... -----------------------------022M+0088K FB------------------------------ FB:0x1616000|022M+0088K|GTT offset:0x0b0b0(entry 0x01616): 007d64c01b FB:0x1617000|022M+0092K|GTT offset:0x0b0b8(entry 0x01617): 007d64d01b ...... -----------------------------092M+0512K FB------------------------------ FB:0x5c80000|092M+0512K|GTT offset:0x2e400(entry 0x05c80): 007d68e01b FB:0x5c81000|092M+0516K|GTT offset:0x2e408(entry 0x05c81): 007d68f01b -----------------------------160M+0492K FB------------------------------ FB:0xa07b000|160M+0492K|GTT offset:0x503d8(entry 0x0a07b): 007d71601b FB:0xa07c000|160M+0496K|GTT offset:0x503e0(entry 0x0a07c): 007d71701b ...... <<<<<< 4.4 onscreen Display onscreen frame buffer information. It might be from DSPASURF or DSPBSURF registers (Display Surface Base Address Register) onscreen Example: igdbg -c "onscreen" >>>>>> Plane A is enabled DSPCNTR:value=0xb8000400(X-tiled(512x8), format 0xe(e:RGBX, f:RGBA)) 31 28 27 24 23 20 19 16 15 12 11 08 07 04 03 00 |1011| |1000| |0000| |0000| |0000| |0100| |0000| |0000| 0xb 0x8 0x0 0x0 0x0 0x4 0x0 0x0 Offset of current display:0xac8f000(172M+572K), GTT offset at 353400 <<<<<< From above, on-screen frame buffer is X-tiled, and the address is at 0xac8f000 4.5 dumpfb/fillfb Access frame buffer through PCI BAR2 which is the "window" of the backing real system RAM mapped by GTT. Another term of this "window" is aperture. dumpfb fillfb Example: Firstly get the onscreen frame buffer address: igdbg -c "onscree" >>>>>> Offset of current display:0xac8f000(172M+572K), GTT offset 353400 with 5 entries: <<<<<< Then dump it with an offset 480 (start from 0x0ac8f1e0): igdbg -c "dumpfb 0xac8f000+480 64" >>>>>> Dump frame buffer from offset 0xac8f1e0,size 128 0x0ac8f1e0: 0x65 0x71 0x16 0xff 0x64 0x70 0x14 0xff 0x0ac8f1e8: 0x63 0x6f 0x13 0xff 0x62 0x6e 0x11 0xff 0x0ac8f1f0: 0x62 0x6d 0x10 0xff 0x61 0x6e 0x10 0xff 0x0ac8f1f8: 0x62 0x6f 0x11 0xff 0x62 0x70 0x12 0xff 0x0ac8f200: 0x6d 0x74 0x28 0xff 0x6d 0x74 0x34 0xff 0x0ac8f208: 0x6e 0x74 0x41 0xff 0x6e 0x75 0x46 0xff 0x0ac8f210: 0x6e 0x75 0x44 0xff 0x6d 0x75 0x41 0xff 0x0ac8f218: 0x6c 0x75 0x42 0xff 0x6d 0x75 0x44 0xff <<<<<< 4.6 dumpfbl/fillfbl Same with above commands, but it will force a "fence" register for the accessed range, thus it will get linear data if frame buffer is tiled format. It is a hack way for the understanding of aperture/fence and tile/linear. dumpfbl fillfbl Example: Dump the same onscreen buffer as above, but use dumpfbl igdbg -c "dumpfbl 0xac8f000+480 64" >>>>>> Force FENCE0 for linear access with stride 5120 Dump frame buffer from offset 0xac8f1e0,size 128 0x0ac8f1e0: 0x65 0x71 0x16 0xff 0x64 0x70 0x14 0xff 0x0ac8f1e8: 0x63 0x6f 0x13 0xff 0x62 0x6e 0x11 0xff 0x0ac8f1f0: 0x62 0x6d 0x10 0xff 0x61 0x6e 0x10 0xff 0x0ac8f1f8: 0x62 0x6f 0x11 0xff 0x62 0x70 0x12 0xff 0x0ac8f200: 0x61 0x71 0x12 0xff 0x60 0x70 0x13 0xff 0x0ac8f208: 0x5f 0x70 0x12 0xff 0x5e 0x70 0x11 0xff 0x0ac8f210: 0x5f 0x70 0x10 0xff 0x5f 0x70 0x10 0xff 0x0ac8f218: 0x5f 0x70 0x11 0xff 0x5e 0x71 0x11 0xff Restore FENCE0 <<<<<< Since the onscreen frame buffer is X-tile that the sub-tile block is 512x8, the first 512 bytes from "dumpfb" and "dumpfbl" is same, but then the following bytes will be different (start from 0x0ac8f200). Similarly, use command: igdbg -c "fillfb 0xac8f000 4096 0xff" igdbg -c "fillfbl 0xac8f000 4096 0xff" They will visually display the difference on screen. The first one will display a 512x8 grey block on screen, and the second will display a grey line 4.7 irq Sample IIR registers (interrupt identify register) to print a rough overview of IRQs. Also the sequence number associated with the command is printed out. It is read out from an offset of Hardware Status Page. The command is for the purpose to understand the engines that are used for a task (e.g. video encode) irq Example: Run video encoding and igdbg at the same time va_encode -r 30 igdbg -c "irq 500" >>>>>> Sample IRQ for 500 seconds....It is not accurate, just rough view Render HWS_PGA=0x008cd000, Video HWS_PGA=0x00904000 T1253.841:iir=0x00000100 VCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010b3) T1262.051:iir=0x00000001 VCS:GT_USER_INTERRUPT (seqno=0x000010b7) T1295.786:iir=0x00000100 VCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010bb) T1360.381:iir=0x00000100 RCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010c0) T1361.176:iir=0x00000001 VCS:GT_USER_INTERRUPT (seqno=0x000010c2) T1361.260:iir=0x00000100 VCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010c3) T1392.961:iir=0x00000100 RCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010c1) T1394.567:iir=0x00000100 VCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010c3) T1394.812:iir=0x00000100 VCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010c7) T1426.393:iir=0x00000001 RCS:GT_USER_INTERRUPT (seqno=0x000010c8) T1427.856:iir=0x00000100 VCS:GT_CONTEXT_SWITCH_INTERRUPT (seqno=0x000010cb) ...... <<<<<< 4.8 dumpstat On GEN8 and above, each context associates a state buffer for context save and restore. dumpstat State bo can get from /sys/kernel/debug/dri/0/i915_context_status Example: Firstly run a video encoding, and get the state buffer address va_encode -i #press one key to encode one frame cat /sys/kernel/debug/dri/0/i915_context_status >>>>>> HW context ir render ring: ffff880024c4f5c0: g 80KiB 01 01 0 0 0 uncached dirty (pinned x 0) (ggtt offset: 0c347000, size: 00014000) (ringbuffer, space: 128448, head: 0, tail: 384, last head: 352) bsd ring: ffff88003f03d040: g 8KiB 01 01 0 0 0 uncached dirty (pinned x 0) (ggtt offset: 0c37c000, size: 00002000) (ringbuffer, space: 128640, head: 0, tail: 224, last head: 192) blitter ring: video enhancement ring: <<<<<< Then: igdbg -c "dumpstat 0x0c347000" >>>>>> reg_state[CTX_LRI_HEADER_0]=0x1100101b reg_state[CTX_CONTEXT_CONTROL]=0x2244 reg_state[CTX_CONTEXT_CONTROL+1]=0xffff0008 reg_state[CTX_RING_HEAD]=0x2034(mmio base+0x34) reg_state[CTX_RING_HEAD+1]=0x178 reg_state[CTX_RING_TAIL]=0x2030(mmio base+0x30) reg_state[CTX_RING_TAIL+1]=0x178 ...... reg_state[CTX_RING_BUFFER_START+1] = 0xc35b000 (ring buffer gtt address) reg_state[CTX_PDP0_LDW+1] = 0x30d4000 (page directory physical address) <<<<<< From the dump, the ring buffer address of the context is 0xc35b000, and the ppgtt physical address is 0x30d4000 4.9 dumppgtt On GEN8 and above, each context has a per-process gtt, thus don't need to put all graphics memory mappings into global GTT dumppgtt Example: Firstly, same above, get the state buffer address of a context, and then igdbg -c "dumpppgtt 0x0c347000" >>>>>> pde[0000]=0x05567003 (ppgtt offset range:0x00000000~0x00200000(0000M~0002M) pte[000] = 0x418bb01b(page no.=268475, ppgtt addr 0x0(0000M+0000K)) pte[001] = 0x418bc01b(page no.=268476, ppgtt addr 0x1000(0000M+0004K)) pte[002] = 0x418bd01b(page no.=268477, ppgtt addr 0x2000(0000M+0008K)) pte[003] = 0x418be01b(page no.=268478, ppgtt addr 0x3000(0000M+0012K)) ...... pde[0001]=0x720b7003 (ppgtt offset range:0x00200000~0x00400000(0002M~0004M) pte[000] = 0x274fa01b(page no.=161018, ppgtt addr 0x200000(0002M+0000K)) pte[001] = 0x274fb01b(page no.=161019, ppgtt addr 0x201000(0002M+0004K)) pte[002] = 0x275ec01b(page no.=161260, ppgtt addr 0x202000(0002M+0008K)) pte[003] = 0x275ed01b(page no.=161261, ppgtt addr 0x203000(0002M+0012K)) ...... <<<<<< 4.10 dumpring On GEN8 and above, each context has a logical ring. "dumpring" can print the instructions in the ring and the chained batch buffers: dumppgtt Example: Firstly, same above, get the state buffer address of a context and the head/tail of the ring, and then: igdbg -c "dumpring 0x0c347000 0 384" >>>>>> 0x0000:0x7a000004 (PIPE_CONTROL) 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 |011| |11| |010| |000| |00000| |0000| |0000| |0000| |0100| 0x0004:0x00101001 (data) 0x0008:0x008cb080 (data) 0x000c:0x00000000 (data) 0x0010:0x00000000 (data) 0x0014:0x00000000 (data) 0x0018:0x11000005 (MI_LOAD_REGISTER_IMM) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |100010| |000| |0000| |0000| |0000| |0000| |0101| 0x001c:0x0000e4f0 (data) 0x0020:0x81208120 (data) 0x0024:0x00007300 (data) 0x0028:0x08100810 (data) 0x002c:0x00007004 (data) 0x0030:0x00400040 (data) 0x0034:0x00000000 (MI_NOOP) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |000000| |000| |0000| |0000| |0000| |0000| |0000| 0x0038:0x7a000004 (PIPE_CONTROL) 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 |011| |11| |010| |000| |00000| |0000| |0000| |0000| |0100| 0x003c:0x00101001 (data) 0x0040:0x008cb080 (data) 0x0044:0x00000000 (data) 0x0048:0x00000000 (data) 0x004c:0x00000000 (data) 0x0050:0x18800001 (MI_BATCH_BUFFER_START)(BB in GGTT) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |110001| |000| |0000| |0000| |0000| |0000| |0001| 0x0054:0x08ece000 (data) 0x0058:0x00000000 (data) 0x005c:0x00000000 (MI_NOOP) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |000000| |000| |0000| |0000| |0000| |0000| |0000| 0x0060:0x10400002 (MI_STORE_DATA_IMM) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |100000| |100| |0000| |0000| |0000| |0000| |0010| 0x0064:0x008cd080 (data) 0x0068:0x00000000 (data) 0x006c:0xfffff5ba (data) 0x0070:0x01000000 (MI_USER_INTERRUPT) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |000010| |000| |0000| |0000| |0000| |0000| |0000| 0x0074:0x00000000 (MI_NOOP) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |000000| |000| |0000| |0000| |0000| |0000| |0000| 0x0078:0x00000000 (MI_NOOP) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |000000| |000| |0000| |0000| |0000| |0000| |0000| 0x007c:0x00000000 (MI_NOOP) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |000000| |000| |0000| |0000| |0000| |0000| |0000| 0x0080:0x7a000004 (PIPE_CONTROL) 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 |011| |11| |010| |000| |00000| |0000| |0000| |0000| |0100| 0x0084:0x01144c1c (data) 0x0088:0x008cb080 (data) 0x008c:0x00000000 (data) 0x0090:0x00000000 (data) 0x0094:0x00000000 (data) 0x0098:0x10800001 (MI_STORE_DATA_INDEX) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |100001| |000| |0000| |0000| |0000| |0000| |0001| 0x009c:0x00000084 (data) 0x00a0:0xfffff5bb (data) 0x00a4:0x00000000 (MI_NOOP) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |000000| |000| |0000| |0000| |0000| |0000| |0000| 0x00a8:0x18800101 (MI_BATCH_BUFFER_START)(BB in PPGTT) 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 |000| |110001| |000| |0000| |0000| |0001| |0000| |0001| 0x00ac:0x0032f000 (data) 0x00b0:0x00000000 (data) BB-L1: >>>>>>>>>>>>BB @ 0x0032f000 Begin>>>>>>>>>>>>> BB-L1: 0x0000:0x7a000004 (PIPE_CONTROL) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |11| |010| |000| |00000| |0000| |0000| |0000| |0100| BB-L1: 0x0004:0x011018bc (data) BB-L1: 0x0008:0x00000000 (data) BB-L1: 0x000c:0x00000000 (data) BB-L1: 0x0010:0x00000000 (data) BB-L1: 0x0014:0x00000000 (data) BB-L1: 0x0018:0x7a000004 (PIPE_CONTROL) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |11| |010| |000| |00000| |0000| |0000| |0000| |0100| BB-L1: 0x001c:0x0110189c (data) BB-L1: 0x0020:0x00000000 (data) BB-L1: 0x0024:0x00000000 (data) BB-L1: 0x0028:0x00000000 (data) BB-L1: 0x002c:0x00000000 (data) BB-L1: 0x0030:0x7a000004 (PIPE_CONTROL) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |11| |010| |000| |00000| |0000| |0000| |0000| |0100| BB-L1: 0x0034:0x00104080 (data) BB-L1: 0x0038:0x00000068 (data) BB-L1: 0x003c:0x00000000 (data) BB-L1: 0x0040:0x00000001 (data) BB-L1: 0x0044:0x00000000 (data) BB-L1: 0x0048:0x11000001 (MI_LOAD_REGISTER_IMM) BB-L1: 31 29 28 23 22 20 19 16 15 12 11 08 07 04 03 00 BB-L1: |000| |100010| |000| |0000| |0000| |0000| |0000| |0001| BB-L1: 0x004c:0x00007034 (data) BB-L1: 0x0050:0x80000040 (data) BB-L1: 0x0054:0x69040001 (PIPELINE_SELECT) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |01| |001| |000| |00100| |0000| |0000| |0000| |0001| BB-L1: 0x0058:0x6101000e (STATE_BASE_ADDRESS) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |00| |001| |000| |00001| |0000| |0000| |0000| |1110| BB-L1: 0x005c:0x00000000 (data) BB-L1: 0x0060:0x00000000 (data) BB-L1: 0x0064:0x00000000 (data) BB-L1: 0x0068:0x00334001 (data) BB-L1: 0x006c:0x00000000 (data) BB-L1: 0x0070:0x0004b001 (data) BB-L1: 0x0074:0x00000000 (data) BB-L1: 0x0078:0x00000000 (data) BB-L1: 0x007c:0x00000000 (data) BB-L1: 0x0080:0x0004d001 (data) BB-L1: 0x0084:0x00000000 (data) BB-L1: 0x0088:0x00000000 (data) BB-L1: 0x008c:0x00002001 (data) BB-L1: 0x0090:0x00000000 (data) BB-L1: 0x0094:0x002c7001 (data) BB-L1: 0x0098:0x70000007 (MEDIA_VFE_STATE) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |10| |000| |000| |00000| |0000| |0000| |0000| |0111| BB-L1: 0x009c:0x00000000 (data) BB-L1: 0x00a0:0x00000000 (data) BB-L1: 0x00a4:0x006f4000 (data) BB-L1: 0x00a8:0x00000000 (data) BB-L1: 0x00ac:0x00010004 (data) BB-L1: 0x00b0:0xc00000ff (data) BB-L1: 0x00b4:0xfff1f00f (data) BB-L1: 0x00b8:0xefe1e01f (data) BB-L1: 0x00bc:0x70010002 (MEDIA_CURBE_LOAD) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |10| |000| |000| |00001| |0000| |0000| |0000| |0010| BB-L1: 0x00c0:0x00000000 (data) BB-L1: 0x00c4:0x00000080 (data) BB-L1: 0x00c8:0x00001f80 (data) BB-L1: 0x00cc:0x70020002 (MEDIA_INTERFACE_DESCRIPTOR_LOAD) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |10| |000| |000| |00010| |0000| |0000| |0000| |0010| BB-L1: 0x00d0:0x00000000 (data) BB-L1: 0x00d4:0x00000040 (data) BB-L1: 0x00d8:0x00001f40 (data) BB-L1: 0x00dc:0x71000005 (MEDIA_OBJECT) BB-L1: 31 29 28 27 26 24 23 21 20 16 15 12 11 08 07 04 03 00 BB-L1: |011| |10| |001| |000| |00000| |0000| |0000| |0000| |0101| BB-L1: 0x00e0:0x00000000 (data) BB-L1: 0x00e4:0x00000000 (data) BB-L1: 0x00e8:0x00000000 (data) BB-L1: 0x00ec:0x00000000 (data) BB-L1: 0x00f0:0x00000000 (data) BB-L1: 0x00f4:0x00000000 (data) ...... <<<<<< The driver may use two engines (thus two rings) for one task, e.g. in above example, the encoding uses "render ring" and "bsd ring", and driver may use the same batch buffer for the two rings. If the dump is at frame boundary, the instructions in the batch buffer of render ring may be overwritten by the instructions of bsd, thus they may be lost and can not dump correctly. 5. Reference A. Linux graphics document: https://01.org/linuxgraphics/documentation B. Intel video driver: http://cgit.freedesktop.org/vaapi/intel-driver/ C. i915 kernel driver: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/