diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index e0f1897..4c05935 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -11766,6 +11766,69 @@ static void svc_gl_watch_note(const struct svc_channel *ch, const char *why, svc_gl.blob_len, svc_gl.subch); } +/* + * eng25 (CONT.486): last-write colour-target validity for a beef-family + * draw-synth window. The direct-GL draw captures admitted by the r929/eng24 + * lane can be non-method data whose large INC run happens to cover the + * C597 RT block (c344: window push=0x4010ed0, 7-word SURF prelude then + * 31000201 = INC cnt=0x100 mthd=0x804). That run's last RT writes are + * RT0 A=0x00 B=0x041e0f0c W=0x040f4800 H=0x02027b60 + * RT1 A=0xff B=0x000480a1 W=0x000ea200 H=0x000b7326 -> VA 0xff000480a0 + * i.e. it OVERWRITES the prelude's valid 0x0c000000 bind with an unmapped + * 40-bit VA; the engine then retires the stream with no stores + * (NOWRITE wrote=0). Require at least one target whose LAST A/B/W/H is a + * usable bind before the window is admitted/replayed. The X-lane window + * (RT1 A=0 B=0x15d0000 W=0x780 H=0x438) passes; the c344 beef window fails. + */ +static bool svc_gl_window_rt_valid(const u8 *buf, u32 len, u32 start_off, + u32 at_off) +{ + u32 A[4] = { 0 }, B[4] = { 0 }, W[4] = { 0 }, H[4] = { 0 }; + bool seen[4] = { false }; + u32 o = start_off, j; + + if (!buf || start_off >= at_off || at_off > len) + return false; + while (o + 4u <= at_off) { + u32 h, op, cnt, m, span = 1u, k; + + memcpy(&h, buf + o, 4); + op = (h >> 29) & 7u; + cnt = (h >> 16) & 0xfffu; + m = (h & 0x1fffu) << 2; + if ((op == 1u || op == 3u || op == 5u) && cnt && + o + 4u + cnt * 4u <= at_off) + span = 1u + cnt; + for (k = 0; k < span; k++) { + u32 mm = m + 4u * k, v = 0; + + if (k && op != 1u && op != 3u) + break; + if (k) + memcpy(&v, buf + o + 4u + k * 4u, 4); + else if (op == 4u) + v = (h >> 16) & 0x1fffu; + else + continue; + for (j = 0; j < 4u; j++) { + u32 base = 0x800u + j * 0x40u; + + if (mm == base) { A[j] = v; seen[j] = true; } + else if (mm == base + 4u) { B[j] = v; seen[j] = true; } + else if (mm == base + 8u) { W[j] = v; seen[j] = true; } + else if (mm == base + 0xcu) { H[j] = v; seen[j] = true; } + } + } + o += span * 4u; + } + for (j = 0; j < 4u; j++) + if (seen[j] && (A[j] & ~0xffu) == 0 && (A[j] & 0xffu) <= 1u && + B[j] < 0x40000000u && (B[j] & 3u) == 0 && + W[j] > 0 && W[j] <= 0x4000u && H[j] > 0 && H[j] <= 0x4000u) + return true; + return false; +} + static void svc_gl_flush(struct nv_vgpu_device *vgpu, struct svc_channel *ch, const struct svc_push_state *st, const u8 *buf, @@ -12846,7 +12909,8 @@ static void svc_gl_flush(struct nv_vgpu_device *vgpu, */ if ((op_src[0] == 's' || op_src[0] == 'h' || (op_src[0] == 'd' && - (ch->h_object & 0xfffff000u) == 0xbeef0000u)) && + (ch->h_object & 0xfffff000u) == 0xbeef0000u && + svc_gl_window_rt_valid(buf, len, svc_gl.start_off, at_off))) && svc_gr_cand.valid && len == svc_gr_cand.push_n * 4 && svc_gl.start_off + 8u <= at_off && @@ -12872,7 +12936,22 @@ static void svc_gl_flush(struct nv_vgpu_device *vgpu, * diagnostic below names the failing condition (the next * bound to size). */ - if (len == svc_gr_cand.push_n * 4 && + if (op_src[0] == 'd' && + !svc_gl_window_rt_valid(buf, len, svc_gl.start_off, + at_off)) { + /* eng25: bounded witness when a beef draw-synth + * window is refused - its last colour-target bind + * is not a usable C597 RT (see the clause above). */ + if (svc_gl_mark_log < 64) { + svc_gl_mark_log++; + pr_info("sema-gl: 3D mark rejected (beef draw-synth: no valid last colour-target bind) h=0x%x push=0x%llx win=%u words @off=0x%x\n", + ch->h_object, push_va, + at_off > svc_gl.start_off ? + (at_off - svc_gl.start_off) / 4u : + 0u, + svc_gl.start_off); + } + } else if (len == svc_gr_cand.push_n * 4 && svc_gl.start_off + 8u <= at_off) { svc_gl_stream_chunks(ch, buf, len, at_off); } else if (gsp_sema_dbg && svc_gl_mark_log < 64) { |
