summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLionel Landwerlin <[email protected]>2018-04-03 11:01:56 +0100
committerLionel Landwerlin <[email protected]>2018-04-03 16:55:53 +0100
commit2841af6238b7648b388ba806f1ad181332b6eef0 (patch)
treee4d7e37c599e5c3609563662fa8f3800e5a040de
parent81375516b273094f29d4e1c4fcb90d832273690a (diff)
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 <[email protected]> Reviewed-by: Scott D Phillips <[email protected]>
-rw-r--r--src/intel/common/gen_decoder.c41
1 files 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;
}