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; |