intel: gen-decoder: don't decode fields beyond a dword length
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Tue, 3 Apr 2018 10:01:56 +0000 (11:01 +0100)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Tue, 3 Apr 2018 15:55:53 +0000 (16:55 +0100)
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 <lionel.g.landwerlin@intel.com>
Reviewed-by: Scott D Phillips <scott.d.phillips@intel.com>
src/intel/common/gen_decoder.c

index 7ca71c0d9fc86decd3420ab2aaf91c73224e7585..595fa29e43d073463c6bef52354be5713d8cf097 100644 (file)
@@ -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;
 }