diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 756e644..ec61f4e 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -20717,6 +20717,29 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) pb, len) != 0; bool injected = false; bool allow_ops = (ch->engine_type != 0); + /* + * r469 (streams_events staging-reuse + * corruption): the primary read was a + * resolved page whose bytes do not parse + * as a method stream AND the fallback + * reads found nothing better - the page + * is (still) the client's unwritten / + * previous-epoch buffer. For a GR entry + * this must count as "content not yet + * written" and feed the no-capture hold: + * consuming it as a no-op lets the + * end-of-pass counter publish advance the + * guest's completion word while the real + * push (and its work) has not even been + * read, and the client then drains a + * staging buffer that still holds the + * PREVIOUS copy's bytes (observed: h_c[2] + * = c0 because the c2 D2H's completion + * word was published 4.5 s before its + * copy ran). Cleared when a later + * candidate read parses. + */ + bool implausible = false; /* * A resolved buffer that does not start @@ -20743,6 +20766,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) &iap) == 0); if (!svc_method_stream_plausible(pb, len)) { svc.false_trans++; + implausible = true; if (injected) { u8 *fb = kmalloc(len, GFP_KERNEL); @@ -20753,6 +20777,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc_method_stream_plausible(fb, len)) { memcpy(pb, fb, len); injected = false; + implausible = false; svc.pushpg_fallback++; if (gsp_sema_dbg && svc_pushpg_fb_log < 16) { @@ -20792,6 +20817,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) memcpy(pb, db, len); injected = false; unreadable = false; + implausible = false; } kfree(db); } @@ -20815,6 +20841,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) memcpy(pb, db, len); injected = false; unreadable = false; + implausible = false; } kfree(db); } @@ -21467,10 +21494,25 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) * through to the historical * consume so the channel can * never livelock. + * + * r469: an IMPLAUSIBLE push + * (the page does not parse as a + * method stream: unwritten or + * previous-epoch content) is the + * same "not the client's work + * yet" condition even though no + * QMD word was seen - consuming + * it as a no-op let the + * end-of-pass counter publish + * satisfy the client's wait + * before the real push was ever + * read (the streams_events + * staging-reuse corruption). */ if (!ch->engine_type && va && len && gsp_phys_gr_forward_enabled() && - svc_gr_qmd_seen > 0 && + (svc_gr_qmd_seen > 0 || + implausible) && !entry_replay && !(svc_gr_cand.valid && svc_gr_cand.h_object == |
