From de91d640757afb40b1f78d659399a5cff3e540c6 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Thu, 15 Oct 2026 17:50:52 -0400 Subject: vgsp-gr: m156 fail-closed release gate - backend half (witness + deferred release0) The engine's QMD/channel completion ack is a front-end retirement, not an execution witness. r155 live evidence: streams2's launch logged qmd_rel=6/ch_rel=0xc0ffee02 while the retirement wait saw '0/205 pages changed' on the initial attempt and all three outcome retries; the backend then returned success and the client read all-zero output (STREAMS bad=32768). The r152 matmul/smiley boots show the same signature. For a data-bearing launch (resolved operand pages + working bounce window): - new param gsp_phys_rmcall_gr_failclosed (default 1) forces release0 to the module semaphore (the m64 rel-mod shape), so the engine's ack cannot reach the guest's release word before an executor is witnessed; - when the retirement wait still saw zero writes after the bounded retries, the backend returns -EIO instead of success and logs 'FAIL-CLOSED: ... success withheld', so the sema service can withhold the guest release and fail loudly (companion commit). Set gsp_phys_rmcall_gr_failclosed=0 to restore the historical fail-open behavior. Build: make -j8 (kernel), green. --- kernel/gsp_phys_gpu.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'kernel/gsp_phys_gpu.c') diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c index 9b7235b..72884b8 100644 --- a/kernel/gsp_phys_gpu.c +++ b/kernel/gsp_phys_gpu.c @@ -973,6 +973,44 @@ int gsp_phys_rmcall_gr_nowrite_retry_value(void) } EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_nowrite_retry_value); +/* + * m156 fail-closed release gate (gsp_phys_rmcall_gr_failclosed; default 1). + * + * The engine's QMD/channel completion ack is a front-end retirement, not an + * execution witness: the r155 live log shows launches reporting + * qmd_rel=6/ch_rel=0xc0ffee02 with the retirement wait observing + * "0/205 pages changed" on the initial attempt and all three outcome + * retries, after which the backend returned success and the client + * (streams2) read all-zero output (STREAMS bad=32768) while the soft + * release machinery also authored the completion for never-attempted + * captures. For a data-bearing launch (resolved operand pages exist) the + * completion release must therefore be host-owned and gated on an observed + * engine write: + * + * - release0 is routed to the module semaphore (the m64 rel-mod shape) so + * the engine's ack cannot reach the guest's release word; + * - the backend returns an error (not success) when the retirement wait + * still saw zero writes after the bounded retries, so the sema service + * holds the guest release instead of authoring it; + * - the sema service delivers a channel error for the withheld release so + * the client observes a launch failure, never stale/zero data as + * success. + * + * Set to 0 to restore the historical fail-open behavior (engine-authored + * release, success returned regardless of writes). + */ +static int gsp_phys_rmcall_gr_failclosed_param = 1; +module_param_named(gsp_phys_rmcall_gr_failclosed, + gsp_phys_rmcall_gr_failclosed_param, int, 0644); +MODULE_PARM_DESC(gsp_phys_rmcall_gr_failclosed, + "Withhold a data-bearing forwarded GR launch's completion release unless the engine wrote data (default 1 = fail closed)"); + +int gsp_phys_rmcall_gr_failclosed_value(void) +{ + return gsp_phys_rmcall_gr_failclosed_param; +} +EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_failclosed_value); + /* * m69 window-0 shadow pool (gsp_phys_rmcall_gr_shadow_win0; default 0). When * set, the forwarded GR launch copies the QMD's program/param pages into the -- cgit v1.2.3