summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 4c05935..4a64a4f 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -17892,6 +17892,122 @@ static void svc_mme_census(const u8 *buf, u32 len, u64 push_va, u32 h_object)
}
/*
+ * eng26 (CONT.487): draw-marker census over every readable client push.
+ *
+ * The eng25 (CONT.486) decode proved the beef 779-word "draw" window carries
+ * NO primitive: zero BEGIN 0x1618 / END 0x1614 / VA/index/vertex markers; its
+ * 256-word INC run is non-method data that merely NUMERICALLY covers the C597
+ * colour-target block, and the guard clause (svc_gl_window_rt_valid) now
+ * refuses it. The open question for the next green cycle is where the
+ * direct-GL client's real draw lives (which push, which offset) - or that its
+ * draws ride a shape the decode loop never sees. This read-only census scans
+ * every push (any non-engine channel) with the canonical op/cnt grammar and
+ * logs a bounded row per push that contains any draw-family method id:
+ * BEGIN 0x1618, END 0x1614, VA_START 0xd74, DRAW_VERTEX_ARRAY 0xd78,
+ * index 0x17c8/0x17d8/0x17e0, draw list 0x1b0, streams 0x1c00/0x1c10.
+ * For multi-word runs the hit carries the method's word index inside the run
+ * (`m@off+k=v`), so a run that only spans a method address is distinguishable
+ * from a real method data word (a real BEGIN's value is its topology, e.g.
+ * 0x01047220). Beef-family pushes with no hits are still enumerated once per
+ * (va,len) so a single cycle yields the full push inventory.
+ * Bounded: 256 hit rows + 256 push rows per boot; read-only.
+ */
+#define SVC_DRAWCENSUS_MAX 256u
+#define SVC_DRAWCENSUS_DEDUP 64u
+
+static u32 svc_drawcensus_flag;
+module_param_named(sema_draw_census, svc_drawcensus_flag, uint, 0644);
+MODULE_PARM_DESC(sema_draw_census,
+ "Draw-marker census (BEGIN 0x1618 / END 0x1614 / 0xd74 / 0xd78 / 0x17c8,0x17d8,0x17e0 / 0x1b0 / 0x1c00,0x1c10) over client pushes, bounded (default 0)");
+
+static u32 svc_drawcensus_hit_n;
+static u32 svc_drawcensus_push_n;
+static u64 svc_drawcensus_va[SVC_DRAWCENSUS_DEDUP];
+static u32 svc_drawcensus_len[SVC_DRAWCENSUS_DEDUP];
+static u32 svc_drawcensus_dedup_pos;
+
+static bool svc_drawcensus_method(u32 m)
+{
+ return m == 0x1618u || m == 0x1614u ||
+ m == 0xd74u || m == 0xd78u ||
+ m == 0x17c8u || m == 0x17d8u || m == 0x17e0u ||
+ m == 0x1b0u ||
+ m == 0x1c00u || m == 0x1c10u;
+}
+
+static void svc_gl_draw_census(const u8 *buf, u32 len, u64 push_va,
+ u32 h_object)
+{
+ char hits[640];
+ u32 off = 0, nhit = 0;
+ int lc = 0;
+ bool newpush = false;
+
+ if (!READ_ONCE(svc_drawcensus_flag) || !buf || len < 8u)
+ return;
+ /* dedup ring: one PUSH row per (va,len) for beef-family pushes */
+ if ((h_object & 0xfffff000u) == 0xbeef0000u) {
+ u32 di;
+
+ for (di = 0; di < SVC_DRAWCENSUS_DEDUP; di++) {
+ if (svc_drawcensus_va[di] == push_va &&
+ svc_drawcensus_len[di] == len)
+ break;
+ }
+ if (di == SVC_DRAWCENSUS_DEDUP) {
+ newpush = true;
+ svc_drawcensus_va[svc_drawcensus_dedup_pos] = push_va;
+ svc_drawcensus_len[svc_drawcensus_dedup_pos] = len;
+ svc_drawcensus_dedup_pos =
+ (svc_drawcensus_dedup_pos + 1u) %
+ SVC_DRAWCENSUS_DEDUP;
+ }
+ }
+ while (off + 4u <= len && nhit < 20u) {
+ u32 hdr, op, cnt, m, k, span = 1u;
+
+ memcpy(&hdr, buf + off, 4);
+ op = (hdr >> 29) & 7u;
+ cnt = (hdr >> 16) & 0xfffu;
+ m = (hdr & 0x1fffu) << 2;
+ if ((op == 1u || op == 3u || op == 5u) && cnt &&
+ off + 4u + cnt * 4u <= len) {
+ span = 1u + cnt;
+ for (k = 0; k < cnt && nhit < 20u; k++) {
+ u32 mm = m + 4u * k, v;
+
+ if (!svc_drawcensus_method(mm))
+ continue;
+ memcpy(&v, buf + off + 4u + k * 4u, 4);
+ lc += scnprintf(hits + lc, sizeof(hits) - lc,
+ "%s0x%x@0x%x+%u=%08x",
+ nhit ? "," : "", mm, off, k, v);
+ nhit++;
+ }
+ } else if ((op == 4u || op == 7u) &&
+ svc_drawcensus_method(m)) {
+ u32 v = (hdr >> 16) & 0x1fffu;
+
+ lc += scnprintf(hits + lc, sizeof(hits) - lc,
+ "%s0x%x@0x%x(imm)=%08x",
+ nhit ? "," : "", m, off, v);
+ nhit++;
+ }
+ off += span * 4u;
+ }
+ if (nhit && svc_drawcensus_hit_n < SVC_DRAWCENSUS_MAX) {
+ svc_drawcensus_hit_n++;
+ pr_info("sema-drawcensus: HITS h=0x%x va=0x%llx len=%u n=%u hits=[%s]\n",
+ h_object, push_va, len, nhit, hits);
+ }
+ if (!nhit && newpush && svc_drawcensus_push_n < SVC_DRAWCENSUS_MAX) {
+ svc_drawcensus_push_n++;
+ pr_info("sema-drawcensus: PUSH h=0x%x va=0x%llx len=%u (no draw markers)\n",
+ h_object, push_va, len);
+ }
+}
+
+/*
* SESSION 153-CONTINUED-101: MME fixed-constant-buffer scratch watch.
*
* mmeCodeOGL_C597_SETUP_FIXED_CONST (macro slot 0) is the only reader of
@@ -21632,6 +21748,10 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
if (ch)
svc_mme_census(buf, len, push_va, ch->h_object);
+ /* eng26 (CONT.487): draw-marker census over every client push. */
+ if (ch && !ch->engine_type)
+ svc_gl_draw_census(buf, len, push_va, ch->h_object);
+
/* SESSION 153-CONTINUED-101: fixed-CB scratch (0x3460) watch, any channel. */
if (ch)
svc_scratch18_watch(buf, len, push_va, ch->h_object);