diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 120 |
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); |
