Linux Physical Address
Five-level page tables article - lwn.net/Articles/717293/
Original post - how to get physical address in Linux: stackoverflow.com/questions/41090469/linux-kernel-how-to-get-physical-address-memory-management
for five-level page tables add "p4d"
p4d_t *p4d; p4d = p4d_offset(pgd, vaddr); if (p4d_none(*p4d) || p4d_bad(*p4d)) { printk("not mapped in p4d\n"); return -1; } pud = pud_offset(p4d, vaddr); printk("pud_val = 0x%lx\n", pud_val(*pud)); if (pud_none(*pud)) { printk("not mapped in pud\n"); return -1; }
Full code
static unsigned long vaddr2paddr(unsigned long vaddr, struct task_struct *task) { pgd_t *pgd; p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned long paddr = 0; unsigned long page_addr = 0; unsigned long page_offset = 0; printk("vaddr %ld\n", vaddr); pgd = pgd_offset(task->mm, vaddr); if (pgd_none(*pgd) || pgd_bad(*pgd)) { printk("\t not mapped in pgd\n"); return -1; } printk("\t pgd_val = 0x%lx\n", pgd_val(*pgd)); printk("\t pgd_index = %lu\n", pgd_index(vaddr)); p4d = p4d_offset(pgd, vaddr); if (p4d_none(*p4d) || p4d_bad(*p4d)) { printk("\t not mapped in p4d\n"); return -1; } pud = pud_offset(p4d, vaddr); printk("\t pud_val = 0x%lx\n", pud_val(*pud)); if (pud_none(*pud)) { printk("\t not mapped in pud\n"); return -1; } pmd = pmd_offset(pud, vaddr); printk("\t pmd_val = 0x%lx\n", pmd_val(*pmd)); printk("\t pmd_index = %lu\n", pmd_index(vaddr)); if (pmd_none(*pmd)) { printk("\t not mapped in pmd\n"); return -1; } pte = pte_offset_kernel(pmd, vaddr); printk("\t pte_val = 0x%lx\n", pte_val(*pte)); printk("\t pte_index = %lu\n", pte_index(vaddr)); if (pte_none(*pte)) { printk("\t not mapped in pte\n"); //return -1; pte = pte_offset_map(pmd, vaddr); printk("\t pte_val map = 0x%lx\n", pte_val(*pte)); printk("\t pte_index map = %lu\n", pte_index(vaddr)); if (pte_none(*pte)) { printk("\t not mapped map in pte\n"); return -1; } } /* Page frame physical address mechanism | offset */ page_addr = pte_val(*pte) & PAGE_MASK; page_offset = vaddr & ~PAGE_MASK; paddr = page_addr | page_offset; printk("\t page_addr = %lx, page_offset = %lx\n", page_addr, page_offset); printk("\t vaddr = %lx, paddr = %lx\n", vaddr, paddr); return paddr; }