diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-24 04:49:38 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-24 04:49:38 -0400 |
| commit | 3765729cdaf6ad340cb11d1c7a971ded44227267 (patch) | |
| tree | 52fa9aa5b2ae74deaf5aca1fb8040de6f930ce50 /kernel/gsp_sema_service.c | |
| parent | e9f5cfb561f7dc94b610e3130dfee9f3325d7d6d (diff) | |
| download | open-iov-3765729cdaf6ad340cb11d1c7a971ded44227267.tar.gz open-iov-3765729cdaf6ad340cb11d1c7a971ded44227267.zip | |
vgsp-gr r604: session-scope the per-VA defer latches; peek the whole channel set incl. eng==0 copy channels
Two fixes, both from the SESSION 49 r603-family capture.
1. The r543 arg-defer latch and the r556 absolute defer cap are keyed by
push VA ALONE, and the UVM pool reuses the same launch push VAs for every
client of a boot - the exact lifetime bug the session flush already fixes
for the r565 exactly-once memories (svc_gr_cap_hist etc.). Carried across
sessions, the r556 stamp armed once at the previous client's first
sighting, so a new client's first decision for a reused VA already read
defer_expired()=true: every partial-argument defer failed closed (r586
path: QMD release authored in software, no engine launch) and the client
read stale/zero buffers. Witness (r603-family boot): the first mail
client (fresh VAs 0x20043be94/0x20043c364) deferred and launched (GUEST
GR LAUNCH OK ok=1/ok=2); every later mail client (VAs
0x20043beac/0x20043c37c reused) saw defer_exp=1 at its FIRST decision
with GR forward REFUSED at defer cap for both launches, and its 'green'
was the previous client's results still in the reused device pages.
Reset both tables with the session; within a session the original
bounds stand unchanged.
2. gsp_phys_gr_peek now logs every drained channel (cap 8 -> 24; the six
CE ranks came first and always spent the cap, so the eng==0
copy-carrying channels were never in the logged set - Session 48's 'the
copy channel's lookahead read empty' was an artifact of that), names the
channel's engine_type, deepens the lookahead to 6 slots, and logs
peek-backlog rows for channels whose live GP_PUT reads ahead of the
pass's consumed position (the r590 watermark skips engine_type==0, so a
published backlog on a GR-class copy channel is invisible to every
existing guard; the capture must show it).
r604 evidence (fresh boot, peek armed, mail first client): both launches
ran (ok=1/ok=2) and green; at the vadd's second decision
'peek-backlog h=0x5c000059 eng=0 put=95 last=94' - the driver's H2D
b-copy entry was already written+published on the eng==0 copy channel
and unconsumed, executed 8 ms after the decision and ~320 ms before the
launch's copy-in; zero write-ahead (+j) rows at any decision.
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 65b8ac1..0e6a141 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -12265,6 +12265,9 @@ static void svc_pending_add(u64 va, u32 payload, u32 op) * exist; drop them instead of resolving them against the next session. */ static void svc_gr_diag_reset(void); /* m150: defined with the fill diag */ +/* r604: defined next to the per-VA defer tables; clears both on session end + * (they are keyed by push VA alone and the UVM pool reuses those VAs). */ +static void svc_gr_defer_reset(void); static void svc_session_flush(void) { @@ -12301,6 +12304,7 @@ static void svc_session_flush(void) } svc_gr_diag_reset(); /* m150: per-session diagnostic budgets */ + svc_gr_defer_reset(); /* r604: per-session defer latches */ svc.map_n = 0; svc_pb_n = 0; svc_pd_found = 0; @@ -20991,6 +20995,40 @@ static bool svc_gr_defer_expired(u64 push_va) } /* + * r604: the r543 arg-defer latch and the r556 absolute defer cap are keyed + * by push VA ALONE, and the UVM pool reuses the same launch push VAs for + * every client of a boot - the exact lifetime bug the session flush already + * fixes for the r565 exactly-once memories (svc_gr_cap_hist, svc_gr_seen, + * svc_inline_once: "matches on the VA ALONE ... a previous client's + * capture could classify a later client's fresh launch"). Carried across + * sessions, the r556 stamp arms once - at the previous client's first + * sighting - so a new client's first decision for a reused VA already reads + * defer_expired()=true: every partial-argument defer fails closed (r586 + * path), the engine never launches, the QMD release is authored in + * software, and the client reads stale/zero buffers. Witnessed r603 family + * boot: the first mail client (fresh VAs 0x20043be94/0x20043c364) deferred + * and launched (`GUEST GR LAUNCH OK`), while every later mail client (VAs + * 0x20043beac/0x20043c37c reused from earlier boot runs) saw defer_exp=1 + * at its FIRST decision and `GR forward REFUSED at defer cap ... argument + * pages still unresolved` for both launches; its "green" was the previous + * client's results still sitting in the reused device pages. + * + * Reset both tables with the session: within a session the original + * bounds stand unchanged (one deferred sighting per VA in the arg window, + * one absolute 15 s cap per VA lifetime); a new session starts with fresh + * push generations and must not inherit either stamp. + */ +static void svc_gr_defer_reset(void) +{ + memset(svc_gr_arg_defer_va, 0, sizeof(svc_gr_arg_defer_va)); + memset(svc_gr_arg_defer_j, 0, sizeof(svc_gr_arg_defer_j)); + svc_gr_arg_defer_pos = 0; + memset(svc_gr_defer_cap_va, 0, sizeof(svc_gr_defer_cap_va)); + memset(svc_gr_defer_cap_j, 0, sizeof(svc_gr_defer_cap_j)); + svc_gr_defer_cap_pos = 0; +} + +/* * r548: is a forward still OWED for this push VA - a captured, never * offered candidate sitting in the candidate ring? The r547 saxpy stall: * both launches were deferred by the r541/r543 guards, the candidate ring @@ -21161,11 +21199,31 @@ u32 gsp_phys_gr_peek; static void svc_gr_peek_lookahead(struct nv_vgpu_device *vgpu, const struct svc_channel *self) { - u32 k, logged = 0; + u32 k, logged = 0, backlog_logged = 0; if (!gsp_phys_gr_peek || !svc_pass_local) return; - for (k = 0; k < svc_pass_local_n && logged < 8; k++) { + /* + * r604 diag: 8 was too small. svc_pass_local carries the six CE ranks + * (engine_type 11/12/13) FIRST and the GR-class channels after, so the + * cap was always spent before the copy-carrying GR-class channels + * (0x5c000059 family - the r595 finding: "the driver's relocation / + * H2D copies live on a compute channel") could be logged. Session 48 + * concluded "the copy channel's lookahead read empty" from captures + * where that channel was never in the logged set at all. 24 covers + * every drained channel of a live client with margin; the lookahead + * depth 6 covers the copy behind the launch's own small pushes. + * + * r604: also name every channel the drained-only filter SKIPS because + * its live GP_PUT reads ahead of the pass consumption position. Those + * are exactly the channels the r590 CE watermark watches - but that + * guard skips engine_type==0, so a published backlog on a GR-class + * copy channel is invisible to every existing guard; the capture must + * show it so a red decision can be attributed to write-ahead (put == + * last, entries logged below) vs published-backlog (put != last, + * logged here) without guessing. + */ + for (k = 0; k < svc_pass_local_n && logged < 24; k++) { const struct svc_channel *c = &svc_pass_local[k]; u32 put = 0, j; @@ -21176,11 +21234,19 @@ static void svc_gr_peek_lookahead(struct nv_vgpu_device *vgpu, c->userd_as, &put, sizeof(put))) continue; put %= c->gpfifo_entries; - if (put != ((u32)c->last_get % c->gpfifo_entries)) - continue; /* real published backlog */ - pr_info("vgsp-gr: peek h=0x%x put=%u last=%u\n", - c->h_object, put, (u32)c->last_get); - for (j = 1; j <= 4; j++) { + if (put != ((u32)c->last_get % c->gpfifo_entries)) { + /* real published backlog */ + if (backlog_logged < 12) { + backlog_logged++; + pr_info("vgsp-gr: peek-backlog h=0x%x eng=%u put=%u last=%u\n", + c->h_object, c->engine_type, put, + (u32)c->last_get); + } + continue; + } + pr_info("vgsp-gr: peek h=0x%x eng=%u put=%u last=%u\n", + c->h_object, c->engine_type, put, (u32)c->last_get); + for (j = 1; j <= 6; j++) { u32 idx = ((u32)c->last_get + j) % c->gpfifo_entries; u8 ent[SVC_GPFIFO_ENTRY_SIZE]; u32 e0, e1, len; |
