aboutsummaryrefslogtreecommitdiffstats
path: root/mmu.c
diff options
context:
space:
mode:
authorJoshua Bakita <jbakita@cs.unc.edu>2024-04-09 17:19:01 -0400
committerJoshua Bakita <jbakita@cs.unc.edu>2024-04-09 17:19:01 -0400
commit5ea953292441e31e37ae074e48d8b3b5ce1d9440 (patch)
tree9fe4d01b480fe38be09483d4b332840e7f09f0b5 /mmu.c
parent664251e57c998ac97b66e8fc1dca1cb1b38a0c1e (diff)
Correctly check return code from vram2PRAMIN()
Blindly using an invalid return address was resulting in undefined behavior due to traversal of non-page-table addresses as though they were part of the page table.
Diffstat (limited to 'mmu.c')
-rw-r--r--mmu.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/mmu.c b/mmu.c
index 30e9362..e420864 100644
--- a/mmu.c
+++ b/mmu.c
@@ -15,11 +15,12 @@
15 15
16/* Convert a physical VRAM address to an offset in the PRAMIN window 16/* Convert a physical VRAM address to an offset in the PRAMIN window
17 @param addr VRAM address to convert 17 @param addr VRAM address to convert
18 @return 0 on error, PRAMIN offset on success 18 @return -errno on error, PRAMIN offset on success
19 19
20 Note: Use off2PRAMIN() instead if you want a dereferenceable address 20 Note: Use off2PRAMIN() instead if you want a dereferenceable address
21 Note: PRAMIN window is only 1MB, so returning an int is safe
21*/ 22*/
22uint32_t vram2PRAMIN(struct nvdebug_state *g, uint64_t addr) { 23static int vram2PRAMIN(struct nvdebug_state *g, uint64_t addr) {
23 uint64_t pramin_base_va; 24 uint64_t pramin_base_va;
24 bar0_window_t window; 25 bar0_window_t window;
25 window.raw = nvdebug_readl(g, NV_PBUS_BAR0_WINDOW); 26 window.raw = nvdebug_readl(g, NV_PBUS_BAR0_WINDOW);
@@ -27,20 +28,26 @@ uint32_t vram2PRAMIN(struct nvdebug_state *g, uint64_t addr) {
27 if (addr & ~0x0001ffffffffffff) { 28 if (addr & ~0x0001ffffffffffff) {
28 printk(KERN_ERR "[nvdebug] Invalid address %llx passed to %s!\n", 29 printk(KERN_ERR "[nvdebug] Invalid address %llx passed to %s!\n",
29 addr, __func__); 30 addr, __func__);
30 return 0; 31 return -EINVAL;
31 } 32 }
32 // For unclear (debugging?) reasons, PRAMIN can point to SYSMEM 33 // For unclear (debugging?) reasons, PRAMIN can point to SYSMEM
33 if (window.target != TARGET_VID_MEM) 34 if (window.target != TARGET_VID_MEM)
34 return 0; 35 return -EFAULT;
35 pramin_base_va = ((uint64_t)window.base) << 16; 36 pramin_base_va = ((uint64_t)window.base) << 16;
36 // Protect against out-of-bounds accesses 37 // Protect against out-of-bounds accesses
37 if (addr < pramin_base_va || addr > pramin_base_va + NV_PRAMIN_LEN) 38 if (addr < pramin_base_va || addr > pramin_base_va + NV_PRAMIN_LEN)
38 return 0; 39 return -ERANGE;
39 return addr - pramin_base_va; 40 return addr - pramin_base_va;
40} 41}
41 42
42// Convert a GPU physical address to CPU virtual address via the PRAMIN window 43// Convert a GPU physical address to CPU virtual address via the PRAMIN window
44// @return A dereferencable address, or 0 (an invalid physical address) on err
43void __iomem *phy2PRAMIN(struct nvdebug_state* g, uint64_t phy) { 45void __iomem *phy2PRAMIN(struct nvdebug_state* g, uint64_t phy) {
46 int off = vram2PRAMIN(g, phy);
47 if (off == -ERANGE)
48 printk(KERN_ERR "[nvdebug] Page table walk off end of PRAMIN!\n");
49 if (off < 0)
50 return 0;
44 return g->regs + NV_PRAMIN + vram2PRAMIN(g, phy); 51 return g->regs + NV_PRAMIN + vram2PRAMIN(g, phy);
45} 52}
46 53