summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c83
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) {