From 4541bae601a330d2a22a21d9e24d0fe879ebf618 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 7 Oct 2026 11:16:02 -0400 Subject: vgsp: m83 - host-readable sysmem error notifier for the RM's channel-error records NV_PGRAPH_EXCEPTION reads 0x01000000 (GPC) with EXCEPTION1 GPC1:0=0b11 at the QMD activation; the fault record the engine writes goes to the channel's error notifier, which is server FBMEM today and unreadable. gsp_phys_rmcall_gr_notifier_sys=1 registers a host sysmem chunk as the hObjectError memory object and carries it in the channel's errorNotifierMem with the SYS aperture, so the RM's asynchronous channel-error report is dumped in the launch post-mortem (the m35 lane still uses the captured substitute object shape). --- kernel/gsp_phys_booter.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++- kernel/gsp_phys_gpu.c | 20 ++++++++++++++ kernel/gsp_phys_gpu.h | 4 +++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 5a5287f..8bf94d8 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -12707,6 +12707,46 @@ static int gsp_phys_rmcall_user_lane_notifier(void __iomem *bar0) u64 base = 0; int ret; + /* + * m83: host-visible sysmem error notifier (gsp_phys_rmcall_gr_notifier_sys; + * default 0). The RM writes asynchronous channel error records into the + * context's error notifier; with the FBMEM aperture nothing can read them + * (the m66..m82 GPC exception has never been decodable). A sysmem chunk + * registered as the hObjectError memory object makes the RM's own fault + * record readable from the host. + */ + if (gsp_phys_rmcall_gr_notifier_sys_value()) { + struct gsp_phys_boot_chunk *n = + &boot_stage.rmcall_user_lane_notifier; + + if (!boot_stage.pdev) { + pr_err("vgsp-boot: rm-call: mode 35 sysmem error-notifier: no claimed pci_dev\n"); + return -EINVAL; + } + if (!n->pages) { + ret = gsp_phys_chunk_alloc(boot_stage.pdev, n, + GSP_PHYS_RMCALL_NOTIFIER_SIZE / + GSP_PHYS_PAGE_SIZE); + if (ret) { + pr_err("vgsp-boot: rm-call: mode 35 sysmem error-notifier chunk allocation failed (%d)\n", + ret); + return ret; + } + gsp_phys_chunk_zero(n); + } + ret = gsp_phys_rmcall_register_chunk(bar0, n, + GSP_PHYS_RMCALL_HANDLE_USER_LANE_NOTIFIER, + "mode 35 user-lane error notifier (sysmem m83)"); + if (ret) + return ret; + base = (u64)gsp_phys_chunk_page_dma(n, 0); + boot_stage.rmcall_user_lane_notifier_pa = base; + pr_info("vgsp-boot: rm-call: mode 35 user-lane error notifier: hObject=0x%x SYSMEM pa=0x%llx size=0x%x (host-readable RM fault records; m83)\n", + GSP_PHYS_RMCALL_HANDLE_USER_LANE_NOTIFIER, base, + GSP_PHYS_RMCALL_NOTIFIER_SIZE); + return 0; + } + ret = gsp_phys_rmcall_alloc_fb_mem(bar0, GSP_PHYS_RMCALL_HANDLE_USER_LANE_NOTIFIER, GSP_PHYS_RMCALL_NOTIFIER_SIZE, &base, @@ -12869,7 +12909,9 @@ static int gsp_phys_rmcall_alloc_user_lane_channel(void __iomem *bar0) ch.error_notifier_mem.size = cpu_to_le64(GSP_PHYS_RMCALL_NOTIFIER_SIZE); ch.error_notifier_mem.address_space = - cpu_to_le32(GSP_PHYS_RMCALL_ADDR_FBMEM); + cpu_to_le32(gsp_phys_rmcall_gr_notifier_sys_value() ? + GSP_PHYS_RMCALL_ADDR_SYSMEM : + GSP_PHYS_RMCALL_ADDR_FBMEM); ch.error_notifier_mem.cache_attrib = cpu_to_le32(GSP_PHYS_RMCALL_CACHE_UNCACHED); @@ -16660,6 +16702,31 @@ gr_page_unmapped: p1[0], p1[1], p1[2], p1[3], p1[4], p1[5], p1[6], p1[7]); } + /* + * m83: the RM's asynchronous channel-error reports + * land in the error notifier; with the sysmem + * aperture they are host-readable after a failure. + */ + if (gsp_phys_rmcall_gr_notifier_sys_value()) { + struct gsp_phys_boot_chunk *nt = + &boot_stage.rmcall_user_lane_notifier; + const u32 *np = nt->pages ? + gsp_phys_chunk_page_va(nt, 0) : NULL; + u32 i; + + if (np) { + for (i = 0; i < 32; i += 8) + pr_info("vgsp-gr: post-mortem notifier w%u..%u = %08x %08x %08x %08x %08x %08x %08x %08x\n", + i, i + 7, + np[i], np[i + 1], + np[i + 2], + np[i + 3], + np[i + 4], + np[i + 5], + np[i + 6], + np[i + 7]); + } + } { u8 *qp2 = qmd_dst_mem ? qmd_dst_mem : (req->qmd_hpa ? diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c index a71ab97..f094d36 100644 --- a/kernel/gsp_phys_gpu.c +++ b/kernel/gsp_phys_gpu.c @@ -795,6 +795,26 @@ unsigned int gsp_phys_rmcall_gr_lmem_tpc_size_value(void) } EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_lmem_tpc_size_value); +/* + * m83 sysmem error notifier (gsp_phys_rmcall_gr_notifier_sys; default 0). + * The mode-35 V7 error notifier is normally a server FBMEM class-0x40 memory + * object (unreadable). With 1 it is a host sysmem chunk registered as the + * hObjectError memory object and carried in the channel's errorNotifierMem + * with the SYS aperture, so the RM's asynchronous channel-error records for + * the GPC exception are readable (dumped in the launch post-mortem). + */ +static int gsp_phys_rmcall_gr_notifier_sys_param; +module_param_named(gsp_phys_rmcall_gr_notifier_sys, + gsp_phys_rmcall_gr_notifier_sys_param, int, 0644); +MODULE_PARM_DESC(gsp_phys_rmcall_gr_notifier_sys, + "Mode-35 error notifier as host sysmem (RM fault records readable; default 0)"); + +int gsp_phys_rmcall_gr_notifier_sys_value(void) +{ + return gsp_phys_rmcall_gr_notifier_sys_param; +} +EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_notifier_sys_value); + /* * m78 lane-enable skip mask (gsp_phys_rmcall_gr_lane_skip; default 0). Bit 0 * skips R2 #1059 GR_SET_CTXSW_PREEMPTION_MODE (CILP), bit 1 skips #1061 diff --git a/kernel/gsp_phys_gpu.h b/kernel/gsp_phys_gpu.h index 216c96e..9bd5624 100644 --- a/kernel/gsp_phys_gpu.h +++ b/kernel/gsp_phys_gpu.h @@ -362,6 +362,10 @@ int gsp_phys_rmcall_gr_lane_tail_value(void); * 4=#1063 device-sched); default 0 = send all. */ int gsp_phys_rmcall_gr_lane_skip_value(void); +/* m83: mode-35 error notifier as host sysmem so the RM's channel-error + * records are readable (default 0 = server FBMEM). */ +int gsp_phys_rmcall_gr_notifier_sys_value(void); + /* * Ladder VAS ownership selector (gsp_phys_rmcall_vas_shared; default 0). * 0 = FERMI_VASPACE_A is allocated IS_EXTERNALLY_OWNED (historical ladder -- cgit v1.2.3