aboutsummaryrefslogtreecommitdiffstats
path: root/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'bus.c')
-rw-r--r--bus.c73
1 files changed, 57 insertions, 16 deletions
diff --git a/bus.c b/bus.c
index c4d991e..f2369eb 100644
--- a/bus.c
+++ b/bus.c
@@ -24,10 +24,11 @@
24/* Obtain the PRAMIN offset at which `addr` can be accessed 24/* Obtain the PRAMIN offset at which `addr` can be accessed
25 @param addr Address to find 25 @param addr Address to find
26 @param target Which address space to use (VRAM, SYS_MEM, PEER(?)) 26 @param target Which address space to use (VRAM, SYS_MEM, PEER(?))
27 @return positive offset or -EINVAL on invalid arguments 27 @return positive offset, -EINVAL on invalid arguments, or -EOPNOTSUPP on
28 an unsupported platform.
28 29
29 Note: Will move the PRAMIN window to accomodate the request. Only guarantees 30 Note: Will move the PRAMIN window to accomodate the request. Only guarantees
30 that the surrounding 64KiB window will be accessible. 31 that the surrounding 64-KiB-aligned window will be accessible.
31 Note: Moving the PRAMIN window will cause problems if it races with driver 32 Note: Moving the PRAMIN window will cause problems if it races with driver
32 code that tries to do the same, or expects the window not to move. 33 code that tries to do the same, or expects the window not to move.
33 Bugs: Untested on PEER. 34 Bugs: Untested on PEER.
@@ -36,6 +37,7 @@ int addr_to_pramin_mut(struct nvdebug_state *g,
36 uint64_t addr, enum INST_TARGET target) { 37 uint64_t addr, enum INST_TARGET target) {
37 bar0_window_t window; 38 bar0_window_t window;
38 uint64_t pramin_base; 39 uint64_t pramin_base;
40 uint32_t window_reg;
39 // For us, accuracy and robustness is more important than speed 41 // For us, accuracy and robustness is more important than speed
40 // Check that the address is valid (49 bits are addressable on-GPU, but 42 // Check that the address is valid (49 bits are addressable on-GPU, but
41 // PRAMIN only supports up to 40 bits). 43 // PRAMIN only supports up to 40 bits).
@@ -44,21 +46,38 @@ int addr_to_pramin_mut(struct nvdebug_state *g,
44 addr, __func__); 46 addr, __func__);
45 return -EINVAL; 47 return -EINVAL;
46 } 48 }
47 window.raw = nvdebug_readl(g, NV_PBUS_BAR0_WINDOW); 49 // Register relocated on Hopper and Blackwell+
48 if (window.target != target) 50 if ((g->chip_id >= NV_CHIP_ID_HOPPER && g->chip_id < NV_CHIP_ID_ADA) || g->chip_id >= NV_CHIP_ID_BLACKWELL)
49 goto relocate; 51 window_reg = NV_XAL_EP_BAR0_WINDOW_BASE;
52 else
53 window_reg = NV_PBUS_BAR0_WINDOW;
54 if ((window.raw = nvdebug_readl(g, window_reg)) == -1) {
55 printk(KERN_ERR "[nvdebug] PRAMIN window configuration inaccessible; "
56 "failing %s\n", __func__);
57 return -EOPNOTSUPP;
58 }
59 if (window.target != target) {
60 // On Hopper and Blackwell+, the window always points at VID_MEM
61 if ((g->chip_id >= NV_CHIP_ID_HOPPER && g->chip_id < NV_CHIP_ID_ADA) || g->chip_id >= NV_CHIP_ID_BLACKWELL)
62 return -EOPNOTSUPP;
63 else
64 goto relocate;
65 }
50 pramin_base = ((uint64_t)window.base) << 16; 66 pramin_base = ((uint64_t)window.base) << 16;
51 if (addr < pramin_base || addr > pramin_base + NV_PRAMIN_LEN) 67 if (addr < pramin_base || addr > pramin_base + NV_PRAMIN_LEN)
52 goto relocate; 68 goto relocate;
53 return addr - pramin_base; // Guaranteed to be < 1MiB, so safe for int 69 return addr - pramin_base; // Guaranteed to be < 1MiB, so safe for int
54relocate: 70relocate:
55 printk(KERN_INFO "[nvdebug] Moving PRAMIN win from base %llx (%s) to %llx (%s) to accomodate %#018llx\n", pramin_base, target_to_text(window.target), (addr >> 16) << 16, target_to_text(target), addr); 71 printk(KERN_INFO "[nvdebug] [SIDE EFFECT] Moving PRAMIN window from base "
72 "%llx (%s) to %llx (%s) to accomodate %#018llx\n",
73 ((uint64_t)window.base) << 16, target_to_text(window.target),
74 (addr >> 16) << 16, target_to_text(target), addr);
56 // Move PRAMIN window to a 64KiB-aligned address 75 // Move PRAMIN window to a 64KiB-aligned address
57 window.base = (u32)(addr >> 16); // Safe, due to above range check 76 window.base = (u32)(addr >> 16); // Safe, due to above range check
58 window.target = target; 77 window.target = target;
59 nvdebug_writel(g, NV_PBUS_BAR0_WINDOW, window.raw); 78 nvdebug_writel(g, window_reg, window.raw);
60 // Wait for the window to move by re-reading (as done in nvgpu driver) 79 // Wait for the window to move by re-reading (as done in nvgpu driver)
61 (void) nvdebug_readl(g, NV_PBUS_BAR0_WINDOW); 80 (void) nvdebug_readl(g, window_reg);
62 return (int)(addr & 0xffffull); 81 return (int)(addr & 0xffffull);
63} 82}
64 83
@@ -72,7 +91,9 @@ relocate:
72*/ 91*/
73int get_bar2_pdb(struct nvdebug_state *g, page_dir_config_t* pd) { 92int get_bar2_pdb(struct nvdebug_state *g, page_dir_config_t* pd) {
74 int ret; 93 int ret;
75 bar_config_block_t bar2_block; 94 uint64_t bar2_ptr;
95 enum INST_TARGET bar2_target;
96 bool bar2_is_virtual;
76 97
77 if (!pd) 98 if (!pd)
78 return -EINVAL; 99 return -EINVAL;
@@ -85,17 +106,37 @@ int get_bar2_pdb(struct nvdebug_state *g, page_dir_config_t* pd) {
85 // hierarchy used to translate BAR2 offsets to VRAM or SYS_MEM addresses. 106 // hierarchy used to translate BAR2 offsets to VRAM or SYS_MEM addresses.
86 107
87 // Determine location of BAR2 instance block 108 // Determine location of BAR2 instance block
88 if ((bar2_block.raw = nvdebug_readl(g, NV_PBUS_BAR2_BLOCK)) == -1) { 109 if ((g->chip_id >= NV_CHIP_ID_HOPPER && g->chip_id < NV_CHIP_ID_ADA) || g->chip_id >= NV_CHIP_ID_BLACKWELL) {
89 printk(KERN_ERR "[nvdebug] Unable to read BAR2/3 configuration! BAR2/3 inaccessible.\n"); 110 // Register layout updated on Hopper and Blackwell+ to support 52-bit
90 return -EOPNOTSUPP; 111 // instance block pointers (vs. 40 bits before)
112 bar_config_block_gh100_t bar2_block;
113 if ((bar2_block.raw = nvdebug_readq(g, NV_VIRTUAL_FUNCTION_PRIV_FUNC_BAR2_BLOCK)) == -1) {
114 printk(KERN_ERR "[nvdebug] Unable to read BAR2/3 configuration! BAR2/3 inaccessible.\n");
115 return -EOPNOTSUPP;
116 }
117 bar2_ptr = (uint64_t)bar2_block.ptr << 12;
118 bar2_target = bar2_block.target;
119 bar2_is_virtual = bar2_block.is_virtual;
120 } else {
121 bar_config_block_t bar2_block;
122 if ((bar2_block.raw = nvdebug_readl(g, NV_PBUS_BAR2_BLOCK)) == -1) {
123 printk(KERN_ERR "[nvdebug] Unable to read BAR2/3 configuration! BAR2/3 inaccessible.\n");
124 return -EOPNOTSUPP;
125 }
126 bar2_ptr = (uint64_t)bar2_block.ptr << 12;
127 bar2_target = bar2_block.target;
128 bar2_is_virtual = bar2_block.is_virtual;
91 } 129 }
92 printk(KERN_INFO "[nvdebug] BAR2 inst block @ %llx in %s's %s address space.\n", ((u64)bar2_block.ptr) << 12, target_to_text(bar2_block.target), bar2_block.is_virtual ? "virtual" : "physical"); 130 printk(KERN_INFO "[nvdebug] BAR2 inst block @ %llx in %s's %s address space.\n", bar2_ptr, target_to_text(bar2_target), bar2_is_virtual ? "virtual" : "physical");
93 // Setup PRAMIN to point at the BAR2 instance block 131 // Setup PRAMIN to point at the BAR2 instance block
94 if ((ret = addr_to_pramin_mut(g, (uint64_t)bar2_block.ptr << 12, bar2_block.target)) < 0) { 132 // TODO: This won't work if the instance block is in SYS_MEM on Hopper or
95 printk(KERN_ERR "[nvdebug] Invalid BAR2/3 Instance Block configuration! BAR2/3 inaccessible.\n"); 133 // Blackwell+. Going through the I/O MMU appears to be fairly
134 // reliable, so I need to switch to using that logic whenever
135 // SYS_MEM may be accessed.
136 if ((ret = addr_to_pramin_mut(g, bar2_ptr, bar2_target)) < 0) {
137 printk(KERN_ERR "[nvdebug] Unable to access BAR2/3 Instance Block configuration via PRAMIN! BAR2/3 inaccessible.\n");
96 return ret; 138 return ret;
97 } 139 }
98 printk(KERN_INFO "[nvdebug] BAR2 inst block at off %x in PRAMIN\n", ret);
99 // Pull the page directory base configuration from the instance block 140 // Pull the page directory base configuration from the instance block
100 if ((pd->raw = nvdebug_readq(g, NV_PRAMIN + ret + NV_PRAMIN_PDB_CONFIG_OFF)) == -1) { 141 if ((pd->raw = nvdebug_readq(g, NV_PRAMIN + ret + NV_PRAMIN_PDB_CONFIG_OFF)) == -1) {
101 printk(KERN_ERR "[nvdebug] Unable to read BAR2/3 PDB configuration! BAR2/3 inaccessible.\n"); 142 printk(KERN_ERR "[nvdebug] Unable to read BAR2/3 PDB configuration! BAR2/3 inaccessible.\n");