summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-21 21:08:06 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-21 21:08:06 -0400
commit55ffe494a749cf0ebf10b3146b8c59a4ab81aa5f (patch)
tree8e961e579950c64ccee564323257342c2862b42b
parent92fa88178956b94439857b8ec97da7f29f42bf9f (diff)
downloadopen-iov-55ffe494a749cf0ebf10b3146b8c59a4ab81aa5f.tar.gz
open-iov-55ffe494a749cf0ebf10b3146b8c59a4ab81aa5f.zip
kernel: TLB invalidate auto-complete (MMU_INVALIDATE trigger) + fn-10 queue logging
- NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE (BAR0+0x30B0, TRIGGER=bit31): driver sets TRIGGER then spins in kgmmuCheckPendingInvalidates_TU102 polling for it to clear. Our shadow held TRIGGER forever -> nv_open_q hard-wedged in RmInitAdapter (TLB invalidate during dmaAllocMapping). Auto-clear the trigger bit in gsp_emu_poll_boot (instant completion). - fn-10/47 handler logs hObjectOld + cmd_read/stat_write/drv_rp/stat_seq. Confirmed: drv_rp tracks stat_write 1:1 (driver drains cleanly, no lapping); frees complete; stat_seq increments per record. - Health-check/crashcat loop (kgspHealthCheck -> crashcatEngineGetNext CrashReport never returns NULL) is a SECONDARY symptom triggered by an RPC failure during RmInitAdapter - under investigation.
-rw-r--r--kernel/gsp_emulation.c11
-rw-r--r--kernel/gsp_emulation.h5
-rw-r--r--kernel/gsp_rm_emulation.c20
3 files changed, 28 insertions, 8 deletions
diff --git a/kernel/gsp_emulation.c b/kernel/gsp_emulation.c
index bca8a52..7b3b261 100644
--- a/kernel/gsp_emulation.c
+++ b/kernel/gsp_emulation.c
@@ -178,6 +178,17 @@ static void gsp_emu_poll_boot(struct gsp_emu_context *ctx)
u32 gsp_cpuctl = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_GSP_CPUCTL);
u32 sec2_cpuctl = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_SEC2_CPUCTL);
u32 engine = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_GSP_ENGINE);
+ u32 mmu_inv = gsp_emu_shadow_read32(ctx, GSP_EMU_REG_MMU_INVALIDATE);
+
+ /* TLB invalidate auto-complete: the driver sets TRIGGER then spins
+ * polling for it to clear (kgmmuCheckPendingInvalidates). Report
+ * instant completion or the driver wedges the open/init path. */
+ if (mmu_inv & GSP_EMU_MMU_INVALIDATE_TRIGGER) {
+ gsp_emu_shadow_write32(ctx, GSP_EMU_REG_MMU_INVALIDATE,
+ mmu_inv & ~GSP_EMU_MMU_INVALIDATE_TRIGGER);
+ pr_info_ratelimited("GSP-BOOT: MMU_INVALIDATE trigger auto-cleared (val=0x%x)\n",
+ mmu_inv);
+ }
/* GSP ENGINE reset asserted -> falcon rebooted, restart stage tracking */
if ((engine & 0x1) && ctx->boot_stage != GSP_BOOT_STAGE_IDLE) {
diff --git a/kernel/gsp_emulation.h b/kernel/gsp_emulation.h
index fe4186e..156499a 100644
--- a/kernel/gsp_emulation.h
+++ b/kernel/gsp_emulation.h
@@ -58,6 +58,11 @@
#define GSP_EMU_REG_SEC2_MAILBOX0 0x840040
#define GSP_EMU_REG_SEC2_ENGINE 0x8403c0
+/* NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE: driver sets TRIGGER(bit31) to
+ * start a TLB invalidate, then polls for bit31==0 (done). We auto-clear it. */
+#define GSP_EMU_REG_MMU_INVALIDATE 0x0030b0
+#define GSP_EMU_MMU_INVALIDATE_TRIGGER (1U << 31)
+
#define GSP_EMU_CPUCTL_STARTCPU 0x2
#define GSP_EMU_CPUCTL_HALTED 0x10
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index 0a040d5..67115b3 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -1289,18 +1289,22 @@ static void gsp_rm_handle_element(struct gsp_emu_context *ctx, const u8 *elem)
* driver's rpcRecvPoll completes. */
rm->unknown_rpcs++;
if (function == 10 || function == 47) {
- /* FREE/UNLOADING: log hObject for unload-cycle debugging */
+ /* FREE/UNLOADING: log hObject + queue positions for
+ * unload-cycle debugging. driver_rp = the peer's status
+ * read pointer (swap-rx): if it lags stat_write, the
+ * driver isn't draining our replies. */
const u8 *p = elem + GSPRM_ELEM_HDR_SIZE +
sizeof(struct gsprm_rpc_header);
- u32 hc = 0, ho = 0;
+ u32 hc = 0, ho = 0, driver_rp = 0;
- if (hdr->length >= sizeof(*hdr) + 8) {
- memcpy(&hc, p, 4);
- memcpy(&ho, p + 4, 4);
- }
- nv_vgpu_info(ctx->vgpu, "GSPRM: RPC %s(%u) seq=%u hClient=0x%x hObject=0x%x cmd_read=%u",
+ if (hdr->length >= sizeof(*hdr) + 12)
+ memcpy(&ho, p + 8, 4); /* hObjectOld */
+ gsp_rm_read_buf(ctx, rm->cmd_off + 0x20,
+ &driver_rp, sizeof(driver_rp));
+ nv_vgpu_info(ctx->vgpu, "GSPRM: RPC %s(%u) seq=%u hRoot=0x%x hObjOld=0x%x cmd_read=%u stat_write=%u drv_rp=%u stat_seq=%u",
gsp_rm_rpc_name(function), function, sequence,
- hc, ho, rm->cmd_read);
+ hc, ho, rm->cmd_read, rm->stat_write,
+ driver_rp, rm->stat_seq);
} else {
nv_vgpu_info(ctx->vgpu, "GSPRM: RPC %s(%u) seq=%u len=%u -> generic SUCCESS reply (unknown #%llu)",
gsp_rm_rpc_name(function), function, sequence,