summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-15 10:44:19 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-15 10:44:19 -0400
commit02249afd91f4ee02589a07657d130b9b9411debd (patch)
treede9cc2d6c23e78593fe1fbbab4c831e420ae59ab /kernel
parent5a446c10c3ffa9180328180318163b46cb00a16d (diff)
downloadopen-iov-02249afd91f4ee02589a07657d130b9b9411debd.tar.gz
open-iov-02249afd91f4ee02589a07657d130b9b9411debd.zip
vgsp-gr: m153 retry only on zero writes (drop wrong-place heuristic)
Live r153 evidence: the highest-reloc data entry (bi=204) is a UVM-internal buffer that correct launches never write, so the 'top operand untouched' condition fired on correct executions and re-executed them up to 3x - a correctness hazard for side-effecting kernels (atomics/printf) and pure waste otherwise. The honest execution witness is the retirement wait's changed count; only zero-writes retries now (safe by construction: a kernel that wrote nothing has nothing to duplicate). Read-only kernels pay the bounded extra polls.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c73
1 files changed, 18 insertions, 55 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 9c19efb..123f93d 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -18351,72 +18351,35 @@ gr_page_unmapped:
* gsp_phys_gr_output_retire_wait().
*
* m153: outcome-verifying retry. The intermittent per-boot
- * mis-execution classes (engine wrote nothing at all; or it wrote
- * into a lower operand window while the highest - output - operand
- * stayed untouched) both complete with qmd_rel/ch_rel satisfied, so
- * they cannot be caught by the completion poll. The retirement wait
- * is the only execution witness. When it saw zero writes, or writes
- * that skipped the highest-reloc operand (n_data >= 2), refill the
- * bounce window from the guest inputs, re-publish the same method
- * block on a fresh ring entry, re-issue the schedule and re-poll,
- * then re-wait - bounded by the same attempt budget as the timeout
- * path. After the budget the launch proceeds to copy-out with
- * whatever the engine produced (a genuinely read-only kernel is
- * indistinguishable here and simply pays the bounded extra polls).
+ * no-execution class (qmd_rel/ch_rel satisfied but the engine wrote
+ * nothing at all) cannot be caught by the completion poll; the
+ * retirement wait is the only execution witness. On zero writes,
+ * refill the bounce window from the guest inputs, re-publish the
+ * same method block on a fresh ring entry, re-issue the schedule and
+ * re-poll, then re-wait - bounded by the same attempt budget as the
+ * timeout path. After the budget the launch proceeds to copy-out
+ * with whatever the engine produced: a genuinely read-only kernel is
+ * indistinguishable from a no-execution here and simply pays the
+ * bounded extra polls (safe to re-execute by construction - a kernel
+ * that writes nothing has no side effects to duplicate). A
+ * wrong-place write detector was tried and removed: the highest-reloc
+ * data entry is often a UVM-internal buffer, not the output, so it
+ * false-fired on correct launches and would re-execute
+ * side-effecting kernels (atomics) up to 3x.
*/
if (req->n_data && boot_stage.rmcall_gr_bounce.pages) {
u32 wrote = gsp_phys_gr_output_retire_wait(req, bounce_csum_in);
if (gsp_phys_rmcall_gr_nowrite_retry_value()) {
- u64 top_reloc = 0;
- u32 top_bi = 0xffffffffu, di2;
-
- for (di2 = 0; di2 < req->n_data; di2++) {
- u64 rv = req->data[di2].reloc_va;
- u32 bi2;
-
- if (!rv || rv <= top_reloc)
- continue;
- bi2 = (u32)((rv -
- GSP_PHYS_RMCALL_GR_BOUNCE_VA0) >>
- 12);
- if (bi2 >= GSP_PHYS_RMCALL_GR_MAIL_SLOT)
- continue;
- top_reloc = rv;
- top_bi = bi2;
- }
while (attempts < GSP_PHYS_RMCALL_GR_ATTEMPTS) {
- bool top_changed = false;
-
- if (top_bi != 0xffffffffu) {
- const u8 *tp =
- gsp_phys_chunk_page_va(
- &boot_stage
- .rmcall_gr_bounce,
- top_bi);
-
- if (tp) {
- u32 ti, tc = 0;
-
- for (ti = 0;
- ti < GSP_PHYS_PAGE_SIZE;
- ti += 4)
- tc += get_unaligned_le32(
- tp + ti);
- top_changed =
- (tc !=
- bounce_csum_in[top_bi]);
- }
- }
- if (wrote > 0 &&
- (req->n_data < 2 || top_changed))
+ if (wrote > 0)
break;
attempts++;
if (attempts > GSP_PHYS_RMCALL_GR_ATTEMPTS)
break;
- pr_info("vgsp-gr: outcome retry %u/%u (wrote=%u top_bi=%u top_changed=%u): refill + re-publish\n",
+ pr_info("vgsp-gr: outcome retry %u/%u (wrote=%u): refill + re-publish\n",
attempts, GSP_PHYS_RMCALL_GR_ATTEMPTS,
- wrote, top_bi, top_changed);
+ wrote);
gsp_phys_gr_fill_bounce(req, bounce_csum_in);
mutex_lock(&gsp_phys_rm_lock);
ret = gsp_phys_rmcall_publish_locked(