From 9199cc9e3bd6070bf54e28f5311867433af3dd59 Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Sun, 29 Oct 2023 13:34:18 -0400 Subject: Support PRAMIN-based runlist access fallback (optional; on by default) Using this may be hazardous---we don't know if some of the GPU drivers use this after initial bring-up. If they do, and we race with them in setting it, or we unexpectedly change it under them, arbitrary state corruption could occur. This is only entirely safe to use if you don't trust the GPU state after the first use of this fallback. In limited experiments vs the `nvgpu` (Tegra) and `nvidia` (closed-source discrete) drivers, no ill side effects have yet been observed, but still please use with caution. --- runlist.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/runlist.c b/runlist.c index f6a05ac..ed35c7e 100644 --- a/runlist.c +++ b/runlist.c @@ -2,6 +2,8 @@ #include "nvdebug.h" +#define FALLBACK_TO_PRAMIN + /* Get runlist head and info (incl. length) @param rl_iter Location at which to store output @param rl_id Which runlist to obtain? @@ -61,7 +63,7 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl uint32_t bar_inst_pramin_offset = vram2PRAMIN(g, (uint64_t)bar2_block.ptr << 12); if (!bar_inst_pramin_offset) { printk(KERN_WARNING "[nvdebug] Unable to find instance block for BAR2/3 in the current NV_PRAMIN window. VRAM inaccessible.\n"); - return -EOPNOTSUPP; + goto attempt_pramin_access; } /* TODO: Support BAR1? bar_inst_pramin_offset = vram2PRAMIN(g, bar1_block.ptr << 12); @@ -82,12 +84,12 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl // TODO: SYSMEM support for page table location if (pd_config.target != TARGET_VID_MEM) { printk(KERN_WARNING "[nvdebug] BAR2 PDB is in an unsupported location.\n"); - return -EOPNOTSUPP; + goto attempt_pramin_access; } uint32_t bar_pdb_pramin_offset = vram2PRAMIN(g, bar_pdb_vram_addr); if (!bar_pdb_pramin_offset) { printk(KERN_WARNING "[nvdebug] Unable to find page directory BAR2/3 in the current NV_PRAMIN window. VRAM inaccessible.\n"); - return -EOPNOTSUPP; + goto attempt_pramin_access; } uint64_t runlist_bar_vaddr; if (pd_config.is_ver2) @@ -96,7 +98,7 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl runlist_bar_vaddr = search_v1_page_directory(g, g->regs + NV_PRAMIN + bar_pdb_pramin_offset, phy2PRAMIN, runlist_iova); if (!runlist_bar_vaddr) { printk(KERN_WARNING "[nvdebug] Unable to find runlist mapping in BAR2/3 page tables.\n"); - return -EOPNOTSUPP; + goto attempt_pramin_access; } printk(KERN_INFO "[nvdebug] Runlist @ %llx in BAR2 virtual address space.\n", runlist_bar_vaddr); /* XXX: Old test code @@ -121,6 +123,28 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl } rl_iter->rl_info = rl_info; return 0; +attempt_pramin_access: +#ifdef FALLBACK_TO_PRAMIN + printk(KERN_INFO "[nvdebug] Attempting to move PRAMIN window to runlist as BAR2/3-based access failed [DANGEROUS SIDE EFFECTS]!\n"); + bar0_window_t win; + win.base = (runlist_iova >> 16); + win.target = TARGET_VID_MEM; + // Shift PRAMIN window. This will cause problems if it races with driver code + // that tries to do the same, or expects the window not to move. + nvdebug_writel(g, NV_PBUS_BAR0_WINDOW, win.raw); + uint32_t off = vram2PRAMIN(g, runlist_iova); + // Workaround bug for if `off` should be zero (vram2PRAMIN normally returns + // this on error) + if (!off && (runlist_iova & 0xffffull != runlist_iova)) { + printk(KERN_INFO "[nvdebug] Unable to shift PRAMIN to runlist. Aborting...\n"); + return -EOPNOTSUPP; + } + rl_iter->curr_entry = g->regs + NV_PRAMIN + off; + rl_iter->rl_info = rl_info; + return 0; +#else + return -EOPNOTSUPP; +#endif // FALLBACK_TO_PRAMIN } int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id) { -- cgit v1.2.2