Skip to content

Instantly share code, notes, and snippets.

@jarlostensen
Created November 14, 2021 12:31
Show Gist options
  • Save jarlostensen/ebd3689f1332166576415b6f977be955 to your computer and use it in GitHub Desktop.
Save jarlostensen/ebd3689f1332166576415b6f977be955 to your computer and use it in GitHub Desktop.
4 level page table traversal
// from josx64, but this code is pretty generic.
// [kernel] fills in the pagetable entries from the given address
//
// see for example Intel Dev Guide Vol 3 4.2
_JOS_API_FUNC void pagetables_traverse_tables(void* at, uintptr_t * entries, size_t num_entries) {
_JOS_ASSERT(entries &&_4_level_paging && num_entries>=4);
memset(entries, 0, 4*sizeof(uintptr_t));
//NOTE: this relies on identity mapping in order to get access to the pagetables themselves
// but this is not essential for understanding the traversal.
uintptr_t address =(uintptr_t)at;
mapping_table_t* cr3 = (mapping_table_t*)x86_64_get_pml4();
uintptr_t pml4e = cr3->entries[PML4_IDX(address)];
entries[0] = pml4e;
if ( pml4e & PAGE_BIT_P_PRESENT ) {
mapping_table_t* pml4 = (mapping_table_t*)(pml4e & PAGE_ADDR_MASK);
uintptr_t pdpte = pml4->entries[PDPT_IDX(address)];
entries[1] = pdpte;
if ( (pdpte & PAGE_HUGE)==0 ) {
if ( pdpte & PAGE_BIT_P_PRESENT ) {
mapping_table_t* pdpt = (mapping_table_t*)(pdpte & PAGE_ADDR_MASK);
uintptr_t pde = pdpt->entries[PD_IDX(address)];
entries[2] = pde;
if ( (pde & PAGE_HUGE)==0 ) {
// 4KB pages
mapping_table_t* pd = (mapping_table_t*)(pde & PAGE_ADDR_MASK);
uintptr_t pte = pd->entries[PT_IDX(address)];
entries[3] = pte;
}
// else 2MB pages
}
}
// else 1GB pages
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment