diff options
author | Joshua Bakita <jbakita@cs.unc.edu> | 2024-04-09 14:15:27 -0400 |
---|---|---|
committer | Joshua Bakita <jbakita@cs.unc.edu> | 2024-04-09 14:15:27 -0400 |
commit | 664251e57c998ac97b66e8fc1dca1cb1b38a0c1e (patch) | |
tree | d254e5c752ba50cb7ca9ff031106006558fe4cd9 | |
parent | 8f9ed4c3b1f0e438107035147b5aa43fdcd66165 (diff) |
Improve debugging messages for reverse page translation
-rw-r--r-- | mmu.c | 10 | ||||
-rw-r--r-- | nvdebug.h | 11 |
2 files changed, 15 insertions, 6 deletions
@@ -64,21 +64,22 @@ uint64_t search_page_directory_subtree(struct nvdebug_state *g, | |||
64 | // Hack to workaround PDE0 being double-size and strangely formatted | 64 | // Hack to workaround PDE0 being double-size and strangely formatted |
65 | if (NV_MMU_PT_V2_ENTRY_SZ[level] == 16) | 65 | if (NV_MMU_PT_V2_ENTRY_SZ[level] == 16) |
66 | pde_offset += 8; | 66 | pde_offset += 8; |
67 | entry.raw = readl(pde_offset); | 67 | entry.raw_w = readq(pde_offset); |
68 | // If we reached an invalid (unpopulated) PDE, walk back up the tree | 68 | // If we reached an invalid (unpopulated) PDE, walk back up the tree |
69 | if (entry.target == PD_AND_TARGET_INVALID) | 69 | if (entry.target == PD_AND_TARGET_INVALID) |
70 | return 0; | 70 | return 0; |
71 | // Succeed when we reach a PTE with the address we want | 71 | // Succeed when we reach a PTE with the address we want |
72 | if (entry.is_pte) { | 72 | if (entry.is_pte) { |
73 | printk(KERN_INFO "[nvdebug] PTE for phy addr %llx (raw: %x)\n", ((u64)entry.addr) << 12, entry.raw); | 73 | // TODO: Handle huge pages here |
74 | printk(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); | ||
74 | return (uint64_t)entry.addr << 12 == addr_to_find; | 75 | return (uint64_t)entry.addr << 12 == addr_to_find; |
75 | } | 76 | } |
76 | printk(KERN_INFO "[nvdebug] Found PDE pointing to %llx in ap '%d' at lvl %d (raw: %x)\n", ((u64)entry.addr) << 12, entry.target, level, entry.raw); | 77 | printk(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); |
77 | // Depth-first search of the page table | 78 | // Depth-first search of the page table |
78 | for (i = 0; i < NV_MMU_PT_V2_SZ[level + 1]; i++) { | 79 | for (i = 0; i < NV_MMU_PT_V2_SZ[level + 1]; i++) { |
79 | next = off2addr(g, ((uint64_t)entry.addr << 12) + NV_MMU_PT_V2_ENTRY_SZ[level + 1] * i); | 80 | next = off2addr(g, ((uint64_t)entry.addr << 12) + NV_MMU_PT_V2_ENTRY_SZ[level + 1] * i); |
80 | // off2addr can fail | 81 | // off2addr can fail |
81 | if (!next) { | 82 | if (!next || !entry.addr_w) { |
82 | printk(KERN_ERR "[nvdebug] %s: Unable to resolve GPU PA to CPU PA\n", __func__); | 83 | printk(KERN_ERR "[nvdebug] %s: Unable to resolve GPU PA to CPU PA\n", __func__); |
83 | return 0; | 84 | return 0; |
84 | } | 85 | } |
@@ -111,6 +112,7 @@ uint64_t search_page_directory(struct nvdebug_state *g, | |||
111 | printk(KERN_WARNING "[nvdebug] Attempting to search for unaligned address %llx in search_page_directory()!\n", addr_to_find); | 112 | printk(KERN_WARNING "[nvdebug] Attempting to search for unaligned address %llx in search_page_directory()!\n", addr_to_find); |
112 | return 0; | 113 | return 0; |
113 | } | 114 | } |
115 | printk(KERN_INFO "[nvdebug] Searching for addr %#018llx in page table with base %#018llx\n", (u64)addr_to_find, (u64)pde_offset); | ||
114 | // Search the top-level page directory (PDE3) | 116 | // Search the top-level page directory (PDE3) |
115 | for (i = 0; i < NV_MMU_PT_V2_SZ[0]; i++) | 117 | for (i = 0; i < NV_MMU_PT_V2_SZ[0]; i++) |
116 | if ((res = search_page_directory_subtree(g, pde_offset + NV_MMU_PT_V2_ENTRY_SZ[0] * i, off2addr, addr_to_find, 0))) | 118 | if ((res = search_page_directory_subtree(g, pde_offset + NV_MMU_PT_V2_ENTRY_SZ[0] * i, off2addr, addr_to_find, 0))) |
@@ -935,7 +935,6 @@ static inline const char *pd_target_to_text(enum PD_TARGET t) { | |||
935 | // | 935 | // |
936 | // V3 introduced with Hopper, but Hopper and Blackwell also support V2 | 936 | // V3 introduced with Hopper, but Hopper and Blackwell also support V2 |
937 | // | 937 | // |
938 | // FIXME: This structure is 32 bits, but PDE/PTEs are actually 64 bits! | ||
939 | typedef union { | 938 | typedef union { |
940 | // Page Directory Entry (PDE) | 939 | // Page Directory Entry (PDE) |
941 | struct { | 940 | struct { |
@@ -943,6 +942,7 @@ typedef union { | |||
943 | bool is_volatile:1; | 942 | bool is_volatile:1; |
944 | uint32_t padding1:4; | 943 | uint32_t padding1:4; |
945 | uint32_t addr:24; | 944 | uint32_t addr:24; |
945 | uint32_t __unused1; | ||
946 | } __attribute__((packed)); | 946 | } __attribute__((packed)); |
947 | // Page Table Entry (PTE) | 947 | // Page Table Entry (PTE) |
948 | struct { | 948 | struct { |
@@ -954,8 +954,15 @@ typedef union { | |||
954 | bool is_readonly:1; | 954 | bool is_readonly:1; |
955 | bool atomics_disabled:1; | 955 | bool atomics_disabled:1; |
956 | uint32_t __addr:24; | 956 | uint32_t __addr:24; |
957 | uint32_t __unused2; | ||
957 | } __attribute__((packed)); | 958 | } __attribute__((packed)); |
958 | uint32_t raw; | 959 | // For wide addresses in PTEs or PDEs; only used if target is SYS_MEM |
960 | struct { | ||
961 | uint32_t __overlap:8; | ||
962 | uint64_t addr_w:46; | ||
963 | uint32_t __unused3:10; | ||
964 | } __attribute__((packed)); | ||
965 | uint64_t raw_w; | ||
959 | } page_dir_entry_t; | 966 | } page_dir_entry_t; |
960 | 967 | ||
961 | // Page Directory Entry/Page Table Entry V1 type | 968 | // Page Directory Entry/Page Table Entry V1 type |