freedreno/cffdec: Fix decode on pixel 2 blob's COMPUTE_CHECKPOINT
authorEric Anholt <eric@anholt.net>
Thu, 25 Feb 2021 19:51:05 +0000 (11:51 -0800)
committerMarge Bot <emma+marge@anholt.net>
Tue, 8 Aug 2023 18:51:59 +0000 (18:51 +0000)
dEQP-GLES31.functional.image_load_store.buffer.image_size.writeonly_7
produces:

t7 opcode: CP_COMPUTE_CHECKPOINT (6e) (8 dwords)
{ ADDR_0_LO = 0x15000 }
{ ADDR_0_HI = 0x5 }
0x18
{ ADDR_1_LEN = 3 }
0xf
{ ADDR_1_LO = 0x2e010 }
{ ADDR_1_HI = 0x5 }

and it was asserting due to sizedwords==7.  Without the assert, we were
dereffing a len past the end of the packet.  This len value we were
loading is also suspiciously not the location of the ADDR_1_LEN field in
the packet's XML.  But then, the command stream at ADDR_1 was clearly 0xf
long, and that puts ADDR_1_LEN at the spot we would expect compared to
SET_RENDER_MODE's ADDR_1.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24358>

src/freedreno/decode/cffdec.c
src/freedreno/registers/adreno/adreno_pm4.xml

index 57d8a66..17b43ec 100644 (file)
@@ -2764,11 +2764,15 @@ cp_compute_checkpoint(uint32_t *dwords, uint32_t sizedwords, int level)
    assert(is_64b());
    assert(options->gpu_id >= 500);
 
-   assert(sizedwords == 8);
-
-   addr = dwords[5];
-   addr |= ((uint64_t)dwords[6]) << 32;
-   len = dwords[7];
+   if (sizedwords == 8) {
+      addr = dwords[5];
+      addr |= ((uint64_t)dwords[6]) << 32;
+      len = dwords[7];
+   } else {
+      addr = dwords[5];
+      addr |= ((uint64_t)dwords[6]) << 32;
+      len = dwords[4];
+   }
 
    printl(3, "%saddr: 0x%016" PRIx64 "\n", levels[level], addr);
    printl(3, "%slen:  0x%x\n", levels[level], len);
index 2450929..0857c5a 100644 (file)
@@ -1580,11 +1580,11 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
        </reg32>
        <reg32 offset="2" name="2">
        </reg32>
+       <reg32 offset="3" name="3"/>
        <!-- second buffer looks like some cmdstream.. length in dwords: -->
-       <reg32 offset="3" name="3">
+       <reg32 offset="4" name="4">
                <bitfield name="ADDR_1_LEN" low="0" high="31" type="uint"/>
        </reg32>
-       <reg32 offset="4" name="4"/>
        <reg32 offset="5" name="5">
                <bitfield name="ADDR_1_LO" low="0" high="31"/>
        </reg32>