From 2841af6238b7648b388ba806f1ad181332b6eef0 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 3 Apr 2018 11:01:56 +0100 Subject: [PATCH] intel: gen-decoder: don't decode fields beyond a dword length For example, a PIPE_CONTROL with DWordLength = 2 should look like this : 0xffffe374: 0x7a000002: PIPE_CONTROL 0xffffe374: 0x7a000002 : Dword 0 DWord Length: 2 0xffffe378: 0x00800000 : Dword 1 Depth Cache Flush Enable: false Stall At Pixel Scoreboard: false State Cache Invalidation Enable: false Constant Cache Invalidation Enable: false VF Cache Invalidation Enable: false DC Flush Enable: false Pipe Control Flush Enable: false Notify Enable: false Indirect State Pointers Disable: false Texture Cache Invalidation Enable: false Instruction Cache Invalidate Enable: false Render Target Cache Flush Enable: false Depth Stall Enable: false Post Sync Operation: 0 (No Write) Generic Media State Clear: false TLB Invalidate: false Global Snapshot Count Reset: false Command Streamer Stall Enable: false Store Data Index: 0 LRI Post Sync Operation: 1 (MMIO Write Immediate Data) Destination Address Type: 0 (PPGTT) Flush LLC: false 0xffffe37c: 0x00000000 : Dword 2 Address: 0x00000000 0xffffe384: 0x05000000: MI_BATCH_BUFFER_END Prior to this change, fields beyond the length of the command would be decoded (notice the MI_BATCH_BUFFER_END decoded as part of the previous PIPE_CONTROL) : 0xffffe374: 0x7a000002: PIPE_CONTROL 0xffffe374: 0x7a000002 : Dword 0 DWord Length: 2 0xffffe378: 0x00800000 : Dword 1 Depth Cache Flush Enable: false Stall At Pixel Scoreboard: false State Cache Invalidation Enable: false Constant Cache Invalidation Enable: false VF Cache Invalidation Enable: false DC Flush Enable: false Pipe Control Flush Enable: false Notify Enable: false Indirect State Pointers Disable: false Texture Cache Invalidation Enable: false Instruction Cache Invalidate Enable: false Render Target Cache Flush Enable: false Depth Stall Enable: false Post Sync Operation: 0 (No Write) Generic Media State Clear: false TLB Invalidate: false Global Snapshot Count Reset: false Command Streamer Stall Enable: false Store Data Index: 0 LRI Post Sync Operation: 1 (MMIO Write Immediate Data) Destination Address Type: 0 (PPGTT) Flush LLC: false 0xffffe37c: 0x00000000 : Dword 2 Address: 0x00000000 0xffffe380: 0x00000000 : Dword 3 0xffffe384: 0x05000000 : Dword 4 Immediate Data: 83886080 0xffffe384: 0x05000000: MI_BATCH_BUFFER_END Signed-off-by: Lionel Landwerlin Reviewed-by: Scott D Phillips --- src/intel/common/gen_decoder.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/intel/common/gen_decoder.c b/src/intel/common/gen_decoder.c index 7ca71c0d9fc..595fa29e43d 100644 --- a/src/intel/common/gen_decoder.c +++ b/src/intel/common/gen_decoder.c @@ -847,35 +847,38 @@ iter_advance_field(struct gen_field_iterator *iter) return true; } -static uint64_t -iter_decode_field_raw(struct gen_field_iterator *iter) +static bool +iter_decode_field_raw(struct gen_field_iterator *iter, uint64_t *qw) { - uint64_t qw = 0; + *qw = 0; int field_start = iter->p_bit + iter->bit; int field_end = field_start + (iter->field->end - iter->field->start); const uint32_t *p = iter->p + (iter->bit / 32); + if (iter->p_end && p >= iter->p_end) + return false; + if ((field_end - field_start) > 32) { - if ((p + 1) < iter->p_end) - qw = ((uint64_t) p[1]) << 32; - qw |= p[0]; + if (!iter->p_end || (p + 1) < iter->p_end) + *qw = ((uint64_t) p[1]) << 32; + *qw |= p[0]; } else - qw = p[0]; + *qw = p[0]; - qw = field_value(qw, field_start, field_end); + *qw = field_value(*qw, field_start, field_end); /* Address & offset types have to be aligned to dwords, their start bit is * a reminder of the alignment requirement. */ if (iter->field->type.kind == GEN_TYPE_ADDRESS || iter->field->type.kind == GEN_TYPE_OFFSET) - qw <<= field_start % 32; + *qw <<= field_start % 32; - return qw; + return true; } -static void +static bool iter_decode_field(struct gen_field_iterator *iter) { union { @@ -890,7 +893,8 @@ iter_decode_field(struct gen_field_iterator *iter) memset(&v, 0, sizeof(v)); - iter->raw_value = iter_decode_field_raw(iter); + if (!iter_decode_field_raw(iter, &iter->raw_value)) + return false; const char *enum_name = NULL; @@ -963,6 +967,8 @@ iter_decode_field(struct gen_field_iterator *iter) " (%s)", fmt_name); } } + + return true; } void @@ -980,10 +986,14 @@ gen_field_iterator_init(struct gen_field_iterator *iter, iter->field = group->next->fields; iter->p = p; iter->p_bit = p_bit; - iter->p_end = &p[gen_group_get_length(iter->group, iter->p)]; + + int length = gen_group_get_length(iter->group, iter->p); + iter->p_end = length > 0 ? &p[length] : NULL; iter->print_colors = print_colors; - iter_decode_field(iter); + bool result = iter_decode_field(iter); + if (length >= 0) + assert(result); } bool @@ -992,7 +1002,8 @@ gen_field_iterator_next(struct gen_field_iterator *iter) if (!iter_advance_field(iter)) return false; - iter_decode_field(iter); + if (!iter_decode_field(iter)) + return false; return true; } -- 2.11.0