aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-10-29 13:34:18 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-10-29 13:34:18 -0400
commit9199cc9e3bd6070bf54e28f5311867433af3dd59 (patch)
tree9e57694f85d15c1bddc9dd22b867b3b7614f76ed
parent39f7f4047e57fc7e7e275e52657f47d3d4bb6e2a (diff)
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.
-rw-r--r--runlist.c32
1 files 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 @@
2 2
3#include "nvdebug.h" 3#include "nvdebug.h"
4 4
5#define FALLBACK_TO_PRAMIN
6
5/* Get runlist head and info (incl. length) 7/* Get runlist head and info (incl. length)
6 @param rl_iter Location at which to store output 8 @param rl_iter Location at which to store output
7 @param rl_id Which runlist to obtain? 9 @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
61 uint32_t bar_inst_pramin_offset = vram2PRAMIN(g, (uint64_t)bar2_block.ptr << 12); 63 uint32_t bar_inst_pramin_offset = vram2PRAMIN(g, (uint64_t)bar2_block.ptr << 12);
62 if (!bar_inst_pramin_offset) { 64 if (!bar_inst_pramin_offset) {
63 printk(KERN_WARNING "[nvdebug] Unable to find instance block for BAR2/3 in the current NV_PRAMIN window. VRAM inaccessible.\n"); 65 printk(KERN_WARNING "[nvdebug] Unable to find instance block for BAR2/3 in the current NV_PRAMIN window. VRAM inaccessible.\n");
64 return -EOPNOTSUPP; 66 goto attempt_pramin_access;
65 } 67 }
66 /* TODO: Support BAR1? 68 /* TODO: Support BAR1?
67 bar_inst_pramin_offset = vram2PRAMIN(g, bar1_block.ptr << 12); 69 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
82 // TODO: SYSMEM support for page table location 84 // TODO: SYSMEM support for page table location
83 if (pd_config.target != TARGET_VID_MEM) { 85 if (pd_config.target != TARGET_VID_MEM) {
84 printk(KERN_WARNING "[nvdebug] BAR2 PDB is in an unsupported location.\n"); 86 printk(KERN_WARNING "[nvdebug] BAR2 PDB is in an unsupported location.\n");
85 return -EOPNOTSUPP; 87 goto attempt_pramin_access;
86 } 88 }
87 uint32_t bar_pdb_pramin_offset = vram2PRAMIN(g, bar_pdb_vram_addr); 89 uint32_t bar_pdb_pramin_offset = vram2PRAMIN(g, bar_pdb_vram_addr);
88 if (!bar_pdb_pramin_offset) { 90 if (!bar_pdb_pramin_offset) {
89 printk(KERN_WARNING "[nvdebug] Unable to find page directory BAR2/3 in the current NV_PRAMIN window. VRAM inaccessible.\n"); 91 printk(KERN_WARNING "[nvdebug] Unable to find page directory BAR2/3 in the current NV_PRAMIN window. VRAM inaccessible.\n");
90 return -EOPNOTSUPP; 92 goto attempt_pramin_access;
91 } 93 }
92 uint64_t runlist_bar_vaddr; 94 uint64_t runlist_bar_vaddr;
93 if (pd_config.is_ver2) 95 if (pd_config.is_ver2)
@@ -96,7 +98,7 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl
96 runlist_bar_vaddr = search_v1_page_directory(g, g->regs + NV_PRAMIN + bar_pdb_pramin_offset, phy2PRAMIN, runlist_iova); 98 runlist_bar_vaddr = search_v1_page_directory(g, g->regs + NV_PRAMIN + bar_pdb_pramin_offset, phy2PRAMIN, runlist_iova);
97 if (!runlist_bar_vaddr) { 99 if (!runlist_bar_vaddr) {
98 printk(KERN_WARNING "[nvdebug] Unable to find runlist mapping in BAR2/3 page tables.\n"); 100 printk(KERN_WARNING "[nvdebug] Unable to find runlist mapping in BAR2/3 page tables.\n");
99 return -EOPNOTSUPP; 101 goto attempt_pramin_access;
100 } 102 }
101 printk(KERN_INFO "[nvdebug] Runlist @ %llx in BAR2 virtual address space.\n", runlist_bar_vaddr); 103 printk(KERN_INFO "[nvdebug] Runlist @ %llx in BAR2 virtual address space.\n", runlist_bar_vaddr);
102 /* XXX: Old test code 104 /* XXX: Old test code
@@ -121,6 +123,28 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl
121 } 123 }
122 rl_iter->rl_info = rl_info; 124 rl_iter->rl_info = rl_info;
123 return 0; 125 return 0;
126attempt_pramin_access:
127#ifdef FALLBACK_TO_PRAMIN
128 printk(KERN_INFO "[nvdebug] Attempting to move PRAMIN window to runlist as BAR2/3-based access failed [DANGEROUS SIDE EFFECTS]!\n");
129 bar0_window_t win;
130 win.base = (runlist_iova >> 16);
131 win.target = TARGET_VID_MEM;
132 // Shift PRAMIN window. This will cause problems if it races with driver code
133 // that tries to do the same, or expects the window not to move.
134 nvdebug_writel(g, NV_PBUS_BAR0_WINDOW, win.raw);
135 uint32_t off = vram2PRAMIN(g, runlist_iova);
136 // Workaround bug for if `off` should be zero (vram2PRAMIN normally returns
137 // this on error)
138 if (!off && (runlist_iova & 0xffffull != runlist_iova)) {
139 printk(KERN_INFO "[nvdebug] Unable to shift PRAMIN to runlist. Aborting...\n");
140 return -EOPNOTSUPP;
141 }
142 rl_iter->curr_entry = g->regs + NV_PRAMIN + off;
143 rl_iter->rl_info = rl_info;
144 return 0;
145#else
146 return -EOPNOTSUPP;
147#endif // FALLBACK_TO_PRAMIN
124} 148}
125 149
126int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id) { 150int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id) {