summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_rm_emulation.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-22 15:47:32 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-22 15:47:32 -0400
commit737aabc28bb4340e80cf801abf85cfc9e6443644 (patch)
treeb79567240a0c4992f8954a88770fb1d6588d50e1 /kernel/gsp_rm_emulation.c
parenta42fdb2cbe6a9b294a160860f38485ba1eb93c34 (diff)
downloadopen-iov-737aabc28bb4340e80cf801abf85cfc9e6443644.tar.gz
open-iov-737aabc28bb4340e80cf801abf85cfc9e6443644.zip
r487 THE GL/VULKAN VASPACE WALL: clamp RM_CONTROL replies to the 64 KB wire record bound (16 x 4096; guest GspMsgQueueReceiveStatus rejects hdr + rpc.length beyond it - 'Incorrect message length 67448', rpcRecvPoll 0x3a, NV_ERR_INVALID_PARAMETER). The stock driver sends PERF_VPSTATES_INFO (0x2080a0a4, paramsSize 67392) during Xorg VASpace construction; the generic reply echoed the whole buffer as a 17-element record the guest refused, vmmCreateVaspace returned ffff and GL died with 'Failed to allocate VASpace object' / EGL_BAD_ALLOC on every prior session. A real GSP-RM cannot reply past the bound either; the echo is clamped with the tail zeroed
Diffstat (limited to 'kernel/gsp_rm_emulation.c')
-rw-r--r--kernel/gsp_rm_emulation.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index cd9cbf2..10633ab 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -3409,6 +3409,34 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx,
break;
}
+ /*
+ * r487 THE GL/VULKAN VASPACE WALL (Xorg/EGL/GZDOOM, every session to
+ * date): the wire RPC record is bounded at 16 x 4096 bytes
+ * (GSP_MSG_QUEUE_ELEMENT_SIZE_MIN * 16 = 65536; the guest's
+ * GspMsgQueueReceiveStatus rejects any record whose
+ * hdr + rpc.length exceeds it - observed "Incorrect message length
+ * 67448", rpcRecvPoll status 0x3a, NV_ERR_INVALID_PARAMETER at
+ * rpc.c:9998). The stock driver sends large in/out controls
+ * (NV2080_CTRL_CMD_PERF_VPSTATES_INFO 0x2080a0a4 paramsSize=67392
+ * during Xorg VASpace construction) and the generic reply echoed the
+ * whole params buffer - a 17-element record the guest refused, so
+ * the control failed, vmmCreateVaspace returned ffff and GL died
+ * with "Failed to allocate VASpace object" / EGL_BAD_ALLOC. A real
+ * GSP-RM cannot reply past the wire bound either; clamp the echoed
+ * params to the largest record the queue carries
+ * (65536 - guest elem hdr 8 - rpc hdr 32 - ctrl hdr 24), the tail
+ * staying zero exactly like the small-control generic reply.
+ */
+#define GSPRM_WIRE_REPLY_PARAMS_MAX \
+ (GSPRM_QUEUE_ELEMENT_SIZE * 16 - 8 - 32 - GSP_RM_CTRL_HDR_SIZE)
+ if (out_params_size > GSPRM_WIRE_REPLY_PARAMS_MAX) {
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: RM_CONTROL cmd=0x%x out=%u clamped to %u (wire record limit; guest would reject the record)",
+ req.cmd, out_params_size,
+ (u32)GSPRM_WIRE_REPLY_PARAMS_MAX);
+ out_params_size = GSPRM_WIRE_REPLY_PARAMS_MAX;
+ }
+
/* Build the reply header */
memcpy(reply + 0, &req.hClient, 4);
memcpy(reply + 4, &req.hObject, 4);