From 41f6bf1a07fbf33036d31fe64c98d64cfe621e67 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 23 Oct 2026 18:40:12 -0400 Subject: r576 diag: launch-decision + event-post payload witnesses (gsp_phys_gr_dec_log, gsp_rm_ev_log) The GR launch-decision dump logs, for the first N draws whose fill saw dropped pages / a partial argument set or whose decision point carries a dstpend/copy-pending verdict: the decision verdicts, the launch's resolved data pages (VA -> guest PA), the live deferred-write records and the pending CE opdef entries - the operand evidence needed to explain a red draw of the readback lottery (the wrong-but-similar page hypothesis). The event-post witness logs every EVENT_POST_EVENT record actually sent with its full payload (hClient/hEvent/notifyIndex/data) and send result, plus a sentinel when post_all_events found valid events but posted none while none were dedup-skipped. This is the evidence needed when a client parks waiting for a completion wake-up that never arrives (the 2nd-client device-state spin): it shows whether the post was generated, for whom, and whether the status-queue write accepted it or dropped it (burst cap / ring full). Both are inert by default (budget 0). --- kernel/gsp_rm_emulation.c | 80 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 10 deletions(-) (limited to 'kernel/gsp_rm_emulation.c') diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c index 90556f2..d381c65 100644 --- a/kernel/gsp_rm_emulation.c +++ b/kernel/gsp_rm_emulation.c @@ -725,6 +725,34 @@ static int gsp_rm_send(struct gsp_emu_context *ctx, u32 function, data_len, false); } +/* + * r576 DIAG: event-post payload witness (gsp_rm_ev_log=N budget per boot). + * Every EVENT_POST_EVENT record actually sent is logged with its full + * payload and send result: when a client parks waiting for a completion + * wake-up that never arrives, this shows whether the post was generated, + * with which hClient/hEvent, and whether the status-queue write accepted it + * (rc=0) or dropped it (burst cap / ring full => rc<0). The companion + * sentinel fires only when post_all_events found valid events but could not + * post any of them while none were dedup-skipped - the "client waits, host + * thinks it posted" anomaly. 0 (default) = off. + */ +unsigned gsp_rm_ev_log_max; +static unsigned gsp_rm_ev_log; + +static void gsp_rm_evlog_post(struct nv_vgpu_device *vgpu, + const struct gsp_rm_emu *rm, u32 idx, + const char *src, int rc) +{ + if (!gsp_rm_ev_log_max || gsp_rm_ev_log >= gsp_rm_ev_log_max) + return; + gsp_rm_ev_log++; + nv_vgpu_info(vgpu, + "vgsp-rm: EVPOST %s ev[%u] cl=0x%x ev=0x%x nidx=0x%x data=0x%x rc=%d", + src, idx, rm->events[idx].h_client, + rm->events[idx].h_event, rm->events[idx].notify_index, + rm->events[idx].data, rc); +} + /* * Post the GPU event that tells the guest's CPU-side RM a channel's * submitted work is complete. A real GPU raises an interrupt, the host GSP @@ -763,9 +791,16 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) memcpy(payload + 8, &rm->events[i].notify_index, 4); memcpy(payload + 12, &rm->events[i].data, 4); /* info16@16, status@20, eventDataSize@24, bNotifyList@28 = 0 */ - if (gsp_rm_send_flags(ctx, GSPRM_RPC_EVENT_POST_EVENT, 0, 0, - payload, sizeof(payload), true)) - continue; + { + int rc = gsp_rm_send_flags(ctx, + GSPRM_RPC_EVENT_POST_EVENT, + 0, 0, payload, + sizeof(payload), true); + + gsp_rm_evlog_post(vgpu, rm, i, "chan", rc); + if (rc) + continue; + } rm->events[i].last_post = jiffies; posted++; } @@ -785,10 +820,17 @@ int gsp_rm_post_channel_event(struct nv_vgpu_device *vgpu, u32 h_src) memcpy(payload + 4, &rm->events[i].h_event, 4); memcpy(payload + 8, &rm->events[i].notify_index, 4); memcpy(payload + 12, &rm->events[i].data, 4); - if (gsp_rm_send_flags(ctx, GSPRM_RPC_EVENT_POST_EVENT, - 0, 0, payload, - sizeof(payload), true)) - continue; + { + int rc = gsp_rm_send_flags(ctx, + GSPRM_RPC_EVENT_POST_EVENT, + 0, 0, payload, + sizeof(payload), + true); + + gsp_rm_evlog_post(vgpu, rm, i, "chanfb", rc); + if (rc) + continue; + } rm->events[i].last_post = jiffies; posted++; } @@ -909,13 +951,31 @@ int gsp_rm_post_all_events(struct nv_vgpu_device *vgpu) memcpy(payload + 4, &rm->events[i].h_event, 4); memcpy(payload + 8, &rm->events[i].notify_index, 4); memcpy(payload + 12, &rm->events[i].data, 4); - if (gsp_rm_send(ctx, GSPRM_RPC_EVENT_POST_EVENT, 0, 0, - payload, sizeof(payload))) - continue; + { + int rc = gsp_rm_send(ctx, GSPRM_RPC_EVENT_POST_EVENT, + 0, 0, payload, sizeof(payload)); + + gsp_rm_evlog_post(vgpu, rm, i, "all", rc); + if (rc) + continue; + } rm->events[i].last_post = jiffies; n++; } + /* + * r576 DIAG: the anomaly sentinel - valid events existed, none were + * dedup-skipped, yet not one post could be sent. Every send rc is in + * the EVPOST lines above (budget permitting). + */ + if (!n && !skipped && gsp_rm_ev_log_max && + gsp_rm_ev_log < gsp_rm_ev_log_max) { + gsp_rm_ev_log++; + nv_vgpu_info(vgpu, + "vgsp-rm: EVPOST all: no postable event (events_n=%u dropped=%llu)", + rm->events_n, rm->events_dropped); + } + if (n) return 0; /* -EAGAIN: valid events existed but every one was dedup-skipped -- cgit v1.2.3