From 419615dc4e1fa5e9c2b4e0d15a0df94ca163a09b Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 16 Oct 2026 22:03:28 -0400 Subject: vgsp: m169 stale device-destination guard (device-dst copies translated only by walk/RAM-scan are held until a pin confirms; r172 streams2_diag stream-1 H2D wrote through a stale walk entry while the launch read the true page) + session-scope the op-trace budget + bigcopy witness covers device-dst copies >=64KB --- kernel/gsp_sema_service.c | 44 +++++++++++++++++++++++++++++++++++++++++++- kernel/gsp_sema_service.h | 6 ++++++ kernel/main.c | 9 +++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 97c41d7..343684b 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -729,6 +729,8 @@ struct sema_svc { u64 op_tr_log; /* operand targeted-resolve budget */ u32 op_tr_pending; /* an operand's targeted scan is in progress */ u64 copy_watch_log; /* sema_copy_watch log budget */ + u64 copy_dst_hold; /* m169: device-dst copies held for + * want of a pin (stale-table guard) */ u64 copy_pat_log; /* sema_copy_pat log budget */ u64 copy_dst_log; /* sema_copy_dst log budget */ u32 op_tr_src; /* provenance of last svc_op_translate */ @@ -4554,6 +4556,30 @@ static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total, dst_virt = true; } } + /* + * m169 (AGENT-F R1): a device-lane destination translated only by a + * page-directory walk (prov 3/4) or the RAM scan (5) can be a stale + * PTE from the previous session - the table CONTENT is not wiped by + * the session flush - and a wrong-but-valid vidmem write is silent. + * r172 streams2_diag: the stream-1 a H2D ran rc=0 through a + * walk-resolved destination while the launch (pin-resolved) read the + * true page still holding the previous client's h_a; the engine + * computed from stale inputs and the client verified 32768 bad. + * Since the resolver tries pins FIRST, prov >= 3 means no pin existed + * at resolve time: hold the copy (-ENOENT feeds the m163 bounded + * hold), which re-decodes after the client's pins land (seconds) and + * is loud on expiry - never silent corruption. Device destinations + * only; sysmem copies keep the historical sources. + */ + if (dst_virt && dst_aperture == CE_APERTURE_VID && + dst_prov >= 3 && dst_orig >= SVC_VAS_FLOOR && + gsp_sema_copy_dst_pin_guard) { + svc.copy_dst_hold++; + if (svc.copy_dst_hold <= 16) + pr_info("sema-svc: device-dst copy held: dst=0x%llx prov=%u (no pin yet; stale-table guard)\n", + dst_orig, dst_prov); + return -ENOENT; + } if (!src_phys) { u64 pa; u32 aper; @@ -4581,7 +4607,8 @@ static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total, * 16 bytes on each side before the copy. The vadd data path is exactly * these copies; this separates a wrong resolution from a wrong copy. */ - if (total >= (1u << 20) && bigcopy_log < 24) { + if ((total >= (1u << 20) || + (dst_virt && dst_orig >= SVC_VAS_FLOOR)) && bigcopy_log < 24) { u8 sb[16] = {0}, db[16] = {0}; bigcopy_log++; @@ -7580,6 +7607,14 @@ static void svc_session_flush(void) */ svc.entry_log = 0; svc_pushalt_log = 0; + /* + * m169: the op-trace budget is session state too. Left un-reset, the + * first client of a boot spends it and the failing client's copy ops + * are invisible in exactly the runs that need them (r172: streams2's + * H2D evidence was blacked out because the shared budget was spent at + * 29704, before the client ran). + */ + svc.op_trace_log = 0; /* * Per-entry/stream decode diagnostics are per-session: the first * client otherwise spends them and the second client's CE->GR @@ -9594,6 +9629,13 @@ unsigned gsp_sema_gr_nocap_hold_ms = 6000; */ bool gsp_sema_pool_hold_fresh = 1; +/* + * m169 (AGENT-F R1): hold device-destination copies whose only + * translation is a page-directory walk or RAM scan (no pin). Default on; + * 0 restores the historical immediate-write behavior. + */ +bool gsp_sema_copy_dst_pin_guard = 1; + /* * CE release fallback: when a push carrying a tracking-semaphore release * cannot be read (and the content rescue failed), advance the channel's diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h index ede8fa0..e0f1587 100644 --- a/kernel/gsp_sema_service.h +++ b/kernel/gsp_sema_service.h @@ -275,4 +275,10 @@ extern unsigned gsp_sema_gr_nocap_hold_ms; */ extern bool gsp_sema_pool_hold_fresh; +/* + * m169 (AGENT-F R1): hold device-destination copies translated only by a + * walk/RAM scan until a pin confirms (default on). + */ +extern bool gsp_sema_copy_dst_pin_guard; + #endif /* _GSP_SEMA_SERVICE_H_ */ diff --git a/kernel/main.c b/kernel/main.c index c4e4792..d2dc57a 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -2788,6 +2788,15 @@ MODULE_PARM_DESC(sema_gr_nocap_hold_ms, "GR no-capture entry hold in ms (default module_param_named(sema_pool_hold_fresh, gsp_sema_pool_hold_fresh, bool, 0644); MODULE_PARM_DESC(sema_pool_hold_fresh, "apply pool releases at fresh-pin time instead of registration+5s (default 1)"); +/* + * m169 (AGENT-F R1): hold device-destination copies translated only by a + * page-directory walk until a pin confirms (default on). A wrong-but-valid + * stale table entry silently writes the wrong vidmem page; the hold lets + * the m163 retry path re-resolve with pins. + */ +module_param_named(sema_copy_dst_pin_guard, gsp_sema_copy_dst_pin_guard, bool, 0644); +MODULE_PARM_DESC(sema_copy_dst_pin_guard, "hold device-dst copies without a pin-resolved translation (default 1)"); + /* * Debug: inject a verified {GPU VA -> guest PA} translation into the * semaphore service (used when the client's mapping cannot be discovered -- cgit v1.2.3