summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-01 13:29:26 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-01 13:29:26 -0500
commitbf5710a6a14fcaa277e3cac28da3eef976bb9e9b (patch)
tree49ddfe23500d2236898503ccfc82b4bc3e48d74c
parentd4a10ced7a4e8fa8ab65fdab1596190f5d567775 (diff)
downloadopen-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.c59
-rw-r--r--kernel/gsp_sema_service.c82
-rw-r--r--kernel/gsp_sema_service.h10
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).