diff options
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]); |
