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 /mmu.c | |
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.
Diffstat (limited to 'mmu.c')
-rw-r--r-- | mmu.c | 18 |
1 files changed, 11 insertions, 7 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]); |