diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-18 00:04:28 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-18 00:26:02 -0400 |
| commit | 1595efde3d9a8fc08dc892fd88b48dbb84715095 (patch) | |
| tree | 9b1351cfd15274a9cd1bbca5ce829c35c7dd79f2 /kernel/gsp_phys_gpu.c | |
| parent | b16269daec0ca5838b8343e9b5f4cabd23015167 (diff) | |
| download | open-iov-1595efde3d9a8fc08dc892fd88b48dbb84715095.tar.gz open-iov-1595efde3d9a8fc08dc892fd88b48dbb84715095.zip | |
vgsp: m179 GR no-write robustness - dedicated re-execution budget + specific zero-write test + loud classified accept
The r200-r202 memcpy_roundtrip/multikernel all-wrong class: a forwarded GR
launch retires with zero tracked engine writes (NOWRITE, qmd_rel satisfied),
the m153 outcome-retry loop either never ran (it shared the timeout ladder's
attempt counter, which the fast re-arm / fresh entries had already consumed)
or exhausted, and the accept path silently restored the release words,
handing the client an all-wrong output with a fabricated completion.
Changes (kernel/gsp_phys_booter.c, gsp_phys_gpu.c, gsp_phys_gpu.h):
1. gsp_phys_gr_nowrite_retries (default 3, clamped [0,4]): the no-write
re-execution loop now has a DEDICATED budget, independent of the timeout
ladder's attempts. Each retry keeps the existing backoff mechanics (zero
release words, fresh qmdwin/win0 bank, refill bounce, rebuild PB,
re-publish + resched, fresh-ack poll, fetch witness, retire wait). Worst
case stays within the 8-entry GPFIFO ring (initial + fast re-arm + 2 fresh
entries + 3 retries = 7 publishes).
2. Specific zero-write test: gsp_phys_gr_output_retire_wait() now reports
n_tracked (the number of data entries that resolve to a bounce page); the
no-write retry/accept path only triggers when n_tracked > 0, so a launch
whose data entries resolve nothing can no longer false-positive as a lost
launch.
3. The accept (last resort after the budget) is now LOUD (pr_warn) and
classified by the QMD fetch sentinel: NOWRITE-CONFIRMED = deposit never
reached the engine (sweep/hold-faked-ack class); NOWRITE-AMBIGUOUS =
engine consumed the deposit, zero tracked writes may be a legitimately
read-only kernel. It also runs when the retry master gate is off, so a
zero-write outcome is never silent.
4. Ordering: explicit wmb() after the retry's fresh qmdwin deposit (the
first-attempt path and the publish tail already carry the barriers;
dma_wmb before GP_PUT advance + wmb before the doorbell in
gsp_phys_rmcall_publish_locked) - deposit->kick order is now explicit on
both paths.
5. Frame bound: the ~370-byte struct gsp_phys_fault_info moved to static
scratch (the function's documented single-inflight contract, same as
methods[]/qmd[]) with a per-submission memset; this clears the
pre-existing >1024-byte frame warning in the submit function instead of
growing it.
Fast re-arm (gsp_phys_gr_retry_fast) and the timeout ladder are untouched.
Build: make kernel -j - green, vgsp.ko; no warnings in touched code.
Diffstat (limited to 'kernel/gsp_phys_gpu.c')
| -rw-r--r-- | kernel/gsp_phys_gpu.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c index 95bd627..81c68b4 100644 --- a/kernel/gsp_phys_gpu.c +++ b/kernel/gsp_phys_gpu.c @@ -1021,6 +1021,38 @@ unsigned int gsp_phys_gr_first_poll_ms_value(void) EXPORT_SYMBOL_GPL(gsp_phys_gr_first_poll_ms_value); /* + * m179 no-write retry budget (gsp_phys_gr_nowrite_retries; default 3, clamped + * to [0, 4]). The m153 outcome retry loop re-executes a data-bearing launch + * whose retirement wait saw zero engine writes; it shared the timeout ladder's + * attempt counter, so a launch that had already spent attempts on the ladder + * (fast re-arm + fresh ring entries) reached the accept path with NO + * re-execution at all - the r200/r201/r202 memcpy_roundtrip / multikernel + * class (a lost launch silently accepted, client output all wrong). This + * budget is dedicated to the no-write loop and independent of the ladder; it + * is read once per submission. 0 keeps the accept-without-retry behavior + * (still logged loudly). The clamp keeps the worst-case host publishes per + * launch (initial + fast re-arm + 2 fresh entries + budget) within the + * 8-entry GPFIFO ring. + */ +static int gsp_phys_gr_nowrite_retries_param = 3; +module_param_named(gsp_phys_gr_nowrite_retries, + gsp_phys_gr_nowrite_retries_param, int, 0644); +MODULE_PARM_DESC(gsp_phys_gr_nowrite_retries, + "Dedicated re-execution budget for a data-bearing GR launch that wrote nothing tracked, clamped [0,4] (default 3)"); + +int gsp_phys_gr_nowrite_retries_value(void) +{ + int v = gsp_phys_gr_nowrite_retries_param; + + if (v < 0) + v = 0; + if (v > 4) + v = 4; + return v; +} +EXPORT_SYMBOL_GPL(gsp_phys_gr_nowrite_retries_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 * window-0 shadow pool (module pages at VAs 0x108000..0x10f000, PTEs planted |
