diff options
| author | Joshua Bakita <bakitajoshua@gmail.com> | 2024-04-21 17:18:10 -0400 |
|---|---|---|
| committer | Joshua Bakita <bakitajoshua@gmail.com> | 2024-04-21 17:18:10 -0400 |
| commit | fa1c67d86e8071fee8873aaa03ab4ece3a189b64 (patch) | |
| tree | 423bfee00a5a21ac549d46315aacc6ac3ec4fb6a | |
| parent | 613b1589a3da73cdc5e9313d65bc7c723f574531 (diff) | |
Match aperture when doing page table searches
Previously, addresses of any aperture would match. This can result
in very confusing results when attempting to verify that a mapping
correctly exists.
| -rw-r--r-- | mmu.c | 18 | ||||
| -rw-r--r-- | nvdebug.h | 10 | ||||
| -rw-r--r-- | runlist.c | 4 |
3 files changed, 19 insertions, 13 deletions
| @@ -70,6 +70,7 @@ uint64_t search_page_directory_subtree(struct nvdebug_state *g, | |||
| 70 | uintptr_t pde_addr, | 70 | uintptr_t pde_addr, |
| 71 | enum PD_TARGET pde_target, | 71 | enum PD_TARGET pde_target, |
| 72 | uint64_t addr_to_find, | 72 | uint64_t addr_to_find, |
| 73 | enum INST_TARGET addr_to_find_aperture, | ||
| 73 | uint32_t level) { | 74 | uint32_t level) { |
| 74 | uint64_t res, i; | 75 | uint64_t res, i; |
| 75 | void __iomem *pde_kern; | 76 | void __iomem *pde_kern; |
| @@ -94,13 +95,13 @@ uint64_t search_page_directory_subtree(struct nvdebug_state *g, | |||
| 94 | if (entry.is_pte) { | 95 | if (entry.is_pte) { |
| 95 | // TODO: Handle huge pages here | 96 | // TODO: Handle huge pages here |
| 96 | printk_debug(KERN_INFO "[nvdebug] PTE for phy addr %#018llx, ap '%s', vol '%d', priv '%d', ro '%d', no_atomics '%d' (raw: %#018llx)\n", ((u64)entry.addr_w) << 12, pd_target_to_text(entry.target), entry.is_volatile, entry.is_privileged, entry.is_readonly, entry.atomics_disabled, entry.raw_w); | 97 | printk_debug(KERN_INFO "[nvdebug] PTE for phy addr %#018llx, ap '%s', vol '%d', priv '%d', ro '%d', no_atomics '%d' (raw: %#018llx)\n", ((u64)entry.addr_w) << 12, pd_target_to_text(entry.target), entry.is_volatile, entry.is_privileged, entry.is_readonly, entry.atomics_disabled, entry.raw_w); |
| 97 | return (uint64_t)entry.addr << 12 == addr_to_find; | 98 | return (uint64_t)entry.addr << 12 == addr_to_find && entry.aperture == addr_to_find_aperture; |
| 98 | } | 99 | } |
| 99 | printk_debug(KERN_INFO "[nvdebug] Found PDE pointing to %#018llx in ap '%s' vol '%d' at lvl %d (raw: %#018llx)\n", ((u64)entry.addr_w) << 12, pd_target_to_text(entry.target), entry.is_volatile, level, entry.raw_w); | 100 | printk_debug(KERN_INFO "[nvdebug] Found PDE pointing to %#018llx in ap '%s' vol '%d' at lvl %d (raw: %#018llx)\n", ((u64)entry.addr_w) << 12, pd_target_to_text(entry.target), entry.is_volatile, level, entry.raw_w); |
| 100 | // Depth-first search of the page table | 101 | // Depth-first search of the page table |
| 101 | for (i = 0; i < NV_MMU_PT_V2_SZ[level + 1]; i++) { | 102 | for (i = 0; i < NV_MMU_PT_V2_SZ[level + 1]; i++) { |
| 102 | uint64_t next = ((uint64_t)entry.addr << 12) + NV_MMU_PT_V2_ENTRY_SZ[level + 1] * i; | 103 | uint64_t next = ((uint64_t)entry.addr << 12) + NV_MMU_PT_V2_ENTRY_SZ[level + 1] * i; |
| 103 | res = search_page_directory_subtree(g, next, entry.target, addr_to_find, level + 1); | 104 | res = search_page_directory_subtree(g, next, entry.target, addr_to_find, addr_to_find_aperture, level + 1); |
| 104 | if (res) | 105 | if (res) |
| 105 | return res | (i << NV_MMU_PT_V2_LSB[level + 1]); | 106 | return res | (i << NV_MMU_PT_V2_LSB[level + 1]); |
| 106 | } | 107 | } |
| @@ -119,12 +120,14 @@ uint64_t search_page_directory_subtree(struct nvdebug_state *g, | |||
| 119 | @param pd_config Page Directory configuration, containing pointer and | 120 | @param pd_config Page Directory configuration, containing pointer and |
| 120 | aperture for the start of the PDE3 entries | 121 | aperture for the start of the PDE3 entries |
| 121 | @param addr_to_find Physical address to reconstruct the virtual address of | 122 | @param addr_to_find Physical address to reconstruct the virtual address of |
| 123 | @param addr_to_find_aperture Aperture (SYS_MEM or VID_MEM) of addr_to_find | ||
| 122 | @return 0 on error, otherwise the virtual address at which addr_to_find is | 124 | @return 0 on error, otherwise the virtual address at which addr_to_find is |
| 123 | mapped into by this page table. (Zero is not a valid virtual address) | 125 | mapped into by this page table. (Zero is not a valid virtual address) |
| 124 | */ | 126 | */ |
| 125 | uint64_t search_page_directory(struct nvdebug_state *g, | 127 | uint64_t search_page_directory(struct nvdebug_state *g, |
| 126 | page_dir_config_t pd_config, | 128 | page_dir_config_t pd_config, |
| 127 | uint64_t addr_to_find) { | 129 | uint64_t addr_to_find, |
| 130 | enum INST_TARGET addr_to_find_aperture) { | ||
| 128 | uint64_t res, i; | 131 | uint64_t res, i; |
| 129 | // Make sure that the query is page-aligned | 132 | // Make sure that the query is page-aligned |
| 130 | if (addr_to_find & 0xfff) { | 133 | if (addr_to_find & 0xfff) { |
| @@ -134,7 +137,7 @@ uint64_t search_page_directory(struct nvdebug_state *g, | |||
| 134 | printk(KERN_INFO "[nvdebug] Searching for addr %#018llx in page table with base %#018lx\n", addr_to_find, (uintptr_t)pd_config.page_dir << 12); | 137 | printk(KERN_INFO "[nvdebug] Searching for addr %#018llx in page table with base %#018lx\n", addr_to_find, (uintptr_t)pd_config.page_dir << 12); |
| 135 | // Search the top-level page directory (PDE3) | 138 | // Search the top-level page directory (PDE3) |
| 136 | for (i = 0; i < NV_MMU_PT_V2_SZ[0]; i++) | 139 | for (i = 0; i < NV_MMU_PT_V2_SZ[0]; i++) |
| 137 | if ((res = search_page_directory_subtree(g, ((uintptr_t)pd_config.page_dir << 12) + NV_MMU_PT_V2_ENTRY_SZ[0] * i, INST2PD_TARGET(pd_config.target), addr_to_find, 0))) | 140 | if ((res = search_page_directory_subtree(g, ((uintptr_t)pd_config.page_dir << 12) + NV_MMU_PT_V2_ENTRY_SZ[0] * i, INST2PD_TARGET(pd_config.target), addr_to_find, addr_to_find_aperture, 0))) |
| 138 | return (res & ~0xfff) | (i << NV_MMU_PT_V2_LSB[0]); | 141 | return (res & ~0xfff) | (i << NV_MMU_PT_V2_LSB[0]); |
| 139 | return 0; | 142 | return 0; |
| 140 | } | 143 | } |
| @@ -143,8 +146,9 @@ uint64_t search_page_directory(struct nvdebug_state *g, | |||
| 143 | (See `search_page_directory()` for documentation.) | 146 | (See `search_page_directory()` for documentation.) |
| 144 | */ | 147 | */ |
| 145 | uint64_t search_v1_page_directory(struct nvdebug_state *g, | 148 | uint64_t search_v1_page_directory(struct nvdebug_state *g, |
| 146 | page_dir_config_t pd_config, | 149 | page_dir_config_t pd_config, |
| 147 | uint64_t addr_to_find) { | 150 | uint64_t addr_to_find, |
| 151 | enum INST_TARGET addr_to_find_aperture) { | ||
| 148 | uint64_t j, i = 0; | 152 | uint64_t j, i = 0; |
| 149 | page_dir_entry_v1_t pde; | 153 | page_dir_entry_v1_t pde; |
| 150 | page_tbl_entry_v1_t pte; | 154 | page_tbl_entry_v1_t pte; |
| @@ -188,7 +192,7 @@ uint64_t search_v1_page_directory(struct nvdebug_state *g, | |||
| 188 | continue; | 192 | continue; |
| 189 | printk_debug(KERN_INFO "[nvdebug] PTE for phy addr %llx %s (raw: %llx)\n", ((u64)pte.addr) << 12, pte.is_present ? "present" : "non-present", pte.raw); | 193 | printk_debug(KERN_INFO "[nvdebug] PTE for phy addr %llx %s (raw: %llx)\n", ((u64)pte.addr) << 12, pte.is_present ? "present" : "non-present", pte.raw); |
| 190 | // If we find a matching PTE, return its virtual address | 194 | // If we find a matching PTE, return its virtual address |
| 191 | if ((uint64_t)pte.addr << 12 == addr_to_find) | 195 | if ((uint64_t)pte.addr << 12 == addr_to_find && pte.target == addr_to_find_aperture) |
| 192 | return i << NV_MMU_PT_V1_LSB[0] | j << NV_MMU_PT_V1_LSB[1]; | 196 | return i << NV_MMU_PT_V1_LSB[0] | j << NV_MMU_PT_V1_LSB[1]; |
| 193 | } | 197 | } |
| 194 | } while (++i < NV_MMU_PT_V1_SZ[0]); | 198 | } while (++i < NV_MMU_PT_V1_SZ[0]); |
| @@ -1084,7 +1084,7 @@ typedef union { | |||
| 1084 | uint64_t addr:28; | 1084 | uint64_t addr:28; |
| 1085 | // 32:63 | 1085 | // 32:63 |
| 1086 | bool is_volatile:1; | 1086 | bool is_volatile:1; |
| 1087 | enum INST_TARGET:2; | 1087 | enum INST_TARGET target:2; |
| 1088 | bool atomics_disabled:1; | 1088 | bool atomics_disabled:1; |
| 1089 | uint32_t kind:8; | 1089 | uint32_t kind:8; |
| 1090 | uint32_t comptag:20; | 1090 | uint32_t comptag:20; |
| @@ -1266,17 +1266,19 @@ extern struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES]; | |||
| 1266 | int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl_iter); | 1266 | int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl_iter); |
| 1267 | int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id); | 1267 | int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id); |
| 1268 | int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id); | 1268 | int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id); |
| 1269 | int resubmit_runlist(struct nvdebug_state *g, uint32_t rl_id); | ||
| 1269 | 1270 | ||
| 1270 | // Defined in mmu.c | 1271 | // Defined in mmu.c |
| 1271 | void __iomem *phy2PRAMIN(struct nvdebug_state* g, uint64_t phy); | ||
| 1272 | uint64_t search_page_directory( | 1272 | uint64_t search_page_directory( |
| 1273 | struct nvdebug_state *g, | 1273 | struct nvdebug_state *g, |
| 1274 | page_dir_config_t pd_config, | 1274 | page_dir_config_t pd_config, |
| 1275 | uint64_t addr_to_find); | 1275 | uint64_t addr_to_find, |
| 1276 | enum INST_TARGET addr_to_find_aperture); | ||
| 1276 | uint64_t search_v1_page_directory( | 1277 | uint64_t search_v1_page_directory( |
| 1277 | struct nvdebug_state *g, | 1278 | struct nvdebug_state *g, |
| 1278 | page_dir_config_t pd_config, | 1279 | page_dir_config_t pd_config, |
| 1279 | uint64_t addr_to_find); | 1280 | uint64_t addr_to_find, |
| 1281 | enum INST_TARGET addr_to_find_aperture); | ||
| 1280 | // Defined in bus.c | 1282 | // Defined in bus.c |
| 1281 | int addr_to_pramin_mut(struct nvdebug_state *g, uint64_t addr, enum INST_TARGET target); | 1283 | int addr_to_pramin_mut(struct nvdebug_state *g, uint64_t addr, enum INST_TARGET target); |
| 1282 | int get_bar2_pdb(struct nvdebug_state *g, page_dir_config_t* pd); | 1284 | int get_bar2_pdb(struct nvdebug_state *g, page_dir_config_t* pd); |
| @@ -64,9 +64,9 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 64 | goto attempt_pramin_access; | 64 | goto attempt_pramin_access; |
| 65 | 65 | ||
| 66 | if (pd_config.is_ver2) | 66 | if (pd_config.is_ver2) |
| 67 | runlist_bar_vaddr = search_page_directory(g, pd_config, runlist_iova); | 67 | runlist_bar_vaddr = search_page_directory(g, pd_config, runlist_iova, TARGET_VID_MEM); |
| 68 | else | 68 | else |
| 69 | runlist_bar_vaddr = search_v1_page_directory(g, pd_config, runlist_iova); | 69 | runlist_bar_vaddr = search_v1_page_directory(g, pd_config, runlist_iova, TARGET_VID_MEM); |
| 70 | if (!runlist_bar_vaddr) { | 70 | if (!runlist_bar_vaddr) { |
| 71 | printk(KERN_WARNING "[nvdebug] Unable to find runlist %d mapping in BAR2/3 page tables for %x.\n", rl_id, g->chip_id); | 71 | printk(KERN_WARNING "[nvdebug] Unable to find runlist %d mapping in BAR2/3 page tables for %x.\n", rl_id, g->chip_id); |
| 72 | err = -EOPNOTSUPP; | 72 | err = -EOPNOTSUPP; |
