Search code examples
windowskernelx86-64pagingpage-tables

How do AMD64 page entry base address fields encode a 52-bit address in 40 bits?


I'm trying to manually walk the paging structures in order to convert a virtual address into its physical address. I have a question about the physical base address fields stored in the PML4E, PDPE, PDE, and PTE. The page size on my system is 4KB. I'm doing this on Windows in kernel mode.

As the amd64 manual says, bits 51-12 of cr3 contain the physical base address of the PML4. However, it says that bits 11-0 should be assumed as 0. I was wondering if the same thing applies to the base address fields of the other paging structures, because the diagrams that describe the translation process says 52, however the actual size is just 40 (bits 51-12).

enter image description here

Sample of how I'm doing the translation in C:

// clear out everything except base address field
ULONG_PTR pPml4 = __readcr3() & ~0xFFF0000000000FFF,
    dataEntry;

copyAddress.PhysicalAddress.QuadPart = pPml4 + (sourceAddress.Hard.PageMapLevel4Index * 8);

if (MmCopyMemory(&dataEntry, copyAddress, 8, MM_COPY_MEMORY_PHYSICAL, &trans) != STATUS_SUCCESS) {
    ...
}

// dataEntry now has correct PML4E

// clear out everything except base address field
dataEntry &= ~0xFFF0000000000FFF;

// do I skip this?
dataEntry >>= 12;

Solution

  • From section 5.4 of the manual:

    Translation-Table Base Address Field. The translation-table base-address field points to the physical base address of the next-lower-level table in the page-translation hierarchy. Page datastructure tables are always aligned on 4-Kbyte boundaries, so only the address bits above bit 11 are stored in the translation-table base-address field. Bits 11:0 are assumed to be 0. The size of the field depends on the mode...

    So yes, the low 12 bits are 0 to make a 52-bit physical address.