From de3b32e38ebb9a143ed9b74018fdd7ffb4a43657 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 6 Nov 2026 08:47:08 -0500 Subject: vgsp-gl: decode the 570.144 MME-wrapper fixed-CB upload form The guest GL driver streams the fixed constant buffer through the C597 MME macros, not the native SET_CONSTANT_BUFFER_SELECTOR/LOAD_CONSTANT_BUFFER methods the r1515 scanner decodes: - CALL_MME_MACRO(0) = SETUP_FIXED_CONST arrives as an IMMD run at method 0x3800 carrying the VPC dword offset (the macro converts it to a byte address, so the fixed-CB offset is imm << 2). - CALL_MME_MACRO(57) = LOAD_CONSTANT_BUFFER_BUG2548370 arrives as a run at 0x39c8 whose payload is [count][count dwords]; the macro writes the data at the current fixed-CB offset and auto-increments it. - CALL_MME_MACRO(58) = LOAD_CONSTANT_BUFFER_OFFSET arrives at 0x39d0 with [offsetBytes]. r1517's own CHUNK1 dump of the 7144-byte draw window carries the real glxgears MVP this way (pixel-space 5.0/6.667 scales, -1.1818/36.3636 near/far row and the -1/40 w row = glFrustum(-1,1,-0.75,0.75,5,60) x translate(0,0,-40)); the old scanner ignored those runs, assembled only the 10 state-patch words, and the strict gate never passed, so every launch ran with the synthetic identity and the geometry clipped. With the wrapper form decoded the assembled 4 KB image carries the client's real MVP at c[0x0][0x80..0xbc], passes svc_gl_cb_mvp_ok(), and svc_gl_cb_copy() delivers it to the forced MME seed page as src=const-upload (src_ssrc=15) instead of synthetic-id. --- kernel/gsp_sema_service.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 2f08064..576582a 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -15894,6 +15894,17 @@ static void svc_gl_cb_upload_scan(struct nv_vgpu_device *vgpu, u32 h_object, 0xffffffffULL) | ((u64)w << 32); svc_gl_cb_sel_seen = true; + } else if (addr == 0x3800u) { + /* + * MME-wrapper form (570.144): the driver emits + * CALL_MME_MACRO(0) = SETUP_FIXED_CONST as an + * IMMD whose payload is the VPC dword offset + * (VPC_CONSTANT_DWORD(offs) = offs << 2); the + * macro converts it to the byte address the + * following LOAD_CONSTANT_BUFFER run writes at. + */ + svc_gl_cb_off = w << 2; + dirty = true; } off += 4u; continue; @@ -15960,6 +15971,44 @@ static void svc_gl_cb_upload_scan(struct nv_vgpu_device *vgpu, u32 h_object, base = (u64)w << 8; if (base && base != svc_gl_cb_img_base) svc_gl_cb_img_reset(base); + } else if (addr == 0x39c8u) { + /* + * MME-wrapper form (570.144): the driver emits + * CALL_MME_MACRO(57) = + * mmeCodeOGL_C597_LOAD_CONSTANT_BUFFER_BUG2548370 + * with the argument stream inline in the run: + * [count][count dwords]. The macro writes the data + * words at the current fixed-CB offset and + * auto-increments, exactly like the native + * LOAD_CONSTANT_BUFFER(i) form. + */ + u32 n; + + memcpy(&n, buf + off + 4u, 4); + if (n > cnt - 1u) + n = cnt - 1u; + for (i = 0; i < n; i++) { + u64 doff = (u64)svc_gl_cb_off + + 4ULL * (u64)i; + + if (doff + 4ULL > SVC_GL_CB_IMG_LIMIT) + continue; + memcpy(&w, buf + off + 8u + 4u * i, 4); + memcpy(svc_gl_cb_img + doff, &w, 4); + words++; + dirty = true; + } + runs++; + svc_gl_cb_off += 4u * n; + } else if (addr == 0x39d0u) { + /* + * CALL_MME_MACRO(58) = + * mmeCodeOGL_C597_LOAD_CONSTANT_BUFFER_OFFSET: + * argument stream is [offsetBytes]. + */ + memcpy(&w, buf + off + 4u, 4); + svc_gl_cb_off = w; + dirty = true; } else if (addr >= 0x2390u && addr < 0x2390u + 0x1000u) { u32 idx = (addr - 0x2390u) / 4u; -- cgit v1.2.3