diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-01 13:29:26 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-01 13:29:26 -0500 |
| commit | bf5710a6a14fcaa277e3cac28da3eef976bb9e9b (patch) | |
| tree | 49ddfe23500d2236898503ccfc82b4bc3e48d74c | |
| parent | d4a10ced7a4e8fa8ab65fdab1596190f5d567775 (diff) | |
| download | open-iov-bf5710a6a14fcaa277e3cac28da3eef976bb9e9b.tar.gz open-iov-bf5710a6a14fcaa277e3cac28da3eef976bb9e9b.zip | |
vgsp: CONT-94 - svc_init_push_scan (per-beef-push census of SET_SHADER_LOCAL_MEMORY_A..D 0x790-0x79c + host-side verbatim capture first >=4KiB beef push per boot INIT-CAP) + gsp-phys-init-push debugfs - lmem lead REFUTED 4 ways: INIT-CAP h=0xbeef0100 va=0x4021004 len=60216 lmem_runs=0; 60216B init push decodes to words:15054 distinct methods:2 = pure MME microcode (0x114x213/0x11c x213), 0 lmem hits; addr=0x79[0-9a-c] in 64 pushraw dumps = 0; whole-RAM scans no genuine run (x86 code bytes only); driver emission point exists (gf100Init.c:1344 gf100program.c:1479) but 570.144 never pushes it here; per-window latch unchanged ds=a6000e20 x5 + first a2000a00 sph=0,00600900,00600200,0,0,00600000 rr=0,0; oracle DS_HWW_ESR 80000000 DS_REPORT_MASK 0 DS_SPH_REGION_A/B 0/0 GR_FIFO 00000001; wedge persists (PARK-RECOVER #11 rc=-110); next: prove client's promoted GR context buffer engine-visible on replay channel at launch - instrument PROMOTE_CTX engine=1 entry[0] pa=0x234200000/va=0x120420000 size=0x133000 bInitialize=1 binding; if absent install it (SPH validation vs zero context matches rr=0/0); parallel decode fwimage DS_HWW_ESR handler (off 0x11a908 SPH0..30) w/ risc-v-gsp-rm-debugger - SESSION 153 r1321
| -rw-r--r-- | kernel/gsp_phys_booter.c | 59 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.c | 82 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.h | 10 |
3 files changed, 151 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index ef882cc..027c81c 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -30621,6 +30621,54 @@ static const struct file_operations gsp_phys_pgraph_fops = { .write = gsp_phys_pgraph_write, }; +/* + * SESSION 153-CONTINUED-94: gsp-phys-init-push - the first large beef push + * captured at decode time (see svc_init_push_scan). Prints a header with + * the push address/length, the local-memory-run count (SET_SHADER_LOCAL_ + * MEMORY_A..D seen in ANY beef push so far; 0 = the client never emitted + * the download-state local-memory block) and the bytes as 16-byte rows. + */ +static int gsp_phys_init_push_show(struct seq_file *m, void *unused) +{ + const u8 *buf; + u32 len, h, lmem, off; + u64 va; + + buf = gsp_sema_init_cap_get(&len, &h, &va, &lmem); + if (!len) { + seq_puts(m, "vgsp-init-push: empty (no >=4 KiB beef push with non-zero head captured yet)\n"); + return 0; + } + seq_printf(m, "vgsp-init-push: h=0x%x va=0x%llx len=%u lmem_runs=%u\n", + h, va, len, lmem); + for (off = 0; off + 4u <= len; off += 16u) { + u32 k, n = min_t(u32, 4u, (len - off) / 4u); + + seq_printf(m, "%06x:", off); + for (k = 0; k < n; k++) { + u32 w; + + memcpy(&w, buf + off + k * 4u, 4); + seq_printf(m, " %08x", w); + } + seq_putc(m, '\n'); + } + return 0; +} + +static int gsp_phys_init_push_open(struct inode *inode, struct file *file) +{ + return single_open(file, gsp_phys_init_push_show, NULL); +} + +static const struct file_operations gsp_phys_init_push_fops = { + .owner = THIS_MODULE, + .open = gsp_phys_init_push_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + int gsp_phys_boot_debugfs_init(void) { struct dentry *file; @@ -30801,6 +30849,17 @@ int gsp_phys_boot_debugfs_init(void) &gsp_phys_pgraph_fops); if (IS_ERR_OR_NULL(file)) pr_warn("vgsp-boot: debugfs file gsp-phys-pgraph-rw creation failed (PGRAPH register lab unavailable)\n"); + /* + * SESSION 153-CONTINUED-94: the captured first large beef push (the + * GL client's channel-init stream) verbatim, so the local-memory + * census and any other method in it can be verified offline after + * the guest's transient pushbuffer is gone. Diagnostic only. + */ + file = debugfs_create_file("gsp-phys-init-push", 0444, + gsp_phys_debugfs_root, NULL, + &gsp_phys_init_push_fops); + if (IS_ERR_OR_NULL(file)) + pr_warn("vgsp-boot: debugfs file gsp-phys-init-push creation failed (init-push capture unavailable)\n"); pr_info("vgsp-boot: debugfs files /sys/kernel/debug/vgsp/{gsp-phys-state read-only, gsp-phys-log-dump read-only, gsp-phys-status-drain read-only, gsp-phys-reg-probe read-only, gsp-phys-ds-spy read-only, gsp-phys-unload-rpc write-only, gsp-phys-rm-probe write-only, gsp-phys-rm-call write-only, gsp-phys-guest-gpa write-only, gsp-phys-guest-ram write-only} ready\n"); return 0; } diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index e96b929..c30cc22 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -14637,6 +14637,84 @@ static void svc_mme_census(const u8 *buf, u32 len, u64 push_va, u32 h_object) } /* + * SESSION 153-CONTINUED-94: client init-push capture + local-memory census. + * + * CONT-93's "single most concrete next fix" was that the GL driver's + * download-state LOCAL MEMORY push (SET_SHADER_LOCAL_MEMORY_A/B/C/D, + * 0x790-0x79c) is the last channel-init class missing from the replayed + * context. The claim is directly decidable at this decode site: every + * client push that reaches the service is walked once, so any INC run at + * 0x790..0x79c is counted and logged with its values (bounded). The + * guest-RAM scrape alone cannot settle it: the client's pushbuffer is + * transient (the staging copies observed at init read back all-zero + * minutes later), so the first large beef push of a boot is preserved + * host-side and dumped through the gsp-phys-init-push debugfs file. + * Read-only instrumentation; beef channels only. + */ +#define SVC_INIT_CAP_BYTES (64u * 1024u) +static u8 svc_init_cap[SVC_INIT_CAP_BYTES]; +static u32 svc_init_cap_len; +static u32 svc_init_cap_h; +static u64 svc_init_cap_va; +static bool svc_init_cap_done; +static u32 svc_lmem_hits; +static u32 svc_lmem_seen; + +static void svc_init_push_scan(const u8 *buf, u32 len, u64 push_va, u32 h_object) +{ + u32 off = 0; + + if ((h_object & 0xfffff000u) != 0xbeef0000u) + return; + while (off + 4u <= len) { + u32 hdr, op, cnt, m; + + memcpy(&hdr, buf + off, 4); + op = (hdr >> 29) & 7u; + cnt = (hdr >> 16) & 0xfffu; + m = (hdr & 0x1fffu) << 2; + if (m >= 0x790u && m <= 0x79cu && + (op == 1u || op == 3u || op == 5u) && + cnt >= 1u && cnt <= 8u && off + 4u + cnt * 4u <= len) { + svc_lmem_seen++; + if (svc_lmem_hits < 16u) { + u32 k, v[4] = {0, 0, 0, 0}; + + for (k = 0; k < cnt && k < 4u; k++) + memcpy(&v[k], buf + off + 4u + k * 4u, 4); + svc_lmem_hits++; + pr_info("vgsp-sema: INIT-LMEM h=0x%x va=0x%llx m=0x%x cnt=%u vals=%08x,%08x,%08x,%08x\n", + h_object, push_va, m, cnt, + v[0], v[1], v[2], v[3]); + } + } + if ((op == 1u || op == 3u || op == 5u) && cnt && cnt <= 0xfffu) + off += 4u + cnt * 4u; + else + off += 4u; + } + if (!svc_init_cap_done && len >= 4096u && + memchr_inv(buf, 0, min_t(u32, len, 64u))) { + svc_init_cap_len = min_t(u32, len, SVC_INIT_CAP_BYTES); + memcpy(svc_init_cap, buf, svc_init_cap_len); + svc_init_cap_h = h_object; + svc_init_cap_va = push_va; + svc_init_cap_done = true; + pr_info("vgsp-sema: INIT-CAP h=0x%x va=0x%llx len=%u lmem_runs=%u (gsp-phys-init-push)\n", + h_object, push_va, svc_init_cap_len, svc_lmem_seen); + } +} + +const u8 *gsp_sema_init_cap_get(u32 *len, u32 *h, u64 *va, u32 *lmem_seen) +{ + *len = svc_init_cap_len; + *h = svc_init_cap_h; + *va = svc_init_cap_va; + *lmem_seen = svc_lmem_seen; + return svc_init_cap; +} + +/* * SESSION 153-CONTINUED-53: MME context-setup prelude buffer. * * The draw-window replay raises a real MME ILLEGAL_OPCODE @@ -16062,6 +16140,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); + /* SESSION 153-CONTINUED-94: init-push capture + local-memory census. */ + if (ch) + svc_init_push_scan(buf, len, push_va, ch->h_object); + /* * SESSION 153-CONTINUED-53: MME context-setup prelude capture. Only a * trusted resolution feeds the buffer (the bytes are replayed into a diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h index 0f22904..24e1094 100644 --- a/kernel/gsp_sema_service.h +++ b/kernel/gsp_sema_service.h @@ -235,6 +235,16 @@ void gsp_sema_service_fwd_gr_stats(u64 *req, u64 *ok, u64 *fallback, u64 *refused, u64 *timeout, u64 *fault); /* + * SESSION 153-CONTINUED-94: the first large beef-channel push of the boot, + * preserved verbatim for the gsp-phys-init-push debugfs dump (the client's + * pushbuffer is transient in guest RAM). Returns the buffer pointer and + * fills len/h/va; lmem_seen counts any SET_SHADER_LOCAL_MEMORY_A..D + * (0x790..0x79c) runs seen in beef pushes so far (0 = the GL client never + * emitted the download-state local-memory block). + */ +const u8 *gsp_sema_init_cap_get(u32 *len, u32 *h, u64 *va, u32 *lmem_seen); + +/* * Discover and pin GR (compute) channel rings after the CE region of the * channel video-memory allocation. Set false to leave GR rings untranslated * (the pump then only runs the CE channels). |
