Path: blob/21.2-virgl/src/intel/common/intel_batch_decoder.c
4547 views
/*1* Copyright © 2017 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "common/intel_decoder.h"24#include "intel_disasm.h"25#include "util/macros.h"26#include "main/macros.h" /* Needed for ROUND_DOWN_TO */2728#include <string.h>2930void31intel_batch_decode_ctx_init(struct intel_batch_decode_ctx *ctx,32const struct intel_device_info *devinfo,33FILE *fp, enum intel_batch_decode_flags flags,34const char *xml_path,35struct intel_batch_decode_bo (*get_bo)(void *,36bool,37uint64_t),38unsigned (*get_state_size)(void *, uint64_t,39uint64_t),40void *user_data)41{42memset(ctx, 0, sizeof(*ctx));4344ctx->devinfo = *devinfo;45ctx->get_bo = get_bo;46ctx->get_state_size = get_state_size;47ctx->user_data = user_data;48ctx->fp = fp;49ctx->flags = flags;50ctx->max_vbo_decoded_lines = -1; /* No limit! */51ctx->engine = I915_ENGINE_CLASS_RENDER;5253if (xml_path == NULL)54ctx->spec = intel_spec_load(devinfo);55else56ctx->spec = intel_spec_load_from_path(devinfo, xml_path);57}5859void60intel_batch_decode_ctx_finish(struct intel_batch_decode_ctx *ctx)61{62intel_spec_destroy(ctx->spec);63}6465#define CSI "\e["66#define RED_COLOR CSI "31m"67#define BLUE_HEADER CSI "0;44m" CSI "1;37m"68#define GREEN_HEADER CSI "1;42m"69#define NORMAL CSI "0m"7071static void72ctx_print_group(struct intel_batch_decode_ctx *ctx,73struct intel_group *group,74uint64_t address, const void *map)75{76intel_print_group(ctx->fp, group, address, map, 0,77(ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) != 0);78}7980static struct intel_batch_decode_bo81ctx_get_bo(struct intel_batch_decode_ctx *ctx, bool ppgtt, uint64_t addr)82{83if (intel_spec_get_gen(ctx->spec) >= intel_make_gen(8,0)) {84/* On Broadwell and above, we have 48-bit addresses which consume two85* dwords. Some packets require that these get stored in a "canonical86* form" which means that bit 47 is sign-extended through the upper87* bits. In order to correctly handle those aub dumps, we need to mask88* off the top 16 bits.89*/90addr &= (~0ull >> 16);91}9293struct intel_batch_decode_bo bo = ctx->get_bo(ctx->user_data, ppgtt, addr);9495if (intel_spec_get_gen(ctx->spec) >= intel_make_gen(8,0))96bo.addr &= (~0ull >> 16);9798/* We may actually have an offset into the bo */99if (bo.map != NULL) {100assert(bo.addr <= addr);101uint64_t offset = addr - bo.addr;102bo.map += offset;103bo.addr += offset;104bo.size -= offset;105}106107return bo;108}109110static int111update_count(struct intel_batch_decode_ctx *ctx,112uint64_t address,113uint64_t base_address,114unsigned element_dwords,115unsigned guess)116{117unsigned size = 0;118119if (ctx->get_state_size)120size = ctx->get_state_size(ctx->user_data, address, base_address);121122if (size > 0)123return size / (sizeof(uint32_t) * element_dwords);124125/* In the absence of any information, just guess arbitrarily. */126return guess;127}128129static void130ctx_disassemble_program(struct intel_batch_decode_ctx *ctx,131uint32_t ksp, const char *type)132{133uint64_t addr = ctx->instruction_base + ksp;134struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);135if (!bo.map)136return;137138fprintf(ctx->fp, "\nReferenced %s:\n", type);139intel_disassemble(&ctx->devinfo, bo.map, 0, ctx->fp);140}141142/* Heuristic to determine whether a uint32_t is probably actually a float143* (http://stackoverflow.com/a/2953466)144*/145146static bool147probably_float(uint32_t bits)148{149int exp = ((bits & 0x7f800000U) >> 23) - 127;150uint32_t mant = bits & 0x007fffff;151152/* +- 0.0 */153if (exp == -127 && mant == 0)154return true;155156/* +- 1 billionth to 1 billion */157if (-30 <= exp && exp <= 30)158return true;159160/* some value with only a few binary digits */161if ((mant & 0x0000ffff) == 0)162return true;163164return false;165}166167static void168ctx_print_buffer(struct intel_batch_decode_ctx *ctx,169struct intel_batch_decode_bo bo,170uint32_t read_length,171uint32_t pitch,172int max_lines)173{174const uint32_t *dw_end =175bo.map + ROUND_DOWN_TO(MIN2(bo.size, read_length), 4);176177int column_count = 0, pitch_col_count = 0, line_count = -1;178for (const uint32_t *dw = bo.map; dw < dw_end; dw++) {179if (pitch_col_count * 4 == pitch || column_count == 8) {180fprintf(ctx->fp, "\n");181column_count = 0;182if (pitch_col_count * 4 == pitch)183pitch_col_count = 0;184line_count++;185186if (max_lines >= 0 && line_count >= max_lines)187break;188}189fprintf(ctx->fp, column_count == 0 ? " " : " ");190191if ((ctx->flags & INTEL_BATCH_DECODE_FLOATS) && probably_float(*dw))192fprintf(ctx->fp, " %8.2f", *(float *) dw);193else194fprintf(ctx->fp, " 0x%08x", *dw);195196column_count++;197pitch_col_count++;198}199fprintf(ctx->fp, "\n");200}201202static struct intel_group *203intel_ctx_find_instruction(struct intel_batch_decode_ctx *ctx, const uint32_t *p)204{205return intel_spec_find_instruction(ctx->spec, ctx->engine, p);206}207208static void209handle_state_base_address(struct intel_batch_decode_ctx *ctx, const uint32_t *p)210{211struct intel_group *inst = intel_ctx_find_instruction(ctx, p);212213struct intel_field_iterator iter;214intel_field_iterator_init(&iter, inst, p, 0, false);215216uint64_t surface_base = 0, dynamic_base = 0, instruction_base = 0;217bool surface_modify = 0, dynamic_modify = 0, instruction_modify = 0;218219while (intel_field_iterator_next(&iter)) {220if (strcmp(iter.name, "Surface State Base Address") == 0) {221surface_base = iter.raw_value;222} else if (strcmp(iter.name, "Dynamic State Base Address") == 0) {223dynamic_base = iter.raw_value;224} else if (strcmp(iter.name, "Instruction Base Address") == 0) {225instruction_base = iter.raw_value;226} else if (strcmp(iter.name, "Surface State Base Address Modify Enable") == 0) {227surface_modify = iter.raw_value;228} else if (strcmp(iter.name, "Dynamic State Base Address Modify Enable") == 0) {229dynamic_modify = iter.raw_value;230} else if (strcmp(iter.name, "Instruction Base Address Modify Enable") == 0) {231instruction_modify = iter.raw_value;232}233}234235if (dynamic_modify)236ctx->dynamic_base = dynamic_base;237238if (surface_modify)239ctx->surface_base = surface_base;240241if (instruction_modify)242ctx->instruction_base = instruction_base;243}244245static void246handle_binding_table_pool_alloc(struct intel_batch_decode_ctx *ctx,247const uint32_t *p)248{249struct intel_group *inst = intel_ctx_find_instruction(ctx, p);250251struct intel_field_iterator iter;252intel_field_iterator_init(&iter, inst, p, 0, false);253254uint64_t bt_pool_base = 0;255bool bt_pool_enable = false;256257while (intel_field_iterator_next(&iter)) {258if (strcmp(iter.name, "Binding Table Pool Base Address") == 0) {259bt_pool_base = iter.raw_value;260} else if (strcmp(iter.name, "Binding Table Pool Enable") == 0) {261bt_pool_enable = iter.raw_value;262}263}264265if (bt_pool_enable) {266ctx->bt_pool_base = bt_pool_base;267} else {268ctx->bt_pool_base = 0;269}270}271272static void273dump_binding_table(struct intel_batch_decode_ctx *ctx,274uint32_t offset, int count)275{276struct intel_group *strct =277intel_spec_find_struct(ctx->spec, "RENDER_SURFACE_STATE");278if (strct == NULL) {279fprintf(ctx->fp, "did not find RENDER_SURFACE_STATE info\n");280return;281}282283/* When 256B binding tables are enabled, we have to shift the offset */284if (ctx->use_256B_binding_tables)285offset <<= 3;286287const uint64_t bt_pool_base = ctx->bt_pool_base ? ctx->bt_pool_base :288ctx->surface_base;289290if (count < 0) {291count = update_count(ctx, bt_pool_base + offset,292bt_pool_base, 1, 8);293}294295if (offset % 32 != 0 || offset >= UINT16_MAX) {296fprintf(ctx->fp, " invalid binding table pointer\n");297return;298}299300struct intel_batch_decode_bo bind_bo =301ctx_get_bo(ctx, true, bt_pool_base + offset);302303if (bind_bo.map == NULL) {304fprintf(ctx->fp, " binding table unavailable\n");305return;306}307308const uint32_t *pointers = bind_bo.map;309for (int i = 0; i < count; i++) {310if (pointers[i] == 0)311continue;312313uint64_t addr = ctx->surface_base + pointers[i];314struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);315uint32_t size = strct->dw_length * 4;316317if (pointers[i] % 32 != 0 ||318addr < bo.addr || addr + size >= bo.addr + bo.size) {319fprintf(ctx->fp, "pointer %u: 0x%08x <not valid>\n", i, pointers[i]);320continue;321}322323fprintf(ctx->fp, "pointer %u: 0x%08x\n", i, pointers[i]);324ctx_print_group(ctx, strct, addr, bo.map + (addr - bo.addr));325}326}327328static void329dump_samplers(struct intel_batch_decode_ctx *ctx, uint32_t offset, int count)330{331struct intel_group *strct = intel_spec_find_struct(ctx->spec, "SAMPLER_STATE");332uint64_t state_addr = ctx->dynamic_base + offset;333334assert(count > 0);335336struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);337const void *state_map = bo.map;338339if (state_map == NULL) {340fprintf(ctx->fp, " samplers unavailable\n");341return;342}343344if (offset % 32 != 0) {345fprintf(ctx->fp, " invalid sampler state pointer\n");346return;347}348349const unsigned sampler_state_size = strct->dw_length * 4;350351if (count * sampler_state_size >= bo.size) {352fprintf(ctx->fp, " sampler state ends after bo ends\n");353assert(!"sampler state ends after bo ends");354return;355}356357for (int i = 0; i < count; i++) {358fprintf(ctx->fp, "sampler state %d\n", i);359ctx_print_group(ctx, strct, state_addr, state_map);360state_addr += sampler_state_size;361state_map += sampler_state_size;362}363}364365static void366handle_interface_descriptor_data(struct intel_batch_decode_ctx *ctx,367struct intel_group *desc, const uint32_t *p)368{369uint64_t ksp = 0;370uint32_t sampler_offset = 0, sampler_count = 0;371uint32_t binding_table_offset = 0, binding_entry_count = 0;372373struct intel_field_iterator iter;374intel_field_iterator_init(&iter, desc, p, 0, false);375while (intel_field_iterator_next(&iter)) {376if (strcmp(iter.name, "Kernel Start Pointer") == 0) {377ksp = strtoll(iter.value, NULL, 16);378} else if (strcmp(iter.name, "Sampler State Pointer") == 0) {379sampler_offset = strtol(iter.value, NULL, 16);380} else if (strcmp(iter.name, "Sampler Count") == 0) {381sampler_count = strtol(iter.value, NULL, 10);382} else if (strcmp(iter.name, "Binding Table Pointer") == 0) {383binding_table_offset = strtol(iter.value, NULL, 16);384} else if (strcmp(iter.name, "Binding Table Entry Count") == 0) {385binding_entry_count = strtol(iter.value, NULL, 10);386}387}388389ctx_disassemble_program(ctx, ksp, "compute shader");390fprintf(ctx->fp, "\n");391392if (sampler_count)393dump_samplers(ctx, sampler_offset, sampler_count);394if (binding_entry_count)395dump_binding_table(ctx, binding_table_offset, binding_entry_count);396}397398static void399handle_media_interface_descriptor_load(struct intel_batch_decode_ctx *ctx,400const uint32_t *p)401{402struct intel_group *inst = intel_ctx_find_instruction(ctx, p);403struct intel_group *desc =404intel_spec_find_struct(ctx->spec, "INTERFACE_DESCRIPTOR_DATA");405406struct intel_field_iterator iter;407intel_field_iterator_init(&iter, inst, p, 0, false);408uint32_t descriptor_offset = 0;409int descriptor_count = 0;410while (intel_field_iterator_next(&iter)) {411if (strcmp(iter.name, "Interface Descriptor Data Start Address") == 0) {412descriptor_offset = strtol(iter.value, NULL, 16);413} else if (strcmp(iter.name, "Interface Descriptor Total Length") == 0) {414descriptor_count =415strtol(iter.value, NULL, 16) / (desc->dw_length * 4);416}417}418419uint64_t desc_addr = ctx->dynamic_base + descriptor_offset;420struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, desc_addr);421const void *desc_map = bo.map;422423if (desc_map == NULL) {424fprintf(ctx->fp, " interface descriptors unavailable\n");425return;426}427428for (int i = 0; i < descriptor_count; i++) {429fprintf(ctx->fp, "descriptor %d: %08x\n", i, descriptor_offset);430431ctx_print_group(ctx, desc, desc_addr, desc_map);432433handle_interface_descriptor_data(ctx, desc, desc_map);434435desc_map += desc->dw_length;436desc_addr += desc->dw_length * 4;437}438}439440static void441handle_compute_walker(struct intel_batch_decode_ctx *ctx,442const uint32_t *p)443{444struct intel_group *inst = intel_ctx_find_instruction(ctx, p);445446struct intel_field_iterator iter;447intel_field_iterator_init(&iter, inst, p, 0, false);448while (intel_field_iterator_next(&iter)) {449if (strcmp(iter.name, "Interface Descriptor") == 0) {450handle_interface_descriptor_data(ctx, iter.struct_desc,451&iter.p[iter.start_bit / 32]);452}453}454}455456static void457handle_3dstate_vertex_buffers(struct intel_batch_decode_ctx *ctx,458const uint32_t *p)459{460struct intel_group *inst = intel_ctx_find_instruction(ctx, p);461struct intel_group *vbs = intel_spec_find_struct(ctx->spec, "VERTEX_BUFFER_STATE");462463struct intel_batch_decode_bo vb = {};464uint32_t vb_size = 0;465int index = -1;466int pitch = -1;467bool ready = false;468469struct intel_field_iterator iter;470intel_field_iterator_init(&iter, inst, p, 0, false);471while (intel_field_iterator_next(&iter)) {472if (iter.struct_desc != vbs)473continue;474475struct intel_field_iterator vbs_iter;476intel_field_iterator_init(&vbs_iter, vbs, &iter.p[iter.start_bit / 32], 0, false);477while (intel_field_iterator_next(&vbs_iter)) {478if (strcmp(vbs_iter.name, "Vertex Buffer Index") == 0) {479index = vbs_iter.raw_value;480} else if (strcmp(vbs_iter.name, "Buffer Pitch") == 0) {481pitch = vbs_iter.raw_value;482} else if (strcmp(vbs_iter.name, "Buffer Starting Address") == 0) {483vb = ctx_get_bo(ctx, true, vbs_iter.raw_value);484} else if (strcmp(vbs_iter.name, "Buffer Size") == 0) {485vb_size = vbs_iter.raw_value;486ready = true;487} else if (strcmp(vbs_iter.name, "End Address") == 0) {488if (vb.map && vbs_iter.raw_value >= vb.addr)489vb_size = (vbs_iter.raw_value + 1) - vb.addr;490else491vb_size = 0;492ready = true;493}494495if (!ready)496continue;497498fprintf(ctx->fp, "vertex buffer %d, size %d\n", index, vb_size);499500if (vb.map == NULL) {501fprintf(ctx->fp, " buffer contents unavailable\n");502continue;503}504505if (vb.map == 0 || vb_size == 0)506continue;507508ctx_print_buffer(ctx, vb, vb_size, pitch, ctx->max_vbo_decoded_lines);509510vb.map = NULL;511vb_size = 0;512index = -1;513pitch = -1;514ready = false;515}516}517}518519static void520handle_3dstate_index_buffer(struct intel_batch_decode_ctx *ctx,521const uint32_t *p)522{523struct intel_group *inst = intel_ctx_find_instruction(ctx, p);524525struct intel_batch_decode_bo ib = {};526uint32_t ib_size = 0;527uint32_t format = 0;528529struct intel_field_iterator iter;530intel_field_iterator_init(&iter, inst, p, 0, false);531while (intel_field_iterator_next(&iter)) {532if (strcmp(iter.name, "Index Format") == 0) {533format = iter.raw_value;534} else if (strcmp(iter.name, "Buffer Starting Address") == 0) {535ib = ctx_get_bo(ctx, true, iter.raw_value);536} else if (strcmp(iter.name, "Buffer Size") == 0) {537ib_size = iter.raw_value;538}539}540541if (ib.map == NULL) {542fprintf(ctx->fp, " buffer contents unavailable\n");543return;544}545546const void *m = ib.map;547const void *ib_end = ib.map + MIN2(ib.size, ib_size);548for (int i = 0; m < ib_end && i < 10; i++) {549switch (format) {550case 0:551fprintf(ctx->fp, "%3d ", *(uint8_t *)m);552m += 1;553break;554case 1:555fprintf(ctx->fp, "%3d ", *(uint16_t *)m);556m += 2;557break;558case 2:559fprintf(ctx->fp, "%3d ", *(uint32_t *)m);560m += 4;561break;562}563}564565if (m < ib_end)566fprintf(ctx->fp, "...");567fprintf(ctx->fp, "\n");568}569570static void571decode_single_ksp(struct intel_batch_decode_ctx *ctx, const uint32_t *p)572{573struct intel_group *inst = intel_ctx_find_instruction(ctx, p);574575uint64_t ksp = 0;576bool is_simd8 = ctx->devinfo.ver >= 11; /* vertex shaders on Gfx8+ only */577bool is_enabled = true;578579struct intel_field_iterator iter;580intel_field_iterator_init(&iter, inst, p, 0, false);581while (intel_field_iterator_next(&iter)) {582if (strcmp(iter.name, "Kernel Start Pointer") == 0) {583ksp = iter.raw_value;584} else if (strcmp(iter.name, "SIMD8 Dispatch Enable") == 0) {585is_simd8 = iter.raw_value;586} else if (strcmp(iter.name, "Dispatch Mode") == 0) {587is_simd8 = strcmp(iter.value, "SIMD8") == 0;588} else if (strcmp(iter.name, "Dispatch Enable") == 0) {589is_simd8 = strcmp(iter.value, "SIMD8") == 0;590} else if (strcmp(iter.name, "Enable") == 0) {591is_enabled = iter.raw_value;592}593}594595const char *type =596strcmp(inst->name, "VS_STATE") == 0 ? "vertex shader" :597strcmp(inst->name, "GS_STATE") == 0 ? "geometry shader" :598strcmp(inst->name, "SF_STATE") == 0 ? "strips and fans shader" :599strcmp(inst->name, "CLIP_STATE") == 0 ? "clip shader" :600strcmp(inst->name, "3DSTATE_DS") == 0 ? "tessellation evaluation shader" :601strcmp(inst->name, "3DSTATE_HS") == 0 ? "tessellation control shader" :602strcmp(inst->name, "3DSTATE_VS") == 0 ? (is_simd8 ? "SIMD8 vertex shader" : "vec4 vertex shader") :603strcmp(inst->name, "3DSTATE_GS") == 0 ? (is_simd8 ? "SIMD8 geometry shader" : "vec4 geometry shader") :604NULL;605606if (is_enabled) {607ctx_disassemble_program(ctx, ksp, type);608fprintf(ctx->fp, "\n");609}610}611612static void613decode_ps_kern(struct intel_batch_decode_ctx *ctx,614struct intel_group *inst, const uint32_t *p)615{616bool single_ksp = ctx->devinfo.ver == 4;617uint64_t ksp[3] = {0, 0, 0};618bool enabled[3] = {false, false, false};619620struct intel_field_iterator iter;621intel_field_iterator_init(&iter, inst, p, 0, false);622while (intel_field_iterator_next(&iter)) {623if (strncmp(iter.name, "Kernel Start Pointer ",624strlen("Kernel Start Pointer ")) == 0) {625int idx = iter.name[strlen("Kernel Start Pointer ")] - '0';626ksp[idx] = strtol(iter.value, NULL, 16);627} else if (strcmp(iter.name, "8 Pixel Dispatch Enable") == 0) {628enabled[0] = strcmp(iter.value, "true") == 0;629} else if (strcmp(iter.name, "16 Pixel Dispatch Enable") == 0) {630enabled[1] = strcmp(iter.value, "true") == 0;631} else if (strcmp(iter.name, "32 Pixel Dispatch Enable") == 0) {632enabled[2] = strcmp(iter.value, "true") == 0;633}634}635636if (single_ksp)637ksp[1] = ksp[2] = ksp[0];638639/* Reorder KSPs to be [8, 16, 32] instead of the hardware order. */640if (enabled[0] + enabled[1] + enabled[2] == 1) {641if (enabled[1]) {642ksp[1] = ksp[0];643ksp[0] = 0;644} else if (enabled[2]) {645ksp[2] = ksp[0];646ksp[0] = 0;647}648} else {649uint64_t tmp = ksp[1];650ksp[1] = ksp[2];651ksp[2] = tmp;652}653654if (enabled[0])655ctx_disassemble_program(ctx, ksp[0], "SIMD8 fragment shader");656if (enabled[1])657ctx_disassemble_program(ctx, ksp[1], "SIMD16 fragment shader");658if (enabled[2])659ctx_disassemble_program(ctx, ksp[2], "SIMD32 fragment shader");660661if (enabled[0] || enabled[1] || enabled[2])662fprintf(ctx->fp, "\n");663}664665static void666decode_ps_kernels(struct intel_batch_decode_ctx *ctx,667const uint32_t *p)668{669struct intel_group *inst = intel_ctx_find_instruction(ctx, p);670decode_ps_kern(ctx, inst, p);671}672673static void674decode_3dstate_constant_all(struct intel_batch_decode_ctx *ctx, const uint32_t *p)675{676struct intel_group *inst =677intel_spec_find_instruction(ctx->spec, ctx->engine, p);678struct intel_group *body =679intel_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_ALL_DATA");680681uint32_t read_length[4];682struct intel_batch_decode_bo buffer[4];683memset(buffer, 0, sizeof(buffer));684685struct intel_field_iterator outer;686intel_field_iterator_init(&outer, inst, p, 0, false);687int idx = 0;688while (intel_field_iterator_next(&outer)) {689if (outer.struct_desc != body)690continue;691692struct intel_field_iterator iter;693intel_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],6940, false);695while (intel_field_iterator_next(&iter)) {696if (!strcmp(iter.name, "Pointer To Constant Buffer")) {697buffer[idx] = ctx_get_bo(ctx, true, iter.raw_value);698} else if (!strcmp(iter.name, "Constant Buffer Read Length")) {699read_length[idx] = iter.raw_value;700}701}702idx++;703}704705for (int i = 0; i < 4; i++) {706if (read_length[i] == 0 || buffer[i].map == NULL)707continue;708709unsigned size = read_length[i] * 32;710fprintf(ctx->fp, "constant buffer %d, size %u\n", i, size);711712ctx_print_buffer(ctx, buffer[i], size, 0, -1);713}714}715716static void717decode_3dstate_constant(struct intel_batch_decode_ctx *ctx, const uint32_t *p)718{719struct intel_group *inst = intel_ctx_find_instruction(ctx, p);720struct intel_group *body =721intel_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_BODY");722723uint32_t read_length[4] = {0};724uint64_t read_addr[4];725726struct intel_field_iterator outer;727intel_field_iterator_init(&outer, inst, p, 0, false);728while (intel_field_iterator_next(&outer)) {729if (outer.struct_desc != body)730continue;731732struct intel_field_iterator iter;733intel_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],7340, false);735736while (intel_field_iterator_next(&iter)) {737int idx;738if (sscanf(iter.name, "Read Length[%d]", &idx) == 1) {739read_length[idx] = iter.raw_value;740} else if (sscanf(iter.name, "Buffer[%d]", &idx) == 1) {741read_addr[idx] = iter.raw_value;742}743}744745for (int i = 0; i < 4; i++) {746if (read_length[i] == 0)747continue;748749struct intel_batch_decode_bo buffer = ctx_get_bo(ctx, true, read_addr[i]);750if (!buffer.map) {751fprintf(ctx->fp, "constant buffer %d unavailable\n", i);752continue;753}754755unsigned size = read_length[i] * 32;756fprintf(ctx->fp, "constant buffer %d, size %u\n", i, size);757758ctx_print_buffer(ctx, buffer, size, 0, -1);759}760}761}762763static void764decode_gfx4_3dstate_binding_table_pointers(struct intel_batch_decode_ctx *ctx,765const uint32_t *p)766{767fprintf(ctx->fp, "VS Binding Table:\n");768dump_binding_table(ctx, p[1], -1);769770fprintf(ctx->fp, "GS Binding Table:\n");771dump_binding_table(ctx, p[2], -1);772773if (ctx->devinfo.ver < 6) {774fprintf(ctx->fp, "CLIP Binding Table:\n");775dump_binding_table(ctx, p[3], -1);776fprintf(ctx->fp, "SF Binding Table:\n");777dump_binding_table(ctx, p[4], -1);778fprintf(ctx->fp, "PS Binding Table:\n");779dump_binding_table(ctx, p[5], -1);780} else {781fprintf(ctx->fp, "PS Binding Table:\n");782dump_binding_table(ctx, p[3], -1);783}784}785786static void787decode_3dstate_binding_table_pointers(struct intel_batch_decode_ctx *ctx,788const uint32_t *p)789{790dump_binding_table(ctx, p[1], -1);791}792793static void794decode_3dstate_sampler_state_pointers(struct intel_batch_decode_ctx *ctx,795const uint32_t *p)796{797dump_samplers(ctx, p[1], 1);798}799800static void801decode_3dstate_sampler_state_pointers_gfx6(struct intel_batch_decode_ctx *ctx,802const uint32_t *p)803{804dump_samplers(ctx, p[1], 1);805dump_samplers(ctx, p[2], 1);806dump_samplers(ctx, p[3], 1);807}808809static bool810str_ends_with(const char *str, const char *end)811{812int offset = strlen(str) - strlen(end);813if (offset < 0)814return false;815816return strcmp(str + offset, end) == 0;817}818819static void820decode_dynamic_state_pointers(struct intel_batch_decode_ctx *ctx,821const char *struct_type, const uint32_t *p,822int count)823{824struct intel_group *inst = intel_ctx_find_instruction(ctx, p);825826uint32_t state_offset = 0;827828struct intel_field_iterator iter;829intel_field_iterator_init(&iter, inst, p, 0, false);830while (intel_field_iterator_next(&iter)) {831if (str_ends_with(iter.name, "Pointer") || !strncmp(iter.name, "Pointer", 7)) {832state_offset = iter.raw_value;833break;834}835}836837uint64_t state_addr = ctx->dynamic_base + state_offset;838struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);839const void *state_map = bo.map;840841if (state_map == NULL) {842fprintf(ctx->fp, " dynamic %s state unavailable\n", struct_type);843return;844}845846struct intel_group *state = intel_spec_find_struct(ctx->spec, struct_type);847if (strcmp(struct_type, "BLEND_STATE") == 0) {848/* Blend states are different from the others because they have a header849* struct called BLEND_STATE which is followed by a variable number of850* BLEND_STATE_ENTRY structs.851*/852fprintf(ctx->fp, "%s\n", struct_type);853ctx_print_group(ctx, state, state_addr, state_map);854855state_addr += state->dw_length * 4;856state_map += state->dw_length * 4;857858struct_type = "BLEND_STATE_ENTRY";859state = intel_spec_find_struct(ctx->spec, struct_type);860}861862count = update_count(ctx, ctx->dynamic_base + state_offset,863ctx->dynamic_base, state->dw_length, count);864865for (int i = 0; i < count; i++) {866fprintf(ctx->fp, "%s %d\n", struct_type, i);867ctx_print_group(ctx, state, state_addr, state_map);868869state_addr += state->dw_length * 4;870state_map += state->dw_length * 4;871}872}873874static void875decode_3dstate_viewport_state_pointers_cc(struct intel_batch_decode_ctx *ctx,876const uint32_t *p)877{878decode_dynamic_state_pointers(ctx, "CC_VIEWPORT", p, 4);879}880881static void882decode_3dstate_viewport_state_pointers_sf_clip(struct intel_batch_decode_ctx *ctx,883const uint32_t *p)884{885decode_dynamic_state_pointers(ctx, "SF_CLIP_VIEWPORT", p, 4);886}887888static void889decode_3dstate_blend_state_pointers(struct intel_batch_decode_ctx *ctx,890const uint32_t *p)891{892decode_dynamic_state_pointers(ctx, "BLEND_STATE", p, 1);893}894895static void896decode_3dstate_cc_state_pointers(struct intel_batch_decode_ctx *ctx,897const uint32_t *p)898{899decode_dynamic_state_pointers(ctx, "COLOR_CALC_STATE", p, 1);900}901902static void903decode_3dstate_ds_state_pointers(struct intel_batch_decode_ctx *ctx,904const uint32_t *p)905{906decode_dynamic_state_pointers(ctx, "DEPTH_STENCIL_STATE", p, 1);907}908909static void910decode_3dstate_scissor_state_pointers(struct intel_batch_decode_ctx *ctx,911const uint32_t *p)912{913decode_dynamic_state_pointers(ctx, "SCISSOR_RECT", p, 1);914}915916static void917decode_3dstate_slice_table_state_pointers(struct intel_batch_decode_ctx *ctx,918const uint32_t *p)919{920decode_dynamic_state_pointers(ctx, "SLICE_HASH_TABLE", p, 1);921}922923static void924handle_gt_mode(struct intel_batch_decode_ctx *ctx,925uint32_t reg_addr, uint32_t val)926{927struct intel_group *reg = intel_spec_find_register(ctx->spec, reg_addr);928929assert(intel_group_get_length(reg, &val) == 1);930931struct intel_field_iterator iter;932intel_field_iterator_init(&iter, reg, &val, 0, false);933934uint32_t bt_alignment;935bool bt_alignment_mask = 0;936937while (intel_field_iterator_next(&iter)) {938if (strcmp(iter.name, "Binding Table Alignment") == 0) {939bt_alignment = iter.raw_value;940} else if (strcmp(iter.name, "Binding Table Alignment Mask") == 0) {941bt_alignment_mask = iter.raw_value;942}943}944945if (bt_alignment_mask)946ctx->use_256B_binding_tables = bt_alignment;947}948949struct reg_handler {950const char *name;951void (*handler)(struct intel_batch_decode_ctx *ctx,952uint32_t reg_addr, uint32_t val);953} reg_handlers[] = {954{ "GT_MODE", handle_gt_mode }955};956957static void958decode_load_register_imm(struct intel_batch_decode_ctx *ctx, const uint32_t *p)959{960struct intel_group *inst = intel_ctx_find_instruction(ctx, p);961const unsigned length = intel_group_get_length(inst, p);962assert(length & 1);963const unsigned nr_regs = (length - 1) / 2;964965for (unsigned i = 0; i < nr_regs; i++) {966struct intel_group *reg = intel_spec_find_register(ctx->spec, p[i * 2 + 1]);967if (reg != NULL) {968fprintf(ctx->fp, "register %s (0x%x): 0x%x\n",969reg->name, reg->register_offset, p[2]);970ctx_print_group(ctx, reg, reg->register_offset, &p[2]);971972for (unsigned i = 0; i < ARRAY_SIZE(reg_handlers); i++) {973if (strcmp(reg->name, reg_handlers[i].name) == 0)974reg_handlers[i].handler(ctx, p[1], p[2]);975}976}977}978}979980static void981decode_vs_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)982{983struct intel_group *strct =984intel_spec_find_struct(ctx->spec, "VS_STATE");985if (strct == NULL) {986fprintf(ctx->fp, "did not find VS_STATE info\n");987return;988}989990struct intel_batch_decode_bo bind_bo =991ctx_get_bo(ctx, true, offset);992993if (bind_bo.map == NULL) {994fprintf(ctx->fp, " vs state unavailable\n");995return;996}997998ctx_print_group(ctx, strct, offset, bind_bo.map);999}10001001static void1002decode_gs_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)1003{1004struct intel_group *strct =1005intel_spec_find_struct(ctx->spec, "GS_STATE");1006if (strct == NULL) {1007fprintf(ctx->fp, "did not find GS_STATE info\n");1008return;1009}10101011struct intel_batch_decode_bo bind_bo =1012ctx_get_bo(ctx, true, offset);10131014if (bind_bo.map == NULL) {1015fprintf(ctx->fp, " gs state unavailable\n");1016return;1017}10181019ctx_print_group(ctx, strct, offset, bind_bo.map);1020}10211022static void1023decode_clip_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)1024{1025struct intel_group *strct =1026intel_spec_find_struct(ctx->spec, "CLIP_STATE");1027if (strct == NULL) {1028fprintf(ctx->fp, "did not find CLIP_STATE info\n");1029return;1030}10311032struct intel_batch_decode_bo bind_bo =1033ctx_get_bo(ctx, true, offset);10341035if (bind_bo.map == NULL) {1036fprintf(ctx->fp, " clip state unavailable\n");1037return;1038}10391040ctx_print_group(ctx, strct, offset, bind_bo.map);10411042struct intel_group *vp_strct =1043intel_spec_find_struct(ctx->spec, "CLIP_VIEWPORT");1044if (vp_strct == NULL) {1045fprintf(ctx->fp, "did not find CLIP_VIEWPORT info\n");1046return;1047}1048uint32_t clip_vp_offset = ((uint32_t *)bind_bo.map)[6] & ~0x3;1049struct intel_batch_decode_bo vp_bo =1050ctx_get_bo(ctx, true, clip_vp_offset);1051if (vp_bo.map == NULL) {1052fprintf(ctx->fp, " clip vp state unavailable\n");1053return;1054}1055ctx_print_group(ctx, vp_strct, clip_vp_offset, vp_bo.map);1056}10571058static void1059decode_sf_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)1060{1061struct intel_group *strct =1062intel_spec_find_struct(ctx->spec, "SF_STATE");1063if (strct == NULL) {1064fprintf(ctx->fp, "did not find SF_STATE info\n");1065return;1066}10671068struct intel_batch_decode_bo bind_bo =1069ctx_get_bo(ctx, true, offset);10701071if (bind_bo.map == NULL) {1072fprintf(ctx->fp, " sf state unavailable\n");1073return;1074}10751076ctx_print_group(ctx, strct, offset, bind_bo.map);10771078struct intel_group *vp_strct =1079intel_spec_find_struct(ctx->spec, "SF_VIEWPORT");1080if (vp_strct == NULL) {1081fprintf(ctx->fp, "did not find SF_VIEWPORT info\n");1082return;1083}10841085uint32_t sf_vp_offset = ((uint32_t *)bind_bo.map)[5] & ~0x3;1086struct intel_batch_decode_bo vp_bo =1087ctx_get_bo(ctx, true, sf_vp_offset);1088if (vp_bo.map == NULL) {1089fprintf(ctx->fp, " sf vp state unavailable\n");1090return;1091}1092ctx_print_group(ctx, vp_strct, sf_vp_offset, vp_bo.map);1093}10941095static void1096decode_wm_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)1097{1098struct intel_group *strct =1099intel_spec_find_struct(ctx->spec, "WM_STATE");1100if (strct == NULL) {1101fprintf(ctx->fp, "did not find WM_STATE info\n");1102return;1103}11041105struct intel_batch_decode_bo bind_bo =1106ctx_get_bo(ctx, true, offset);11071108if (bind_bo.map == NULL) {1109fprintf(ctx->fp, " wm state unavailable\n");1110return;1111}11121113ctx_print_group(ctx, strct, offset, bind_bo.map);11141115decode_ps_kern(ctx, strct, bind_bo.map);1116}11171118static void1119decode_cc_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)1120{1121struct intel_group *strct =1122intel_spec_find_struct(ctx->spec, "COLOR_CALC_STATE");1123if (strct == NULL) {1124fprintf(ctx->fp, "did not find COLOR_CALC_STATE info\n");1125return;1126}11271128struct intel_batch_decode_bo bind_bo =1129ctx_get_bo(ctx, true, offset);11301131if (bind_bo.map == NULL) {1132fprintf(ctx->fp, " cc state unavailable\n");1133return;1134}11351136ctx_print_group(ctx, strct, offset, bind_bo.map);11371138struct intel_group *vp_strct =1139intel_spec_find_struct(ctx->spec, "CC_VIEWPORT");1140if (vp_strct == NULL) {1141fprintf(ctx->fp, "did not find CC_VIEWPORT info\n");1142return;1143}1144uint32_t cc_vp_offset = ((uint32_t *)bind_bo.map)[4] & ~0x3;1145struct intel_batch_decode_bo vp_bo =1146ctx_get_bo(ctx, true, cc_vp_offset);1147if (vp_bo.map == NULL) {1148fprintf(ctx->fp, " cc vp state unavailable\n");1149return;1150}1151ctx_print_group(ctx, vp_strct, cc_vp_offset, vp_bo.map);1152}1153static void1154decode_pipelined_pointers(struct intel_batch_decode_ctx *ctx, const uint32_t *p)1155{1156fprintf(ctx->fp, "VS State Table:\n");1157decode_vs_state(ctx, p[1]);1158if (p[2] & 1) {1159fprintf(ctx->fp, "GS State Table:\n");1160decode_gs_state(ctx, p[2] & ~1);1161}1162fprintf(ctx->fp, "Clip State Table:\n");1163decode_clip_state(ctx, p[3] & ~1);1164fprintf(ctx->fp, "SF State Table:\n");1165decode_sf_state(ctx, p[4]);1166fprintf(ctx->fp, "WM State Table:\n");1167decode_wm_state(ctx, p[5]);1168fprintf(ctx->fp, "CC State Table:\n");1169decode_cc_state(ctx, p[6]);1170}11711172static void1173decode_cps_pointers(struct intel_batch_decode_ctx *ctx, const uint32_t *p)1174{1175decode_dynamic_state_pointers(ctx, "CPS_STATE", p, 1);1176}11771178struct custom_decoder {1179const char *cmd_name;1180void (*decode)(struct intel_batch_decode_ctx *ctx, const uint32_t *p);1181} custom_decoders[] = {1182{ "STATE_BASE_ADDRESS", handle_state_base_address },1183{ "3DSTATE_BINDING_TABLE_POOL_ALLOC", handle_binding_table_pool_alloc },1184{ "MEDIA_INTERFACE_DESCRIPTOR_LOAD", handle_media_interface_descriptor_load },1185{ "COMPUTE_WALKER", handle_compute_walker },1186{ "3DSTATE_VERTEX_BUFFERS", handle_3dstate_vertex_buffers },1187{ "3DSTATE_INDEX_BUFFER", handle_3dstate_index_buffer },1188{ "3DSTATE_VS", decode_single_ksp },1189{ "3DSTATE_GS", decode_single_ksp },1190{ "3DSTATE_DS", decode_single_ksp },1191{ "3DSTATE_HS", decode_single_ksp },1192{ "3DSTATE_PS", decode_ps_kernels },1193{ "3DSTATE_WM", decode_ps_kernels },1194{ "3DSTATE_CONSTANT_VS", decode_3dstate_constant },1195{ "3DSTATE_CONSTANT_GS", decode_3dstate_constant },1196{ "3DSTATE_CONSTANT_PS", decode_3dstate_constant },1197{ "3DSTATE_CONSTANT_HS", decode_3dstate_constant },1198{ "3DSTATE_CONSTANT_DS", decode_3dstate_constant },1199{ "3DSTATE_CONSTANT_ALL", decode_3dstate_constant_all },12001201{ "3DSTATE_BINDING_TABLE_POINTERS", decode_gfx4_3dstate_binding_table_pointers },1202{ "3DSTATE_BINDING_TABLE_POINTERS_VS", decode_3dstate_binding_table_pointers },1203{ "3DSTATE_BINDING_TABLE_POINTERS_HS", decode_3dstate_binding_table_pointers },1204{ "3DSTATE_BINDING_TABLE_POINTERS_DS", decode_3dstate_binding_table_pointers },1205{ "3DSTATE_BINDING_TABLE_POINTERS_GS", decode_3dstate_binding_table_pointers },1206{ "3DSTATE_BINDING_TABLE_POINTERS_PS", decode_3dstate_binding_table_pointers },12071208{ "3DSTATE_SAMPLER_STATE_POINTERS_VS", decode_3dstate_sampler_state_pointers },1209{ "3DSTATE_SAMPLER_STATE_POINTERS_HS", decode_3dstate_sampler_state_pointers },1210{ "3DSTATE_SAMPLER_STATE_POINTERS_DS", decode_3dstate_sampler_state_pointers },1211{ "3DSTATE_SAMPLER_STATE_POINTERS_GS", decode_3dstate_sampler_state_pointers },1212{ "3DSTATE_SAMPLER_STATE_POINTERS_PS", decode_3dstate_sampler_state_pointers },1213{ "3DSTATE_SAMPLER_STATE_POINTERS", decode_3dstate_sampler_state_pointers_gfx6 },12141215{ "3DSTATE_VIEWPORT_STATE_POINTERS_CC", decode_3dstate_viewport_state_pointers_cc },1216{ "3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP", decode_3dstate_viewport_state_pointers_sf_clip },1217{ "3DSTATE_BLEND_STATE_POINTERS", decode_3dstate_blend_state_pointers },1218{ "3DSTATE_CC_STATE_POINTERS", decode_3dstate_cc_state_pointers },1219{ "3DSTATE_DEPTH_STENCIL_STATE_POINTERS", decode_3dstate_ds_state_pointers },1220{ "3DSTATE_SCISSOR_STATE_POINTERS", decode_3dstate_scissor_state_pointers },1221{ "3DSTATE_SLICE_TABLE_STATE_POINTERS", decode_3dstate_slice_table_state_pointers },1222{ "MI_LOAD_REGISTER_IMM", decode_load_register_imm },1223{ "3DSTATE_PIPELINED_POINTERS", decode_pipelined_pointers },1224{ "3DSTATE_CPS_POINTERS", decode_cps_pointers },1225};12261227void1228intel_print_batch(struct intel_batch_decode_ctx *ctx,1229const uint32_t *batch, uint32_t batch_size,1230uint64_t batch_addr, bool from_ring)1231{1232const uint32_t *p, *end = batch + batch_size / sizeof(uint32_t);1233int length;1234struct intel_group *inst;1235const char *reset_color = ctx->flags & INTEL_BATCH_DECODE_IN_COLOR ? NORMAL : "";12361237if (ctx->n_batch_buffer_start >= 100) {1238fprintf(ctx->fp, "%s0x%08"PRIx64": Max batch buffer jumps exceeded%s\n",1239(ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) ? RED_COLOR : "",1240(ctx->flags & INTEL_BATCH_DECODE_OFFSETS) ? batch_addr : 0,1241reset_color);1242return;1243}12441245ctx->n_batch_buffer_start++;12461247for (p = batch; p < end; p += length) {1248inst = intel_ctx_find_instruction(ctx, p);1249length = intel_group_get_length(inst, p);1250assert(inst == NULL || length > 0);1251length = MAX2(1, length);12521253uint64_t offset;1254if (ctx->flags & INTEL_BATCH_DECODE_OFFSETS)1255offset = batch_addr + ((char *)p - (char *)batch);1256else1257offset = 0;12581259if (inst == NULL) {1260fprintf(ctx->fp, "%s0x%08"PRIx64": unknown instruction %08x%s\n",1261(ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) ? RED_COLOR : "",1262offset, p[0], reset_color);12631264for (int i=1; i < length; i++) {1265fprintf(ctx->fp, "%s0x%08"PRIx64": -- %08x%s\n",1266(ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) ? RED_COLOR : "",1267offset + i * 4, p[i], reset_color);1268}12691270continue;1271}12721273const char *color;1274const char *inst_name = intel_group_get_name(inst);1275if (ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) {1276reset_color = NORMAL;1277if (ctx->flags & INTEL_BATCH_DECODE_FULL) {1278if (strcmp(inst_name, "MI_BATCH_BUFFER_START") == 0 ||1279strcmp(inst_name, "MI_BATCH_BUFFER_END") == 0)1280color = GREEN_HEADER;1281else1282color = BLUE_HEADER;1283} else {1284color = NORMAL;1285}1286} else {1287color = "";1288reset_color = "";1289}12901291fprintf(ctx->fp, "%s0x%08"PRIx64": 0x%08x: %-80s%s\n",1292color, offset, p[0], inst_name, reset_color);12931294if (ctx->flags & INTEL_BATCH_DECODE_FULL) {1295ctx_print_group(ctx, inst, offset, p);12961297for (int i = 0; i < ARRAY_SIZE(custom_decoders); i++) {1298if (strcmp(inst_name, custom_decoders[i].cmd_name) == 0) {1299custom_decoders[i].decode(ctx, p);1300break;1301}1302}1303}13041305if (strcmp(inst_name, "MI_BATCH_BUFFER_START") == 0) {1306uint64_t next_batch_addr = 0;1307bool ppgtt = false;1308bool second_level = false;1309bool predicate = false;1310struct intel_field_iterator iter;1311intel_field_iterator_init(&iter, inst, p, 0, false);1312while (intel_field_iterator_next(&iter)) {1313if (strcmp(iter.name, "Batch Buffer Start Address") == 0) {1314next_batch_addr = iter.raw_value;1315} else if (strcmp(iter.name, "Second Level Batch Buffer") == 0) {1316second_level = iter.raw_value;1317} else if (strcmp(iter.name, "Address Space Indicator") == 0) {1318ppgtt = iter.raw_value;1319} else if (strcmp(iter.name, "Predication Enable") == 0) {1320predicate = iter.raw_value;1321}1322}13231324if (!predicate) {1325struct intel_batch_decode_bo next_batch = ctx_get_bo(ctx, ppgtt, next_batch_addr);13261327if (next_batch.map == NULL) {1328fprintf(ctx->fp, "Secondary batch at 0x%08"PRIx64" unavailable\n",1329next_batch_addr);1330} else {1331intel_print_batch(ctx, next_batch.map, next_batch.size,1332next_batch.addr, false);1333}1334if (second_level) {1335/* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" set acts1336* like a subroutine call. Commands that come afterwards get1337* processed once the 2nd level batch buffer returns with1338* MI_BATCH_BUFFER_END.1339*/1340continue;1341} else if (!from_ring) {1342/* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" unset acts1343* like a goto. Nothing after it will ever get processed. In1344* order to prevent the recursion from growing, we just reset the1345* loop and continue;1346*/1347break;1348}1349}1350} else if (strcmp(inst_name, "MI_BATCH_BUFFER_END") == 0) {1351break;1352}1353}13541355ctx->n_batch_buffer_start--;1356}135713581359