summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c138
-rw-r--r--tools/guest-diag/guest_pin_stream.py43
-rw-r--r--tools/guest-diag/pin_gr_stream.py26
3 files changed, 189 insertions, 18 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 741fdc2..e86c463 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -1111,6 +1111,9 @@ struct sema_svc {
u64 fwd_gr_dstpend; /* r541: held for an unexecuted
* device write on a data page */
u32 fwd_gr_dstpend_log;
+ u64 fwd_gr_closed; /* r583: fail-closed at the defer
+ * cap (dstpend still live) */
+ u32 fwd_gr_closed_log;
u64 fwd_gr_argdefer; /* r543: held for a partial
* argument set (unresolved arg) */
u32 fwd_gr_argdefer_log;
@@ -5445,7 +5448,34 @@ static int svc_fill_1d(struct nv_vgpu_device *vgpu, u64 addr, u64 value, u32 ele
u32 aper;
u32 prov = 0; /* r384: 1 pin, 2 ledger, 3 walk/scan */
- if (svc_vas_has(addr)) {
+ /*
+ * r584: a VID-aperture fill whose destination is a vidmem
+ * WINDOW VA (the guest's 0x2xxxxxxxx family) is offset-
+ * mapped by construction: VA - SVC_VIDMEM_VA_BASE is the
+ * FB offset into the emulated BAR1 shadow (the svc_lookup
+ * window convention; see also the 0x200080000 rationale at
+ * SVC_VIDMEM_VA_BASE). The generic chain below (pin ->
+ * ledger -> translate) answered SYS for the r583 boot's CE
+ * channel-setup fill to 0x204820000 (a stale landing), the
+ * r369 below-floor guard refused it, the fill never ran,
+ * and its DSTPEND note stalled GR launches to the fail-
+ * closed cap. Window VAs resolve structurally - no guest
+ * page table can express an "engineering window" offset.
+ */
+ if (aperture == CE_APERTURE_VID &&
+ va0 >= SVC_VIDMEM_VA_BASE &&
+ va0 - SVC_VIDMEM_VA_BASE + total <=
+ svc_fb_shadow_size(vgpu)) {
+ addr = va0 - SVC_VIDMEM_VA_BASE;
+ /* aperture stays CE_APERTURE_VID: the whole-range
+ * contiguity block below writes it into the shadow */
+ prov = 4; /* structural window convention */
+ if (svc_lowfill_log < 64) {
+ svc_lowfill_log++;
+ pr_info("sema-lowfill-window va=0x%llx -> fb offset 0x%llx (vidmem window convention) elem=%u count=%u value=0x%llx\n",
+ va0, addr, elem, count, value);
+ }
+ } else if (svc_vas_has(addr)) {
shadow = true;
} else if (!svc_pin_lookup_any(addr, &pa, &aper)) {
u64 lpa = 0;
@@ -20665,10 +20695,29 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu,
u32 dl;
svc_gr_drop_log_va = svc_fwd_req.gr_push_va;
- for (dl = 0; dl < 4 && dl < dropped_pages; dl++)
+ for (dl = 0; dl < 4 && dl < dropped_pages; dl++) {
+ /*
+ * r585: DEMAND the dropped pages through the
+ * pin channel. The host pin stream parses the
+ * "stalled VA #N: 0x..." lines (svc_log_stalled_va)
+ * and pushes each VA to the guest scanner within
+ * ~3 s, whose pin then lands inside the launch's
+ * bounded argument-defer window - the r584 matmul
+ * draw dropped 18 staging pages that were NEVER
+ * demanded (the GRFILL-DROP line format is
+ * invisible to the host's demand regex), the r543
+ * defer window expired, and the r564 degenerate
+ * refusal SW-completed a launch that wrote
+ * nothing (MATMUL bad=65536 csum=0). One demand
+ * per page per boot (svc_log_stalled_va dedups);
+ * one episode per launch push VA (the marker
+ * above).
+ */
+ svc_log_stalled_va(drop_va[dl]);
pr_info("vgsp-gr: GRFILL-DROP va=0x%llx kind=%c idx=%u\n",
drop_va[dl], drop_kind[dl],
drop_idx[dl]);
+ }
}
}
if (svc_gr_data_stalled)
@@ -21232,19 +21281,50 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu,
* busy-defer + gr_hold machinery as every other busy refusal, so it
* can never hang the launch.
*/
- if (svc_gr_dstpend_overlap() &&
- !svc_gr_defer_expired(svc_gr_cand.push_va)) {
- clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state);
- mutex_unlock(&svc_fwd_lock);
- svc_gr_busy_defer = true;
+ if (svc_gr_dstpend_overlap()) {
+ if (!svc_gr_defer_expired(svc_gr_cand.push_va)) {
+ clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state);
+ mutex_unlock(&svc_fwd_lock);
+ svc_gr_busy_defer = true;
+ svc.fwd_gr_refused++;
+ svc.fwd_gr_dstpend++;
+ if (svc.fwd_gr_dstpend_log < 32) {
+ svc.fwd_gr_dstpend_log++;
+ pr_info("vgsp-work: GR forward deferred h=0x%x push=0x%llx (data page has an unexecuted device write; bounded retry)\n",
+ ch->h_object, svc_gr_cand.push_va);
+ }
+ return false;
+ }
+ /*
+ * r583: the absolute defer cap expired while a data page still
+ * overlaps a pending device write (r581 saxpy live: GR-DEC
+ * dstpend=1 defer_exp=1 -> forwarded anyway -> bad=524121
+ * with dstpend ages 9.5-85 s). Never forward a KNOWN-stale
+ * operand: fail-closed - author the candidate's QMD
+ * completion in software (forward-only, latched so the
+ * consume tail cannot author it twice) and refuse the
+ * engine launch. The client completes; the engine stays
+ * away from a page whose writer never ran. Witnessed.
+ */
svc.fwd_gr_refused++;
- svc.fwd_gr_dstpend++;
- if (svc.fwd_gr_dstpend_log < 32) {
- svc.fwd_gr_dstpend_log++;
- pr_info("vgsp-work: GR forward deferred h=0x%x push=0x%llx (data page has an unexecuted device write; bounded retry)\n",
+ svc.fwd_gr_closed++;
+ if (svc_gr_cand.rel_va) {
+ svc_gr_sw_release(vgpu, ch->h_object,
+ svc_gr_cand.rel_va,
+ svc_gr_cand.rel_payload);
+ svc_gr_cand.rel_done = true;
+ }
+ svc_gr_cand.offered = true;
+ svc_gr_cand.valid = false;
+ if (svc.fwd_gr_closed_log < 32) {
+ svc.fwd_gr_closed_log++;
+ pr_warn("vgsp-work: GR forward REFUSED at defer cap h=0x%x push=0x%llx (data page still has an unexecuted device write; fail-closed, QMD release authored in software)\n",
ch->h_object, svc_gr_cand.push_va);
}
- return false;
+ clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state);
+ mutex_unlock(&svc_fwd_lock);
+ return false; /* no busy-defer: the pump consumes; the
+ * candidate is owned and sw-completed */
}
/*
* r568: the coarse companion gate - any unexecuted CE write at all
@@ -21295,6 +21375,40 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu,
return false;
}
/*
+ * r586: the defer cap expired with argument pages still unresolved -
+ * fail-closed like the r583 dstpend cap. The historical path
+ * forwarded the launch with the partial set and the engine read
+ * stale/zero operands (r585 boot saxpy: n_data=969 dropped=7
+ * partial=1 -> forwarded at the cap -> bad=1047527 csum=130523290;
+ * r584 matmul: n_data=2 dropped=18 -> r564 degenerate refusal ->
+ * no-write). Refuse the forward, author the completion in software,
+ * consume; the dropped pages were already demanded through the pin
+ * channel (r585) so the retry path had its chance first.
+ */
+ if (svc_fwd_req.gr_arg_partial && !svc_gr_data_stalled &&
+ svc_gr_defer_expired(svc_gr_cand.push_va)) {
+ svc.fwd_gr_refused++;
+ svc.fwd_gr_closed++;
+ if (svc_gr_cand.rel_va) {
+ svc_gr_sw_release(vgpu, ch->h_object,
+ svc_gr_cand.rel_va,
+ svc_gr_cand.rel_payload);
+ svc_gr_cand.rel_done = true;
+ }
+ svc_gr_cand.offered = true;
+ svc_gr_cand.valid = false;
+ if (svc.fwd_gr_closed_log < 32) {
+ svc.fwd_gr_closed_log++;
+ pr_warn("vgsp-work: GR forward REFUSED at defer cap h=0x%x push=0x%llx (argument pages still unresolved: %u; fail-closed, QMD release authored in software)\n",
+ ch->h_object, svc_gr_cand.push_va,
+ svc_fwd_req.gr_dropped);
+ }
+ clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state);
+ mutex_unlock(&svc_fwd_lock);
+ return false; /* no busy-defer: the pump consumes; the
+ * candidate is owned and sw-completed */
+ }
+ /*
* m150: the fill found high argument pointers that no source can
* translate (the second-client zeros class). Do NOT forward a launch
* whose kernel would dereference unresolved pointers: leave the
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py
index aa21655..175ed23 100644
--- a/tools/guest-diag/guest_pin_stream.py
+++ b/tools/guest-diag/guest_pin_stream.py
@@ -1772,8 +1772,21 @@ def main():
st_d = os.stat("/tmp/guest_want_vas.txt")
if st_d.st_mtime != _want_state.get("mtime"):
with open("/tmp/guest_want_vas.txt") as fw:
- wvas = [int(t, 16) for t in fw.read().split()
- if t.startswith("0x")]
+ # r582: tolerate malformed historical lines. The
+ # r581 boot's scanner died here: a transport-escaped
+ # append merged VAs into one token containing
+ # literal backslash-n ('0x20400f000\\n0x121000000\\n
+ # ...') and int(t, 16) raised ValueError out of
+ # main(), stopping ALL new pins (the observed
+ # pool-pin latency). Extract every 0x token instead;
+ # a bad token is skipped, never fatal.
+ wvas = []
+ for t in re.findall(r"0x[0-9a-fA-F]+",
+ fw.read()):
+ try:
+ wvas.append(int(t, 16))
+ except ValueError:
+ pass
_want_state["mtime"] = st_d.st_mtime
for wv in wvas[-64:]:
if wv in _want_state["done"]:
@@ -1806,6 +1819,32 @@ def main():
except Exception:
ok = False
got = []
+ # r586: a demanded VA outside the CE
+ # pushbuffer window (the GRFILL staging pages,
+ # high client VAs) is a plain client mapping
+ # page: resolve it through the client's own
+ # pagemap. Without this the demand for those
+ # VAs was a silent no-op (resolve_va_by_content
+ # rejects anything outside PB_CE_LO..PB_CE_HI)
+ # and the fills kept dropping them.
+ if not ok and not got and pid:
+ try:
+ pfd = os.open('/proc/%d/pagemap' % pid,
+ os.O_RDONLY)
+ try:
+ sub = {}
+ vpg = wv & ~0xFFF
+ scan_range(pfd, vpg, vpg + 0x1000,
+ sub)
+ finally:
+ os.close(pfd)
+ if sub:
+ for v, p in sub.items():
+ got.append('0x%x,0x%x,1\n'
+ % (v, p))
+ ok = True
+ except OSError:
+ pass
if ok and got:
lines.extend(got)
_want_state["done"].add(wv)
diff --git a/tools/guest-diag/pin_gr_stream.py b/tools/guest-diag/pin_gr_stream.py
index 6eb5be7..ff7e299 100644
--- a/tools/guest-diag/pin_gr_stream.py
+++ b/tools/guest-diag/pin_gr_stream.py
@@ -100,15 +100,33 @@ def _scanner_alive():
return "ALIVE" in (out or "")
+def _demand_write_cmd(vas):
+ """Build a transport-proof append command for the guest demand file.
+
+ r582: the old `printf '%s' '<lines with real LF>'` form was mangled by
+ the guest-agent transport under load - the newlines arrived as LITERAL
+ backslash-n text and merged VAs onto one line, and the guest scanner's
+ parser then crashed on `int('0x20400f000\\\\n0x121000000...', 16)`
+ (ValueError in main; r581 boot scanner log). The scanner's death stopped
+ ALL new pins while the host only re-asserted known pairs - the observed
+ pool-pin-latency (0x121000000 never arrived while other injections
+ flowed). One `echo <va> >> file` per VA carries no newlines and no
+ backslashes at all, so no transport layer can escape them."""
+ return "; ".join("echo 0x%x >> /tmp/guest_want_vas.txt" % va
+ for va in vas)
+
+
def _demand_send(vas):
"""Append VA hints to the guest scanner's demand file (best-effort).
Same channel pin_gr_stream._demand_loop uses for host-dmesg stalls; the
stall watchdog uses it to ask the scanner to re-resolve the fixed
pre-capture VAs (counter page / UVM pool) by content/pagemap."""
- lines = "".join("0x%x\n" % va for va in vas)
+ cmd = _demand_write_cmd(vas)
+ if not cmd:
+ return
try:
- vexec("printf '%%s' '%s' >> /tmp/guest_want_vas.txt" % lines, 30)
+ vexec(cmd, 30)
except Exception:
pass
@@ -222,9 +240,9 @@ def _demand_loop():
todo = [va for va, (f, l) in track.items() if now - l > 20.0]
if not todo:
continue
- lines = "".join("0x%x\n" % va for va in todo)
+ cmd = _demand_write_cmd(todo)
try:
- vexec("printf '%%s' '%s' >> /tmp/guest_want_vas.txt" % lines, 30)
+ vexec(cmd, 30)
except Exception:
continue
for va in todo: