| 120 | static const uint64_t PMASK = (~0xfull << 8) & 0xfffffffffull; |
| 121 | |
| 122 | uint64_t TranslateLinearAddress(uint64_t directoryTableBase, uint64_t virtualAddress) { |
| 123 | directoryTableBase &= ~0xf; |
| 124 | |
| 125 | uint64_t pageOffset = virtualAddress & ~(~0ul << PAGE_OFFSET_SIZE); |
| 126 | uint64_t pte = ((virtualAddress >> 12) & (0x1ffll)); |
| 127 | uint64_t pt = ((virtualAddress >> 21) & (0x1ffll)); |
| 128 | uint64_t pd = ((virtualAddress >> 30) & (0x1ffll)); |
| 129 | uint64_t pdp = ((virtualAddress >> 39) & (0x1ffll)); |
| 130 | |
| 131 | SIZE_T readsize = 0; |
| 132 | uint64_t pdpe = 0; |
| 133 | ReadPhysicalAddress(directoryTableBase + 8 * pdp, &pdpe, sizeof(pdpe), &readsize); |
| 134 | if (~pdpe & 1) |
| 135 | return 0; |
| 136 | |
| 137 | uint64_t pde = 0; |
| 138 | ReadPhysicalAddress((pdpe & PMASK) + 8 * pd, &pde, sizeof(pde), &readsize); |
| 139 | if (~pde & 1) |
| 140 | return 0; |
| 141 | |
| 142 | /* 1GB large page, use pde's 12-34 bits */ |
| 143 | if (pde & 0x80) |
| 144 | return (pde & (~0ull << 42 >> 12)) + (virtualAddress & ~(~0ull << 30)); |
| 145 | |
| 146 | uint64_t pteAddr = 0; |
| 147 | ReadPhysicalAddress((pde & PMASK) + 8 * pt, &pteAddr, sizeof(pteAddr), &readsize); |
| 148 | if (~pteAddr & 1) |
| 149 | return 0; |
| 150 | |
| 151 | /* 2MB large page */ |
| 152 | if (pteAddr & 0x80) |
| 153 | return (pteAddr & PMASK) + (virtualAddress & ~(~0ull << 21)); |
| 154 | |
| 155 | virtualAddress = 0; |
| 156 | ReadPhysicalAddress((pteAddr & PMASK) + 8 * pte, &virtualAddress, sizeof(virtualAddress), &readsize); |
| 157 | virtualAddress &= PMASK; |
| 158 | |
| 159 | if (!virtualAddress) |
| 160 | return 0; |
| 161 | |
| 162 | return virtualAddress + pageOffset; |
| 163 | } |
| 164 | |
| 165 | |
| 166 | // |
no test coverage detected